1 // Copyright (C) 2003 Davis E. King (davis@dlib.net), Miguel Grinberg 2 // License: Boost Software License See LICENSE.txt for the full license. 3 #ifndef DLIB_SOCKETS_KERNEl_1_ 4 #define DLIB_SOCKETS_KERNEl_1_ 5 6 #ifdef DLIB_ISO_CPP_ONLY 7 #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." 8 #endif 9 10 #include "sockets_kernel_abstract.h" 11 12 #include <memory> 13 #include <string> 14 15 #include "../algs.h" 16 #include "../threads.h" 17 #include "../uintn.h" 18 19 20 namespace dlib 21 { 22 23 // ---------------------------------------------------------------------------------------- 24 25 // forward declarations 26 class socket_factory; 27 class listener; 28 class SOCKET_container; 29 30 // ---------------------------------------------------------------------------------------- 31 32 // lookup functions 33 34 int 35 get_local_hostname ( 36 std::string& hostname 37 ); 38 39 // ----------------- 40 41 int 42 hostname_to_ip ( 43 const std::string& hostname, 44 std::string& ip, 45 int n = 0 46 ); 47 48 // ----------------- 49 50 int 51 ip_to_hostname ( 52 const std::string& ip, 53 std::string& hostname 54 ); 55 56 // ---------------------------------------------------------------------------------------- 57 // ---------------------------------------------------------------------------------------- 58 // connection object 59 // ---------------------------------------------------------------------------------------- 60 // ---------------------------------------------------------------------------------------- 61 62 class connection 63 { 64 /*! 65 INITIAL_VALUE 66 - sd == false 67 - sdo == false 68 - sdr == 0 69 70 CONVENTION 71 - connection_socket == the socket handle for this connection. 72 - connection_foreign_port == the port that foreign host is using for 73 this connection. 74 - connection_foreign_ip == a string containing the IP address of the 75 foreign host. 76 - connection_local_port == the port that the local host is using for 77 this connection. 78 - connection_local_ip == a string containing the IP address of the 79 local interface being used by this connection. 80 81 - sd == if shutdown() has been called then true else false. 82 - sdo == if shutdown_outgoing() has been called then true else false. 83 - sdr == the return value of shutdown() if it has been called. if it 84 hasn't been called then 0. 85 86 !*/ 87 88 friend class listener; // make listener a friend of connection 89 // make create_connection a friend of connection 90 friend int create_connection ( 91 connection*& new_connection, 92 unsigned short foreign_port, 93 const std::string& foreign_ip, 94 unsigned short local_port, 95 const std::string& local_ip 96 ); 97 98 public: 99 100 ~connection ( 101 ); 102 103 void* user_data; 104 105 long write ( 106 const char* buf, 107 long num 108 ); 109 110 long read ( 111 char* buf, 112 long num 113 ); 114 115 long read ( 116 char* buf, 117 long num, 118 unsigned long timeout 119 ); 120 get_local_port()121 unsigned short get_local_port ( 122 ) const { return connection_local_port; } 123 get_foreign_port()124 unsigned short get_foreign_port ( 125 ) const { return connection_foreign_port; } 126 get_local_ip()127 const std::string& get_local_ip ( 128 ) const { return connection_local_ip; } 129 get_foreign_ip()130 const std::string& get_foreign_ip ( 131 ) const { return connection_foreign_ip; } 132 133 int shutdown_outgoing ( 134 ); 135 136 int shutdown ( 137 ); 138 139 // I would use SOCKET here but I don't want to include the windows 140 // header files since they bring in a bunch of unpleasantness. So 141 // I'm doing this instead which should ultimately be the same type 142 // as the SOCKET win the windows API. 143 typedef unsigned_type<void*>::type socket_descriptor_type; 144 145 int disable_nagle( 146 ); 147 148 socket_descriptor_type get_socket_descriptor ( 149 ) const; 150 151 private: 152 153 bool readable ( 154 unsigned long timeout 155 ) const; 156 /*! 157 requires 158 - timeout < 2000000 159 ensures 160 - returns true if a read call on this connection will not block. 161 - returns false if a read call on this connection will block or if 162 there was an error. 163 !*/ 164 sd_called()165 bool sd_called ( 166 )const 167 /*! 168 ensures 169 - returns true if shutdown() has been called else 170 returns false 171 !*/ 172 { 173 sd_mutex.lock(); 174 bool temp = sd; 175 sd_mutex.unlock(); 176 return temp; 177 } 178 sdo_called()179 bool sdo_called ( 180 )const 181 /*! 182 ensures 183 - returns true if shutdown_outgoing() or shutdown() has been called 184 else returns false 185 !*/ 186 { 187 sd_mutex.lock(); 188 bool temp = false; 189 if (sdo || sd) 190 temp = true; 191 sd_mutex.unlock(); 192 return temp; 193 } 194 195 196 // data members 197 SOCKET_container& connection_socket; 198 const unsigned short connection_foreign_port; 199 const std::string connection_foreign_ip; 200 const unsigned short connection_local_port; 201 const std::string connection_local_ip; 202 203 bool sd; // called shutdown 204 bool sdo; // called shutdown_outgoing 205 int sdr; // return value for shutdown 206 mutex sd_mutex; // a lock for the three above vars 207 208 209 connection( 210 SOCKET_container sock, 211 unsigned short foreign_port, 212 const std::string& foreign_ip, 213 unsigned short local_port, 214 const std::string& local_ip 215 ); 216 /*! 217 requires 218 sock is a socket handle and 219 sock is the handle for the connection between foreign_ip:foreign_port 220 and local_ip:local_port 221 ensures 222 *this is initialized correctly with the above parameters 223 !*/ 224 225 226 // restricted functions 227 connection(connection&); // copy constructor 228 connection& operator=(connection&); // assignment operator 229 }; 230 231 // ---------------------------------------------------------------------------------------- 232 // ---------------------------------------------------------------------------------------- 233 // listener object 234 // ---------------------------------------------------------------------------------------- 235 // ---------------------------------------------------------------------------------------- 236 237 class listener 238 { 239 /*! 240 CONVENTION 241 if (inaddr_any == false) 242 { 243 listening_ip == a string containing the address the listener is 244 listening on 245 } 246 else 247 { 248 the listener is listening on all interfaces 249 } 250 251 listening_port == the port the listener is listening on 252 listening_socket == the listening socket handle for this object 253 !*/ 254 255 // make the create_listener a friend of listener 256 friend int create_listener ( 257 listener*& new_listener, 258 unsigned short port, 259 const std::string& ip 260 ); 261 262 public: 263 264 ~listener ( 265 ); 266 267 int accept ( 268 connection*& new_connection, 269 unsigned long timeout = 0 270 ); 271 272 int accept ( 273 std::unique_ptr<connection>& new_connection, 274 unsigned long timeout = 0 275 ); 276 get_listening_port()277 unsigned short get_listening_port ( 278 ) { return listening_port; } 279 get_listening_ip()280 const std::string& get_listening_ip ( 281 ) { return listening_ip; } 282 283 private: 284 285 // data members 286 SOCKET_container& listening_socket; 287 const unsigned short listening_port; 288 const std::string listening_ip; 289 const bool inaddr_any; 290 291 listener( 292 SOCKET_container sock, 293 unsigned short port, 294 const std::string& ip 295 ); 296 /*! 297 requires 298 sock is a socket handle and 299 sock is listening on the port and ip(may be "") indicated in the 300 above parameters 301 ensures 302 *this is initialized correctly with the above parameters 303 !*/ 304 305 306 // restricted functions 307 listener(listener&); // copy constructor 308 listener& operator=(listener&); // assignment operator 309 }; 310 311 // ---------------------------------------------------------------------------------------- 312 313 int create_listener ( 314 listener*& new_listener, 315 unsigned short port, 316 const std::string& ip = "" 317 ); 318 319 int create_connection ( 320 connection*& new_connection, 321 unsigned short foreign_port, 322 const std::string& foreign_ip, 323 unsigned short local_port = 0, 324 const std::string& local_ip = "" 325 ); 326 327 int create_listener ( 328 std::unique_ptr<listener>& new_listener, 329 unsigned short port, 330 const std::string& ip = "" 331 ); 332 333 int create_connection ( 334 std::unique_ptr<connection>& new_connection, 335 unsigned short foreign_port, 336 const std::string& foreign_ip, 337 unsigned short local_port = 0, 338 const std::string& local_ip = "" 339 ); 340 341 // ---------------------------------------------------------------------------------------- 342 343 344 } 345 346 #ifdef NO_MAKEFILE 347 #include "sockets_kernel_1.cpp" 348 #endif 349 350 #endif // DLIB_SOCKETS_KERNEl_1_ 351 352