src/Network/Socket.cc
author Tero Marttila <terom@fixme.fi>
Fri, 11 Sep 2009 15:34:48 +0300
changeset 446 e411c0799fcc
parent 399 c7295b72731a
permissions -rw-r--r--
fix NetworkSocket to not forget want_* state if resetting between connect()'s
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) :
446
e411c0799fcc fix NetworkSocket to not forget want_* state if resetting between connect()'s
Tero Marttila <terom@fixme.fi>
parents: 399
diff changeset
    22
    sock_type(family, socktype, protocol), fd(-1), type(family, socktype, protocol),
e411c0799fcc fix NetworkSocket to not forget want_* state if resetting between connect()'s
Tero Marttila <terom@fixme.fi>
parents: 399
diff changeset
    23
    bound(false),
e411c0799fcc fix NetworkSocket to not forget want_* state if resetting between connect()'s
Tero Marttila <terom@fixme.fi>
parents: 399
diff changeset
    24
    registered(false), reactor(reactor ? reactor : NetworkReactor::current),
e411c0799fcc fix NetworkSocket to not forget want_* state if resetting between connect()'s
Tero Marttila <terom@fixme.fi>
parents: 399
diff changeset
    25
    want_read(false), want_write(false)
378
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    26
{
446
e411c0799fcc fix NetworkSocket to not forget want_* state if resetting between connect()'s
Tero Marttila <terom@fixme.fi>
parents: 399
diff changeset
    27
378
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    28
}
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
NetworkSocket::NetworkSocket (int fd, socket_type type, NetworkReactor *reactor) :
446
e411c0799fcc fix NetworkSocket to not forget want_* state if resetting between connect()'s
Tero Marttila <terom@fixme.fi>
parents: 399
diff changeset
    31
    sock_type(type), fd(fd), type(type), 
e411c0799fcc fix NetworkSocket to not forget want_* state if resetting between connect()'s
Tero Marttila <terom@fixme.fi>
parents: 399
diff changeset
    32
    bound(false),
e411c0799fcc fix NetworkSocket to not forget want_* state if resetting between connect()'s
Tero Marttila <terom@fixme.fi>
parents: 399
diff changeset
    33
    registered(false), reactor(reactor ? reactor : NetworkReactor::current),
e411c0799fcc fix NetworkSocket to not forget want_* state if resetting between connect()'s
Tero Marttila <terom@fixme.fi>
parents: 399
diff changeset
    34
    want_read(false), want_write(false)
378
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    35
{
446
e411c0799fcc fix NetworkSocket to not forget want_* state if resetting between connect()'s
Tero Marttila <terom@fixme.fi>
parents: 399
diff changeset
    36
378
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
        
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    39
NetworkSocket::~NetworkSocket (void) {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    40
    // close any remaining socket
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    41
    if (fd >= 0)
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    42
        force_close();
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    43
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    44
    // unregister from reactor?
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    45
    if (registered)
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    46
        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
    47
}
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    48
        
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    49
void NetworkSocket::reset (void) {
446
e411c0799fcc fix NetworkSocket to not forget want_* state if resetting between connect()'s
Tero Marttila <terom@fixme.fi>
parents: 399
diff changeset
    50
    fd = -1;
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    51
    bound = false;
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    52
}
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    53
378
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    54
void NetworkSocket::lazy_socket (int family, int socktype, int protocol) {
399
c7295b72731a documentation work on Network
Tero Marttila <terom@fixme.fi>
parents: 385
diff changeset
    55
    // if we already have a socket, good
c7295b72731a documentation work on Network
Tero Marttila <terom@fixme.fi>
parents: 385
diff changeset
    56
    // XXX: should we check family/socktype/protocol against sock_type?
378
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    57
    if (fd >= 0)
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    58
        return;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    59
    
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    60
    // 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
    61
    if (
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    62
        (sock_type.family && family != sock_type.family) || 
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    63
        (sock_type.socktype && socktype != sock_type.socktype) || 
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    64
        (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
    65
    )
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    66
        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
    67
    
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    68
    // 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
    69
    if ((fd = ::socket(family, socktype, protocol)) < 0)
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    70
        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
    71
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    72
    // update our family/type/protocol
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    73
    type.family = family;
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    74
    type.socktype = socktype;
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    75
    type.protocol = protocol;
378
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    76
}
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    77
        
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    78
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
    79
    // use closesocket
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    80
    if (::closesocket(fd))
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    81
        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
    82
    
446
e411c0799fcc fix NetworkSocket to not forget want_* state if resetting between connect()'s
Tero Marttila <terom@fixme.fi>
parents: 399
diff changeset
    83
    // forget fd
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    84
    reset();
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
381
9b35bc329d23 separate sockaddr stuff out of NetworkAddress... now called NetworkEndpoint
terom
parents: 380
diff changeset
    87
void NetworkSocket::bind (const NetworkEndpoint &addr) {
378
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    88
    // get our addrinfo
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    89
    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
    90
    
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    91
    // 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
    92
    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
    93
        // 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
    94
        try {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    95
            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
    96
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
    97
        } catch (NetworkSocketError &e) {
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
    98
            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
    99
            continue;
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
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   102
        // 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
   103
        if (::bind(fd, r->ai_addr, r->ai_addrlen)) {
385
e56af22c04dd better error reporting of NetworkSocket bind/connect failures
terom
parents: 381
diff changeset
   104
            Engine::log(WARN, "socket.bind") << "unable to bind on " << addr << " (" << 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
   105
            
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   106
            // close the bad socket
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   107
            force_close();
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   108
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   109
            continue;
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
        } else {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   112
            // 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
   113
            break;
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
   
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   117
    // release our addrinfo
381
9b35bc329d23 separate sockaddr stuff out of NetworkAddress... now called NetworkEndpoint
terom
parents: 380
diff changeset
   118
    addr.free_addrinfo(results);
378
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
    // 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
   121
    if (r == NULL)
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   122
        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
   123
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   124
    // mark ourselves as bound
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   125
    bound = true;
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::listen (int backlog) {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   129
    // just call listen
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   130
    if (::listen(fd, backlog))
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   131
        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
   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
NetworkAddress NetworkSocket::get_local_address (void) {
381
9b35bc329d23 separate sockaddr stuff out of NetworkAddress... now called NetworkEndpoint
terom
parents: 380
diff changeset
   135
    NetworkAddress addr;
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
    // do getsockname()
381
9b35bc329d23 separate sockaddr stuff out of NetworkAddress... now called NetworkEndpoint
terom
parents: 380
diff changeset
   138
    if (::getsockname(fd, addr.get_sockaddr(), addr.get_socklen_ptr()))
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   139
        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
   140
446
e411c0799fcc fix NetworkSocket to not forget want_* state if resetting between connect()'s
Tero Marttila <terom@fixme.fi>
parents: 399
diff changeset
   141
    // updated sockaddr
381
9b35bc329d23 separate sockaddr stuff out of NetworkAddress... now called NetworkEndpoint
terom
parents: 380
diff changeset
   142
    addr.update();
9b35bc329d23 separate sockaddr stuff out of NetworkAddress... now called NetworkEndpoint
terom
parents: 380
diff changeset
   143
9b35bc329d23 separate sockaddr stuff out of NetworkAddress... now called NetworkEndpoint
terom
parents: 380
diff changeset
   144
    return addr;
378
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
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   147
NetworkAddress NetworkSocket::get_remote_address (void) {
381
9b35bc329d23 separate sockaddr stuff out of NetworkAddress... now called NetworkEndpoint
terom
parents: 380
diff changeset
   148
    NetworkAddress addr;
378
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
    // do getpeername()
381
9b35bc329d23 separate sockaddr stuff out of NetworkAddress... now called NetworkEndpoint
terom
parents: 380
diff changeset
   151
    if (::getpeername(fd, addr.get_sockaddr(), addr.get_socklen_ptr()))
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   152
        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
   153
446
e411c0799fcc fix NetworkSocket to not forget want_* state if resetting between connect()'s
Tero Marttila <terom@fixme.fi>
parents: 399
diff changeset
   154
    // updated sockaddr
381
9b35bc329d23 separate sockaddr stuff out of NetworkAddress... now called NetworkEndpoint
terom
parents: 380
diff changeset
   155
    addr.update();
9b35bc329d23 separate sockaddr stuff out of NetworkAddress... now called NetworkEndpoint
terom
parents: 380
diff changeset
   156
9b35bc329d23 separate sockaddr stuff out of NetworkAddress... now called NetworkEndpoint
terom
parents: 380
diff changeset
   157
    return addr;
378
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
        
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   160
void NetworkSocket::set_nonblocking (bool nonblocking) {
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   161
    // linux-specific
378
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   162
    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
   163
        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
   164
}
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   165
 
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   166
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
   167
    int new_fd;
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
    // try and get the FD
381
9b35bc329d23 separate sockaddr stuff out of NetworkAddress... now called NetworkEndpoint
terom
parents: 380
diff changeset
   170
    // pass src sock* pointers if provided
9b35bc329d23 separate sockaddr stuff out of NetworkAddress... now called NetworkEndpoint
terom
parents: 380
diff changeset
   171
    if ((new_fd = ::accept(
9b35bc329d23 separate sockaddr stuff out of NetworkAddress... now called NetworkEndpoint
terom
parents: 380
diff changeset
   172
            fd, 
9b35bc329d23 separate sockaddr stuff out of NetworkAddress... now called NetworkEndpoint
terom
parents: 380
diff changeset
   173
            src ? src->get_sockaddr() : NULL,
9b35bc329d23 separate sockaddr stuff out of NetworkAddress... now called NetworkEndpoint
terom
parents: 380
diff changeset
   174
            src ? src->get_socklen_ptr() : NULL
9b35bc329d23 separate sockaddr stuff out of NetworkAddress... now called NetworkEndpoint
terom
parents: 380
diff changeset
   175
    )) < 0)
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   176
        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
   177
    
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   178
    // allocate new NetworkSocket for new_fd
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   179
    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
   180
    
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   181
    // update src
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   182
    if (src)
381
9b35bc329d23 separate sockaddr stuff out of NetworkAddress... now called NetworkEndpoint
terom
parents: 380
diff changeset
   183
        src->update();
378
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
    return socket;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   186
}
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   187
        
381
9b35bc329d23 separate sockaddr stuff out of NetworkAddress... now called NetworkEndpoint
terom
parents: 380
diff changeset
   188
void NetworkSocket::connect (const NetworkEndpoint &addr) {
378
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   189
    // get our addrinfo
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   190
    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
   191
    
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   192
    // 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
   193
    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
   194
        // 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
   195
        try {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   196
            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
   197
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   198
        } catch (NetworkSocketError &e) {
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   199
            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
   200
            continue;
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
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   203
        // 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
   204
        if (::connect(fd, r->ai_addr, r->ai_addrlen)) {
385
e56af22c04dd better error reporting of NetworkSocket bind/connect failures
terom
parents: 381
diff changeset
   205
            Engine::log(WARN, "socket.connect") << "unable to connect to " << addr << " (" << 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
   206
            
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   207
            // 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
   208
            if (!bound)
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   209
                force_close();
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   210
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   211
            continue;
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
        } else {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   214
            // 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
   215
            break;
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
   
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   219
    // release our addrinfo
381
9b35bc329d23 separate sockaddr stuff out of NetworkAddress... now called NetworkEndpoint
terom
parents: 380
diff changeset
   220
    addr.free_addrinfo(results);
378
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
    // 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
   223
    if (r == NULL)
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   224
        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
   225
}
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   226
        
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   227
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
   228
    ssize_t ret;
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
    // use send or sendto?
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   231
    if (dest) {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   232
        // sendto()
381
9b35bc329d23 separate sockaddr stuff out of NetworkAddress... now called NetworkEndpoint
terom
parents: 380
diff changeset
   233
        if ((ret = ::sendto(fd, buf, size, 0, dest->get_sockaddr(), dest->get_socklen())) < 0 && errno != EAGAIN)
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   234
            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
   235
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   236
    } else {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   237
        // send()
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   238
        if ((ret = ::send(fd, buf, size, 0)) < 0 && errno != EAGAIN)
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   239
            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
   240
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
    
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   243
    // sanity-check
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   244
    if (ret == 0) {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   245
        // 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
   246
        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
   247
        return 0;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   248
    }
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   249
    
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   250
    // EAGAIN? 
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   251
    if (ret < 0) {
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   252
        // set want_write so we get a sig_write
399
c7295b72731a documentation work on Network
Tero Marttila <terom@fixme.fi>
parents: 385
diff changeset
   253
        // XXX: this is the job of the user
c7295b72731a documentation work on Network
Tero Marttila <terom@fixme.fi>
parents: 385
diff changeset
   254
        // want_write = true;
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   255
378
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   256
        return 0;
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   257
    }
378
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
    // 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
   260
    return 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
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   263
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
   264
    ssize_t ret;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   265
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   266
    // use recv or recvfrom?
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   267
    if (src) {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   268
        // recvfrom()
381
9b35bc329d23 separate sockaddr stuff out of NetworkAddress... now called NetworkEndpoint
terom
parents: 380
diff changeset
   269
        if ((ret = ::recvfrom(fd, buf, size, 0, src->get_sockaddr(), src->get_socklen_ptr())) < 0 && errno != EAGAIN)
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   270
            throw NetworkSocketErrno(*this, "recvfrom");
381
9b35bc329d23 separate sockaddr stuff out of NetworkAddress... now called NetworkEndpoint
terom
parents: 380
diff changeset
   271
        
9b35bc329d23 separate sockaddr stuff out of NetworkAddress... now called NetworkEndpoint
terom
parents: 380
diff changeset
   272
        // update if valid
9b35bc329d23 separate sockaddr stuff out of NetworkAddress... now called NetworkEndpoint
terom
parents: 380
diff changeset
   273
        if (ret > 0)
9b35bc329d23 separate sockaddr stuff out of NetworkAddress... now called NetworkEndpoint
terom
parents: 380
diff changeset
   274
            src->update();
378
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   275
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   276
    } else {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   277
        // recv
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   278
        if ((ret = ::recv(fd, buf, size, 0)) < 0 && errno != EAGAIN)
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   279
            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
   280
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
    // EOF?
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   284
    if (ret == 0)
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   285
        throw NetworkSocketEOFError(*this, "recv");
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   286
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   287
    // EAGAIN?
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   288
    if (ret < 0)
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   289
        return 0;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   290
    
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   291
    // 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
   292
    return ret;
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   293
}
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
void NetworkSocket::close (void) {
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   296
    // use closesocket
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   297
    if (::closesocket(fd))
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   298
        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
   299
    
446
e411c0799fcc fix NetworkSocket to not forget want_* state if resetting between connect()'s
Tero Marttila <terom@fixme.fi>
parents: 399
diff changeset
   300
    // forget fd
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
}
5589abf5e61b break the network code. Too late to set up a branch for this now
terom
parents: 187
diff changeset
   303
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   304
void NetworkSocket::register_poll (void) { 
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   305
    if (registered) return; 
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   306
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   307
    reactor->add_socket(this); 
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   308
    registered = true; 
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   309
}
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   310
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
 * NetworkSocketError
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   313
 */
187
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
   314
std::string NetworkSocketError::build_str (const NetworkSocket &socket, const char *op, const char *err) {
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
   315
    std::stringstream ss;
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
   316
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
   317
    ss << "socket #" << socket.get_socket() << " " << op << ": " << err;
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
   318
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
   319
    return ss.str();
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
   320
}
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
   321
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
   322
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
   323
    Error(build_str(socket, op, err)) 
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   324
{
187
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
   325
    // nothing
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
   326
}
f41f894213ca restructure network code a bit
terom
parents:
diff changeset
   327
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   328
NetworkSocketErrno::NetworkSocketErrno (const NetworkSocket &socket, const char *op) :
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   329
    NetworkSocketError(socket, op, strerror(errno)) 
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   330
{ 
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents: 378
diff changeset
   331
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