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