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