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