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