src/Network/Socket.cc
author terom
Tue, 16 Dec 2008 23:21:26 +0000
changeset 380 d193dd1d8a7e
parent 378 5589abf5e61b
child 381 9b35bc329d23
permissions -rw-r--r--
new NetworkReactor, fix everything to actually work
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
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
     5
#include <cerrno>
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
     6
#include <cstring>
187
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
     7
#include <sstream>
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
     8
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
     9
static std::string dump_addrinfo (addrinfo *r) {
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    10
    std::stringstream ss;
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    11
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    12
    ss << "ai_family=" << r->ai_family << ", ai_canonname=" << r->ai_canonname << ": " << strerror(errno);
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    13
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    14
    return ss.str();
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    15
}
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    16
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    17
static std::string dump_errno (void) {
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    18
    return std::string(strerror(errno));
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    19
}
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    20
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    21
NetworkSocket::NetworkSocket (int family, int socktype, int protocol, NetworkReactor *reactor) :
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    22
    sock_type(family, socktype, protocol), fd(-1), type(family, socktype, protocol), registered(0), reactor(reactor ? reactor : NetworkReactor::current)
378
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    23
{
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    24
    reset();
378
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    25
}
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    26
        
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    27
NetworkSocket::NetworkSocket (int fd, socket_type type, NetworkReactor *reactor) :
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    28
    sock_type(type), fd(fd), type(type), registered(0), reactor(reactor ? reactor : NetworkReactor::current)
378
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    29
{
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    30
    reset();
378
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    31
}
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    32
        
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    33
NetworkSocket::~NetworkSocket (void) {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    34
    // close any remaining socket
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    35
    if (fd >= 0)
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    36
        force_close();
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    37
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    38
    // unregister from reactor?
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    39
    if (registered)
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    40
        reactor->remove_socket(this);
378
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
        
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    43
void NetworkSocket::reset (void) {
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    44
    bound = false;
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    45
    want_read = false;
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    46
    want_write = false;
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    47
}
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    48
378
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    49
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
    50
    // 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
    51
    if (fd >= 0)
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    52
        return;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    53
    
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    54
    // ignore if we've requested a specific sock_type
378
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    55
    if (
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    56
        (sock_type.family && family != sock_type.family) || 
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    57
        (sock_type.socktype && socktype != sock_type.socktype) || 
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    58
        (sock_type.protocol && protocol != sock_type.protocol)
378
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    59
    )
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    60
        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
    61
    
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    62
    // 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
    63
    if ((fd = ::socket(family, socktype, protocol)) < 0)
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    64
        throw NetworkSocketErrno(*this, "socket");
378
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    65
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    66
    // update our family/type/protocol
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    67
    type.family = family;
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    68
    type.socktype = socktype;
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    69
    type.protocol = protocol;
378
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
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
    73
    // use closesocket
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    74
    if (::closesocket(fd))
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    75
        Engine::log(WARN, "socket.force_close") << "error closing socket: " << dump_errno();
378
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    76
    
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    77
    // reset state
378
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    78
    fd = -1;
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    79
    reset();
378
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
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    82
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
    83
    // get our addrinfo
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    84
    addrinfo *r, *results = addr.get_addrinfo(type.family, type.socktype, type.protocol, AI_PASSIVE);
378
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
    // 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
    87
    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
    88
        // 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
    89
        try {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    90
            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
    91
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    92
        } catch (NetworkSocketError &e) {
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    93
            Engine::log(WARN, "socket.bind") << "unable to create socket for " << dump_addrinfo(r) << ": " << e.what();
378
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    94
            continue;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    95
        }
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
        // 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
    98
        if (::bind(fd, r->ai_addr, r->ai_addrlen)) {
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    99
            Engine::log(WARN, "socket.bind") << "unable to bind on " << dump_addrinfo(r) << ": " << dump_errno();
378
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   100
            
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   101
            // close the bad socket
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   102
            force_close();
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
            continue;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   105
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   106
        } else {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   107
            // 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
   108
            break;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   109
        }
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   110
    }
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
    // release our addrinfo
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   113
    freeaddrinfo(results);
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
    // 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
   116
    if (r == NULL)
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   117
        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
   118
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   119
    // mark ourselves as bound
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   120
    bound = true;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   121
}
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   122
        
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   123
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
   124
    // just call listen
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   125
    if (::listen(fd, backlog))
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   126
        throw NetworkSocketErrno(*this, "listen");
378
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
        
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   129
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
   130
    sockaddr_storage addr;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   131
    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
   132
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   133
    // do getsockname()
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   134
    if (::getsockname(fd, (sockaddr *) &addr, &addrlen))
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   135
        throw NetworkSocketErrno(*this, "getsockname");
378
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   136
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   137
    // return addr
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   138
    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
   139
}
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   140
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   141
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
   142
    sockaddr_storage addr;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   143
    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
   144
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   145
    // do getpeername()
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   146
    if (::getpeername(fd, (sockaddr *) &addr, &addrlen))
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   147
        throw NetworkSocketErrno(*this, "getpeername");
378
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   148
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   149
    // return addr
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   150
    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
   151
}
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
void NetworkSocket::set_nonblocking (bool nonblocking) {
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   154
    // linux-specific
378
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   155
    if (fcntl(fd, F_SETFL, O_NONBLOCK, nonblocking ? 1 : 0) == -1)
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   156
        throw NetworkSocketErrno(*this, "fcntl(F_SETFL, O_NONBLOCK)");
378
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
 
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   159
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
   160
    int new_fd;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   161
    sockaddr_storage addr;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   162
    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
   163
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   164
    // try and get the FD
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   165
    if ((new_fd = ::accept(fd, (sockaddr *) &addr, &addrlen)) < 0)
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   166
        throw NetworkSocketErrno(*this, "accept");
378
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
    // allocate new NetworkSocket for new_fd
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   169
    NetworkSocket *socket = new NetworkSocket(new_fd, type, reactor);
378
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   170
    
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   171
    // update src
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   172
    if (src)
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   173
        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
   174
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   175
    // done
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   176
    return socket;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   177
}
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
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
   180
    // get our addrinfo
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   181
    addrinfo *r, *results = addr.get_addrinfo(type.family, type.socktype, type.protocol);
378
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
    // 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
   184
    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
   185
        // 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
   186
        try {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   187
            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
   188
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   189
        } catch (NetworkSocketError &e) {
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   190
            Engine::log(WARN, "socket.connect") << "unable to create socket for " << dump_addrinfo(r) << ": " << e.what();
378
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   191
            continue;
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
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   194
        // 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
   195
        if (::connect(fd, r->ai_addr, r->ai_addrlen)) {
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   196
            Engine::log(WARN, "socket.connect") << "unable to connect to " << dump_addrinfo(r) << ": " << dump_errno();
378
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   197
            
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   198
            // 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
   199
            if (!bound)
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   200
                force_close();
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   201
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   202
            continue;
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
        } else {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   205
            // 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
   206
            break;
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
    }
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   209
   
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   210
    // release our addrinfo
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   211
    freeaddrinfo(results);
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
    // 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
   214
    if (r == NULL)
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   215
        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
   216
}
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   217
        
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   218
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
   219
    ssize_t ret;
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
    // use send or sendto?
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   222
    if (dest) {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   223
        const sockaddr *addr;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   224
        socklen_t addr_len;
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
        // get destination address
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   227
        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
   228
        
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   229
        // sendto()
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   230
        if ((ret = ::sendto(fd, buf, size, 0, addr, addr_len)) < 0 && errno != EAGAIN)
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   231
            throw NetworkSocketErrno(*this, "sendto");
378
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
    } else {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   234
        // send()
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   235
        if ((ret = ::send(fd, buf, size, 0)) < 0 && errno != EAGAIN)
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   236
            throw NetworkSocketErrno(*this, "send");
378
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
    }
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   239
    
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   240
    // sanity-check
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   241
    if (ret == 0) {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   242
        // 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
   243
        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
   244
        return 0;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   245
    }
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   246
    
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   247
    // EAGAIN? 
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   248
    if (ret < 0) {
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   249
        // set want_write so we get a sig_write
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   250
        want_write = true;
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   251
378
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   252
        return 0;
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   253
    }
378
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   254
    
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   255
    // 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
   256
    return ret;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   257
}
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   258
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   259
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
   260
    ssize_t ret;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   261
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   262
    // use recv or recvfrom?
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   263
    if (src) {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   264
        sockaddr_storage addr;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   265
        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
   266
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   267
        // recvfrom()
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   268
        if ((ret = ::recvfrom(fd, buf, size, 0, (sockaddr *) &addr, &addr_len)) < 0 && errno != EAGAIN)
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   269
            throw NetworkSocketErrno(*this, "recvfrom");
378
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   270
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   271
        // update source address if recvfrom suceeded
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   272
        if (ret > 0) {
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   273
            // modify src...
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   274
            src->set_sockaddr((sockaddr *) &addr, addr_len);
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   275
        }
378
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   276
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   277
    } else {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   278
        // recv
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   279
        if ((ret = ::recv(fd, buf, size, 0)) < 0 && errno != EAGAIN)
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   280
            throw NetworkSocketErrno(*this, "recv");
378
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   281
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   282
    }
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   283
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   284
    // EOF?
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   285
    if (ret == 0)
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   286
        throw NetworkSocketEOFError(*this, "recv");
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   287
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   288
    // EAGAIN?
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   289
    if (ret < 0)
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   290
        return 0;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   291
    
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   292
    // 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
   293
    return ret;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   294
}
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   295
        
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   296
void NetworkSocket::close (void) {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   297
    // use closesocket
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   298
    if (::closesocket(fd))
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   299
        throw NetworkSocketErrno(*this, "close");
378
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   300
    
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   301
    // reset
378
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   302
    fd = -1;
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   303
    reset();
378
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   304
}
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   305
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   306
void NetworkSocket::register_poll (void) { 
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   307
    if (registered) return; 
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   308
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   309
    reactor->add_socket(this); 
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   310
    registered = true; 
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   311
}
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   312
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   313
/*
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   314
 * NetworkSocketError
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   315
 */
187
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
   316
std::string NetworkSocketError::build_str (const NetworkSocket &socket, const char *op, const char *err) {
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
   317
    std::stringstream ss;
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
   318
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
   319
    ss << "socket #" << socket.get_socket() << " " << op << ": " << err;
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
   320
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
   321
    return ss.str();
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
   322
}
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
   323
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
   324
NetworkSocketError::NetworkSocketError (const NetworkSocket &socket, const char *op, const char *err) :
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   325
    Error(build_str(socket, op, err)) 
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   326
{
187
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
   327
    // nothing
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
   328
}
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
   329
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   330
NetworkSocketErrno::NetworkSocketErrno (const NetworkSocket &socket, const char *op) :
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   331
    NetworkSocketError(socket, op, strerror(errno)) 
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   332
{ 
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   333
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   334
}
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   335