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 # include <stdlib.h>
00050 # include <arpa/inet.h>
00051 }
00052 #endif // _WINDOWS
00053
00054 #endif // MAKEDEPEND
00055
00056
00057 #if defined(__APPLE__) || defined(__MACH__)
00058 # ifndef MSG_NOSIGNAL
00059 # define MSG_NOSIGNAL SO_NOSIGPIPE
00060 # endif
00061 #endif
00062
00063
00064 using namespace XmlRpc;
00065
00066
00067 bool XmlRpcSocket::s_use_ipv6_ = false;
00068
00069 #if defined(_WINDOWS)
00070
00071 static void initWinSock()
00072 {
00073 static bool wsInit = false;
00074 if (! wsInit)
00075 {
00076 WORD wVersionRequested = MAKEWORD( 2, 0 );
00077 WSADATA wsaData;
00078 WSAStartup(wVersionRequested, &wsaData);
00079 wsInit = true;
00080 }
00081 }
00082
00083 #else
00084
00085 #define initWinSock()
00086
00087 #endif // _WINDOWS
00088
00089
00090
00091 static inline bool
00092 nonFatalError()
00093 {
00094 int err = XmlRpcSocket::getError();
00095 return (err == EINPROGRESS || err == EAGAIN || err == EWOULDBLOCK || err == EINTR);
00096 }
00097
00098 int
00099 XmlRpcSocket::socket()
00100 {
00101 initWinSock();
00102 return (int) ::socket(s_use_ipv6_ ? AF_INET6 : AF_INET, SOCK_STREAM, 0);
00103 }
00104
00105
00106 void
00107 XmlRpcSocket::close(int fd)
00108 {
00109 XmlRpcUtil::log(4, "XmlRpcSocket::close: fd %d.", fd);
00110 #if defined(_WINDOWS)
00111 closesocket(fd);
00112 #else
00113 ::close(fd);
00114 #endif // _WINDOWS
00115 }
00116
00117
00118
00119
00120 bool
00121 XmlRpcSocket::setNonBlocking(int fd)
00122 {
00123 #if defined(_WINDOWS)
00124 unsigned long flag = 1;
00125 return (ioctlsocket((SOCKET)fd, FIONBIO, &flag) == 0);
00126 #else
00127 return (fcntl(fd, F_SETFL, O_NONBLOCK) == 0);
00128 #endif // _WINDOWS
00129 }
00130
00131
00132 bool
00133 XmlRpcSocket::setReuseAddr(int fd)
00134 {
00135
00136 int sflag = 1;
00137 return (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&sflag, sizeof(sflag)) == 0);
00138 }
00139
00140
00141
00142 bool
00143 XmlRpcSocket::bind(int fd, int port)
00144 {
00145 sockaddr_storage ss;
00146 socklen_t ss_len;
00147 memset(&ss, 0, sizeof(ss));
00148
00149 if (s_use_ipv6_)
00150 {
00151 sockaddr_in6 *address = (sockaddr_in6 *)&ss;
00152 ss_len = sizeof(sockaddr_in6);
00153
00154 address->sin6_family = AF_INET6;
00155 address->sin6_addr = in6addr_any;
00156 address->sin6_port = htons((u_short) port);
00157 }
00158 else
00159 {
00160 sockaddr_in *address = (sockaddr_in *)&ss;
00161 ss_len = sizeof(sockaddr_in);
00162
00163 address->sin_family = AF_INET;
00164 address->sin_addr.s_addr = htonl(INADDR_ANY);
00165 address->sin_port = htons((u_short) port);
00166 }
00167
00168 return (::bind(fd, (sockaddr*)&ss, ss_len) == 0);
00169 }
00170
00171
00172
00173 bool
00174 XmlRpcSocket::listen(int fd, int backlog)
00175 {
00176 return (::listen(fd, backlog) == 0);
00177 }
00178
00179
00180 int
00181 XmlRpcSocket::accept(int fd)
00182 {
00183 struct sockaddr_in addr;
00184 #if defined(_WINDOWS)
00185 int
00186 #else
00187 socklen_t
00188 #endif
00189 addrlen = sizeof(addr);
00190
00191
00192
00193 return (int) ::accept(fd, (struct sockaddr*)&addr, &addrlen);
00194 }
00195
00196
00197
00198
00199 bool
00200 XmlRpcSocket::connect(int fd, std::string& host, int port)
00201 {
00202 sockaddr_storage ss;
00203 socklen_t ss_len;
00204 memset(&ss, 0, sizeof(ss));
00205
00206 struct addrinfo* addr;
00207 struct addrinfo hints;
00208 memset(&hints, 0, sizeof(hints));
00209 hints.ai_family = AF_UNSPEC;
00210 if (getaddrinfo(host.c_str(), NULL, &hints, &addr) != 0)
00211 {
00212 fprintf(stderr, "Couldn't find an %s address for [%s]\n", s_use_ipv6_ ? "AF_INET6" : "AF_INET", host.c_str());
00213 return false;
00214 }
00215
00216 bool found = false;
00217 struct addrinfo* it = addr;
00218
00219 socklen_t len;
00220 struct sockaddr *address;
00221
00222 for (; it; it = it->ai_next)
00223 {
00224 if (!s_use_ipv6_ && it->ai_family == AF_INET)
00225 {
00226 sockaddr_in *address = (sockaddr_in *)&ss;
00227 ss_len = sizeof(sockaddr_in);
00228
00229 memcpy(address, it->ai_addr, it->ai_addrlen);
00230 address->sin_family = it->ai_family;
00231 address->sin_port = htons((u_short) port);
00232
00233 XmlRpcUtil::log(5, "found host as %s\n", inet_ntoa(address->sin_addr));
00234 found = true;
00235 break;
00236 }
00237 if (s_use_ipv6_ && it->ai_family == AF_INET6)
00238 {
00239 sockaddr_in6 *address = (sockaddr_in6 *)&ss;
00240 ss_len = sizeof(sockaddr_in6);
00241
00242 memcpy(address, it->ai_addr, it->ai_addrlen);
00243 address->sin6_family = it->ai_family;
00244 address->sin6_port = htons((u_short) port);
00245
00246 char buf[128];
00247
00248 XmlRpcUtil::log(5, "found ipv6 host as %s\n", inet_ntop(AF_INET6, (void*)&(address->sin6_addr), buf, sizeof(buf)));
00249 found = true;
00250 break;
00251 }
00252
00253 }
00254
00255 if (!found)
00256 {
00257 printf("Couldn't find an %s address for [%s]\n", s_use_ipv6_ ? "AF_INET6" : "AF_INET", host.c_str());
00258 freeaddrinfo(addr);
00259 return false;
00260 }
00261
00262
00263
00264 int result = ::connect(fd, (sockaddr*)&ss, ss_len);
00265 if (result != 0 ) {
00266 int error = getError();
00267 if ( (error != EINPROGRESS) && error != EWOULDBLOCK) {
00268 printf("::connect error = %d\n", getError());
00269 }
00270 }
00271
00272 freeaddrinfo(addr);
00273
00274 return result == 0 || nonFatalError();
00275 }
00276
00277
00278
00279
00280 bool
00281 XmlRpcSocket::nbRead(int fd, std::string& s, bool *eof)
00282 {
00283 const int READ_SIZE = 4096;
00284 char readBuf[READ_SIZE];
00285
00286 bool wouldBlock = false;
00287 *eof = false;
00288
00289 while ( ! wouldBlock && ! *eof) {
00290 #if defined(_WINDOWS)
00291 int n = recv(fd, readBuf, READ_SIZE-1, 0);
00292 #else
00293 int n = read(fd, readBuf, READ_SIZE-1);
00294 #endif
00295 XmlRpcUtil::log(5, "XmlRpcSocket::nbRead: read/recv returned %d.", n);
00296
00297 if (n > 0) {
00298 readBuf[n] = 0;
00299 s.append(readBuf, n);
00300 } else if (n == 0) {
00301 *eof = true;
00302 } else if (nonFatalError()) {
00303 wouldBlock = true;
00304 } else {
00305 return false;
00306 }
00307 }
00308 return true;
00309 }
00310
00311
00312
00313 bool
00314 XmlRpcSocket::nbWrite(int fd, std::string& s, int *bytesSoFar)
00315 {
00316 int nToWrite = int(s.length()) - *bytesSoFar;
00317 char *sp = const_cast<char*>(s.c_str()) + *bytesSoFar;
00318 bool wouldBlock = false;
00319
00320 while ( nToWrite > 0 && ! wouldBlock ) {
00321 #if defined(_WINDOWS)
00322 int n = send(fd, sp, nToWrite, 0);
00323 #else
00324 int n = write(fd, sp, nToWrite);
00325 #endif
00326 XmlRpcUtil::log(5, "XmlRpcSocket::nbWrite: send/write returned %d.", n);
00327
00328 if (n > 0) {
00329 sp += n;
00330 *bytesSoFar += n;
00331 nToWrite -= n;
00332 } else if (nonFatalError()) {
00333 wouldBlock = true;
00334 } else {
00335 return false;
00336 }
00337 }
00338 return true;
00339 }
00340
00341
00342
00343 int
00344 XmlRpcSocket::getError()
00345 {
00346 #if defined(_WINDOWS)
00347 return WSAGetLastError();
00348 #else
00349 return errno;
00350 #endif
00351 }
00352
00353
00354
00355 std::string
00356 XmlRpcSocket::getErrorMsg()
00357 {
00358 return getErrorMsg(getError());
00359 }
00360
00361
00362 std::string
00363 XmlRpcSocket::getErrorMsg(int error)
00364 {
00365 char err[60];
00366 #ifdef _MSC_VER
00367 strerror_s(err,60,error);
00368 #else
00369 snprintf(err,sizeof(err),"%s",strerror(error));
00370 #endif
00371 return std::string(err);
00372 }
00373
00374 int XmlRpcSocket::get_port(int socket)
00375 {
00376 sockaddr_storage ss;
00377 socklen_t ss_len = sizeof(ss);
00378 getsockname(socket, (sockaddr *)&ss, &ss_len);
00379
00380 sockaddr_in *sin = (sockaddr_in *)&ss;
00381 sockaddr_in6 *sin6 = (sockaddr_in6 *)&ss;
00382
00383 switch (ss.ss_family)
00384 {
00385 case AF_INET:
00386 return ntohs(sin->sin_port);
00387 case AF_INET6:
00388 return ntohs(sin6->sin6_port);
00389 }
00390 return 0;
00391 }
00392