// Copyright (C) 2003 Davis E. King (davis@dlib.net), Miguel Grinberg // License: Boost Software License See LICENSE.txt for the full license. #ifndef DLIB_SOCKETS_KERNEl_1_ #define DLIB_SOCKETS_KERNEl_1_ #ifdef DLIB_ISO_CPP_ONLY #error "DLIB_ISO_CPP_ONLY is defined so you can't use this OS dependent code. Turn DLIB_ISO_CPP_ONLY off if you want to use it." #endif #include "sockets_kernel_abstract.h" #include <memory> #include <string> #include "../algs.h" #include "../threads.h" #include "../uintn.h" namespace dlib { // ---------------------------------------------------------------------------------------- // forward declarations class socket_factory; class listener; class SOCKET_container; // ---------------------------------------------------------------------------------------- // lookup functions int get_local_hostname ( std::string& hostname ); // ----------------- int hostname_to_ip ( const std::string& hostname, std::string& ip, int n = 0 ); // ----------------- int ip_to_hostname ( const std::string& ip, std::string& hostname ); // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- // connection object // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- class connection { /*! INITIAL_VALUE - sd == false - sdo == false - sdr == 0 CONVENTION - connection_socket == the socket handle for this connection. - connection_foreign_port == the port that foreign host is using for this connection. - connection_foreign_ip == a string containing the IP address of the foreign host. - connection_local_port == the port that the local host is using for this connection. - connection_local_ip == a string containing the IP address of the local interface being used by this connection. - sd == if shutdown() has been called then true else false. - sdo == if shutdown_outgoing() has been called then true else false. - sdr == the return value of shutdown() if it has been called. if it hasn't been called then 0. !*/ friend class listener; // make listener a friend of connection // make create_connection a friend of connection friend int create_connection ( connection*& new_connection, unsigned short foreign_port, const std::string& foreign_ip, unsigned short local_port, const std::string& local_ip ); public: ~connection ( ); void* user_data; long write ( const char* buf, long num ); long read ( char* buf, long num ); long read ( char* buf, long num, unsigned long timeout ); unsigned short get_local_port ( ) const { return connection_local_port; } unsigned short get_foreign_port ( ) const { return connection_foreign_port; } const std::string& get_local_ip ( ) const { return connection_local_ip; } const std::string& get_foreign_ip ( ) const { return connection_foreign_ip; } int shutdown_outgoing ( ); int shutdown ( ); // I would use SOCKET here but I don't want to include the windows // header files since they bring in a bunch of unpleasantness. So // I'm doing this instead which should ultimately be the same type // as the SOCKET win the windows API. typedef unsigned_type<void*>::type socket_descriptor_type; int disable_nagle( ); socket_descriptor_type get_socket_descriptor ( ) const; private: bool readable ( unsigned long timeout ) const; /*! requires - timeout < 2000000 ensures - returns true if a read call on this connection will not block. - returns false if a read call on this connection will block or if there was an error. !*/ bool sd_called ( )const /*! ensures - returns true if shutdown() has been called else returns false !*/ { sd_mutex.lock(); bool temp = sd; sd_mutex.unlock(); return temp; } bool sdo_called ( )const /*! ensures - returns true if shutdown_outgoing() or shutdown() has been called else returns false !*/ { sd_mutex.lock(); bool temp = false; if (sdo || sd) temp = true; sd_mutex.unlock(); return temp; } // data members SOCKET_container& connection_socket; const unsigned short connection_foreign_port; const std::string connection_foreign_ip; const unsigned short connection_local_port; const std::string connection_local_ip; bool sd; // called shutdown bool sdo; // called shutdown_outgoing int sdr; // return value for shutdown mutex sd_mutex; // a lock for the three above vars connection( SOCKET_container sock, unsigned short foreign_port, const std::string& foreign_ip, unsigned short local_port, const std::string& local_ip ); /*! requires sock is a socket handle and sock is the handle for the connection between foreign_ip:foreign_port and local_ip:local_port ensures *this is initialized correctly with the above parameters !*/ // restricted functions connection(connection&); // copy constructor connection& operator=(connection&); // assignment operator }; // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- // listener object // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- class listener { /*! CONVENTION if (inaddr_any == false) { listening_ip == a string containing the address the listener is listening on } else { the listener is listening on all interfaces } listening_port == the port the listener is listening on listening_socket == the listening socket handle for this object !*/ // make the create_listener a friend of listener friend int create_listener ( listener*& new_listener, unsigned short port, const std::string& ip ); public: ~listener ( ); int accept ( connection*& new_connection, unsigned long timeout = 0 ); int accept ( std::unique_ptr<connection>& new_connection, unsigned long timeout = 0 ); unsigned short get_listening_port ( ) { return listening_port; } const std::string& get_listening_ip ( ) { return listening_ip; } private: // data members SOCKET_container& listening_socket; const unsigned short listening_port; const std::string listening_ip; const bool inaddr_any; listener( SOCKET_container sock, unsigned short port, const std::string& ip ); /*! requires sock is a socket handle and sock is listening on the port and ip(may be "") indicated in the above parameters ensures *this is initialized correctly with the above parameters !*/ // restricted functions listener(listener&); // copy constructor listener& operator=(listener&); // assignment operator }; // ---------------------------------------------------------------------------------------- int create_listener ( listener*& new_listener, unsigned short port, const std::string& ip = "" ); int create_connection ( connection*& new_connection, unsigned short foreign_port, const std::string& foreign_ip, unsigned short local_port = 0, const std::string& local_ip = "" ); int create_listener ( std::unique_ptr<listener>& new_listener, unsigned short port, const std::string& ip = "" ); int create_connection ( std::unique_ptr<connection>& new_connection, unsigned short foreign_port, const std::string& foreign_ip, unsigned short local_port = 0, const std::string& local_ip = "" ); // ---------------------------------------------------------------------------------------- } #ifdef NO_MAKEFILE #include "sockets_kernel_1.cpp" #endif #endif // DLIB_SOCKETS_KERNEl_1_