// Copyright (C) 2006  Davis E. King (davis@dlib.net)
// License: Boost Software License   See LICENSE.txt for the full license.
#ifndef DLIB_SOCKETS_EXTENSIONs_
#define DLIB_SOCKETS_EXTENSIONs_

#include <iosfwd>
#include <memory>
#include <string>

#include "../sockets.h"
#include "../smart_pointers/scoped_ptr.h"
#include "sockets_extensions_abstract.h"


namespace dlib
{

// ----------------------------------------------------------------------------------------

    class invalid_network_address : public dlib::error 
    { 
    public: 
        invalid_network_address(const std::string& msg) : dlib::error(msg) {};
    };

// ----------------------------------------------------------------------------------------

    struct network_address
    {
        network_address() : port(0){}

        network_address(
            const std::string& full_address
        );

        network_address (
            const char* full_address
        )
        {
            *this = network_address(std::string(full_address));
        }

        network_address(
            const std::string& host_address_,
            const unsigned short port_
        ) : host_address(host_address_), port(port_) {}
            
        std::string host_address;
        unsigned short port;
    };

// ----------------------------------------------------------------------------------------

    inline bool operator < (
        const network_address& a,
        const network_address& b
    ) 
    {
        if (a.host_address < b.host_address)
            return true;
        else if (a.host_address > b.host_address)
            return false;
        else if (a.port < b.port)
            return true;
        else
            return false;
    }

    inline bool operator== (
        const network_address& a,
        const network_address& b
    ) { return a.host_address == b.host_address && a.port == b.port; }

    inline bool operator != (
        const network_address& a,
        const network_address& b
    ) { return !(a == b); }

// ----------------------------------------------------------------------------------------

    void serialize(
        const network_address& item,
        std::ostream& out
    );

    void deserialize(
        network_address& item,
        std::istream& in 
    );

    std::ostream& operator<< (
        std::ostream& out,
        const network_address& item
    );

    std::istream& operator>> (
        std::istream& in,
        network_address& item
    );

// ----------------------------------------------------------------------------------------

    connection* connect (
        const std::string& host_or_ip,
        unsigned short port
    );

// ----------------------------------------------------------------------------------------

    connection* connect (
        const network_address& addr
    );

// ----------------------------------------------------------------------------------------

    connection* connect (
        const std::string& host_or_ip,
        unsigned short port,
        unsigned long timeout
    );

// ----------------------------------------------------------------------------------------

    bool is_ip_address (
        std::string ip
    );

// ----------------------------------------------------------------------------------------

    void close_gracefully (
        connection* con,
        unsigned long timeout = 500
    );

// ----------------------------------------------------------------------------------------

    void close_gracefully (
        std::unique_ptr<connection>& con,
        unsigned long timeout = 500
    );

// ----------------------------------------------------------------------------------------

}

#ifdef NO_MAKEFILE
#include "sockets_extensions.cpp"
#endif

#endif // DLIB_SOCKETS_EXTENSIONs_