12 # include <winsock2.h>
13 # include <ws2tcpip.h>
33 # define EAGAIN WSATRY_AGAIN
34 # define EINTR WSAEINTR
35 # define EINPROGRESS WSAEINPROGRESS
36 # define EWOULDBLOCK WSAEWOULDBLOCK
37 # define ETIMEDOUT WSAETIMEDOUT
42 # include <sys/types.h>
43 # include <sys/socket.h>
44 # include <netinet/in.h>
50 # include <arpa/inet.h>
59 #if defined(__APPLE__) || defined(__MACH__)
61 # define MSG_NOSIGNAL SO_NOSIGPIPE
75 static bool wsInit =
false;
78 WORD wVersionRequested = MAKEWORD( 2, 0 );
80 WSAStartup(wVersionRequested, &wsaData);
97 return (err == EINPROGRESS || err == EAGAIN || err == EWOULDBLOCK || err == EINTR);
112 #if defined(_WINDOWS)
125 #if defined(_WINDOWS)
126 unsigned long flag = 1;
127 return (ioctlsocket((SOCKET)fd, FIONBIO, &flag) == 0);
129 return (fcntl(fd, F_SETFL, O_NONBLOCK) == 0);
139 return (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (
const char *)&sflag,
sizeof(sflag)) == 0);
149 memset(&ss, 0,
sizeof(ss));
153 sockaddr_in6 *address = (sockaddr_in6 *)&ss;
154 ss_len =
sizeof(sockaddr_in6);
156 address->sin6_family = AF_INET6;
157 address->sin6_addr = in6addr_any;
158 address->sin6_port = htons((u_short) port);
162 sockaddr_in *address = (sockaddr_in *)&ss;
163 ss_len =
sizeof(sockaddr_in);
165 address->sin_family = AF_INET;
166 address->sin_addr.s_addr = htonl(INADDR_ANY);
167 address->sin_port = htons((u_short) port);
170 return (::
bind(fd, (sockaddr*)&ss, ss_len) == 0);
178 return (::
listen(fd, backlog) == 0);
185 struct sockaddr_in addr;
186 #if defined(_WINDOWS)
191 addrlen =
sizeof(addr);
195 return (
int)
::accept(fd, (
struct sockaddr*)&addr, &addrlen);
206 memset(&ss, 0,
sizeof(ss));
208 struct addrinfo* addr;
209 struct addrinfo hints;
210 memset(&hints, 0,
sizeof(hints));
211 hints.ai_family = AF_UNSPEC;
212 int getaddr_err = getaddrinfo(host.c_str(), NULL, &hints, &addr);
213 if (0 != getaddr_err) {
214 #if !defined(_WINDOWS)
215 if(getaddr_err == EAI_SYSTEM) {
221 XmlRpcUtil::error(
"Couldn't find an %s address for [%s]: %s\n",
s_use_ipv6_ ?
"AF_INET6" :
"AF_INET", host.c_str(), gai_strerror(getaddr_err));
227 struct addrinfo* it = addr;
229 for (; it; it = it->ai_next)
233 sockaddr_in *address = (sockaddr_in *)&ss;
234 ss_len =
sizeof(sockaddr_in);
236 memcpy(address, it->ai_addr, it->ai_addrlen);
237 address->sin_family = it->ai_family;
238 address->sin_port = htons((u_short) port);
240 XmlRpcUtil::log(5,
"found host as %s\n", inet_ntoa(address->sin_addr));
246 sockaddr_in6 *address = (sockaddr_in6 *)&ss;
247 ss_len =
sizeof(sockaddr_in6);
249 memcpy(address, it->ai_addr, it->ai_addrlen);
250 address->sin6_family = it->ai_family;
251 address->sin6_port = htons((u_short) port);
255 XmlRpcUtil::log(5,
"found ipv6 host as %s\n", inet_ntop(AF_INET6, (
void*)&(address->sin6_addr), buf,
sizeof(buf)));
271 int result =
::connect(fd, (sockaddr*)&ss, ss_len);
276 #if defined(_WINDOWS)
277 if (error != EWOULDBLOCK) {
279 if (error != EINPROGRESS) {
297 const int READ_SIZE = 4096;
298 char readBuf[READ_SIZE];
300 bool wouldBlock =
false;
303 while ( ! wouldBlock && ! *eof) {
304 #if defined(_WINDOWS)
305 int n = recv(fd, readBuf, READ_SIZE-1, 0);
307 int n = read(fd, readBuf, READ_SIZE-1);
313 s.append(readBuf, n);
323 if (
s.length() >
size_t(INT_MAX)) {
324 XmlRpcUtil::error(
"XmlRpcSocket::nbRead: text size (%u) exceeds the maximum allowed size (%s).",
325 s.length(), INT_MAX);
338 if (
s.length() >
size_t(INT_MAX)) {
339 XmlRpcUtil::error(
"XmlRpcSocket::nbWrite: text size (%u) exceeds the maximum allowed size(%s)",
340 s.length(), INT_MAX);
343 int nToWrite = int(
s.length()) - *bytesSoFar;
344 char *sp =
const_cast<char*
>(
s.c_str()) + *bytesSoFar;
345 bool wouldBlock =
false;
347 while ( nToWrite > 0 && ! wouldBlock ) {
348 #if defined(_WINDOWS)
349 int n = send(fd, sp, nToWrite, 0);
351 int n = write(fd, sp, nToWrite);
353 XmlRpcUtil::log(5,
"XmlRpcSocket::nbWrite: send/write returned %d.", n);
373 #if defined(_WINDOWS)
374 return WSAGetLastError();
393 std::snprintf(err,
sizeof(err),
"%s",strerror(error));
394 return std::string(err);
400 socklen_t ss_len =
sizeof(ss);
401 if(getsockname(
socket, (sockaddr *)&ss, &ss_len) == 0) {
402 sockaddr_in *sin = (sockaddr_in *)&ss;
403 sockaddr_in6 *sin6 = (sockaddr_in6 *)&ss;
405 switch (ss.ss_family)
408 return ntohs(sin->sin_port);
410 return ntohs(sin6->sin6_port);