src/Network/Socket.cc
changeset 380 d193dd1d8a7e
parent 378 5589abf5e61b
child 381 9b35bc329d23
equal deleted inserted replaced
379:2a8e780844d2 380:d193dd1d8a7e
     1 
     1 
     2 #include "Socket.hh"
     2 #include "Socket.hh"
     3 #include "../Engine.hh"
     3 #include "../Engine.hh"
     4 
     4 
       
     5 #include <cerrno>
       
     6 #include <cstring>
     5 #include <sstream>
     7 #include <sstream>
     6 
     8 
     7 NetworkSocket::NetworkSocket (int family, int socktype, int protocol) :
     9 static std::string dump_addrinfo (addrinfo *r) {
     8     fd(-1), family(family), socktype(socktype), protocol(protocol), bound(false)
    10     std::stringstream ss;
       
    11 
       
    12     ss << "ai_family=" << r->ai_family << ", ai_canonname=" << r->ai_canonname << ": " << strerror(errno);
       
    13 
       
    14     return ss.str();
       
    15 }
       
    16 
       
    17 static std::string dump_errno (void) {
       
    18     return std::string(strerror(errno));
       
    19 }
       
    20 
       
    21 NetworkSocket::NetworkSocket (int family, int socktype, int protocol, NetworkReactor *reactor) :
       
    22     sock_type(family, socktype, protocol), fd(-1), type(family, socktype, protocol), registered(0), reactor(reactor ? reactor : NetworkReactor::current)
     9 {
    23 {
    10 
    24     reset();
    11 }
    25 }
    12         
    26         
    13 NetworkSocket::NetworkSocket (int fd) :
    27 NetworkSocket::NetworkSocket (int fd, socket_type type, NetworkReactor *reactor) :
    14     fd(fd), family(0), socktype(0), protocol(0), bound(false)
    28     sock_type(type), fd(fd), type(type), registered(0), reactor(reactor ? reactor : NetworkReactor::current)
    15 {
    29 {
    16     
    30     reset();
    17 }
    31 }
    18         
    32         
    19 NetworkSocket::~NetworkSocket (void) {
    33 NetworkSocket::~NetworkSocket (void) {
    20     // close any remaining socket
    34     // close any remaining socket
    21     if (fd >= 0)
    35     if (fd >= 0)
    22         force_close();
    36         force_close();
    23 }
    37 
    24         
    38     // unregister from reactor?
       
    39     if (registered)
       
    40         reactor->remove_socket(this);
       
    41 }
       
    42         
       
    43 void NetworkSocket::reset (void) {
       
    44     bound = false;
       
    45     want_read = false;
       
    46     want_write = false;
       
    47 }
       
    48 
    25 void NetworkSocket::lazy_socket (int family, int socktype, int protocol) {
    49 void NetworkSocket::lazy_socket (int family, int socktype, int protocol) {
    26     // if we already have a socket, exit
    50     // if we already have a socket, exit
    27     if (fd >= 0)
    51     if (fd >= 0)
    28         return;
    52         return;
    29     
    53     
    30     // check that we don't have conflicting family/type/protocol
    54     // ignore if we've requested a specific sock_type
    31     if (
    55     if (
    32         (this->family && family != this->family) || 
    56         (sock_type.family && family != sock_type.family) || 
    33         (this->socktype && socktype != this->socktype) || 
    57         (sock_type.socktype && socktype != sock_type.socktype) || 
    34         (this->protocol && protocol != this->protocol)
    58         (sock_type.protocol && protocol != sock_type.protocol)
    35     )
    59     )
    36         throw NetworkSocketError(*this, "socket.create", "family/socktype/protocol mismatch");
    60         throw NetworkSocketError(*this, "socket.create", "family/socktype/protocol mismatch");
    37     
    61     
    38     // create the socket or fail
    62     // create the socket or fail
    39     if ((fd = ::socket(family, socktype, protocol)) < 0)
    63     if ((fd = ::socket(family, socktype, protocol)) < 0)
    40         throw NetworkSocketOSError(*this, "socket");
    64         throw NetworkSocketErrno(*this, "socket");
    41 
    65 
    42     // update our family/type/protocol
    66     // update our family/type/protocol
    43     this->family = family;
    67     type.family = family;
    44     this->socktype = socktype;
    68     type.socktype = socktype;
    45     this->protocol = protocol;
    69     type.protocol = protocol;
    46 }
    70 }
    47         
    71         
    48 void NetworkSocket::force_close (void) {
    72 void NetworkSocket::force_close (void) {
    49     // use closesocket
    73     // use closesocket
    50     if (::closesocket(fd))
    74     if (::closesocket(fd))
    51         Engine::log(WARN, "socket.force_close") << "error closing socket: " /* XXX: errno */;
    75         Engine::log(WARN, "socket.force_close") << "error closing socket: " << dump_errno();
    52     
    76     
    53     // invalidate fd
    77     // reset state
    54     fd = -1;
    78     fd = -1;
       
    79     reset();
    55 }
    80 }
    56 
    81 
    57 void NetworkSocket::bind (const NetworkAddress &addr) {
    82 void NetworkSocket::bind (const NetworkAddress &addr) {
    58     // get our addrinfo
    83     // get our addrinfo
    59     addrinfo *r, *results = addr.get_addrinfo(family, socktype, protocol, AI_PASSIVE);
    84     addrinfo *r, *results = addr.get_addrinfo(type.family, type.socktype, type.protocol, AI_PASSIVE);
    60     
    85     
    61     // find the right address to bind to
    86     // find the right address to bind to
    62     for (r = results; r; r = r->ai_next) {
    87     for (r = results; r; r = r->ai_next) {
    63         // create socket if needed, warn on errors
    88         // create socket if needed, warn on errors
    64         try {
    89         try {
    65             lazy_socket(r->ai_family, r->ai_socktype, r->ai_protocol);
    90             lazy_socket(r->ai_family, r->ai_socktype, r->ai_protocol);
    66 
    91 
    67         } catch (NetworkSocketError &e) {
    92         } catch (NetworkSocketError &e) {
    68             Engine::log(WARN, "socket.bind") << "unable to create socket for " << r << ": " << e.what();
    93             Engine::log(WARN, "socket.bind") << "unable to create socket for " << dump_addrinfo(r) << ": " << e.what();
    69             continue;
    94             continue;
    70         }
    95         }
    71 
    96 
    72         // bind it, warn on errors
    97         // bind it, warn on errors
    73         if (::bind(fd, r->ai_addr, r->ai_addrlen)) {
    98         if (::bind(fd, r->ai_addr, r->ai_addrlen)) {
    74             Engine::log(WARN, "socket.bind") << "unable to bind on " << r /* XXX: errno */ ;
    99             Engine::log(WARN, "socket.bind") << "unable to bind on " << dump_addrinfo(r) << ": " << dump_errno();
    75             
   100             
    76             // close the bad socket
   101             // close the bad socket
    77             force_close();
   102             force_close();
    78 
   103 
    79             continue;
   104             continue;
    96 }
   121 }
    97         
   122         
    98 void NetworkSocket::listen (int backlog) {
   123 void NetworkSocket::listen (int backlog) {
    99     // just call listen
   124     // just call listen
   100     if (::listen(fd, backlog))
   125     if (::listen(fd, backlog))
   101         throw NetworkSocketOSError(*this, "listen");
   126         throw NetworkSocketErrno(*this, "listen");
   102 }
   127 }
   103         
   128         
   104 NetworkAddress NetworkSocket::get_local_address (void) {
   129 NetworkAddress NetworkSocket::get_local_address (void) {
   105     sockaddr_storage addr;
   130     sockaddr_storage addr;
   106     socklen_t addrlen = sizeof(addr);
   131     socklen_t addrlen = sizeof(addr);
   107 
   132 
   108     // do getsockname()
   133     // do getsockname()
   109     if (::getsockname(fd, (sockaddr *) &addr, &addrlen))
   134     if (::getsockname(fd, (sockaddr *) &addr, &addrlen))
   110         throw NetworkSocketOSError(*this, "getsockname");
   135         throw NetworkSocketErrno(*this, "getsockname");
   111 
   136 
   112     // return addr
   137     // return addr
   113     return NetworkAddress((sockaddr *) &addr, addrlen);
   138     return NetworkAddress((sockaddr *) &addr, addrlen);
   114 }
   139 }
   115 
   140 
   117     sockaddr_storage addr;
   142     sockaddr_storage addr;
   118     socklen_t addrlen = sizeof(addr);
   143     socklen_t addrlen = sizeof(addr);
   119 
   144 
   120     // do getpeername()
   145     // do getpeername()
   121     if (::getpeername(fd, (sockaddr *) &addr, &addrlen))
   146     if (::getpeername(fd, (sockaddr *) &addr, &addrlen))
   122         throw NetworkSocketOSError(*this, "getpeername");
   147         throw NetworkSocketErrno(*this, "getpeername");
   123 
   148 
   124     // return addr
   149     // return addr
   125     return NetworkAddress((sockaddr *) &addr, addrlen);
   150     return NetworkAddress((sockaddr *) &addr, addrlen);
   126 }
   151 }
   127         
   152         
   128 void NetworkSocket::set_nonblocking (bool nonblocking) {
   153 void NetworkSocket::set_nonblocking (bool nonblocking) {
   129     // XXX: linux-specific
   154     // linux-specific
   130     if (fcntl(fd, F_SETFL, O_NONBLOCK, nonblocking ? 1 : 0) == -1)
   155     if (fcntl(fd, F_SETFL, O_NONBLOCK, nonblocking ? 1 : 0) == -1)
   131         throw NetworkSocketOSError(*this, "fcntl(F_SETFL, O_NONBLOCK)");
   156         throw NetworkSocketErrno(*this, "fcntl(F_SETFL, O_NONBLOCK)");
   132 }
   157 }
   133  
   158  
   134 NetworkSocket* NetworkSocket::accept (NetworkAddress *src) {
   159 NetworkSocket* NetworkSocket::accept (NetworkAddress *src) {
   135     int new_fd;
   160     int new_fd;
   136     sockaddr_storage addr;
   161     sockaddr_storage addr;
   137     socklen_t addrlen = sizeof(addr);
   162     socklen_t addrlen = sizeof(addr);
   138 
   163 
   139     // try and get the FD
   164     // try and get the FD
   140     if ((new_fd = ::accept(fd, (sockaddr *) &addr, &addrlen)))
   165     if ((new_fd = ::accept(fd, (sockaddr *) &addr, &addrlen)) < 0)
   141         throw NetworkSocketOSError(*this, "accept");
   166         throw NetworkSocketErrno(*this, "accept");
   142     
   167     
   143     // allocate new NetworkSocket for new_fd
   168     // allocate new NetworkSocket for new_fd
   144     NetworkSocket *socket = new NetworkSocket(new_fd);
   169     NetworkSocket *socket = new NetworkSocket(new_fd, type, reactor);
   145     
   170     
   146     // update src
   171     // update src
   147     if (src)
   172     if (src)
   148         src->set_sockaddr((sockaddr *) &addr, addrlen);    
   173         src->set_sockaddr((sockaddr *) &addr, addrlen);    
   149 
   174 
   151     return socket;
   176     return socket;
   152 }
   177 }
   153         
   178         
   154 void NetworkSocket::connect (const NetworkAddress &addr) {
   179 void NetworkSocket::connect (const NetworkAddress &addr) {
   155     // get our addrinfo
   180     // get our addrinfo
   156     addrinfo *r, *results = addr.get_addrinfo(family, socktype, protocol);
   181     addrinfo *r, *results = addr.get_addrinfo(type.family, type.socktype, type.protocol);
   157     
   182     
   158     // find the right address to bind to
   183     // find the right address to bind to
   159     for (r = results; r; r = r->ai_next) {
   184     for (r = results; r; r = r->ai_next) {
   160         // create socket if needed, warn on errors
   185         // create socket if needed, warn on errors
   161         try {
   186         try {
   162             lazy_socket(r->ai_family, r->ai_socktype, r->ai_protocol);
   187             lazy_socket(r->ai_family, r->ai_socktype, r->ai_protocol);
   163 
   188 
   164         } catch (NetworkSocketError &e) {
   189         } catch (NetworkSocketError &e) {
   165             Engine::log(WARN, "socket.connect") << "unable to create socket for " << r << ": " << e.what();
   190             Engine::log(WARN, "socket.connect") << "unable to create socket for " << dump_addrinfo(r) << ": " << e.what();
   166             continue;
   191             continue;
   167         }
   192         }
   168 
   193 
   169         // connect it, warn on errors
   194         // connect it, warn on errors
   170         if (::connect(fd, r->ai_addr, r->ai_addrlen)) {
   195         if (::connect(fd, r->ai_addr, r->ai_addrlen)) {
   171             Engine::log(WARN, "socket.connect") << "unable to connect to " << r /* XXX: errno */ ;
   196             Engine::log(WARN, "socket.connect") << "unable to connect to " << dump_addrinfo(r) << ": " << dump_errno();
   172             
   197             
   173             // close unless bound, to not keep invalid sockets hanging around
   198             // close unless bound, to not keep invalid sockets hanging around
   174             if (!bound)
   199             if (!bound)
   175                 force_close();
   200                 force_close();
   176 
   201 
   201         // get destination address
   226         // get destination address
   202         addr = dest->get_sockaddr(addr_len);
   227         addr = dest->get_sockaddr(addr_len);
   203         
   228         
   204         // sendto()
   229         // sendto()
   205         if ((ret = ::sendto(fd, buf, size, 0, addr, addr_len)) < 0 && errno != EAGAIN)
   230         if ((ret = ::sendto(fd, buf, size, 0, addr, addr_len)) < 0 && errno != EAGAIN)
   206             throw NetworkSocketOSError(*this, "sendto");
   231             throw NetworkSocketErrno(*this, "sendto");
   207 
   232 
   208     } else {
   233     } else {
   209         // send()
   234         // send()
   210         if ((ret = ::send(fd, buf, size, 0)) < 0 && errno != EAGAIN)
   235         if ((ret = ::send(fd, buf, size, 0)) < 0 && errno != EAGAIN)
   211             throw NetworkSocketOSError(*this, "send");
   236             throw NetworkSocketErrno(*this, "send");
   212 
   237 
   213     }
   238     }
   214     
   239     
   215     // sanity-check
   240     // sanity-check
   216     if (ret == 0) {
   241     if (ret == 0) {
   217         // XXX: not sure what this means...
   242         // XXX: not sure what this means...
   218         Engine::log(ERROR, "socket.send") << "send[to] returned zero, trying again...";
   243         Engine::log(ERROR, "socket.send") << "send[to] returned zero, trying again...";
   219         return 0;
   244         return 0;
   220     }
   245     }
   221     
   246     
   222     // EAGAIN?
   247     // EAGAIN? 
   223     if (ret < 0)
   248     if (ret < 0) {
       
   249         // set want_write so we get a sig_write
       
   250         want_write = true;
       
   251 
   224         return 0;
   252         return 0;
       
   253     }
   225     
   254     
   226     // return number of bytes sent
   255     // return number of bytes sent
   227     return ret;
   256     return ret;
   228 }
   257 }
   229 
   258 
   235         sockaddr_storage addr;
   264         sockaddr_storage addr;
   236         socklen_t addr_len = sizeof(addr);
   265         socklen_t addr_len = sizeof(addr);
   237 
   266 
   238         // recvfrom()
   267         // recvfrom()
   239         if ((ret = ::recvfrom(fd, buf, size, 0, (sockaddr *) &addr, &addr_len)) < 0 && errno != EAGAIN)
   268         if ((ret = ::recvfrom(fd, buf, size, 0, (sockaddr *) &addr, &addr_len)) < 0 && errno != EAGAIN)
   240             throw NetworkSocketOSError(*this, "recvfrom");
   269             throw NetworkSocketErrno(*this, "recvfrom");
   241 
   270 
   242         // modify src...
   271         // update source address if recvfrom suceeded
   243         src->set_sockaddr((sockaddr *) &addr, addr_len);
   272         if (ret > 0) {
       
   273             // modify src...
       
   274             src->set_sockaddr((sockaddr *) &addr, addr_len);
       
   275         }
   244 
   276 
   245     } else {
   277     } else {
   246         // recv
   278         // recv
   247         if ((ret = ::recv(fd, buf, size, 0)) < 0 && errno != EAGAIN)
   279         if ((ret = ::recv(fd, buf, size, 0)) < 0 && errno != EAGAIN)
   248             throw NetworkSocketOSError(*this, "recv");
   280             throw NetworkSocketErrno(*this, "recv");
   249 
   281 
   250     }
   282     }
   251 
   283 
   252     // EOF?
   284     // EOF?
   253     if (ret == 0)
   285     if (ret == 0)
   262 }
   294 }
   263         
   295         
   264 void NetworkSocket::close (void) {
   296 void NetworkSocket::close (void) {
   265     // use closesocket
   297     // use closesocket
   266     if (::closesocket(fd))
   298     if (::closesocket(fd))
   267         throw NetworkSocketOSError(*this, "close");
   299         throw NetworkSocketErrno(*this, "close");
   268     
   300     
   269     // invalidate fd
   301     // reset
   270     fd = -1;
   302     fd = -1;
   271 }
   303     reset();
   272 
   304 }
       
   305 
       
   306 void NetworkSocket::register_poll (void) { 
       
   307     if (registered) return; 
       
   308 
       
   309     reactor->add_socket(this); 
       
   310     registered = true; 
       
   311 }
       
   312 
       
   313 /*
       
   314  * NetworkSocketError
       
   315  */
   273 std::string NetworkSocketError::build_str (const NetworkSocket &socket, const char *op, const char *err) {
   316 std::string NetworkSocketError::build_str (const NetworkSocket &socket, const char *op, const char *err) {
   274     std::stringstream ss;
   317     std::stringstream ss;
   275 
   318 
   276     ss << "socket #" << socket.get_socket() << " " << op << ": " << err;
   319     ss << "socket #" << socket.get_socket() << " " << op << ": " << err;
   277 
   320 
   278     return ss.str();
   321     return ss.str();
   279 }
   322 }
   280 
   323 
   281 NetworkSocketError::NetworkSocketError (const NetworkSocket &socket, const char *op, const char *err) :
   324 NetworkSocketError::NetworkSocketError (const NetworkSocket &socket, const char *op, const char *err) :
   282     Error(build_str(socket, op, err)) {
   325     Error(build_str(socket, op, err)) 
   283     
   326 {
   284     // nothing
   327     // nothing
   285 }
   328 }
   286 
   329 
       
   330 NetworkSocketErrno::NetworkSocketErrno (const NetworkSocket &socket, const char *op) :
       
   331     NetworkSocketError(socket, op, strerror(errno)) 
       
   332 { 
       
   333 
       
   334 }
       
   335