src/Network/Address.hh
author Tero Marttila <terom@fixme.fi>
Fri, 16 Jan 2009 21:24:45 +0200
changeset 399 c7295b72731a
parent 383 2a57f0a871b0
child 400 d64bf28c4340
permissions -rw-r--r--
documentation work on Network
#ifndef NETWORK_ADDRESS_H
#define NETWORK_ADDRESS_H

/**
 * @file
 *
 * Binary NetworkAddress
 */

#include "Platform.hh"
#include "Endpoint.hh"

/**
 * A NetworkAddress represents a single network address in the form of a `struct sockaddr`, as used by the OS's socket
 * API. A NetworkAddress's value may only be constructed/manipulated in sockaddr form, and the class then emulates the
 * get_addrinfo (by building our own addrinfo struct value) and get_hostname()/get_service() (by using libc's
 * getnameinfo() when the address is updated).
 *
 * This means that a NetworkAddress can be used like a NetworkEndpoint (like a literal IP address), but can also be
 * used in a more specifc fashion like NetworkSocket::send or NetworkSocket::accept, where a definitive address is
 * required.
 *
 * XXX: currently, there is no way to form a NetworkAddress from a NetworkEndpoint for e.g. sending UDP packets without
 * an associated TCP connection.
 */
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.
         *
         * XXX: use of memcmp is broken... there's garbage in the padding
         */
        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