Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

netsocket.cc

Go to the documentation of this file.
00001 /*
00002 ** netsocket.cc
00003 ** Login : Julien Lemoine <speedblue@happycoder.org>
00004 ** Started on  Mon May 12 22:23:27 2003 Julien Lemoine
00005 ** $Id: netsocket.cc,v 1.11 2004/07/08 05:17:38 speedblue Exp $
00006 **
00007 ** Copyright (C) 2003,2004 Julien Lemoine
00008 ** This program is free software; you can redistribute it and/or modify
00009 ** it under the terms of the GNU Lesser General Public License as published by
00010 ** the Free Software Foundation; either version 2 of the License, or
00011 ** (at your option) any later version.
00012 **
00013 ** This program is distributed in the hope that it will be useful,
00014 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 ** GNU Lesser General Public License for more details.
00017 **
00018 ** You should have received a copy of the GNU Lesser General Public License
00019 ** along with this program; if not, write to the Free Software
00020 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00021 */
00022 
00023 #include <iostream>
00024 #include "netsocket.hh"
00025 #include "socket.hxx"
00026 
00027 namespace Network
00028 {
00029 
00030   struct sockaddr_in    NetSocket::_get_addr(const std::string& host,
00031                                              int port) const
00032   {
00033     struct hostent      *he;
00034     struct sockaddr_in  addr;
00035 
00036     memset(&addr, 0, sizeof(struct sockaddr_in));
00037     he = gethostbyname(host.c_str());
00038     if (!he)
00039       throw HostnameError("Unknown Hostname", HERE);
00040     addr.sin_addr = *((struct in_addr *)he->h_addr);
00041     addr.sin_port = htons(port);
00042     addr.sin_family = AF_INET;
00043     return addr;
00044   }
00045 
00046 #ifdef IPV6_ENABLED
00047   struct sockaddr_in6   NetSocket::_get_addr6(const std::string& host,
00048                                               int port) const
00049   {
00050     struct sockaddr_in6 addr;
00051 
00052     memset(&addr, 0, sizeof(struct sockaddr_in6));
00053     if ( inet_pton(AF_INET6, host.c_str(), &addr.sin6_addr) == 0 )
00054       throw InetptonError("Unknown Hostname", HERE);
00055     addr.sin6_port = htons(port);
00056     addr.sin6_family = AF_INET6;
00057     return addr;
00058   }
00059 #endif
00060 
00061   struct sockaddr_in    NetSocket::_get_addr(int port) const
00062   {
00063     struct sockaddr_in  addr;
00064 
00065     memset(&addr, 0, sizeof(struct sockaddr_in));
00066     addr.sin_addr.s_addr = htonl(INADDR_ANY);
00067     addr.sin_port = htons(port);
00068     addr.sin_family = AF_INET;
00069     return addr;
00070   }
00071 
00072 #ifdef IPV6_ENABLED
00073   struct sockaddr_in6   NetSocket::_get_addr6(int port) const
00074   {
00075     struct sockaddr_in6 addr;
00076 
00077     memset(&addr, 0, sizeof(struct sockaddr_in6));
00078     if ( inet_pton(AF_INET6, "0::0", &addr.sin6_addr) == 0 )
00079       throw InetptonError("Not a valid address", HERE);
00080     addr.sin6_port = htons(port);
00081     addr.sin6_family = AF_INET6;
00082     return addr;
00083   }
00084 #endif
00085 
00086   int           NetSocket::_bind(int port, const std::string& host)
00087   {
00088     int                 s;
00089 
00090     if (_kind == UDP)
00091       {
00092 #ifdef IPV6_ENABLED
00093         if (_version == V4)
00094 #endif
00095           s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
00096 #ifdef IPV6_ENABLED
00097         else
00098           s = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
00099 #endif
00100       }
00101     else if (_kind == TCP)
00102       {
00103 #ifdef IPV6_ENABLED
00104         if (_version == V4)
00105 #endif
00106           s = socket(PF_INET, SOCK_STREAM, 0);
00107 #ifdef IPV6_ENABLED
00108         else
00109           s = socket(PF_INET6, SOCK_STREAM, 0);
00110 #endif
00111       }
00112     else
00113       throw Exception("Unknown Protocole", HERE);
00114 
00115     if (s < 0)
00116       throw SocketError("Socket error", HERE);
00117 #ifdef IPV6_ENABLED
00118     if (_version == V4)
00119 #endif
00120       _addr = _get_addr(host, port);
00121 #ifdef IPV6_ENABLED
00122     else
00123       _addr6 = _get_addr6(host, port);
00124 #endif
00125     return s;
00126   }
00127 
00128   int           NetSocket::_bind(int port)
00129   {
00130     int                 s, on;
00131 
00132     if (_kind == TCP)
00133       {
00134 #ifdef IPV6_ENABLED
00135         if (_version == V4)
00136 #endif
00137           s = socket(PF_INET, SOCK_STREAM, 0);
00138 #ifdef IPV6_ENABLED
00139         else
00140           s = socket(PF_INET6, SOCK_STREAM, 0);
00141 #endif
00142       }
00143     else if (_kind == UDP)
00144       {
00145 #ifdef IPV6_ENABLED
00146         if (_version == V4)
00147 #endif
00148           s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
00149 #ifdef IPV6_ENABLED
00150         else
00151           s = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
00152 #endif
00153       }
00154     else
00155       throw Exception("Unknown Protocole", HERE);
00156     if (s < 0)
00157       throw SocketError("Socket error", HERE);
00158     on = 1;
00159 
00160 #ifndef LIBSOCKET_WIN
00161     if (_kind == TCP && setsockopt(s, SOL_SOCKET,
00162                                    SO_REUSEADDR, (void *)&on,
00163                                    sizeof (on)) == -1)
00164       throw SetsockoptError("setsockopt error", HERE);
00165 #endif
00166 
00167 #ifdef IPV6_ENABLED
00168     if (_version == V4)
00169       {
00170 #endif
00171         struct sockaddr_in      addr;
00172         addr = _get_addr(port);
00173         if (bind(s,(struct sockaddr*)&addr, (int)sizeof(addr)) == -1)
00174           throw BindError("Bind error", HERE);
00175 #ifdef IPV6_ENABLED
00176       }
00177     else
00178       {
00179         struct sockaddr_in6     addr6;
00180         addr6 = _get_addr6(port);
00181         if (bind(s,(struct sockaddr*)&addr6, (int)sizeof(addr6)) == -1)
00182           throw BindError("Bind error", HERE);
00183       }
00184 #endif
00185     return s;
00186   }
00187 
00188   void  NetSocket::_connect(int socket, int port,
00189                             const std::string& host) const
00190   {
00191 #ifdef IPV6_ENABLED
00192     if (_version == V4)
00193       {
00194 #endif
00195         struct sockaddr_in      addr;
00196         addr = _get_addr(host, port);
00197         if (connect(socket, (struct sockaddr *)&addr,
00198                     sizeof (addr)) < 0)
00199           throw ConnectError("Unable to connect", HERE);
00200 #ifdef IPV6_ENABLED
00201       }
00202     else
00203       {
00204         struct sockaddr_in6     addr6;
00205         addr6 = _get_addr6(host, port);
00206         if (connect(socket, (struct sockaddr *)&addr6,
00207                     sizeof (addr6)) < 0)
00208           throw ConnectError("Unable to connect", HERE);
00209       }
00210 #endif
00211   }
00212 
00213   int           NetSocket::_accept(int port, int socket) const
00214   {
00215 #ifdef LIBSOCKET_WIN
00216     int                         size;
00217 #else
00218     socklen_t                   size;
00219 #endif
00220     int                 s;
00221     struct sockaddr_in  addr;
00222 #ifdef IPV6_ENABLED
00223     struct sockaddr_in6 addr6;
00224 
00225     if (_version == V4)
00226       {
00227 #endif
00228         addr = _get_addr(port);
00229         size = sizeof(addr);
00230         s = accept(socket, (struct sockaddr*)&addr, &size);
00231 #ifdef IPV6_ENABLED
00232       }
00233     else
00234       {
00235         addr6 = _get_addr6(port);
00236         size = sizeof(addr6);
00237         s = accept(socket, (struct sockaddr*)&addr6, &size);
00238       }
00239 #endif
00240     if (s < 0)
00241       throw AcceptError("Accept Error", HERE);
00242     return s;
00243   }
00244 
00245   std::string   NetSocket::_get_ip(int port, int socket) const
00246   {
00247     struct sockaddr_in        addr;
00248 #ifdef LIBSOCKET_WIN
00249     int                         size;
00250 #else
00251     socklen_t                   size;
00252 #endif
00253 
00254     memset(&addr, '\0', sizeof(addr));
00255     addr.sin_family = AF_INET;
00256     addr.sin_addr.s_addr = htonl(INADDR_ANY);
00257     addr.sin_port = htons(port);
00258     size = sizeof(addr);
00259     getpeername(socket, (struct sockaddr *)&addr, &size);
00260     return(std::string(inet_ntoa(addr.sin_addr)));
00261   }
00262 
00263   std::string   NetSocket::_read_line(int socket)
00264   {
00265     char                chr[MAXPKTSIZE];
00266     std::string         str = "";
00267     int                 res = 1, i;
00268     std::pair<int, int> delim;
00269     bool                end = false;
00270 
00271     if (socket < 0)
00272       throw NoConnection("No Socket", HERE);
00273     if (!_update_buffer(delim, i, str))
00274       while (!end)
00275         {
00276           memset(chr, 0, MAXPKTSIZE);
00277           if (_state_timeout)
00278             _set_timeout(true, _socket, _state_timeout);
00279           if (_kind == UDP)
00280 #ifdef LIBSOCKET_WIN
00281             res = recv(socket, chr, MAXPKTSIZE, 0);
00282 #else
00283             res = recv(socket, chr, MAXPKTSIZE, MSG_TRUNC);
00284 #endif
00285           else
00286 #ifdef TLS
00287             if (_tls)
00288               res = gnutls_record_recv(_session, chr, MAXPKTSIZE);
00289             else
00290 #endif
00291               res = recv(socket, chr, MAXPKTSIZE, 0);
00292           if (_check_answer(res, str))
00293             return str;
00294           _buffer += std::string(chr, res);
00295           if (_update_buffer(delim, i, str))
00296             end = true;
00297         }
00298     _state_timeout = 0;
00299     return str;
00300   }
00301 
00302   std::string   NetSocket::_read_line(int socket, int& port,
00303                                       std::string& host)
00304   {
00305     char                        chr[MAXPKTSIZE];
00306     std::string                 str = "";
00307     int                         res = 1, i;
00308     std::pair<int, int>         delim;
00309     struct sockaddr_in          addr;
00310 #ifdef IPV6_ENABLED
00311     struct sockaddr_in6         addr6;
00312 #endif
00313 #ifdef LIBSOCKET_WIN
00314     int                         size;
00315 #else
00316     socklen_t                   size;
00317 #endif
00318     bool                        end = false;
00319 
00320 #ifdef IPV6_ENABLED
00321     if (V4 == _version)
00322 #endif
00323       size = sizeof(addr);
00324 #ifdef IPV6_ENABLED
00325     else
00326       size = sizeof(addr6);
00327 #endif
00328     if (socket < 0)
00329       throw NoConnection("No Socket", HERE);
00330     if (!_update_buffer(delim, i, str))
00331       while (!end)
00332         {
00333           if (_state_timeout)
00334             _set_timeout(true, _socket, _state_timeout);
00335           if (_kind == UDP)
00336             {
00337 #ifdef LIBSOCKET_WIN
00338               int flags = 0;
00339 #else
00340               int flags = MSG_TRUNC;
00341 #endif
00342 
00343 #ifdef IPV6_ENABLED
00344               if (V4 == _version)
00345 #endif
00346                 res = recvfrom(socket, chr, MAXPKTSIZE, flags,
00347                                (struct sockaddr *) &addr, &size);
00348 #ifdef IPV6_ENABLED
00349               else
00350                 res = recvfrom(socket, chr, MAXPKTSIZE, flags,
00351                                (struct sockaddr *) &addr6, &size);
00352 #endif
00353             }
00354           else
00355             {
00356 #ifdef TLS
00357               if (_tls)
00358                 res = gnutls_record_recv(_session, chr, MAXPKTSIZE);
00359               else
00360 #endif
00361                 res = recvfrom(socket, chr, MAXPKTSIZE, 0, NULL, 0);
00362 #ifdef IPV6_ENABLED
00363               if (V4 == _version)
00364                 {
00365 #endif
00366                   if (getpeername(socket, (struct sockaddr *) &addr, &size) < 0)
00367                     throw GetpeernameError("getpeername error", HERE);
00368 #ifdef IPV6_ENABLED
00369                 }
00370               else
00371                 if (getpeername(socket, (struct sockaddr *) &addr6, &size) < 0)
00372                   throw GetpeernameError("getpeername error", HERE);
00373 #endif
00374             }
00375           if (_check_answer(res, str))
00376             return str;
00377           _buffer += std::string(chr, res);
00378           if (_update_buffer(delim, i, str))
00379             end = true;
00380         }
00381 #ifdef IPV6_ENABLED
00382     if (V4 == _version)
00383       {
00384 #endif
00385         host = std::string(inet_ntoa(addr.sin_addr));
00386         port = ntohs(addr.sin_port);
00387 #ifdef IPV6_ENABLED
00388       }
00389     else
00390       {
00391         char buf[INET6_ADDRSTRLEN];
00392         if (inet_ntop(AF_INET6, &addr6.sin6_addr, buf, INET6_ADDRSTRLEN) == 0)
00393           throw InetntopError("Not a valid address", HERE);
00394         host = std::string(buf);
00395         port = ntohs(addr6.sin6_port);
00396       }
00397 #endif
00398     _state_timeout = 0;
00399     return str;
00400   }
00401 
00402   void  NetSocket::_write_str(int socket, const std::string& str,
00403                               const std::string& host, int port) const
00404   {
00405     struct sockaddr_in          addr;
00406 #ifdef IPV6_ENABLED
00407     struct sockaddr_in6         addr6;
00408 #endif
00409     int                         res = 1;
00410     const char                  *buf = str.c_str();
00411     unsigned int                count = 0;
00412 
00413 #ifdef IPV6_ENABLED
00414     if (V4 == _version)
00415 #endif
00416       addr = _get_addr(host, port);
00417 #ifdef IPV6_ENABLED
00418     else
00419       addr6 = _get_addr6(host, port);
00420 #endif
00421     if (socket < 0)
00422       throw NoConnection("No Socket", HERE);
00423     while (res && count < str.size())
00424       {
00425 #ifdef IPV6_ENABLED
00426         if (V4 == _version)
00427 #endif
00428 #ifdef TLS
00429           if (_tls)
00430             res = gnutls_record_send(_session, buf + count, str.size() - count);
00431           else
00432 #endif
00433             res = sendto(socket, buf + count,
00434                          str.size() - count, SENDTO_FLAGS,
00435                          (const struct sockaddr*)&addr, sizeof(_addr));
00436 #ifdef IPV6_ENABLED
00437         else
00438           res = sendto(socket, buf + count,
00439                        str.size() - count, SENDTO_FLAGS,
00440                        (const struct sockaddr*)&addr6, sizeof(_addr6));
00441 #endif
00442         if (res <= 0)
00443           throw ConnectionClosed("Connection Closed", HERE);
00444         count += res;
00445       }
00446   }
00447 
00448   void  NetSocket::_write_str_bin(int socket, const std::string& str,
00449                                   const std::string& host, int port) const
00450   {
00451     struct sockaddr_in          addr;
00452 #ifdef IPV6_ENABLED
00453     struct sockaddr_in6         addr6;
00454 #endif
00455     int                         res = 1;
00456     unsigned int                count = 0;
00457 #ifdef LIBSOCKET_WIN
00458     char*                       buf = new char[str.size() + 2];
00459 #else
00460     char                        buf[str.size() + 2];
00461 #endif
00462 
00463     buf[0] = str.size() / 256;
00464     buf[1] = str.size() % 256;
00465     memcpy(buf + 2, str.c_str(), str.size());
00466 #ifdef IPV6_ENABLED
00467     if (V4 == _version)
00468 #endif
00469       addr = _get_addr(host, port);
00470 #ifdef IPV6_ENABLED
00471     else
00472       addr6 = _get_addr6(host, port);
00473 #endif
00474     if (socket < 0)
00475       throw NoConnection("No Socket", HERE);
00476     while (res && count < str.size() + 2)
00477       {
00478 #ifdef IPV6_ENABLED
00479         if (V4 == _version)
00480 #endif
00481 #ifdef TLS
00482           if (_tls)
00483             res = gnutls_record_send(_session, buf + count, str.size() + 2 - count);
00484           else
00485 #endif
00486             res = sendto(socket, buf + count, str.size() + 2 - count, 
00487                          SENDTO_FLAGS,
00488                          (const struct sockaddr*)&addr, sizeof(_addr));
00489 #ifdef IPV6_ENABLED
00490         else
00491           res = sendto(socket, buf + count, str.size() + 2 - count, 
00492                        SENDTO_FLAGS,
00493                        (const struct sockaddr*)&addr6, sizeof(_addr6));
00494 #endif
00495         if (res <= 0)
00496           throw ConnectionClosed("Connection Closed", HERE);
00497         count += res;
00498       }
00499 #ifdef LIBSOCKET_WIN
00500     delete[] buf;
00501 #endif
00502   }
00503 
00504   void  NetSocket::writeto(const std::string& str,
00505                            const std::string& host, int port)
00506   {
00507     if (_proto_kind == binary)
00508       _write_str_bin(_socket, str, host, port);
00509     else
00510       _write_str(_socket, str, host, port);
00511   }
00512 
00513   std::string   NetSocket::read(int& port, std::string& host)
00514   {
00515     if (_proto_kind == binary)
00516       return _read_line_bin(_socket, port, host, 0);
00517     else
00518       return _read_line(_socket, port, host);
00519   }
00520 
00521   std::string   NetSocket::read(int& port, std::string& host, int timeout)
00522   {
00523     if (_proto_kind == binary)
00524       {
00525         _set_timeout(true, _socket, timeout);
00526         return _read_line_bin(_socket, port, host, 0);
00527       }
00528     else
00529       {
00530         _state_timeout = timeout;
00531         return _read_line(_socket, port, host);
00532       }
00533   }
00534 
00535   std::string   NetSocket::read()
00536   {
00537     if (_proto_kind == binary)
00538       return _read_line_bin(_socket, 0);
00539     else
00540       return _read_line(_socket);
00541   }
00542 
00543   std::string   NetSocket::read(int timeout)
00544   {
00545     if (_proto_kind == binary)
00546       {
00547         _set_timeout(true, _socket, timeout);
00548         return _read_line_bin(_socket, 0);
00549       }
00550     else
00551       {
00552         _state_timeout = timeout;
00553         return _read_line(_socket);
00554       }
00555   }
00556 
00557   std::string   NetSocket::readn(int& port, std::string& host,
00558                                  unsigned int size)
00559   {
00560     // _read_line_bin is bufferised with the same buffer as textual
00561     // protocols, so this function can be used for binary and text
00562     // protocols.
00563     return _read_line_bin(_socket, port, host, size);
00564   }
00565 
00566   std::string   NetSocket::readn(int& port, std::string& host, int timeout,
00567                                  unsigned int size)
00568   {
00569     if (!size || size > _buffer.size())
00570       _set_timeout(true, _socket, timeout);
00571     // _read_line_bin is bufferised with the same buffer as textual
00572     // protocols, so this function can be used for binary and text
00573     // protocols.
00574     return _read_line_bin(_socket, port, host, size);
00575   }
00576 
00577   std::string   NetSocket::readn(unsigned int size)
00578   {
00579     // _read_line_bin is bufferised with the same buffer as textual
00580     // protocols, so this function can be used for binary and text
00581     // protocols.
00582     return _read_line_bin(_socket, size);
00583   }
00584 
00585   std::string   NetSocket::readn(int timeout, unsigned int size)
00586   {
00587     if (!size || size > _buffer.size())
00588       _set_timeout(true, _socket, timeout);
00589     // _read_line_bin is bufferised with the same buffer as textual
00590     // protocols, so this function can be used for binary and text
00591     // protocols.
00592     return _read_line_bin(_socket, size);
00593   }
00594 }

Generated on Fri Apr 8 06:13:01 2005 for libsocket by  doxygen 1.4.0