Skip to content

Commit 437ed42

Browse files
committed
[FOLD]
1 parent a0feec0 commit 437ed42

File tree

4 files changed

+198
-22
lines changed

4 files changed

+198
-22
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ set(BOOST_WS_IO_DEPENDENCIES
6060
Boost::system
6161
Boost::url
6262
Boost::ws_proto
63+
Boost::http_io
6364
)
6465

6566
foreach (BOOST_WS_IO_DEPENDENCY ${BOOST_WS_IO_DEPENDENCIES})

test/unit/server.cpp

Lines changed: 150 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
// Official repository: https://github.com/boostorg/beast
88
//
99

10-
#include "server.hpp"
11-
1210
#if 0
1311

1412
#include <boost/beast/core.hpp>
@@ -61,7 +59,7 @@ class session : public std::enable_shared_from_this<session>
6159
// on the I/O objects in this session. Although not strictly necessary
6260
// for single-threaded contexts, this example code is written to be
6361
// thread-safe by default.
64-
net::dispatch(ws_.get_executor(),
62+
asio::dispatch(ws_.get_executor(),
6563
beast::bind_front_handler(
6664
&session::on_run,
6765
shared_from_this()));
@@ -158,12 +156,12 @@ class session : public std::enable_shared_from_this<session>
158156
// Accepts incoming connections and launches the sessions
159157
class listener : public std::enable_shared_from_this<listener>
160158
{
161-
net::io_context& ioc_;
159+
asio::io_context& ioc_;
162160
tcp::acceptor acceptor_;
163161

164162
public:
165163
listener(
166-
net::io_context& ioc,
164+
asio::io_context& ioc,
167165
tcp::endpoint endpoint)
168166
: ioc_(ioc)
169167
, acceptor_(ioc)
@@ -179,7 +177,7 @@ class listener : public std::enable_shared_from_this<listener>
179177
}
180178

181179
// 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);
183181
if(ec)
184182
{
185183
fail(ec, "set_option");
@@ -196,7 +194,7 @@ class listener : public std::enable_shared_from_this<listener>
196194

197195
// Start listening for connections
198196
acceptor_.listen(
199-
net::socket_base::max_listen_connections, ec);
197+
asio::socket_base::max_listen_connections, ec);
200198
if(ec)
201199
{
202200
fail(ec, "listen");
@@ -217,7 +215,7 @@ class listener : public std::enable_shared_from_this<listener>
217215
{
218216
// The new connection gets its own strand
219217
acceptor_.async_accept(
220-
net::make_strand(ioc_),
218+
asio::make_strand(ioc_),
221219
beast::bind_front_handler(
222220
&listener::on_accept,
223221
shared_from_this()));
@@ -254,12 +252,12 @@ int main(int argc, char* argv[])
254252
" websocket-server-async 0.0.0.0 8080 1\n";
255253
return EXIT_FAILURE;
256254
}
257-
auto const address = net::ip::make_address(argv[1]);
255+
auto const address = asio::ip::make_address(argv[1]);
258256
auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
259257
auto const threads = std::max<int>(1, std::atoi(argv[3]));
260258

261259
// The io_context is required for all I/O
262-
net::io_context ioc{threads};
260+
asio::io_context ioc{threads};
263261

264262
// Create and launch a listening port
265263
std::make_shared<listener>(ioc, tcp::endpoint{address, port})->run();
@@ -280,35 +278,152 @@ int main(int argc, char* argv[])
280278

281279
#endif
282280

281+
#include "test/unit/server.hpp"
283282
#include <boost/asio/io_context.hpp>
284283
#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>
285288
#include <thread>
289+
#include <utility>
290+
291+
#include "test_suite.hpp"
286292

287293
namespace boost {
288294
namespace ws_io {
289295
namespace test {
290296

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+
291399
struct server::impl
292400
{
293401
asio::io_context ioc_;
294-
asio::executor_work_guard<
295-
asio::io_context::executor_type> wg_;
296-
std::thread t_;
297402

298403
impl()
299-
: wg_(ioc_.get_executor())
300-
, t_(
301-
[&]
302-
{
303-
ioc_.run();
304-
})
305404
{
306405
}
307406

308407
~impl()
309408
{
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();
312427
}
313428
};
314429

@@ -324,6 +439,20 @@ server::
324439
delete impl_;
325440
}
326441

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+
327456
} // test
328457
} // ws_io
329458
} // boost

test/unit/server.hpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,50 @@
77
// Official repository: https://github.com/cppalliance/ws_io
88
//
99

10+
#include <boost/asio/ip/tcp.hpp>
11+
#include "test_suite.hpp"
12+
1013
namespace boost {
1114
namespace ws_io {
1215
namespace test {
1316

17+
//------------------------------------------------
18+
19+
using socket_type =
20+
asio::basic_stream_socket<
21+
asio::ip::tcp,
22+
asio::io_context::executor_type>;
23+
1424
class server
1525
{
1626
public:
1727
server();
1828
~server();
1929

30+
socket_type
31+
connect();
32+
33+
void
34+
run();
35+
2036
private:
2137
struct impl;
2238
impl* impl_;
2339
};
2440

41+
//------------------------------------------------
42+
43+
struct success_handler
44+
{
45+
bool pass = false;
46+
47+
void
48+
operator()(system::error_code ec, ...)
49+
{
50+
pass = BOOST_TEST(! ec.failed());
51+
}
52+
};
53+
2554
} // test
2655
} // ws_io
2756
} // boost

test/unit/stream.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
//
99

1010
#include <boost/ws_proto/handshake.hpp>
11+
#include <boost/http_proto/context.hpp>
12+
#include <boost/http_proto/response_parser.hpp>
13+
#include <boost/http_io/read.hpp>
14+
#include <boost/asio/write.hpp>
1115
#include "test/unit/server.hpp"
1216
#include "test_suite.hpp"
1317

@@ -24,7 +28,20 @@ struct stream_test
2428
void
2529
run()
2630
{
27-
auto req = ws_proto::make_upgrade("");
31+
test::server srv;
32+
auto sock = srv.connect();
33+
auto req = ws_proto::make_upgrade("/");
34+
asio::write(sock, asio::buffer(req.buffer()));
35+
srv.run();
36+
http_proto::context ctx;
37+
http_proto::parser::config_base cfg;
38+
http_proto::install_parser_service(ctx, cfg);
39+
http_proto::response_parser pr(ctx);
40+
pr.reset();
41+
pr.start();
42+
http_io::async_read_header(sock, pr, test::success_handler());
43+
srv.run();
44+
auto res = pr.get();
2845
}
2946
};
3047

0 commit comments

Comments
 (0)