blob: f7860d26cfb7b4e4874b601a88054dcfc4a541bd (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
|
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_SERVER_KERNEL_ABSTRACT_
#ifdef DLIB_SERVER_KERNEL_ABSTRACT_
#include "../threads/threads_kernel_abstract.h"
#include "../sockets/sockets_kernel_abstract.h"
#include <string>
namespace dlib
{
class server
{
/*!
INITIAL VALUE
get_listening_ip() == ""
get_listening_port() == 0
is_running() == false
get_max_connections() == 1000
get_graceful_close_timeout() == 500
CALLBACK FUNCTIONS
on_connect():
To use this object inherit from it and define the pure virtual function
on_connect. Inside this function is where you will handle each new
connection. Note that the connection object passed to on_connect() should
NOT be closed, just let the function end and it will be gracefully closed
for you. Also note that each call to on_connect() is run in its own
thread. Also note that on_connect() should NOT throw any exceptions,
all exceptions must be dealt with inside on_connect() and cannot be
allowed to leave.
on_listening_port_assigned():
This function is called to let the client know that the operating
system has assigned a port number to the listening port. This
happens if a port number of zero was given. Note that this
function does not need to be defined. If you don't care then
don't define it and it will do nothing. Note also that this function
is NOT called in its own thread. Thus, making it block might hang the
server.
WHAT THIS OBJECT REPRESENTS
This object represents a server that listens on a port and spawns new
threads to handle each new connection.
Note that the clear() function does not return until all calls to
on_connect() have finished and the start() function has been shutdown.
Also note that when clear() is called all open connection objects
will be shutdown().
A note about get_max_connections(): when the maximum number of connections
has been reached accept() will simply not be called until the number of
open connections drops below get_max_connections(). This means connections
will just wait to be serviced, rather than being outright refused.
THREAD SAFETY
All member functions are thread-safe.
!*/
public:
server(
);
/*!
ensures
- #*this is properly initialized
throws
- std::bad_alloc
- dlib::thread_error
!*/
virtual ~server(
);
/*!
requires
- is not called from any of server's callbacks
ensures
- all resources associated with *this have been released
!*/
void clear(
);
/*!
requires
- is not called from any of server's callbacks
ensures
- #*this has its initial value
- all open connection objects passed to on_connect() are shutdown()
- blocks until all calls to on_connect() have finished
- blocks until the start() function has released all its resources
throws
- std::bad_alloc
if this exception is thrown then the server object is unusable
until clear() is called and succeeds
!*/
void start (
);
/*!
requires
- is_running() == false
ensures
- starts listening on the port and ip specified by get_listening_ip()
and #get_listening_port() for new connections.
- if (get_listening_port() == 0) then
- a port to listen on will be automatically selected
- #get_listening_port() == the selected port being used
- if (get_listening_ip() == "" ) then
- all local IPs will be listened on
- blocks until clear() is called or an error occurs
throws
- dlib::socket_error
start() will throw this exception if there is some problem binding
ports and/or starting the server or if there is a problem
accepting new connections while it's running.
If this happens then
- All open connection objects passed to on_connect() are shutdown()
and the exception will not be thrown until all on_connect() calls
have terminated.
- The server will be cleared and returned to its initial value.
- dlib::thread_error
start() will throw this exception if there is a problem
creating new threads. Or it may throw this exception if there
is a problem creating threading objects.
If this happens then
- All open connection objects passed to on_connect() are shutdown()
and the exception will not be thrown until all on_connect() calls
have terminated.
- The server will be cleared and returned to its initial value.
- std::bad_alloc
start() may throw this exception and if it does then the object
will be unusable until clear() is called and succeeds
!*/
void start_async (
);
/*!
ensures
- starts listening on the port and ip specified by get_listening_ip()
and #get_listening_port() for new connections.
- if (get_listening_port() == 0) then
- a port to listen on will be automatically selected
- #get_listening_port() == the selected port being used
- if (get_listening_ip() == "" ) then
- all local IPs will be listened on
- does NOT block. That is, this function will return right away and
the server will run on a background thread until clear() or this
object's destructor is called (or until some kind of fatal error
occurs).
- if an error occurs in the background thread while the server is
running then it will shut itself down, set is_running() to false, and
log the error to a dlib::logger object.
- calling start_async() on a running server has no effect.
throws
- dlib::socket_error
start_async() will throw this exception if there is some problem binding
ports and/or starting the server.
If this happens then
- The server will be cleared and returned to its initial value.
!*/
bool is_running (
) const;
/*!
ensures
- returns true if start() is running
- returns false if start() is not running or has released all
its resources and is about to terminate
throws
- std::bad_alloc
!*/
int get_max_connections (
) const;
/*!
ensures
- returns the maximum number of connections the server will accept
at a time.
- returns 0 if the server will accept any number of connections
throws
- std::bad_alloc
!*/
const std::string get_listening_ip (
) const;
/*!
ensures
- returns the local ip to listen for new connections on
- returns "" if ALL local ips are to be listened on
throws
- std::bad_alloc
!*/
int get_listening_port (
) const;
/*!
ensures
- returns the local port number to listen for new connections on
- returns 0 if the local port number has not yet been set
throws
- std::bad_alloc
!*/
void set_listening_port (
int port
);
/*!
requires
- port >= 0
- is_running() == false
ensures
- #get_listening_port() == port
throws
- std::bad_alloc
!*/
void set_listening_ip (
const std::string& ip
);
/*!
requires
- is_ip_address(ip) == true or ip == ""
- is_running() == false
ensures
- #get_listening_ip() == ip
throws
- std::bad_alloc
!*/
void set_max_connections (
int max
);
/*!
requires
- max >= 0
ensures
- #get_max_connections() == max
throws
- std::bad_alloc
!*/
void set_graceful_close_timeout (
unsigned long timeout
);
/*!
ensures
- #get_graceful_close_timeout() == timeout
!*/
unsigned long get_graceful_close_timeout (
) const;
/*!
ensures
- When on_connect() terminates, it will close the connection using
close_gracefully(). This is done so that any data still in the
operating system's output buffers gets a chance to be properly
transmitted to the remote host. Part of this involves waiting for
the remote host to close their end of the connection. Therefore,
get_graceful_close_timeout() returns the timeout, in milliseconds,
that we wait for the remote host to close their end of the
connection. This is the timeout value given to close_gracefully().
!*/
private:
virtual void on_connect (
connection& new_connection
)=0;
/*!
requires
- on_connect() is run in its own thread
- is_running() == true
- the number of current connections < get_max_connection()
- new_connection == the new connection to the server which is
to be serviced by this call to on_connect()
ensures
- when new_connection is shutdown() on_connect() will terminate
- this function will not call clear()
throws
- does not throw any exceptions
!*/
// do nothing by default
virtual void on_listening_port_assigned (
) {}
/*!
requires
- is called if a listening port of zero was specified and
an actual port number has just been assigned to the server
ensures
- this function will not block
- this function will not call clear()
throws
- does not throw any exceptions
!*/
// restricted functions
server(server&); // copy constructor
server& operator=(server&); // assignment operator
};
}
#endif // DLIB_SERVER_KERNEL_ABSTRACT_
|