src/Network/Address.hh
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
#ifndef NETWORK_ADDRESS_HH
#define NETWORK_ADDRESS_HH

#include "../Error.hh"

/*
 * Platform-specific includes
 */
#ifndef WIN32
    // linux
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netdb.h>
#else
    #error "This network code won't compile on win32 :)"
#endif

#include <string>

// assume...
#if INET6_ADDRSTRLEN < INET_ADDRSTRLEN
    #error INET6_ADDRSTRLEN is smaller than INET_ADDRSTRLEN
#endif

/**
 * Length of a network address
 */
const socklen_t NETWORK_ADDRESS_LENGTH = INET6_ADDRSTRLEN;

/**
 * We use ClanLib's IPAddress API, but with our own name
 */ 
class NetworkAddress {
    private:
        /**
         * Our human-readable hostname
         */
        std::string hostname;

        /**
         * Our human-readable service
         */
        std::string service;

        /**
         * Our machine-readable address and its length
         */
        sockaddr_storage address;
        socklen_t address_length;

    public:
        /**
         * Construct an empty NetworkAddress
         */
        NetworkAddress (void);

        /**
         * Construct a NetworkAddress with a NULL hostname, and a specific service
         */
        NetworkAddress (std::string service);

        /**
         * Construct a NetworkAddress on a specific hostname and service
         */
        NetworkAddress (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
         */
   
    public:    
        /**
         * Get a addrinfo* for this address using the given family/type/protocol/flags.
         *
         * Remember to free the returned pointer using freeaddrinfo() after use.
         *
         * @param family the socket family for hints.ai_family
         * @param socktype the socket type for hints.ai_socktype
         * @param protoocl the socket protocol for hints.ai_protocol
         * @param flags the flags for hints.ai_flags
         * @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;

        /**
         * 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
         */
        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);

        /**
         * Get the human-readable hostname
         */
        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;
        }
};

/**
 * Formatted as  [<addr>:<port>]
 */
std::ostream& operator<< (std::ostream &s, const NetworkAddress &addr);

/**
 *
 */
class NetworkAddressError : public Error {
    protected:
        static std::string build_str (const NetworkAddress &addr, const char *op, const char *msg);

    public:
        NetworkAddressError (const NetworkAddress &addr, const char *op, const char *msg);
};

#endif /* NETWORK_ADDRESS_HH */