14e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
24e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#include "XmlRpcSocket.h"
34e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#include "XmlRpcUtil.h"
44e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
54e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#ifndef MAKEDEPEND
64e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
74e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#if defined(_WINDOWS)
84e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius# include <stdio.h>
94e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius# include <winsock2.h>
104e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius//# pragma lib(WS2_32.lib)
114e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
124e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius# define EINPROGRESS	WSAEINPROGRESS
134e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius# define EWOULDBLOCK	WSAEWOULDBLOCK
144e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius# define ETIMEDOUT	    WSAETIMEDOUT
154e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#else
164e2ea8184cc1f9609f1f1251394316629a108a78Roshan Piusextern "C" {
174e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius# include <unistd.h>
184e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius# include <stdio.h>
194e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius# include <sys/types.h>
204e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius# include <sys/socket.h>
214e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius# include <netinet/in.h>
224e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius# include <netdb.h>
234e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius# include <errno.h>
244e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius# include <fcntl.h>
254e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius}
264e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#endif  // _WINDOWS
274e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
284e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#endif // MAKEDEPEND
294e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
304e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
314e2ea8184cc1f9609f1f1251394316629a108a78Roshan Piususing namespace XmlRpc;
324e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
334e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
344e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
354e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#if defined(_WINDOWS)
364e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
374e2ea8184cc1f9609f1f1251394316629a108a78Roshan Piusstatic void initWinSock()
384e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius{
394e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  static bool wsInit = false;
404e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  if (! wsInit)
414e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  {
424e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius    WORD wVersionRequested = MAKEWORD( 2, 0 );
434e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius    WSADATA wsaData;
444e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius    WSAStartup(wVersionRequested, &wsaData);
454e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius    wsInit = true;
464e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  }
474e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius}
484e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
494e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#else
504e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
514e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#define initWinSock()
524e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
534e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#endif // _WINDOWS
544e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
554e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
564e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius// These errors are not considered fatal for an IO operation; the operation will be re-tried.
574e2ea8184cc1f9609f1f1251394316629a108a78Roshan Piusstatic inline bool
584e2ea8184cc1f9609f1f1251394316629a108a78Roshan PiusnonFatalError()
594e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius{
604e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  int err = XmlRpcSocket::getError();
614e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  return (err == EINPROGRESS || err == EAGAIN || err == EWOULDBLOCK || err == EINTR);
624e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius}
634e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
644e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
654e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
664e2ea8184cc1f9609f1f1251394316629a108a78Roshan Piusint
674e2ea8184cc1f9609f1f1251394316629a108a78Roshan PiusXmlRpcSocket::socket()
684e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius{
694e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  initWinSock();
704e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  return (int) ::socket(AF_INET, SOCK_STREAM, 0);
714e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius}
724e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
734e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
744e2ea8184cc1f9609f1f1251394316629a108a78Roshan Piusvoid
754e2ea8184cc1f9609f1f1251394316629a108a78Roshan PiusXmlRpcSocket::close(int fd)
764e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius{
774e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  XmlRpcUtil::log(4, "XmlRpcSocket::close: fd %d.", fd);
784e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#if defined(_WINDOWS)
794e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  closesocket(fd);
804e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#else
814e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  ::close(fd);
824e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#endif // _WINDOWS
834e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius}
844e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
854e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
864e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
874e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
884e2ea8184cc1f9609f1f1251394316629a108a78Roshan Piusbool
894e2ea8184cc1f9609f1f1251394316629a108a78Roshan PiusXmlRpcSocket::setNonBlocking(int fd)
904e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius{
914e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#if defined(_WINDOWS)
924e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  unsigned long flag = 1;
934e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  return (ioctlsocket((SOCKET)fd, FIONBIO, &flag) == 0);
944e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#else
954e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  return (fcntl(fd, F_SETFL, O_NONBLOCK) == 0);
964e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#endif // _WINDOWS
974e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius}
984e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
994e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
1004e2ea8184cc1f9609f1f1251394316629a108a78Roshan Piusbool
1014e2ea8184cc1f9609f1f1251394316629a108a78Roshan PiusXmlRpcSocket::setReuseAddr(int fd)
1024e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius{
1034e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  // Allow this port to be re-bound immediately so server re-starts are not delayed
1044e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  int sflag = 1;
1054e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  return (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&sflag, sizeof(sflag)) == 0);
1064e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius}
1074e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
1084e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
1094e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius// Bind to a specified port
1104e2ea8184cc1f9609f1f1251394316629a108a78Roshan Piusbool
1114e2ea8184cc1f9609f1f1251394316629a108a78Roshan PiusXmlRpcSocket::bind(int fd, int port)
1124e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius{
1134e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  struct sockaddr_in saddr;
1144e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  memset(&saddr, 0, sizeof(saddr));
1154e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  saddr.sin_family = AF_INET;
1164e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  saddr.sin_addr.s_addr = htonl(INADDR_ANY);
1174e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  saddr.sin_port = htons((u_short) port);
1184e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  return (::bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)) == 0);
1194e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius}
1204e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
1214e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
1224e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius// Set socket in listen mode
1234e2ea8184cc1f9609f1f1251394316629a108a78Roshan Piusbool
1244e2ea8184cc1f9609f1f1251394316629a108a78Roshan PiusXmlRpcSocket::listen(int fd, int backlog)
1254e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius{
1264e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  return (::listen(fd, backlog) == 0);
1274e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius}
1284e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
1294e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
1304e2ea8184cc1f9609f1f1251394316629a108a78Roshan Piusint
1314e2ea8184cc1f9609f1f1251394316629a108a78Roshan PiusXmlRpcSocket::accept(int fd)
1324e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius{
1334e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  struct sockaddr_in addr;
1344e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#if defined(_WINDOWS)
1354e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  int
1364e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#else
1374e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  socklen_t
1384e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#endif
1394e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius    addrlen = sizeof(addr);
1404e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
1414e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  return (int) ::accept(fd, (struct sockaddr*)&addr, &addrlen);
1424e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius}
1434e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
1444e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
1454e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
1464e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius// Connect a socket to a server (from a client)
1474e2ea8184cc1f9609f1f1251394316629a108a78Roshan Piusbool
1484e2ea8184cc1f9609f1f1251394316629a108a78Roshan PiusXmlRpcSocket::connect(int fd, std::string& host, int port)
1494e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius{
1504e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  struct sockaddr_in saddr;
1514e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  memset(&saddr, 0, sizeof(saddr));
1524e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  saddr.sin_family = AF_INET;
1534e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
1544e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  struct hostent *hp = gethostbyname(host.c_str());
1554e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  if (hp == 0) return false;
1564e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
1574e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  saddr.sin_family = hp->h_addrtype;
1584e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  memcpy(&saddr.sin_addr, hp->h_addr, hp->h_length);
1594e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  saddr.sin_port = htons((u_short) port);
1604e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
1614e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  // For asynch operation, this will return EWOULDBLOCK (windows) or
1624e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  // EINPROGRESS (linux) and we just need to wait for the socket to be writable...
1634e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  int result = ::connect(fd, (struct sockaddr *)&saddr, sizeof(saddr));
1644e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  return result == 0 || nonFatalError();
1654e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius}
1664e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
1674e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
1684e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
1694e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius// Read available text from the specified socket. Returns false on error.
1704e2ea8184cc1f9609f1f1251394316629a108a78Roshan Piusbool
1714e2ea8184cc1f9609f1f1251394316629a108a78Roshan PiusXmlRpcSocket::nbRead(int fd, std::string& s, bool *eof)
1724e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius{
1734e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  const int READ_SIZE = 4096;   // Number of bytes to attempt to read at a time
1744e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  char readBuf[READ_SIZE];
1754e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
1764e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  bool wouldBlock = false;
1774e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  *eof = false;
1784e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
1794e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  while ( ! wouldBlock && ! *eof) {
1804e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#if defined(_WINDOWS)
1814e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius    int n = recv(fd, readBuf, READ_SIZE-1, 0);
1824e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#else
1834e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius    int n = read(fd, readBuf, READ_SIZE-1);
1844e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#endif
1854e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius    XmlRpcUtil::log(5, "XmlRpcSocket::nbRead: read/recv returned %d.", n);
1864e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
1874e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius    if (n > 0) {
1884e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius      readBuf[n] = 0;
1894e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius      s.append(readBuf, n);
1904e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius    } else if (n == 0) {
1914e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius      *eof = true;
1924e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius    } else if (nonFatalError()) {
1934e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius      wouldBlock = true;
1944e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius    } else {
1954e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius      return false;   // Error
1964e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius    }
1974e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  }
1984e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  return true;
1994e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius}
2004e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
2014e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
2024e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius// Write text to the specified socket. Returns false on error.
2034e2ea8184cc1f9609f1f1251394316629a108a78Roshan Piusbool
2044e2ea8184cc1f9609f1f1251394316629a108a78Roshan PiusXmlRpcSocket::nbWrite(int fd, std::string& s, int *bytesSoFar)
2054e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius{
2064e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  int nToWrite = int(s.length()) - *bytesSoFar;
2074e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  char *sp = const_cast<char*>(s.c_str()) + *bytesSoFar;
2084e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  bool wouldBlock = false;
2094e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
2104e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  while ( nToWrite > 0 && ! wouldBlock ) {
2114e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#if defined(_WINDOWS)
2124e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius    int n = send(fd, sp, nToWrite, 0);
2134e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#else
2144e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius    int n = write(fd, sp, nToWrite);
2154e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#endif
2164e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius    XmlRpcUtil::log(5, "XmlRpcSocket::nbWrite: send/write returned %d.", n);
2174e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
2184e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius    if (n > 0) {
2194e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius      sp += n;
2204e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius      *bytesSoFar += n;
2214e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius      nToWrite -= n;
2224e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius    } else if (nonFatalError()) {
2234e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius      wouldBlock = true;
2244e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius    } else {
2254e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius      return false;   // Error
2264e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius    }
2274e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  }
2284e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  return true;
2294e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius}
2304e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
2314e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
2324e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius// Returns last errno
2334e2ea8184cc1f9609f1f1251394316629a108a78Roshan Piusint
2344e2ea8184cc1f9609f1f1251394316629a108a78Roshan PiusXmlRpcSocket::getError()
2354e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius{
2364e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#if defined(_WINDOWS)
2374e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  return WSAGetLastError();
2384e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#else
2394e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  return errno;
2404e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#endif
2414e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius}
2424e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
2434e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
2444e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius// Returns message corresponding to last errno
2454e2ea8184cc1f9609f1f1251394316629a108a78Roshan Piusstd::string
2464e2ea8184cc1f9609f1f1251394316629a108a78Roshan PiusXmlRpcSocket::getErrorMsg()
2474e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius{
2484e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  return getErrorMsg(getError());
2494e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius}
2504e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
2514e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius// Returns message corresponding to errno... well, it should anyway
2524e2ea8184cc1f9609f1f1251394316629a108a78Roshan Piusstd::string
2534e2ea8184cc1f9609f1f1251394316629a108a78Roshan PiusXmlRpcSocket::getErrorMsg(int error)
2544e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius{
2554e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  char err[60];
2564e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  snprintf(err,sizeof(err),"error %d", error);
2574e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  return std::string(err);
2584e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius}
2594e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
2604e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
261