7
7
// Official repository: https://github.com/boostorg/beast
8
8
//
9
9
10
- #include " server.hpp"
11
-
12
10
#if 0
13
11
14
12
#include <boost/beast/core.hpp>
@@ -61,7 +59,7 @@ class session : public std::enable_shared_from_this<session>
61
59
// on the I/O objects in this session. Although not strictly necessary
62
60
// for single-threaded contexts, this example code is written to be
63
61
// thread-safe by default.
64
- net ::dispatch(ws_.get_executor(),
62
+ asio ::dispatch(ws_.get_executor(),
65
63
beast::bind_front_handler(
66
64
&session::on_run,
67
65
shared_from_this()));
@@ -158,12 +156,12 @@ class session : public std::enable_shared_from_this<session>
158
156
// Accepts incoming connections and launches the sessions
159
157
class listener : public std::enable_shared_from_this<listener>
160
158
{
161
- net ::io_context& ioc_;
159
+ asio ::io_context& ioc_;
162
160
tcp::acceptor acceptor_;
163
161
164
162
public:
165
163
listener(
166
- net ::io_context& ioc,
164
+ asio ::io_context& ioc,
167
165
tcp::endpoint endpoint)
168
166
: ioc_(ioc)
169
167
, acceptor_(ioc)
@@ -179,7 +177,7 @@ class listener : public std::enable_shared_from_this<listener>
179
177
}
180
178
181
179
// Allow address reuse
182
- acceptor_.set_option(net ::socket_base::reuse_address(true), ec);
180
+ acceptor_.set_option(asio ::socket_base::reuse_address(true), ec);
183
181
if(ec)
184
182
{
185
183
fail(ec, "set_option");
@@ -196,7 +194,7 @@ class listener : public std::enable_shared_from_this<listener>
196
194
197
195
// Start listening for connections
198
196
acceptor_.listen(
199
- net ::socket_base::max_listen_connections, ec);
197
+ asio ::socket_base::max_listen_connections, ec);
200
198
if(ec)
201
199
{
202
200
fail(ec, "listen");
@@ -217,7 +215,7 @@ class listener : public std::enable_shared_from_this<listener>
217
215
{
218
216
// The new connection gets its own strand
219
217
acceptor_.async_accept(
220
- net ::make_strand(ioc_),
218
+ asio ::make_strand(ioc_),
221
219
beast::bind_front_handler(
222
220
&listener::on_accept,
223
221
shared_from_this()));
@@ -254,12 +252,12 @@ int main(int argc, char* argv[])
254
252
" websocket-server-async 0.0.0.0 8080 1\n";
255
253
return EXIT_FAILURE;
256
254
}
257
- auto const address = net ::ip::make_address(argv[1]);
255
+ auto const address = asio ::ip::make_address(argv[1]);
258
256
auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
259
257
auto const threads = std::max<int>(1, std::atoi(argv[3]));
260
258
261
259
// The io_context is required for all I/O
262
- net ::io_context ioc{threads};
260
+ asio ::io_context ioc{threads};
263
261
264
262
// Create and launch a listening port
265
263
std::make_shared<listener>(ioc, tcp::endpoint{address, port})->run();
@@ -280,35 +278,152 @@ int main(int argc, char* argv[])
280
278
281
279
#endif
282
280
281
+ #include " test/unit/server.hpp"
283
282
#include < boost/asio/io_context.hpp>
284
283
#include < boost/asio/executor_work_guard.hpp>
284
+ #include < boost/beast/websocket/stream.hpp>
285
+ #include < boost/assert.hpp>
286
+ #include < boost/smart_ptr/enable_shared_from.hpp>
287
+ #include < memory>
285
288
#include < thread>
289
+ #include < utility>
290
+
291
+ #include " test_suite.hpp"
286
292
287
293
namespace boost {
288
294
namespace ws_io {
289
295
namespace test {
290
296
297
+ // ------------------------------------------------
298
+
299
+ template <class MF , class T , class ... Args0>
300
+ struct bind_wrapper
301
+ {
302
+ MF mf_;
303
+ boost::shared_ptr<T> self_;
304
+ // std::tuple<Args0...> args0_;
305
+
306
+ template <class ... Args>
307
+ void
308
+ operator ()(Args&&... args) const
309
+ {
310
+ (self_.get ()->*mf_)(std::forward<Args>(args)...);
311
+ }
312
+ };
313
+
314
+ template <class MF , class Arg0 , class ... Argn>
315
+ bind_wrapper<MF, Arg0, Argn...>
316
+ bind_front (
317
+ MF&& mf,
318
+ Arg0* arg0,
319
+ Argn&&... argn)
320
+ {
321
+ return bind_wrapper<MF, Arg0, Argn...>{ mf, shared_from (arg0) };
322
+ }
323
+
324
+ // ------------------------------------------------
325
+
326
+ class session
327
+ : public boost::enable_shared_from
328
+ {
329
+ beast::websocket::stream<socket_type> ws_;
330
+
331
+ public:
332
+ session (socket_type&& sock)
333
+ : ws_(std::move(sock))
334
+ {
335
+ }
336
+
337
+ void
338
+ run ()
339
+ {
340
+ ws_.async_accept (
341
+ bind_front (&session::on_accept, this ));
342
+ }
343
+
344
+ void
345
+ on_accept (
346
+ system::error_code ec)
347
+ {
348
+ if (! BOOST_TEST (! ec.failed ()))
349
+ return ;
350
+ BOOST_TEST_PASS ();
351
+
352
+ }
353
+ };
354
+
355
+ // ------------------------------------------------
356
+
357
+ /* * Connect two TCP sockets together.
358
+ */
359
+ template <class Executor >
360
+ bool
361
+ connect (
362
+ asio::basic_stream_socket<asio::ip::tcp, Executor>& s1,
363
+ asio::basic_stream_socket<asio::ip::tcp, Executor>& s2)
364
+
365
+ {
366
+ BOOST_ASSERT (s1.get_executor () == s2.get_executor ());
367
+ try
368
+ {
369
+ asio::basic_socket_acceptor<
370
+ asio::ip::tcp, Executor> a (s1.get_executor ());
371
+ auto ep = asio::ip::tcp::endpoint (
372
+ asio::ip::make_address_v4 (" 127.0.0.1" ), 0 );
373
+ a.open (ep.protocol ());
374
+ a.set_option (
375
+ asio::socket_base::reuse_address (true ));
376
+ a.bind (ep);
377
+ a.listen (0 );
378
+ ep = a.local_endpoint ();
379
+ a.async_accept (s2, success_handler ());
380
+ s1.async_connect (ep, success_handler ());
381
+ s1.get_executor ().context ().restart ();
382
+ s1.get_executor ().context ().run ();
383
+ if (! BOOST_TEST_EQ (s1.remote_endpoint (), s2.local_endpoint ()))
384
+ return false ;
385
+ if (! BOOST_TEST_EQ (s2.remote_endpoint (), s1.local_endpoint ()))
386
+ return false ;
387
+ }
388
+ catch (std::exception const &)
389
+ {
390
+ BOOST_TEST_FAIL ();
391
+ return false ;
392
+ }
393
+
394
+ return true ;
395
+ }
396
+
397
+ // ------------------------------------------------
398
+
291
399
struct server ::impl
292
400
{
293
401
asio::io_context ioc_;
294
- asio::executor_work_guard<
295
- asio::io_context::executor_type> wg_;
296
- std::thread t_;
297
402
298
403
impl ()
299
- : wg_(ioc_.get_executor())
300
- , t_(
301
- [&]
302
- {
303
- ioc_.run ();
304
- })
305
404
{
306
405
}
307
406
308
407
~impl ()
309
408
{
310
- wg_.reset ();
311
- t_.join ();
409
+ }
410
+
411
+ socket_type
412
+ connect ()
413
+ {
414
+ socket_type s0 (ioc_.get_executor ());
415
+ socket_type s1 (ioc_.get_executor ());
416
+ test::connect (s0, s1);
417
+ auto s = boost::make_shared<session>(std::move (s0));
418
+ s->run ();
419
+ return s1;
420
+ }
421
+
422
+ void
423
+ run ()
424
+ {
425
+ ioc_.restart ();
426
+ ioc_.run ();
312
427
}
313
428
};
314
429
@@ -324,6 +439,20 @@ server::
324
439
delete impl_;
325
440
}
326
441
442
+ socket_type
443
+ server::
444
+ connect ()
445
+ {
446
+ return impl_->connect ();
447
+ }
448
+
449
+ void
450
+ server::
451
+ run ()
452
+ {
453
+ return impl_->run ();
454
+ }
455
+
327
456
} // test
328
457
} // ws_io
329
458
} // boost
0 commit comments