1 // Copyright (C) 2011  Davis E. King (davis@dlib.net)
2 // License: Boost Software License   See LICENSE.txt for the full license.
3 #undef DLIB_BRIDGe_ABSTRACT_
4 #ifdef DLIB_BRIDGe_ABSTRACT_
5 
6 #include <string>
7 #include "../pipe/pipe_kernel_abstract.h"
8 
9 namespace dlib
10 {
11 
12 // ----------------------------------------------------------------------------------------
13 
14     struct connect_to_ip_and_port
15     {
16         connect_to_ip_and_port (
17             const std::string& ip,
18             unsigned short port
19         );
20         /*!
21             requires
22                 - is_ip_address(ip) == true
23                 - port != 0
24             ensures
25                 - this object will represent a request to make a TCP connection
26                   to the given IP address and port number.
27         !*/
28     };
29 
30     connect_to_ip_and_port connect_to (
31         const network_address& addr
32     );
33     /*!
34         requires
35             - addr.port != 0
36         ensures
37             - converts the given network_address object into a connect_to_ip_and_port
38               object.
39     !*/
40 
41     struct listen_on_port
42     {
43         listen_on_port(
44             unsigned short port
45         );
46         /*!
47             requires
48                 - port != 0
49             ensures
50                 - this object will represent a request to listen on the given
51                   port number for incoming TCP connections.
52         !*/
53     };
54 
55     template <
56         typename pipe_type
57         >
58     bridge_transmit_decoration<pipe_type> transmit (
59         pipe_type& p
60     );
61     /*!
62         requires
63             - pipe_type is some kind of dlib::pipe object
64             - the objects in the pipe must be serializable
65         ensures
66             - Adds a type decoration to the given pipe, marking it as a transmit pipe, and
67               then returns it.
68     !*/
69 
70     template <
71         typename pipe_type
72         >
73     bridge_receive_decoration<pipe_type> receive (
74         pipe_type& p
75     );
76     /*!
77         requires
78             - pipe_type is some kind of dlib::pipe object
79             - the objects in the pipe must be serializable
80         ensures
81             - Adds a type decoration to the given pipe, marking it as a receive pipe, and
82               then returns it.
83     !*/
84 
85 // ----------------------------------------------------------------------------------------
86 
87     struct bridge_status
88     {
89         /*!
90             WHAT THIS OBJECT REPRESENTS
91                 This simple struct represents the state of a bridge object.  A
92                 bridge is either connected or not.  If it is connected then it
93                 is connected to a foreign host with an IP address and port number
94                 as indicated by this object.
95         !*/
96 
97         bridge_status(
98         );
99         /*!
100             ensures
101                 - #is_connected == false
102                 - #foreign_port == 0
103                 - #foreign_ip == ""
104         !*/
105 
106         bool is_connected;
107         unsigned short foreign_port;
108         std::string foreign_ip;
109     };
110 
111 // ----------------------------------------------------------------------------------------
112 
113     class bridge : noncopyable
114     {
115         /*!
116             WHAT THIS OBJECT REPRESENTS
117                 This object is a tool for bridging a dlib::pipe object between
118                 two network connected applications.
119 
120 
121                 Note also that this object contains a dlib::logger object
122                 which will log various events taking place inside a bridge.
123                 If you want to see these log messages then enable the logger
124                 named "dlib.bridge".
125 
126 
127             BRIDGE PROTOCOL DETAILS
128                 The bridge object creates a single TCP connection between
129                 two applications.  Whenever it sends an object from a pipe
130                 over a TCP connection it sends a byte with the value 1 followed
131                 immediately by the serialized copy of the object from the pipe.
132                 The serialization is performed by calling the global serialize()
133                 function.
134 
135                 Additionally, a bridge object will periodically send bytes with
136                 a value of 0 to ensure the TCP connection remains alive.  These
137                 are just read and ignored.
138         !*/
139 
140     public:
141 
142         bridge (
143         );
144         /*!
145             ensures
146                 - this object is properly initialized
147                 - #get_bridge_status().is_connected == false
148         !*/
149 
150         template <typename T, typename U, typename V>
151         bridge (
152             T network_parameters,
153             U pipe1,
154             V pipe2
155         );
156         /*!
157             requires
158                 - T is of type connect_to_ip_and_port or listen_on_port
159                 - U and V are of type bridge_transmit_decoration or bridge_receive_decoration,
160                   however, U and V must be of different types (i.e. one is a receive type and
161                   another a transmit type).
162             ensures
163                 - this object is properly initialized
164                 - performs: reconfigure(network_parameters, pipe1, pipe2)
165                   (i.e. using this constructor is identical to using the default constructor
166                   and then calling reconfigure())
167         !*/
168 
169         template <typename T, typename U>
170         bridge (
171             T network_parameters,
172             U pipe
173         );
174         /*!
175             requires
176                 - T is of type connect_to_ip_and_port or listen_on_port
177                 - U is of type bridge_transmit_decoration or bridge_receive_decoration.
178             ensures
179                 - this object is properly initialized
180                 - performs: reconfigure(network_parameters, pipe)
181                   (i.e. using this constructor is identical to using the default constructor
182                   and then calling reconfigure())
183         !*/
184 
185         ~bridge (
186         );
187         /*!
188             ensures
189                 - blocks until all resources associated with this object have been destroyed.
190         !*/
191 
192         void clear (
193         );
194         /*!
195             ensures
196                 - returns this object to its default constructed state.  That is, it will
197                   be inactive, neither maintaining a connection nor attempting to acquire one.
198                 - Any active connections or listening sockets will be closed.
199         !*/
200 
201         bridge_status get_bridge_status (
202         ) const;
203         /*!
204             ensures
205                 - returns the current status of this bridge object. In particular, returns
206                   an object BS such that:
207                     - BS.is_connected == true if and only if the bridge has an active TCP
208                       connection to another computer.
209                     - if (BS.is_connected) then
210                         - BS.foreign_ip == the IP address of the remote host we are connected to.
211                         - BS.foreign_port == the port number on the remote host we are connected to.
212                     - else if (the bridge has previously been connected to a remote host but hasn't been
213                                reconfigured or cleared since) then
214                         - BS.foreign_ip == the IP address of the remote host we were connected to.
215                         - BS.foreign_port == the port number on the remote host we were connected to.
216                     - else
217                         - BS.foreign_ip == ""
218                         - BS.foreign_port == 0
219         !*/
220 
221 
222 
223         template < typename T, typename R >
224         void reconfigure (
225             listen_on_port network_parameters,
226             bridge_transmit_decoration<T> transmit_pipe,
227             bridge_receive_decoration<R> receive_pipe
228         );
229         /*!
230             ensures
231                 - This object will begin listening on the port specified by network_parameters
232                   for incoming TCP connections.  Any previous bridge state is cleared out.
233                 - Onces a connection is established we will:
234                     - Stop accepting new connections.
235                     - Begin dequeuing objects from the transmit pipe and serializing them over
236                       the TCP connection.
237                     - Begin deserializing objects from the TCP connection and enqueueing them
238                       onto the receive pipe.
239                 - if (the current TCP connection is lost) then
240                     - This object goes back to listening for a new connection.
241                 - if (the receive pipe can contain bridge_status objects) then
242                     - Whenever the bridge's status changes the updated bridge_status will be
243                       enqueued onto the receive pipe unless the change was a TCP disconnect
244                       resulting from a user calling reconfigure(), clear(), or destructing this
245                       bridge.  The status contents are defined by get_bridge_status().
246             throws
247                 - socket_error
248                   This exception is thrown if we are unable to open the listening socket.
249         !*/
250         template < typename T, typename R >
251         void reconfigure (
252             listen_on_port network_parameters,
253             bridge_receive_decoration<R> receive_pipe,
254             bridge_transmit_decoration<T> transmit_pipe
255         );
256         /*!
257             ensures
258                 - performs reconfigure(network_parameters, transmit_pipe, receive_pipe)
259         !*/
260         template < typename T >
261         void reconfigure (
262             listen_on_port network_parameters,
263             bridge_transmit_decoration<T> transmit_pipe
264         );
265         /*!
266             ensures
267                 - This function is identical to the above two reconfigure() functions
268                   except that there is no receive pipe.
269         !*/
270         template < typename R >
271         void reconfigure (
272             listen_on_port network_parameters,
273             bridge_receive_decoration<R> receive_pipe
274         );
275         /*!
276             ensures
277                 - This function is identical to the above three reconfigure() functions
278                   except that there is no transmit pipe.
279         !*/
280 
281 
282 
283         template <typename T, typename R>
284         void reconfigure (
285             connect_to_ip_and_port network_parameters,
286             bridge_transmit_decoration<T> transmit_pipe,
287             bridge_receive_decoration<R> receive_pipe
288         );
289         /*!
290             ensures
291                 - This object will begin making TCP connection attempts to the IP address and port
292                   specified by network_parameters.  Any previous bridge state is cleared out.
293                 - Onces a connection is established we will:
294                     - Stop attempting new connections.
295                     - Begin dequeuing objects from the transmit pipe and serializing them over
296                       the TCP connection.
297                     - Begin deserializing objects from the TCP connection and enqueueing them
298                       onto the receive pipe.
299                 - if (the current TCP connection is lost) then
300                     - This object goes back to attempting to make a TCP connection with the
301                       IP address and port specified by network_parameters.
302                 - if (the receive pipe can contain bridge_status objects) then
303                     - Whenever the bridge's status changes the updated bridge_status will be
304                       enqueued onto the receive pipe unless the change was a TCP disconnect
305                       resulting from a user calling reconfigure(), clear(), or destructing this
306                       bridge.  The status contents are defined by get_bridge_status().
307         !*/
308         template <typename T, typename R>
309         void reconfigure (
310             connect_to_ip_and_port network_parameters,
311             bridge_receive_decoration<R> receive_pipe,
312             bridge_transmit_decoration<T> transmit_pipe
313         );
314         /*!
315             ensures
316                 - performs reconfigure(network_parameters, transmit_pipe, receive_pipe)
317         !*/
318         template <typename T>
319         void reconfigure (
320             connect_to_ip_and_port network_parameters,
321             bridge_transmit_decoration<T> transmit_pipe
322         );
323         /*!
324             ensures
325                 - This function is identical to the above two reconfigure() functions
326                   except that there is no receive pipe.
327         !*/
328         template <typename R>
329         void reconfigure (
330             connect_to_ip_and_port network_parameters,
331             bridge_receive_decoration<R> receive_pipe
332         );
333         /*!
334             ensures
335                 - This function is identical to the above three reconfigure() functions
336                   except that there is no transmit pipe.
337         !*/
338 
339     };
340 
341 // ----------------------------------------------------------------------------------------
342 
343 }
344 
345 #endif // DLIB_BRIDGe_ABSTRACT_
346 
347 
348