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