sockets.h

Go to the documentation of this file.
00001 
00002  //
00003  // XMLStorage XML-RPC extension
00004  //
00005  // Copyright (c) 2009, 2014 Martin Fuchs <martin-fuchs@gmx.net>
00006  //
00007 
00008 
00009 /*
00010 
00011   All rights reserved.
00012 
00013   Redistribution and use in source and binary forms, with or without
00014   modification, are permitted provided that the following conditions are met:
00015 
00016   * Redistributions of source code must retain the above copyright
00017     notice, this list of conditions and the following disclaimer.
00018   * Redistributions in binary form must reproduce the above copyright
00019     notice, this list of conditions and the following disclaimer in
00020     the documentation and/or other materials provided with the
00021     distribution.
00022 
00023   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00024   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00025   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00026   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00027   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00028   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00029   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00030   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00031   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00032   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00033   POSSIBILITY OF SUCH DAMAGE.
00034 
00035 */
00036 
00037 
00038 struct URL
00039 {
00040     URL(const char* url)
00041     {
00042         parse_url(url);
00043     }
00044 
00045     string  _scheme;
00046     string  _hostname;
00047     string  _port;
00048     string  _path;
00049 
00050     bool    parse_url(const char* str, const char* default_port="80")
00051     {
00052         if (!str || !*str)
00053             return false;
00054 
00055         const char* p1 = strstr(str, "://");
00056 
00057         if (p1) {
00058             _scheme.assign(str, p1-str);
00059             p1 += 3;
00060         } else
00061             p1 = str;
00062 
00063         const char* p2 = strchr(p1, ':');
00064         const char* p3 = p2? strchr(p2+1, '/'): p2;
00065 
00066         if (p2) {
00067             _hostname.assign(p1, p2-p1);
00068             _port.assign(p2+1, p3-(p2+1));
00069             _path = p3;
00070         } else {
00071             _hostname = p1;
00072             _port = default_port;
00073             _path.erase();
00074         }
00075 
00076         if (_path.empty())
00077             _path = "/";
00078 
00079         return true;
00080     }
00081 };
00082 
00083 
00084 #ifdef _WIN32
00085 
00086  // WINSOCK initialization
00087 struct WinSockInit : public WSADATA
00088 {
00089     WinSockInit(WORD version=MAKEWORD(2,2))
00090     {
00091         _error = WSAStartup(version, this);
00092 
00093         if (!_error && wVersion!=version) {
00094             _error = WSAVERNOTSUPPORTED;
00095             WSACleanup();
00096         }
00097     }
00098 
00099     WinSockInit::~WinSockInit()
00100     {
00101         if (!_error)
00102             WSACleanup();
00103     }
00104 
00105     int _error;
00106 };
00107 
00108 #define S_ADDR(a)   (a.S_un.S_addr)
00109 
00110 #else   // _WIN32
00111 
00112 #include <unistd.h>
00113 #include <sys/socket.h>
00114 
00115 typedef u_int SOCKET;
00116 #define SOCKET_ERROR (-1)
00117 #define INVALID_SOCKET (SOCKET)(~0)
00118 
00119 #define S_ADDR(a)   (a.s_addr)
00120 
00121 typedef struct sockaddr_in SOCKADDR_IN;
00122 
00123 #define closesocket(fd) close(fd)
00124 #define WSAGetLastError() errno
00125 #define WSAEWOULDBLOCK EWOULDBLOCK
00126 
00127 #endif // _WIN32
00128 
00129 
00130 #ifndef SD_SEND
00131 #define SD_RECEIVE      0x00
00132 #define SD_SEND         0x01
00133 #define SD_BOTH         0x02
00134 #endif
00135 
00136 
00137 #ifndef socklen_t
00138 #ifdef _WIN32
00139 typedef int socklen_t;
00140 #else
00141 typedef unsigned int socklen_t;
00142 #endif
00143 #endif
00144 
00145  // network address list
00146 struct AddressList
00147 {
00148     AddressList()
00149      :  _paddr_info(NULL)
00150     {
00151     }
00152 
00153     ~AddressList()
00154     {
00155         clear();
00156     }
00157 
00158     void clear()
00159     {
00160         if (_paddr_info) {
00161             freeaddrinfo(_paddr_info);
00162             _paddr_info = NULL;
00163         }
00164     }
00165 
00166     void resolve(const char* hostname, const char* service, int flags, int family=PF_INET)
00167     {
00168         addrinfo hints = {flags, family, SOCK_STREAM};
00169 
00170         int ret = getaddrinfo(hostname, service, &hints, &_paddr_info);
00171 
00172         if (ret != 0) {
00173 #ifdef _WIN32
00174             throw WE(ret);
00175 #else
00176             throw Exception(gai_strerror(ret));
00177 #endif
00178         }
00179 
00180 //      const sockaddr_in& sa = *(sockaddr_in*) _paddr_info->ai_addr;
00181     }
00182 
00183     const addrinfo* get_first() const
00184     {
00185         assert(_paddr_info!=NULL);
00186         return _paddr_info;
00187     }
00188 
00189 private:
00190     addrinfo* _paddr_info;
00191 };
00192 
00193 
00194  // socket encapsulation
00195 struct Socket
00196 {
00197     Socket()
00198      :  _sock(INVALID_SOCKET)
00199     {
00200     }
00201 
00202     Socket(SOCKET socket)
00203     {
00204         init(socket);
00205     }
00206 
00207     void init(SOCKET socket)
00208     {
00209         _sock = socket;
00210     }
00211 
00212     ~Socket()
00213     {
00214         close();
00215     }
00216 
00217     operator SOCKET() {return _sock;}
00218 
00219     void connect(const AddressList& addr)
00220     {
00221         assert(_sock==INVALID_SOCKET);
00222 
00223          // create and connect a new socket to one of the given addresses
00224         for(const addrinfo*pai=addr.get_first(); pai; pai=pai->ai_next) {
00225             _sock = socket(pai->ai_family, pai->ai_socktype, pai->ai_protocol);
00226 
00227             if (_sock != INVALID_SOCKET)
00228                 if (::connect(_sock, pai->ai_addr, pai->ai_addrlen) != SOCKET_ERROR)
00229                     return;
00230                 else
00231 					::closesocket(_sock);
00232         }
00233 
00234         throw LWSE();
00235     }
00236 
00237     void bind(const AddressList& addr)
00238     {
00239         assert(_sock==INVALID_SOCKET);
00240 
00241          // create and bind a socket to one of the given addresses
00242         for(const addrinfo*pai=addr.get_first(); pai; pai=pai->ai_next) {
00243             _sock = socket(pai->ai_family, pai->ai_socktype, pai->ai_protocol);
00244 
00245             if (_sock != INVALID_SOCKET)
00246                 if (::bind(_sock, pai->ai_addr, pai->ai_addrlen) != SOCKET_ERROR)
00247                     return;
00248                 else
00249 					::closesocket(_sock);
00250         }
00251 
00252         throw LWSE();
00253     }
00254 
00255     void close()
00256     {
00257         if (_sock != INVALID_SOCKET) {
00258         /*
00259             The Winsock Programmer's FAQ recommends explicitly shutdown down the socket before closing it,
00260             but it considerably slows down the message processing when not using persistsnt connections.
00261             if (shutdown(_sock, SD_SEND) != SOCKET_ERROR) {
00262                 char buffer[1024];
00263 
00264                 do {
00265                 } while(recv(_sock, (char*)buffer, sizeof(buffer), 0) > 0); // != SOCKET_ERROR
00266             }
00267         */
00268 			::closesocket(_sock);
00269 
00270             _sock = INVALID_SOCKET;
00271         }
00272     }
00273 
00274      // read from the socket until the buffer is full or there is no more data available
00275     int receive(char* buffer, size_t len, int flags=0)
00276     {
00277         int sum = 0;
00278 
00279         while(len > 0) {
00280             int rcvd = receive_fragmented(buffer, len, flags);
00281             if (rcvd <= 0)
00282                 break;
00283 
00284             buffer += rcvd;
00285             len -= rcvd;
00286             sum += rcvd;
00287         }
00288 
00289         return sum;
00290     }
00291 
00292      // receive a chunk of bytes from the socket
00293     int receive_fragmented(char* buffer, int len, int flags=0)
00294     {
00295         int ret = ::recv(_sock, (char*)buffer, len, flags);
00296 
00297         if (ret == SOCKET_ERROR) {
00298             int error = WSAGetLastError();
00299 
00300             if (error == WSAEWOULDBLOCK)
00301                 ret = 0;
00302             else
00303                 throw LWSE();
00304         }
00305 
00306         return ret;
00307     }
00308 
00309      // send data into the socket
00310     int send(const char* buffer, size_t len, int flags=0)
00311     {
00312         int ret = ::send(_sock, buffer, len, flags);
00313 
00314         if (ret == SOCKET_ERROR)
00315             throw LWSE();
00316 
00317         return ret;
00318     }
00319 
00320 protected:
00321     SOCKET  _sock;
00322 };
00323 
00324  // buffered socket reader
00325 struct SocketReader
00326 {
00327     SocketReader(Socket& socket)
00328      :  _socket(socket),
00329         _state(0),
00330         _g_ptr(_buffer),
00331         _e_ptr(_buffer)
00332     {
00333         *_buffer = '\0';
00334     }
00335 
00336     int get_state()
00337     {
00338         return _state;
00339     }
00340 
00341     int peek()
00342     {
00343         if (_g_ptr == _e_ptr)
00344             fetch();
00345 
00346         if (_g_ptr != _e_ptr)
00347             return *_g_ptr;
00348         else
00349             return EOF;
00350     }
00351 
00352     void next()
00353     {
00354         if (_g_ptr != _e_ptr)
00355             ++_g_ptr;
00356     }
00357 
00358      // read one line from the socket
00359     int read_line(char* line, size_t len)
00360     {
00361         char* p = NULL;
00362         char* end = line + (len-1);
00363 
00364         for(;;) {
00365             if (p && p>=end)
00366                 break;
00367 
00368             int c = peek();
00369 
00370             if (c == EOF) {
00371                 _state |= ios_base::eofbit;
00372 
00373                 if (p == line)
00374                     _state |= ios_base::failbit;
00375                 break;
00376             }
00377 
00378             if (!p)
00379                 p = line;
00380 
00381             if (c == '\n') {
00382                 next();
00383 
00384                 break;
00385             } else if (c == '\r') {
00386                 next();
00387 
00388                 if (peek() == '\n')
00389                     next();
00390 
00391                 break;
00392             } else
00393                 *p++ = (char)c;
00394 
00395             next();
00396         }
00397 
00398         if (!p)
00399             p = line;
00400 
00401         *p = '\0';
00402 
00403         return p - line;
00404     }
00405 
00406      // read the specified number of bytes from the socket
00407     int read(char* buffer, size_t len)
00408     {
00409         int sum = 0;
00410 
00411          // first read the available data from the buffer
00412         size_t avail = _e_ptr - _g_ptr;
00413 
00414         if (avail > 0) {
00415             size_t read = min(avail, len);
00416             memcpy(buffer, _g_ptr, read);
00417             _g_ptr += read;
00418 
00419             buffer += read;
00420             len -= read;
00421         }
00422 
00423          // Do we need more data?
00424         if (len > 0)
00425             sum += _socket.receive(buffer, len);
00426 
00427         return sum;
00428     }
00429 
00430      // read data from the socket until there is no more data
00431     string receive_all()
00432     {
00433         ostringstream ret;
00434         char buffer[BUFFER_LEN];
00435 
00436          // first read all data from the buffer
00437         int avail = _e_ptr - _g_ptr;
00438 
00439         if (avail > 0) {
00440             ret.write(_g_ptr, avail);
00441             _g_ptr = _e_ptr;
00442         }
00443 
00444          // now loop until no more data can be read from the socket
00445         for(;;) {
00446             int read = _socket.receive_fragmented(buffer, BUFFER_LEN);
00447 
00448             if (read <= 0)
00449                 break;
00450 
00451             ret.write(buffer, read);
00452         }
00453 
00454         return ret.str();
00455     }
00456 
00457 private:
00458     Socket& _socket;
00459     int     _state;
00460 
00461     char    _buffer[BUFFER_LEN];
00462     char*   _g_ptr;
00463     char*   _e_ptr;
00464 
00465     void fetch()
00466     {
00467         int read = _socket.receive_fragmented(_buffer, BUFFER_LEN);
00468 
00469         if (read >= 0) {
00470             _g_ptr = _buffer;
00471             _e_ptr = _buffer + read;
00472         }
00473     }
00474 };
00475 
00476  // socket connection handling
00477 struct INConnect : public Socket
00478 {
00479     INConnect(const AddressList& addr)
00480     {
00481         Socket::connect(addr);
00482     }
00483 };