BOSS 8.0.0
BESIII Offline Software System
Loading...
Searching...
No Matches
XmlRpcSocket.cpp
Go to the documentation of this file.
1
2#include "XmlRpcSocket.h"
3#include "XmlRpcUtil.h"
4
5#ifndef MAKEDEPEND
6
7# if defined( _WINDOWS )
8# include <stdio.h>
9# include <winsock2.h>
10// # pragma lib(WS2_32.lib)
11
12# define EINPROGRESS WSAEINPROGRESS
13# define EWOULDBLOCK WSAEWOULDBLOCK
14# define ETIMEDOUT WSAETIMEDOUT
15# else
16extern "C" {
17# include <cstring>
18# include <errno.h>
19# include <fcntl.h>
20# include <netdb.h>
21# include <netinet/in.h>
22# include <stdio.h>
23# include <sys/socket.h>
24# include <sys/types.h>
25# include <unistd.h>
26}
27# endif // _WINDOWS
28
29#endif // MAKEDEPEND
30
31using namespace XmlRpc;
32
33#if defined( _WINDOWS )
34
35static void initWinSock() {
36 static bool wsInit = false;
37 if ( !wsInit )
38 {
39 WORD wVersionRequested = MAKEWORD( 2, 0 );
40 WSADATA wsaData;
41 WSAStartup( wVersionRequested, &wsaData );
42 wsInit = true;
43 }
44}
45
46#else
47
48# define initWinSock()
49
50#endif // _WINDOWS
51
52// These errors are not considered fatal for an IO operation; the operation will be re-tried.
53static inline bool nonFatalError() {
54 int err = XmlRpcSocket::getError();
55 return ( err == EINPROGRESS || err == EAGAIN || err == EWOULDBLOCK || err == EINTR );
56}
57
60 return (int)::socket( AF_INET, SOCK_STREAM, 0 );
61}
62
63void XmlRpcSocket::close( int fd ) {
64 XmlRpcUtil::log( 4, "XmlRpcSocket::close: fd %d.", fd );
65#if defined( _WINDOWS )
66 closesocket( fd );
67#else
68 ::close( fd );
69#endif // _WINDOWS
70}
71
73#if defined( _WINDOWS )
74 unsigned long flag = 1;
75 return ( ioctlsocket( (SOCKET)fd, FIONBIO, &flag ) == 0 );
76#else
77 return ( fcntl( fd, F_SETFL, O_NONBLOCK ) == 0 );
78#endif // _WINDOWS
79}
80
82 // Allow this port to be re-bound immediately so server re-starts are not delayed
83 int sflag = 1;
84 return ( setsockopt( fd, SOL_SOCKET, SO_REUSEADDR, (const char*)&sflag, sizeof( sflag ) ) ==
85 0 );
86}
87
88// Bind to a specified port
89bool XmlRpcSocket::bind( int fd, int port ) {
90 struct sockaddr_in saddr;
91 memset( &saddr, 0, sizeof( saddr ) );
92 saddr.sin_family = AF_INET;
93 saddr.sin_addr.s_addr = htonl( INADDR_ANY );
94 saddr.sin_port = htons( (u_short)port );
95 return ( ::bind( fd, (struct sockaddr*)&saddr, sizeof( saddr ) ) == 0 );
96}
97
98// Set socket in listen mode
99bool XmlRpcSocket::listen( int fd, int backlog ) { return ( ::listen( fd, backlog ) == 0 ); }
100
101int XmlRpcSocket::accept( int fd ) {
102 struct sockaddr_in addr;
103#if defined( _WINDOWS )
104 int
105#else
106 socklen_t
107#endif
108 addrlen = sizeof( addr );
109
110 return (int)::accept( fd, (struct sockaddr*)&addr, &addrlen );
111}
112
113// Connect a socket to a server (from a client)
114bool XmlRpcSocket::connect( int fd, std::string& host, int port ) {
115 struct sockaddr_in saddr;
116 memset( &saddr, 0, sizeof( saddr ) );
117 saddr.sin_family = AF_INET;
118
119 struct hostent* hp = gethostbyname( host.c_str() );
120 if ( hp == 0 ) return false;
121
122 saddr.sin_family = hp->h_addrtype;
123 memcpy( &saddr.sin_addr, hp->h_addr, hp->h_length );
124 saddr.sin_port = htons( (u_short)port );
125
126 // For asynch operation, this will return EWOULDBLOCK (windows) or
127 // EINPROGRESS (linux) and we just need to wait for the socket to be writable...
128 int result = ::connect( fd, (struct sockaddr*)&saddr, sizeof( saddr ) );
129 return result == 0 || nonFatalError();
130}
131
132// Read available text from the specified socket. Returns false on error.
133bool XmlRpcSocket::nbRead( int fd, std::string& s, bool* eof ) {
134 const int READ_SIZE = 4096; // Number of bytes to attempt to read at a time
135 char readBuf[READ_SIZE];
136
137 bool wouldBlock = false;
138 *eof = false;
139
140 while ( !wouldBlock && !*eof )
141 {
142#if defined( _WINDOWS )
143 int n = recv( fd, readBuf, READ_SIZE - 1, 0 );
144#else
145 int n = read( fd, readBuf, READ_SIZE - 1 );
146#endif
147 XmlRpcUtil::log( 5, "XmlRpcSocket::nbRead: read/recv returned %d.", n );
148
149 if ( n > 0 )
150 {
151 readBuf[n] = 0;
152 s.append( readBuf, n );
153 }
154 else if ( n == 0 ) { *eof = true; }
155 else if ( nonFatalError() ) { wouldBlock = true; }
156 else
157 {
158 return false; // Error
159 }
160 }
161 return true;
162}
163
164// Write text to the specified socket. Returns false on error.
165bool XmlRpcSocket::nbWrite( int fd, std::string& s, int* bytesSoFar ) {
166 int nToWrite = int( s.length() ) - *bytesSoFar;
167 char* sp = const_cast<char*>( s.c_str() ) + *bytesSoFar;
168 bool wouldBlock = false;
169
170 while ( nToWrite > 0 && !wouldBlock )
171 {
172#if defined( _WINDOWS )
173 int n = send( fd, sp, nToWrite, 0 );
174#else
175 int n = write( fd, sp, nToWrite );
176#endif
177 XmlRpcUtil::log( 5, "XmlRpcSocket::nbWrite: send/write returned %d.", n );
178
179 if ( n > 0 )
180 {
181 sp += n;
182 *bytesSoFar += n;
183 nToWrite -= n;
184 }
185 else if ( nonFatalError() ) { wouldBlock = true; }
186 else
187 {
188 return false; // Error
189 }
190 }
191 return true;
192}
193
194// Returns last errno
196#if defined( _WINDOWS )
197 return WSAGetLastError();
198#else
199 return errno;
200#endif
201}
202
203// Returns message corresponding to last errno
204std::string XmlRpcSocket::getErrorMsg() { return getErrorMsg( getError() ); }
205
206// Returns message corresponding to errno... well, it should anyway
207std::string XmlRpcSocket::getErrorMsg( int error ) {
208 char err[60];
209 snprintf( err, sizeof( err ), "error %d", error );
210 return std::string( err );
211}
const Int_t n
XmlRpcServer s
#define initWinSock()
static int socket()
Creates a stream (TCP) socket. Returns -1 on failure.
static bool listen(int socket, int backlog)
Set socket in listen mode.
static int getError()
Returns last errno.
static int accept(int socket)
Accept a client connection request.
static bool nbWrite(int socket, std::string &s, int *bytesSoFar)
Write text to the specified socket. Returns false on error.
static bool setReuseAddr(int socket)
static bool connect(int socket, std::string &host, int port)
Connect a socket to a server (from a client).
static bool setNonBlocking(int socket)
Sets a stream (TCP) socket to perform non-blocking IO. Returns false on failure.
static void close(int socket)
Closes a socket.
static bool nbRead(int socket, std::string &s, bool *eof)
Read text from the specified socket. Returns false on error.
static bool bind(int socket, int port)
Bind to a specified port.
static std::string getErrorMsg()
Returns message corresponding to last error.
static void log(int level, const char *fmt,...)
Dump messages somewhere.