src/Network/Socket.cc
author terom
Mon, 15 Dec 2008 23:56:42 +0000
changeset 378 5589abf5e61b
parent 187 f41f894213ca
child 380 d193dd1d8a7e
permissions -rw-r--r--
break the network code. Too late to set up a branch for this now
187
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
     1
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
     2
#include "Socket.hh"
378
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
     3
#include "../Engine.hh"
187
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
     4
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
     5
#include <sstream>
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
     6
378
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
     7
NetworkSocket::NetworkSocket (int family, int socktype, int protocol) :
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
     8
    fd(-1), family(family), socktype(socktype), protocol(protocol), bound(false)
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
     9
{
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    10
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    11
}
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    12
        
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    13
NetworkSocket::NetworkSocket (int fd) :
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    14
    fd(fd), family(0), socktype(0), protocol(0), bound(false)
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    15
{
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    16
    
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    17
}
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    18
        
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    19
NetworkSocket::~NetworkSocket (void) {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    20
    // close any remaining socket
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    21
    if (fd >= 0)
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    22
        force_close();
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    23
}
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    24
        
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    25
void NetworkSocket::lazy_socket (int family, int socktype, int protocol) {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    26
    // if we already have a socket, exit
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    27
    if (fd >= 0)
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    28
        return;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    29
    
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    30
    // check that we don't have conflicting family/type/protocol
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    31
    if (
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    32
        (this->family && family != this->family) || 
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    33
        (this->socktype && socktype != this->socktype) || 
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    34
        (this->protocol && protocol != this->protocol)
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    35
    )
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    36
        throw NetworkSocketError(*this, "socket.create", "family/socktype/protocol mismatch");
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    37
    
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    38
    // create the socket or fail
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    39
    if ((fd = ::socket(family, socktype, protocol)) < 0)
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    40
        throw NetworkSocketOSError(*this, "socket");
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    41
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    42
    // update our family/type/protocol
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    43
    this->family = family;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    44
    this->socktype = socktype;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    45
    this->protocol = protocol;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    46
}
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    47
        
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    48
void NetworkSocket::force_close (void) {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    49
    // use closesocket
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    50
    if (::closesocket(fd))
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    51
        Engine::log(WARN, "socket.force_close") << "error closing socket: " /* XXX: errno */;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    52
    
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    53
    // invalidate fd
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    54
    fd = -1;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    55
}
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    56
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    57
void NetworkSocket::bind (const NetworkAddress &addr) {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    58
    // get our addrinfo
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    59
    addrinfo *r, *results = addr.get_addrinfo(family, socktype, protocol, AI_PASSIVE);
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    60
    
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    61
    // find the right address to bind to
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    62
    for (r = results; r; r = r->ai_next) {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    63
        // create socket if needed, warn on errors
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    64
        try {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    65
            lazy_socket(r->ai_family, r->ai_socktype, r->ai_protocol);
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    66
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    67
        } catch (NetworkSocketError &e) {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    68
            Engine::log(WARN, "socket.bind") << "unable to create socket for " << r << ": " << e.what();
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    69
            continue;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    70
        }
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    71
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    72
        // bind it, warn on errors
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    73
        if (::bind(fd, r->ai_addr, r->ai_addrlen)) {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    74
            Engine::log(WARN, "socket.bind") << "unable to bind on " << r /* XXX: errno */ ;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    75
            
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    76
            // close the bad socket
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    77
            force_close();
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    78
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    79
            continue;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    80
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    81
        } else {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    82
            // we have a bound socket, break
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    83
            break;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    84
        }
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    85
    }
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    86
   
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    87
    // release our addrinfo
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    88
    freeaddrinfo(results);
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    89
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    90
    // if we failed to bind, r is a NULL pointer
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    91
    if (r == NULL)
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    92
        throw NetworkSocketError(*this, "bind", "unable to bind on any addresses");
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    93
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    94
    // mark ourselves as bound
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    95
    bound = true;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    96
}
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    97
        
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    98
void NetworkSocket::listen (int backlog) {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    99
    // just call listen
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   100
    if (::listen(fd, backlog))
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   101
        throw NetworkSocketOSError(*this, "listen");
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   102
}
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   103
        
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   104
NetworkAddress NetworkSocket::get_local_address (void) {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   105
    sockaddr_storage addr;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   106
    socklen_t addrlen = sizeof(addr);
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   107
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   108
    // do getsockname()
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   109
    if (::getsockname(fd, (sockaddr *) &addr, &addrlen))
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   110
        throw NetworkSocketOSError(*this, "getsockname");
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   111
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   112
    // return addr
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   113
    return NetworkAddress((sockaddr *) &addr, addrlen);
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   114
}
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   115
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   116
NetworkAddress NetworkSocket::get_remote_address (void) {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   117
    sockaddr_storage addr;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   118
    socklen_t addrlen = sizeof(addr);
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   119
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   120
    // do getpeername()
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   121
    if (::getpeername(fd, (sockaddr *) &addr, &addrlen))
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   122
        throw NetworkSocketOSError(*this, "getpeername");
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   123
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   124
    // return addr
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   125
    return NetworkAddress((sockaddr *) &addr, addrlen);
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   126
}
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   127
        
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   128
void NetworkSocket::set_nonblocking (bool nonblocking) {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   129
    // XXX: linux-specific
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   130
    if (fcntl(fd, F_SETFL, O_NONBLOCK, nonblocking ? 1 : 0) == -1)
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   131
        throw NetworkSocketOSError(*this, "fcntl(F_SETFL, O_NONBLOCK)");
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   132
}
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   133
 
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   134
NetworkSocket* NetworkSocket::accept (NetworkAddress *src) {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   135
    int new_fd;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   136
    sockaddr_storage addr;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   137
    socklen_t addrlen = sizeof(addr);
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   138
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   139
    // try and get the FD
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   140
    if ((new_fd = ::accept(fd, (sockaddr *) &addr, &addrlen)))
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   141
        throw NetworkSocketOSError(*this, "accept");
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   142
    
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   143
    // allocate new NetworkSocket for new_fd
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   144
    NetworkSocket *socket = new NetworkSocket(new_fd);
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   145
    
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   146
    // update src
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   147
    if (src)
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   148
        src->set_sockaddr((sockaddr *) &addr, addrlen);    
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   149
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   150
    // done
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   151
    return socket;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   152
}
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   153
        
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   154
void NetworkSocket::connect (const NetworkAddress &addr) {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   155
    // get our addrinfo
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   156
    addrinfo *r, *results = addr.get_addrinfo(family, socktype, protocol);
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   157
    
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   158
    // find the right address to bind to
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   159
    for (r = results; r; r = r->ai_next) {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   160
        // create socket if needed, warn on errors
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   161
        try {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   162
            lazy_socket(r->ai_family, r->ai_socktype, r->ai_protocol);
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   163
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   164
        } catch (NetworkSocketError &e) {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   165
            Engine::log(WARN, "socket.connect") << "unable to create socket for " << r << ": " << e.what();
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   166
            continue;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   167
        }
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   168
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   169
        // connect it, warn on errors
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   170
        if (::connect(fd, r->ai_addr, r->ai_addrlen)) {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   171
            Engine::log(WARN, "socket.connect") << "unable to connect to " << r /* XXX: errno */ ;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   172
            
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   173
            // close unless bound, to not keep invalid sockets hanging around
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   174
            if (!bound)
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   175
                force_close();
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   176
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   177
            continue;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   178
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   179
        } else {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   180
            // we have a connected socket, break
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   181
            break;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   182
        }
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   183
    }
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   184
   
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   185
    // release our addrinfo
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   186
    freeaddrinfo(results);
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   187
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   188
    // if we failed to connect, r is a NULL pointer
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   189
    if (r == NULL)
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   190
        throw NetworkSocketError(*this, "connect", "unable to connect to any addresses");
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   191
}
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   192
        
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   193
size_t NetworkSocket::send (const char *buf, size_t size, const NetworkAddress *dest) {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   194
    ssize_t ret;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   195
    
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   196
    // use send or sendto?
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   197
    if (dest) {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   198
        const sockaddr *addr;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   199
        socklen_t addr_len;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   200
        
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   201
        // get destination address
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   202
        addr = dest->get_sockaddr(addr_len);
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   203
        
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   204
        // sendto()
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   205
        if ((ret = ::sendto(fd, buf, size, 0, addr, addr_len)) < 0 && errno != EAGAIN)
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   206
            throw NetworkSocketOSError(*this, "sendto");
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   207
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   208
    } else {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   209
        // send()
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   210
        if ((ret = ::send(fd, buf, size, 0)) < 0 && errno != EAGAIN)
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   211
            throw NetworkSocketOSError(*this, "send");
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   212
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   213
    }
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   214
    
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   215
    // sanity-check
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   216
    if (ret == 0) {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   217
        // XXX: not sure what this means...
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   218
        Engine::log(ERROR, "socket.send") << "send[to] returned zero, trying again...";
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   219
        return 0;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   220
    }
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   221
    
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   222
    // EAGAIN?
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   223
    if (ret < 0)
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   224
        return 0;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   225
    
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   226
    // return number of bytes sent
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   227
    return ret;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   228
}
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   229
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   230
size_t NetworkSocket::recv (char *buf, size_t size, NetworkAddress *src) {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   231
    ssize_t ret;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   232
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   233
    // use recv or recvfrom?
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   234
    if (src) {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   235
        sockaddr_storage addr;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   236
        socklen_t addr_len = sizeof(addr);
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   237
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   238
        // recvfrom()
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   239
        if ((ret = ::recvfrom(fd, buf, size, 0, (sockaddr *) &addr, &addr_len)) < 0 && errno != EAGAIN)
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   240
            throw NetworkSocketOSError(*this, "recvfrom");
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   241
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   242
        // modify src...
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   243
        src->set_sockaddr((sockaddr *) &addr, addr_len);
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   244
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   245
    } else {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   246
        // recv
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   247
        if ((ret = ::recv(fd, buf, size, 0)) < 0 && errno != EAGAIN)
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   248
            throw NetworkSocketOSError(*this, "recv");
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   249
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   250
    }
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   251
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   252
    // EOF?
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   253
    if (ret == 0)
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   254
        throw NetworkSocketEOFError(*this, "recv");
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   255
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   256
    // EAGAIN?
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   257
    if (ret < 0)
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   258
        return 0;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   259
    
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   260
    // return number of bytes received
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   261
    return ret;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   262
}
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   263
        
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   264
void NetworkSocket::close (void) {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   265
    // use closesocket
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   266
    if (::closesocket(fd))
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   267
        throw NetworkSocketOSError(*this, "close");
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   268
    
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   269
    // invalidate fd
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   270
    fd = -1;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   271
}
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   272
187
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
   273
std::string NetworkSocketError::build_str (const NetworkSocket &socket, const char *op, const char *err) {
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
   274
    std::stringstream ss;
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
   275
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
   276
    ss << "socket #" << socket.get_socket() << " " << op << ": " << err;
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
   277
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
   278
    return ss.str();
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
   279
}
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
   280
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
   281
NetworkSocketError::NetworkSocketError (const NetworkSocket &socket, const char *op, const char *err) :
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
   282
    Error(build_str(socket, op, err)) {
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
   283
    
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
   284
    // nothing
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
   285
}
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
   286