separate sockaddr stuff out of NetworkAddress... now called NetworkEndpoint
authorterom
Wed, 17 Dec 2008 00:40:22 +0000
changeset 381 9b35bc329d23
parent 380 d193dd1d8a7e
child 382 190f81d30624
separate sockaddr stuff out of NetworkAddress... now called NetworkEndpoint
src/Engine.cc
src/Network/Address.cc
src/Network/Address.hh
src/Network/Client.cc
src/Network/Client.hh
src/Network/Error.cc
src/Network/Server.cc
src/Network/Server.hh
src/Network/Session.cc
src/Network/Session.hh
src/Network/SockAddr.cc
src/Network/SockAddr.hh
src/Network/Socket.cc
src/Network/Socket.hh
src/Network/TCP.cc
src/Network/TCP.hh
src/Network/UDP.cc
src/Network/UDP.hh
--- a/src/Engine.cc	Tue Dec 16 23:21:26 2008 +0000
+++ b/src/Engine.cc	Wed Dec 17 00:40:22 2008 +0000
@@ -18,13 +18,15 @@
 }
 
 void Engine::setupNetworkServer (const std::string &listen_port) {
+    NetworkEndpoint listen_addr(listen_port);
+
     // create the server
-    net_server = new NetworkServer(game_state, listen_port);
+    net_server = new NetworkServer(game_state, listen_addr);
 }
 
 void Engine::setupNetworkClient (const std::string &connect_host, const std::string &connect_port) {
     // connect_to
-    NetworkAddress connect_addr(connect_host, connect_port);
+    NetworkEndpoint connect_addr(connect_host, connect_port);
 
     // create the client
     net_client = new NetworkClient(*this, game_state, connect_addr);
--- a/src/Network/Address.cc	Tue Dec 16 23:21:26 2008 +0000
+++ b/src/Network/Address.cc	Wed Dec 17 00:40:22 2008 +0000
@@ -3,32 +3,25 @@
 
 #include <sstream>
 
-NetworkAddress::NetworkAddress (void) :
-    hostname(), service(), address_length(0)
+NetworkEndpoint::NetworkEndpoint (void) :
+    hostname(), service()
 {
 
 }
 
-NetworkAddress::NetworkAddress (std::string service) :
-    hostname(), service(service), address_length(0)
+NetworkEndpoint::NetworkEndpoint (std::string service) :
+    hostname(), service(service)
 {
 
 }
         
-NetworkAddress::NetworkAddress (std::string hostname, std::string service) :
-    hostname(hostname), service(service), address_length(0)
+NetworkEndpoint::NetworkEndpoint (std::string hostname, std::string service) :
+    hostname(hostname), service(service)
 {
 
 }
-        
-NetworkAddress::NetworkAddress (const sockaddr *addr, socklen_t len) :
-    hostname(), service(), address_length(0)
-{
-    // proxy to set_sockaddr
-    set_sockaddr(addr, len);
-}
-        
-addrinfo* NetworkAddress::get_addrinfo (int family, int socktype, int protocol, int flags) const {
+       
+addrinfo* NetworkEndpoint::get_addrinfo (int family, int socktype, int protocol, int flags) const {
     addrinfo hints, *results;
     int err;
     
@@ -53,49 +46,18 @@
     return results;
 }
         
-const sockaddr* NetworkAddress::get_sockaddr (socklen_t &len_ref) const {
-    // we can't figure this out ourselves...
-    if (address_length == 0)
-        throw Error("NetworkAddress::get_sockaddr called without a valid sockaddr set");
-    
-    // update len
-    len_ref = address_length;
-    
-    // and return a pointer to our internal address
-    return (const sockaddr*) &address;
+void NetworkEndpoint::free_addrinfo (addrinfo *info) const {
+    freeaddrinfo(info);
 }
 
-void NetworkAddress::set_sockaddr (const sockaddr *addr, socklen_t len) {
-    char host_buf[NI_MAXHOST], serv_buf[NI_MAXSERV];
-    int err;
-
-    // invalid length?
-    if (len > sizeof(this->address))
-        throw NetworkAddressError(*this, "set_sockaddr", "invalid sockaddr length");
-
-    // do getnameinfo()
-    if ((err = getnameinfo(addr, len, host_buf, NI_MAXHOST, serv_buf, NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV)))
-        throw NetworkAddressError(*this, "getnameinfo", gai_strerror(err));
-    
-    // copy over to address
-    memcpy(&this->address, addr, len);
-
-    // and update address_length
-    this->address_length = len;
-
-    // and the hostname + service
-    hostname = host_buf;
-    service = serv_buf;
-}
-
-std::ostream& operator<< (std::ostream &s, const NetworkAddress &addr) {
+std::ostream& operator<< (std::ostream &s, const NetworkEndpoint &addr) {
     s << "[" << addr.get_hostname() << ":" << addr.get_service() << "]";
 
     return s;
 
 }
  
-std::string NetworkAddressError::build_str (const NetworkAddress &addr, const char *op, const char *msg) {
+std::string NetworkAddressError::build_str (const NetworkEndpoint &addr, const char *op, const char *msg) {
     std::stringstream ss;
 
     ss << op << ": " << addr << ": " << msg;
@@ -103,11 +65,9 @@
     return ss.str();
 }
 
-NetworkAddressError::NetworkAddressError (const NetworkAddress &addr, const char *op, const char *msg) :
+NetworkAddressError::NetworkAddressError (const NetworkEndpoint &addr, const char *op, const char *msg) :
     Error(build_str(addr, op, msg))
 {
 
 }
 
-
-
--- a/src/Network/Address.hh	Tue Dec 16 23:21:26 2008 +0000
+++ b/src/Network/Address.hh	Wed Dec 17 00:40:22 2008 +0000
@@ -9,7 +9,6 @@
 #ifndef WIN32
     // linux
     #include <sys/types.h>
-    #include <sys/socket.h>
     #include <netdb.h>
 #else
     #error "This network code won't compile on win32 :)"
@@ -30,8 +29,8 @@
 /**
  * We use ClanLib's IPAddress API, but with our own name
  */ 
-class NetworkAddress {
-    private:
+class NetworkEndpoint {
+    protected:
         /**
          * Our human-readable hostname
          */
@@ -42,33 +41,22 @@
          */
         std::string service;
 
-        /**
-         * Our machine-readable address and its length
-         */
-        sockaddr_storage address;
-        socklen_t address_length;
-
     public:
         /**
-         * Construct an empty NetworkAddress
+         * Construct an empty NetworkEndpoint
          */
-        NetworkAddress (void);
+        NetworkEndpoint (void);
 
         /**
-         * Construct a NetworkAddress with a NULL hostname, and a specific service
+         * Construct a NetworkEndpoint with a NULL hostname, and a specific service
          */
-        NetworkAddress (std::string service);
+        explicit NetworkEndpoint (std::string service);
 
         /**
-         * Construct a NetworkAddress on a specific hostname and service
+         * Construct a NetworkEndpoint on a specific hostname and service
          */
-        NetworkAddress (std::string hostname, std::string service);
+        NetworkEndpoint (std::string hostname, std::string service);
         
-        /**
-         * Construct a NetworkAddress from a machine-readable address of the given length
-         */
-        NetworkAddress (const sockaddr *addr, socklen_t len);
-
         /*
          * We can use the default copy-constructor and assignment operator
          */
@@ -86,78 +74,38 @@
          * @return linked list of addrinfo's
          * @throw NetworkAddressError if resolving this address fails
          */
-        addrinfo* get_addrinfo (int family, int socktype, int protocol = 0, int flags = 0) const;
-
+        virtual addrinfo* get_addrinfo (int family, int socktype, int protocol = 0, int flags = 0) const;
+        
         /**
-         * Get a sockaddr* for this address. This is only valid for NetworkAddress's which have had set_sockaddr called
-         * on them.
-         *
-         * @param len_ref updated to the sockaddr length
-         * @return borrowed sockaddr pointer
+         * Free an addrinfo returned by get_addrinfo
          */
-        const sockaddr* get_sockaddr (socklen_t &len_ref) const;
-
-        /**
-         * Set a sockaddr for this address
-         *
-         * @param addr the address to copy, of len bytes
-         * @param len the size of the sockaddr
-         */
-        void set_sockaddr (const sockaddr *addr, socklen_t len);
+        virtual void free_addrinfo (addrinfo *info) const;
 
         /**
          * Get the human-readable hostname
          */
-        std::string get_hostname (void) const { return hostname; }
+        virtual std::string get_hostname (void) const { return hostname; }
 
         /**
          * Get the human-readable service name
          */
-        std::string get_service (void) const { return service; }
-
-        /**
-         * Equal-to comparison operator. This requires that the machine-readable address be available.
-         */
-        bool operator== (const NetworkAddress &other) const {
-            return (address_length == other.address_length) && memcmp(&address, &other.address, address_length) == 0;
-        }
-
-        /**
-         * Not-qqual-to comparison operator. This requires that the machine-readable address be available.
-         */
-        bool operator!= (const NetworkAddress &other) const {
-            return (address_length != other.address_length) || memcmp(&address, &other.address, address_length) != 0;
-        }
-
-        /**
-         * Less-than comparison operator. Smaller addresses are always lesser.
-         */
-        bool operator< (const NetworkAddress &other) const {
-            return (address_length < other.address_length) || memcmp(&address, &other.address, other.address_length) < 0;
-        }
-
-        /**
-         * Greater-than comparison operator. Bigger addresses are always greater.
-         */
-        bool operator> (const NetworkAddress &other) const {
-            return (address_length > other.address_length) || memcmp(&address, &other.address, address_length) > 0;
-        }
+        virtual std::string get_service (void) const { return service; }
 };
 
 /**
  * Formatted as  [<addr>:<port>]
  */
-std::ostream& operator<< (std::ostream &s, const NetworkAddress &addr);
+std::ostream& operator<< (std::ostream &s, const NetworkEndpoint &addr);
 
 /**
  *
  */
 class NetworkAddressError : public Error {
     protected:
-        static std::string build_str (const NetworkAddress &addr, const char *op, const char *msg);
+        static std::string build_str (const NetworkEndpoint &addr, const char *op, const char *msg);
 
     public:
-        NetworkAddressError (const NetworkAddress &addr, const char *op, const char *msg);
+        NetworkAddressError (const NetworkEndpoint &addr, const char *op, const char *msg);
 };
 
 #endif /* NETWORK_ADDRESS_HH */
--- a/src/Network/Client.cc	Tue Dec 16 23:21:26 2008 +0000
+++ b/src/Network/Client.cc	Wed Dec 17 00:40:22 2008 +0000
@@ -7,7 +7,7 @@
 
 #include <cassert>
 
-NetworkClient::NetworkClient (Engine &engine, GameState &state, const NetworkAddress &connect_to) : 
+NetworkClient::NetworkClient (Engine &engine, GameState &state, const NetworkEndpoint &connect_to) : 
     engine(engine), state(state), netsession(NETWORK_MAGIC_ID), server(netsession.connect(connect_to)),
     controller(*this)
 {
--- a/src/Network/Client.hh	Tue Dec 16 23:21:26 2008 +0000
+++ b/src/Network/Client.hh	Wed Dec 17 00:40:22 2008 +0000
@@ -99,13 +99,13 @@
 
     public:
         /**
-         * Create a NetworkClient with the given GameState, connecting a server on the given NetworkAddress
+         * Create a NetworkClient with the given GameState, connecting a server on the given NetworkEndpoint
          *
          * @param engine the Engine we're running as
          * @param state the GameState to use
          * @param connect_to the address to connect to
          */
-        NetworkClient (Engine &engine, GameState &state, const NetworkAddress &connect_to);
+        NetworkClient (Engine &engine, GameState &state, const NetworkEndpoint &connect_to);
     
     protected:
         /**
--- a/src/Network/Error.cc	Tue Dec 16 23:21:26 2008 +0000
+++ b/src/Network/Error.cc	Wed Dec 17 00:40:22 2008 +0000
@@ -7,7 +7,7 @@
 std::string NetworkErrno::build_str (std::string op, int err) {
     std::stringstream ss;
 
-    ss << op << ": " << strerror(errno);
+    ss << op << ": " << strerror(err);
 
     return ss.str();
 }
--- a/src/Network/Server.cc	Tue Dec 16 23:21:26 2008 +0000
+++ b/src/Network/Server.cc	Wed Dec 17 00:40:22 2008 +0000
@@ -7,7 +7,7 @@
 
 #include <cassert>
 
-NetworkServer::NetworkServer (GameState &state, const NetworkAddress &listen_addr) : 
+NetworkServer::NetworkServer (GameState &state, const NetworkEndpoint &listen_addr) : 
     state(state), netsession(NETWORK_MAGIC_ID), controller(netsession, NETCHAN_CORE) {
     
     // connect slots
--- a/src/Network/Server.hh	Tue Dec 16 23:21:26 2008 +0000
+++ b/src/Network/Server.hh	Wed Dec 17 00:40:22 2008 +0000
@@ -47,7 +47,7 @@
         /**
          * Construct a NetworkServer, using the given GameState and listening on the given address
          */
-        NetworkServer (GameState &state, const NetworkAddress &listen_addr);
+        NetworkServer (GameState &state, const NetworkEndpoint &listen_addr);
     
     protected:
         /**
--- a/src/Network/Session.cc	Tue Dec 16 23:21:26 2008 +0000
+++ b/src/Network/Session.cc	Wed Dec 17 00:40:22 2008 +0000
@@ -10,7 +10,7 @@
     // nothing
 }
         
-void NetworkSession::listen (const NetworkAddress &addr) {
+void NetworkSession::listen (const NetworkEndpoint &addr) {
     assert(tcp_srv == NULL && udp_srv == NULL);
     
     // create TCP/UDP servers
@@ -30,7 +30,7 @@
     return new NetworkNode(*this, tcp, udp, addr);
 }
 
-NetworkNode* NetworkSession::connect (const NetworkAddress &addr) {
+NetworkNode* NetworkSession::connect (const NetworkEndpoint &addr) {
     // XXX: only one connect
     assert(!udp_client);
 
--- a/src/Network/Session.hh	Tue Dec 16 23:21:26 2008 +0000
+++ b/src/Network/Session.hh	Wed Dec 17 00:40:22 2008 +0000
@@ -80,7 +80,7 @@
          *
          * @param addr local address to listen on
          */
-        void listen (const NetworkAddress &addr);
+        void listen (const NetworkEndpoint &addr);
 
         /**
          * Have the NetworkSession enter client mode, establishing a TCP connection to the server, and then allocating
@@ -88,7 +88,7 @@
          *
          * @param addr remote address to connect to
          */
-        NetworkNode* connect (const NetworkAddress &addr);
+        NetworkNode* connect (const NetworkEndpoint &addr);
     
     protected:
         /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Network/SockAddr.cc	Wed Dec 17 00:40:22 2008 +0000
@@ -0,0 +1,76 @@
+
+#include "SockAddr.hh"
+
+#include <cstdlib>
+
+NetworkAddress::NetworkAddress (void) :
+    NetworkEndpoint(), address_length(0)
+{
+
+}
+
+NetworkAddress::NetworkAddress (const sockaddr *addr, socklen_t len) :
+    NetworkEndpoint(), address_length(0)
+{
+    // proxy to set_sockaddr
+    set_sockaddr(addr, len);
+}
+ 
+void NetworkAddress::set_sockaddr (const sockaddr *addr, socklen_t len) {
+    // invalid length?
+    if (len <= 0 || len > sizeof(address))
+        throw NetworkAddressError(*this, "set_sockaddr", "invalid sockaddr length");
+
+    // copy over to address
+    memcpy(&address, addr, len);
+    
+    // set address_length
+    address_length = len;
+    
+   // update
+   update();
+}
+
+void NetworkAddress::update (void) {
+    char host_buf[NI_MAXHOST], serv_buf[NI_MAXSERV];
+    int err;
+
+    // do getnameinfo()
+    if ((err = getnameinfo((sockaddr *) &address, address_length, host_buf, NI_MAXHOST, serv_buf, NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV)))
+        throw NetworkAddressError(*this, "getnameinfo", gai_strerror(err));
+    
+    // update hostname + service
+    hostname = host_buf;
+    service = serv_buf;
+}
+
+addrinfo* NetworkAddress::get_addrinfo (int family, int socktype, int protocol, int flags) const {
+    (void) flags;
+
+    // get my family from address
+    int my_family = address.ss_family;
+    
+    // right family?
+    if (family && family != my_family)
+        throw NetworkAddressError(*this, "fake_getaddrinfo", "ai_family mismatch");
+    
+    // alllocate new addrinfo
+    addrinfo *r = new addrinfo;
+
+    // set it up
+    r->ai_flags = 0;
+    r->ai_family = my_family;
+    r->ai_socktype = socktype;
+    r->ai_protocol = protocol;
+    r->ai_addrlen = get_socklen();
+    r->ai_addr = const_cast<sockaddr *>(get_sockaddr());
+    r->ai_canonname = const_cast<char *>(get_hostname().c_str());
+    r->ai_next = NULL;
+
+    // return it
+    return r;
+}
+
+void NetworkAddress::free_addrinfo (addrinfo *info) const {
+    delete info;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Network/SockAddr.hh	Wed Dec 17 00:40:22 2008 +0000
@@ -0,0 +1,122 @@
+#ifndef NETWORK_SOCKADDR_H
+#define NETWORK_SOCKADDR_H
+
+#include "Address.hh"
+
+/*
+ * Platform-specific includes
+ */
+#ifndef WIN32
+    // linux
+    #include <netinet/in.h>
+#else
+    #error "This network code won't compile on win32 :)"
+#endif
+
+
+/**
+ * This represents a `struct sockaddr` as used by the socket API.
+ *
+ * It can be used like a NetworkEndpoint, but it's also suitable for use with recvfrom/sendto
+ */
+class NetworkAddress : public NetworkEndpoint {
+    protected:
+        /**
+         * The machine-readable address
+         */
+        sockaddr_storage address;
+
+        /**
+         * The address length
+         */
+        socklen_t address_length;
+
+    public:
+        /**
+         * Construct an empty SockAddr for later update()
+         */
+        NetworkAddress (void);
+
+        /**
+         * Construct a NetworkAddress from a machine-readable address of the given length
+         */
+        NetworkAddress (const sockaddr *addr, socklen_t len);
+
+        /**
+         * Get a const sockaddr* in this address
+         *
+         * @return read-only sockaddr pointer
+         */
+        const sockaddr* get_sockaddr (void) const { return (const sockaddr *) &address; }
+
+        /**
+         * Get a mutable sockaddr* in this address
+         *
+         * @return writeable sockaddr pointer
+         */
+        sockaddr* get_sockaddr (void) { return (sockaddr *) &address; }
+
+        /**
+         * Get the current address length
+         *
+         * @return address length
+         */
+        socklen_t get_socklen (void) const { return address_length; }
+
+        /**
+         * Get a the address length pointer, initialized to the size of our sockaddr_storage.
+         *
+         * @return address length pointer
+         */
+        socklen_t* get_socklen_ptr (void) { address_length = sizeof(address); return &address_length; }
+
+        /**
+         * Copy given sockaddr/len + update
+         */
+        void set_sockaddr (const sockaddr *addr, socklen_t len);
+
+        /**
+         * Update internal state for NetworkAddress after sockaddr/socklen_ptr have been modified.
+         */
+        void update (void);
+        
+        /**
+         * Returns a "fake" addrinfo
+         */
+        virtual addrinfo* get_addrinfo (int family, int socktype, int protocol = 0, int flags = 0) const;
+
+        /**
+         * Free an addrinfo returned by get_addrinfo
+         */
+        virtual void free_addrinfo (addrinfo *info) const;
+
+        /**
+         * Equal-to comparison operator. Invalid addresses compare equal and are always smaller
+         */
+        bool operator== (const NetworkAddress &other) const {
+            return (address_length == other.address_length) && memcmp(&address, &other.address, address_length) == 0;
+        }
+
+        /**
+         * Not-equal-to comparison operator. Invalid addresses compare equal and are always smaller
+         */
+        bool operator!= (const NetworkAddress &other) const {
+            return (address_length != other.address_length) || memcmp(&address, &other.address, address_length) != 0;
+        }
+
+        /**
+         * Less-than comparison operator. Smaller addresses are always lesser.
+         */
+        bool operator< (const NetworkAddress &other) const {
+            return (address_length < other.address_length) || memcmp(&address, &other.address, other.address_length) < 0;
+        }
+
+        /**
+         * Greater-than comparison operator. Bigger addresses are always greater.
+         */
+        bool operator> (const NetworkAddress &other) const {
+            return (address_length > other.address_length) || memcmp(&address, &other.address, address_length) > 0;
+        }
+};
+
+#endif
--- a/src/Network/Socket.cc	Tue Dec 16 23:21:26 2008 +0000
+++ b/src/Network/Socket.cc	Wed Dec 17 00:40:22 2008 +0000
@@ -79,7 +79,7 @@
     reset();
 }
 
-void NetworkSocket::bind (const NetworkAddress &addr) {
+void NetworkSocket::bind (const NetworkEndpoint &addr) {
     // get our addrinfo
     addrinfo *r, *results = addr.get_addrinfo(type.family, type.socktype, type.protocol, AI_PASSIVE);
     
@@ -110,7 +110,7 @@
     }
    
     // release our addrinfo
-    freeaddrinfo(results);
+    addr.free_addrinfo(results);
 
     // if we failed to bind, r is a NULL pointer
     if (r == NULL)
@@ -127,27 +127,31 @@
 }
         
 NetworkAddress NetworkSocket::get_local_address (void) {
-    sockaddr_storage addr;
-    socklen_t addrlen = sizeof(addr);
+    NetworkAddress addr;
 
     // do getsockname()
-    if (::getsockname(fd, (sockaddr *) &addr, &addrlen))
+    if (::getsockname(fd, addr.get_sockaddr(), addr.get_socklen_ptr()))
         throw NetworkSocketErrno(*this, "getsockname");
 
+    // update
+    addr.update();
+
     // return addr
-    return NetworkAddress((sockaddr *) &addr, addrlen);
+    return addr;
 }
 
 NetworkAddress NetworkSocket::get_remote_address (void) {
-    sockaddr_storage addr;
-    socklen_t addrlen = sizeof(addr);
+    NetworkAddress addr;
 
     // do getpeername()
-    if (::getpeername(fd, (sockaddr *) &addr, &addrlen))
+    if (::getpeername(fd, addr.get_sockaddr(), addr.get_socklen_ptr()))
         throw NetworkSocketErrno(*this, "getpeername");
 
+    // update
+    addr.update();
+
     // return addr
-    return NetworkAddress((sockaddr *) &addr, addrlen);
+    return addr;
 }
         
 void NetworkSocket::set_nonblocking (bool nonblocking) {
@@ -158,11 +162,14 @@
  
 NetworkSocket* NetworkSocket::accept (NetworkAddress *src) {
     int new_fd;
-    sockaddr_storage addr;
-    socklen_t addrlen = sizeof(addr);
 
     // try and get the FD
-    if ((new_fd = ::accept(fd, (sockaddr *) &addr, &addrlen)) < 0)
+    // pass src sock* pointers if provided
+    if ((new_fd = ::accept(
+            fd, 
+            src ? src->get_sockaddr() : NULL,
+            src ? src->get_socklen_ptr() : NULL
+    )) < 0)
         throw NetworkSocketErrno(*this, "accept");
     
     // allocate new NetworkSocket for new_fd
@@ -170,13 +177,13 @@
     
     // update src
     if (src)
-        src->set_sockaddr((sockaddr *) &addr, addrlen);    
+        src->update();
 
     // done
     return socket;
 }
         
-void NetworkSocket::connect (const NetworkAddress &addr) {
+void NetworkSocket::connect (const NetworkEndpoint &addr) {
     // get our addrinfo
     addrinfo *r, *results = addr.get_addrinfo(type.family, type.socktype, type.protocol);
     
@@ -208,7 +215,7 @@
     }
    
     // release our addrinfo
-    freeaddrinfo(results);
+    addr.free_addrinfo(results);
 
     // if we failed to connect, r is a NULL pointer
     if (r == NULL)
@@ -220,14 +227,8 @@
     
     // use send or sendto?
     if (dest) {
-        const sockaddr *addr;
-        socklen_t addr_len;
-        
-        // get destination address
-        addr = dest->get_sockaddr(addr_len);
-        
         // sendto()
-        if ((ret = ::sendto(fd, buf, size, 0, addr, addr_len)) < 0 && errno != EAGAIN)
+        if ((ret = ::sendto(fd, buf, size, 0, dest->get_sockaddr(), dest->get_socklen())) < 0 && errno != EAGAIN)
             throw NetworkSocketErrno(*this, "sendto");
 
     } else {
@@ -261,18 +262,13 @@
 
     // use recv or recvfrom?
     if (src) {
-        sockaddr_storage addr;
-        socklen_t addr_len = sizeof(addr);
-
         // recvfrom()
-        if ((ret = ::recvfrom(fd, buf, size, 0, (sockaddr *) &addr, &addr_len)) < 0 && errno != EAGAIN)
+        if ((ret = ::recvfrom(fd, buf, size, 0, src->get_sockaddr(), src->get_socklen_ptr())) < 0 && errno != EAGAIN)
             throw NetworkSocketErrno(*this, "recvfrom");
-
-        // update source address if recvfrom suceeded
-        if (ret > 0) {
-            // modify src...
-            src->set_sockaddr((sockaddr *) &addr, addr_len);
-        }
+        
+        // update if valid
+        if (ret > 0)
+            src->update();
 
     } else {
         // recv
--- a/src/Network/Socket.hh	Tue Dec 16 23:21:26 2008 +0000
+++ b/src/Network/Socket.hh	Wed Dec 17 00:40:22 2008 +0000
@@ -6,6 +6,7 @@
 
 #include "../Error.hh"
 #include "Address.hh"
+#include "SockAddr.hh"
 #include "Reactor.hh"
 
 /*
@@ -128,7 +129,7 @@
         /**
          * Bind to a specific local address
          */ 
-        void bind (const NetworkAddress &addr);
+        void bind (const NetworkEndpoint &addr);
 
         /**
          * Put socket into listen mode
@@ -158,11 +159,14 @@
         /**
          * Establish a new connection
          */
-        void connect (const NetworkAddress &addr);
+        void connect (const NetworkEndpoint &addr);
 
         /**
          * Send, optionally using the specific destination
          *
+         * @param buf bytes to send
+         * @param size how many bytes to try and send
+         * @param dest optional specific destination address
          * @return number of bytes sent, zero if busy
          * @throw NetworkSocketError on error
          */
@@ -171,6 +175,9 @@
         /**
          * Recv, optionally storing the source in src
          *
+         * @param buf where to recv into
+         * @param size how many bytes to try and receive
+         * @param src optionally store source address
          * @return number of bytes received, zero if none available
          * @throw NetworkSocketEOFError if the connection was closed
          * @throw NetworkSocketError on error
--- a/src/Network/TCP.cc	Tue Dec 16 23:21:26 2008 +0000
+++ b/src/Network/TCP.cc	Wed Dec 17 00:40:22 2008 +0000
@@ -97,7 +97,7 @@
 /*
  * NetworkTCPServer
  */
-NetworkTCPServer::NetworkTCPServer (const NetworkAddress &listen_addr) :
+NetworkTCPServer::NetworkTCPServer (const NetworkEndpoint &listen_addr) :
     socket(AF_UNSPEC, SOCK_STREAM) {
     
     // bind
@@ -134,7 +134,7 @@
 /*
  * NetworkTCPClient
  */
-NetworkTCPClient::NetworkTCPClient (const NetworkAddress &connect_addr) :
+NetworkTCPClient::NetworkTCPClient (const NetworkEndpoint &connect_addr) :
     NetworkTCPTransport(new NetworkSocket(AF_UNSPEC, SOCK_STREAM)) {
     
     // connect
--- a/src/Network/TCP.hh	Tue Dec 16 23:21:26 2008 +0000
+++ b/src/Network/TCP.hh	Wed Dec 17 00:40:22 2008 +0000
@@ -122,7 +122,7 @@
         /**
          * Listen on the specific address.
          */
-        NetworkTCPServer (const NetworkAddress &listen_addr);
+        NetworkTCPServer (const NetworkEndpoint &listen_addr);
 
     private:
         /**
@@ -162,7 +162,7 @@
          *
          * @param connect_addr the address to connect to
          */
-        NetworkTCPClient (const NetworkAddress &connect_addr);
+        NetworkTCPClient (const NetworkEndpoint &connect_addr);
 };
 
 #endif /* NETWORK_TCP_HH */
--- a/src/Network/UDP.cc	Tue Dec 16 23:21:26 2008 +0000
+++ b/src/Network/UDP.cc	Wed Dec 17 00:40:22 2008 +0000
@@ -20,7 +20,7 @@
     socket.set_poll_read(true);
 }
 
-NetworkUDP::NetworkUDP (const NetworkAddress &bind_addr) :
+NetworkUDP::NetworkUDP (const NetworkEndpoint &bind_addr) :
     socket(AF_UNSPEC, SOCK_DGRAM) {
     
     // bind socket
--- a/src/Network/UDP.hh	Tue Dec 16 23:21:26 2008 +0000
+++ b/src/Network/UDP.hh	Wed Dec 17 00:40:22 2008 +0000
@@ -28,7 +28,7 @@
          *
          * @param bind_addr the local address to bind to
          */
-        NetworkUDP (const NetworkAddress &bind_addr);
+        NetworkUDP (const NetworkEndpoint &bind_addr);
 
     private:
         /**