00001
00002
00003
00004
00005 #include "XmlRpcSocket.h"
00006 #include "XmlRpcUtil.h"
00007
00008 #ifndef MAKEDEPEND
00009
00010 #if defined(_WINDOWS)
00011 # include <stdio.h>
00012 # include <winsock2.h>
00013 # include <ws2tcpip.h>
00014
00015
00016
00017
00018 #ifdef EAGAIN
00019 #undef EAGAIN
00020 #endif
00021 #ifdef EINTR
00022 #undef EINTR
00023 #endif
00024 #ifdef EINPROGRESS
00025 #undef EINPROGRESS
00026 #endif
00027 #ifdef EWOULDBLOCK
00028 #undef EWOULDBLOCK
00029 #endif
00030 #ifdef ETIMEDOUT
00031 #undef ETIMEDOUT
00032 #endif
00033 # define EAGAIN WSATRY_AGAIN
00034 # define EINTR WSAEINTR
00035 # define EINPROGRESS WSAEINPROGRESS
00036 # define EWOULDBLOCK WSAEWOULDBLOCK
00037 # define ETIMEDOUT WSAETIMEDOUT
00038 #else
00039 extern "C" {
00040 # include <unistd.h>
00041 # include <stdio.h>
00042 # include <sys/types.h>
00043 # include <sys/socket.h>
00044 # include <netinet/in.h>
00045 # include <netdb.h>
00046 # include <errno.h>
00047 # include <fcntl.h>
00048 # include <string.h>
00049 }
00050 #endif // _WINDOWS
00051
00052 #endif // MAKEDEPEND
00053
00054
00055 #if defined(__APPLE__) || defined(__MACH__)
00056 # ifndef MSG_NOSIGNAL
00057 # define MSG_NOSIGNAL SO_NOSIGPIPE
00058 # endif
00059 #endif
00060
00061
00062 using namespace XmlRpc;
00063
00064
00065
00066 #if defined(_WINDOWS)
00067
00068 static void initWinSock()
00069 {
00070 static bool wsInit = false;
00071 if (! wsInit)
00072 {
00073 WORD wVersionRequested = MAKEWORD( 2, 0 );
00074 WSADATA wsaData;
00075 WSAStartup(wVersionRequested, &wsaData);
00076 wsInit = true;
00077 }
00078 }
00079
00080 #else
00081
00082 #define initWinSock()
00083
00084 #endif // _WINDOWS
00085
00086
00087
00088 static inline bool
00089 nonFatalError()
00090 {
00091 int err = XmlRpcSocket::getError();
00092 return (err == EINPROGRESS || err == EAGAIN || err == EWOULDBLOCK || err == EINTR);
00093 }
00094
00095
00096
00097 int
00098 XmlRpcSocket::socket()
00099 {
00100 initWinSock();
00101 return (int) ::socket(AF_INET, SOCK_STREAM, 0);
00102 }
00103
00104
00105 void
00106 XmlRpcSocket::close(int fd)
00107 {
00108 XmlRpcUtil::log(4, "XmlRpcSocket::close: fd %d.", fd);
00109 #if defined(_WINDOWS)
00110 closesocket(fd);
00111 #else
00112 ::close(fd);
00113 #endif // _WINDOWS
00114 }
00115
00116
00117
00118
00119 bool
00120 XmlRpcSocket::setNonBlocking(int fd)
00121 {
00122 #if defined(_WINDOWS)
00123 unsigned long flag = 1;
00124 return (ioctlsocket((SOCKET)fd, FIONBIO, &flag) == 0);
00125 #else
00126 return (fcntl(fd, F_SETFL, O_NONBLOCK) == 0);
00127 #endif // _WINDOWS
00128 }
00129
00130
00131 bool
00132 XmlRpcSocket::setReuseAddr(int fd)
00133 {
00134
00135 int sflag = 1;
00136 return (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&sflag, sizeof(sflag)) == 0);
00137 }
00138
00139
00140
00141 bool
00142 XmlRpcSocket::bind(int fd, int port)
00143 {
00144 struct sockaddr_in saddr;
00145 memset(&saddr, 0, sizeof(saddr));
00146 saddr.sin_family = AF_INET;
00147 saddr.sin_addr.s_addr = htonl(INADDR_ANY);
00148 saddr.sin_port = htons((u_short) port);
00149 return (::bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)) == 0);
00150 }
00151
00152
00153
00154 bool
00155 XmlRpcSocket::listen(int fd, int backlog)
00156 {
00157 return (::listen(fd, backlog) == 0);
00158 }
00159
00160
00161 int
00162 XmlRpcSocket::accept(int fd)
00163 {
00164 struct sockaddr_in addr;
00165 #if defined(_WINDOWS)
00166 int
00167 #else
00168 socklen_t
00169 #endif
00170 addrlen = sizeof(addr);
00171
00172 return (int) ::accept(fd, (struct sockaddr*)&addr, &addrlen);
00173 }
00174
00175
00176
00177
00178 bool
00179 XmlRpcSocket::connect(int fd, std::string& host, int port)
00180 {
00181 struct sockaddr_in saddr;
00182 memset(&saddr, 0, sizeof(saddr));
00183 saddr.sin_family = AF_INET;
00184
00185 struct addrinfo* addr;
00186 if (getaddrinfo(host.c_str(), NULL, NULL, &addr) != 0)
00187 {
00188 return false;
00189 }
00190
00191 bool found = false;
00192 struct addrinfo* it = addr;
00193 for (; it; it = it->ai_next)
00194 {
00195 if (it->ai_family == AF_INET)
00196 {
00197 memcpy(&saddr, it->ai_addr, it->ai_addrlen);
00198 saddr.sin_family = it->ai_family;
00199 saddr.sin_port = htons((u_short) port);
00200
00201 found = true;
00202 break;
00203 }
00204 }
00205
00206 if (!found)
00207 {
00208 printf("Couldn't find an AF_INET address for [%s]\n", host.c_str());
00209 freeaddrinfo(addr);
00210 return false;
00211 }
00212
00213
00214
00215 int result = ::connect(fd, (struct sockaddr *)&saddr, sizeof(saddr));
00216 if (result != 0 ) {
00217 int error = getError();
00218 if ( (error != EINPROGRESS) && error != EWOULDBLOCK) {
00219 printf("::connect error = %d\n", getError());
00220 }
00221 }
00222
00223 freeaddrinfo(addr);
00224
00225 return result == 0 || nonFatalError();
00226 }
00227
00228
00229
00230
00231 bool
00232 XmlRpcSocket::nbRead(int fd, std::string& s, bool *eof)
00233 {
00234 const int READ_SIZE = 4096;
00235 char readBuf[READ_SIZE];
00236
00237 bool wouldBlock = false;
00238 *eof = false;
00239
00240 while ( ! wouldBlock && ! *eof) {
00241 #if defined(_WINDOWS)
00242 int n = recv(fd, readBuf, READ_SIZE-1, 0);
00243 #else
00244 int n = read(fd, readBuf, READ_SIZE-1);
00245 #endif
00246 XmlRpcUtil::log(5, "XmlRpcSocket::nbRead: read/recv returned %d.", n);
00247
00248 if (n > 0) {
00249 readBuf[n] = 0;
00250 s.append(readBuf, n);
00251 } else if (n == 0) {
00252 *eof = true;
00253 } else if (nonFatalError()) {
00254 wouldBlock = true;
00255 } else {
00256 return false;
00257 }
00258 }
00259 return true;
00260 }
00261
00262
00263
00264 bool
00265 XmlRpcSocket::nbWrite(int fd, std::string& s, int *bytesSoFar)
00266 {
00267 int nToWrite = int(s.length()) - *bytesSoFar;
00268 char *sp = const_cast<char*>(s.c_str()) + *bytesSoFar;
00269 bool wouldBlock = false;
00270
00271 while ( nToWrite > 0 && ! wouldBlock ) {
00272 #if defined(_WINDOWS)
00273 int n = send(fd, sp, nToWrite, 0);
00274 #else
00275 int n = send(fd, sp, nToWrite, MSG_NOSIGNAL);
00276 #endif
00277 XmlRpcUtil::log(5, "XmlRpcSocket::nbWrite: send/write returned %d.", n);
00278
00279 if (n > 0) {
00280 sp += n;
00281 *bytesSoFar += n;
00282 nToWrite -= n;
00283 } else if (nonFatalError()) {
00284 wouldBlock = true;
00285 } else {
00286 return false;
00287 }
00288 }
00289 return true;
00290 }
00291
00292
00293
00294 int
00295 XmlRpcSocket::getError()
00296 {
00297 #if defined(_WINDOWS)
00298 return WSAGetLastError();
00299 #else
00300 return errno;
00301 #endif
00302 }
00303
00304
00305
00306 std::string
00307 XmlRpcSocket::getErrorMsg()
00308 {
00309 return getErrorMsg(getError());
00310 }
00311
00312
00313 std::string
00314 XmlRpcSocket::getErrorMsg(int error)
00315 {
00316 char err[60];
00317 #ifdef _MSC_VER
00318 strerror_s(err,60,error);
00319 #else
00320 snprintf(err,sizeof(err),"%s",strerror(error));
00321 #endif
00322 return std::string(err);
00323 }
00324
00325 int XmlRpcSocket::get_port(int socket)
00326 {
00327 sockaddr_in sin;
00328 socklen_t sin_len = sizeof(sin);
00329 getsockname(socket, (sockaddr *)&sin, &sin_len);
00330 return ntohs(sin.sin_port);
00331 }
00332