2
// XmlRpc++ Copyright (c) 2002-2008 by Chris Morley
5
#include "XmlRpcSocket.h"
6
#include "XmlRpcUtil.h"
11
# include <winsock2.h>
12
//# pragma lib(WS2_32.lib)
14
# define EINPROGRESS WSAEINPROGRESS
15
# define EWOULDBLOCK WSAEWOULDBLOCK
16
# define ETIMEDOUT WSAETIMEDOUT
18
typedef int socklen_t;
25
# include <sys/types.h>
26
# include <sys/socket.h>
27
# include <netinet/in.h>
36
using namespace XmlRpc;
39
// One-time initializations
40
static bool initialized = false;
43
static void initialize()
49
WORD wVersionRequested = MAKEWORD( 2, 0 );
51
WSAStartup(wVersionRequested, &wsaData);
56
(void) signal(SIGPIPE, SIG_IGN);
63
// These errors are not considered fatal for an IO operation; the operation will be re-tried.
65
XmlRpcSocket::nonFatalError()
67
int err = XmlRpcSocket::getError();
68
return (err == EINPROGRESS ||
80
XmlRpcSocket::socket()
82
if ( ! initialized) initialize();
83
return ::socket(AF_INET, SOCK_STREAM, 0);
88
XmlRpcSocket::close(XmlRpcSocket::Socket fd)
90
XmlRpcUtil::log(4, "XmlRpcSocket::close: fd %d.", fd);
102
XmlRpcSocket::setNonBlocking(XmlRpcSocket::Socket fd)
104
#if defined(_WINDOWS)
105
unsigned long flag = 1;
106
return (ioctlsocket(fd, FIONBIO, &flag) == 0);
108
return (fcntl(fd, F_SETFL, O_NONBLOCK) == 0);
114
XmlRpcSocket::setReuseAddr(XmlRpcSocket::Socket fd)
116
// Allow this port to be re-bound immediately so server re-starts are not delayed
118
return (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&sflag, sizeof(sflag)) == 0);
122
// Bind to a specified port
124
XmlRpcSocket::bind(XmlRpcSocket::Socket fd, int port)
126
struct sockaddr_in saddr;
127
memset(&saddr, 0, sizeof(saddr));
128
saddr.sin_family = AF_INET;
129
saddr.sin_addr.s_addr = htonl(INADDR_ANY);
130
saddr.sin_port = htons((u_short) port);
131
return (::bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)) == 0);
135
// Set socket in listen mode
137
XmlRpcSocket::listen(XmlRpcSocket::Socket fd, int backlog)
139
return (::listen(fd, backlog) == 0);
144
XmlRpcSocket::accept(XmlRpcSocket::Socket fd)
146
struct sockaddr_in addr;
147
socklen_t addrlen = sizeof(addr);
149
return ::accept(fd, (struct sockaddr*)&addr, &addrlen);
154
// Connect a socket to a server (from a client)
156
XmlRpcSocket::connect(XmlRpcSocket::Socket fd, std::string& host, int port)
158
struct sockaddr_in saddr;
159
memset(&saddr, 0, sizeof(saddr));
160
saddr.sin_family = AF_INET;
162
struct hostent *hp = gethostbyname(host.c_str());
163
if (hp == 0) return false;
165
saddr.sin_family = hp->h_addrtype;
166
memcpy(&saddr.sin_addr, hp->h_addr, hp->h_length);
167
saddr.sin_port = htons((u_short) port);
169
// For asynch operation, this will return EWOULDBLOCK (windows) or
170
// EINPROGRESS (linux) and we just need to wait for the socket to be writable...
171
int result = ::connect(fd, (struct sockaddr *)&saddr, sizeof(saddr));
172
return result == 0 || nonFatalError();
177
// Get the port of a bound socket
179
XmlRpcSocket::getPort(XmlRpcSocket::Socket socket)
181
struct sockaddr_in saddr;
182
socklen_t saddr_len = sizeof(saddr);
185
int result = ::getsockname(socket, (sockaddr*) &saddr, &saddr_len);
190
port = ntohs(saddr.sin_port);
196
// Returns last errno
198
XmlRpcSocket::getError()
200
#if defined(_WINDOWS)
201
return WSAGetLastError();
208
// Returns message corresponding to last errno
210
XmlRpcSocket::getErrorMsg()
212
return getErrorMsg(getError());
215
// Returns message corresponding to errno... well, it should anyway
217
XmlRpcSocket::getErrorMsg(int error)
220
snprintf(err,sizeof(err),"error %d", error);
221
return std::string(err);