rippled
short_read_test.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4 
5  Copyright 2014 Ripple Labs Inc.
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #include <ripple/basics/make_SSLContext.h>
21 #include <ripple/beast/core/CurrentThreadName.h>
22 #include <ripple/beast/unit_test.h>
23 #include <test/jtx/envconfig.h>
24 
25 #include <boost/asio.hpp>
26 #include <boost/asio/ssl.hpp>
27 #include <boost/utility/in_place_factory.hpp>
28 
29 #include <cassert>
30 #include <condition_variable>
31 #include <functional>
32 #include <memory>
33 #include <optional>
34 #include <thread>
35 #include <utility>
36 
37 namespace ripple {
38 /*
39 
40 Findings from the test:
41 
42 If the remote host calls async_shutdown then the local host's
43 async_read will complete with eof.
44 
45 If both hosts call async_shutdown then the calls to async_shutdown
46 will complete with eof.
47 
48 */
49 
50 class short_read_test : public beast::unit_test::suite
51 {
52 private:
53  using io_context_type = boost::asio::io_context;
54  using strand_type = boost::asio::io_context::strand;
55  using timer_type =
56  boost::asio::basic_waitable_timer<std::chrono::steady_clock>;
57  using acceptor_type = boost::asio::ip::tcp::acceptor;
58  using socket_type = boost::asio::ip::tcp::socket;
59  using stream_type = boost::asio::ssl::stream<socket_type&>;
60  using error_code = boost::system::error_code;
61  using endpoint_type = boost::asio::ip::tcp::endpoint;
62  using address_type = boost::asio::ip::address;
63 
69 
70  template <class Streambuf>
71  static void
72  write(Streambuf& sb, std::string const& s)
73  {
74  using boost::asio::buffer;
75  using boost::asio::buffer_copy;
76  using boost::asio::buffer_size;
77  boost::asio::const_buffers_1 buf(s.data(), s.size());
78  sb.commit(buffer_copy(sb.prepare(buffer_size(buf)), buf));
79  }
80 
81  //--------------------------------------------------------------------------
82 
83  class Base
84  {
85  protected:
86  class Child
87  {
88  private:
90 
91  public:
92  explicit Child(Base& base) : base_(base)
93  {
94  }
95 
96  virtual ~Child()
97  {
98  base_.remove(this);
99  }
100 
101  virtual void
102  close() = 0;
103  };
104 
105  private:
109  bool closed_ = false;
110 
111  public:
113  {
114  // Derived class must call wait() in the destructor
115  assert(list_.empty());
116  }
117 
118  void
120  {
121  std::lock_guard lock(mutex_);
122  list_.emplace(child.get(), child);
123  }
124 
125  void
126  remove(Child* child)
127  {
128  std::lock_guard lock(mutex_);
129  list_.erase(child);
130  if (list_.empty())
131  cond_.notify_one();
132  }
133 
134  void
136  {
138  {
139  std::lock_guard lock(mutex_);
140  v.reserve(list_.size());
141  if (closed_)
142  return;
143  closed_ = true;
144  for (auto const& c : list_)
145  {
146  if (auto p = c.second.lock())
147  {
148  p->close();
149  // Must destroy shared_ptr outside the
150  // lock otherwise deadlock from the
151  // managed object's destructor.
152  v.emplace_back(std::move(p));
153  }
154  }
155  }
156  }
157 
158  void
160  {
162  while (!list_.empty())
163  cond_.wait(lock);
164  }
165  };
166 
167  //--------------------------------------------------------------------------
168 
169  class Server : public Base
170  {
171  private:
174 
175  struct Acceptor : Child, std::enable_shared_from_this<Acceptor>
176  {
182 
183  explicit Acceptor(Server& server)
184  : Child(server)
185  , server_(server)
186  , test_(server_.test_)
187  , acceptor_(
190  beast::IP::Address::from_string(
191  test::getEnvLocalhostAddr()),
192  0))
195  {
196  acceptor_.listen();
197  server_.endpoint_ = acceptor_.local_endpoint();
198  test_.log << "[server] up on port: " << server_.endpoint_.port()
199  << std::endl;
200  }
201 
202  void
203  close() override
204  {
205  if (!strand_.running_in_this_thread())
206  return post(
207  strand_,
209  acceptor_.close();
210  }
211 
212  void
213  run()
214  {
215  acceptor_.async_accept(
216  socket_,
217  bind_executor(
218  strand_,
219  std::bind(
222  std::placeholders::_1)));
223  }
224 
225  void
226  fail(std::string const& what, error_code ec)
227  {
228  if (acceptor_.is_open())
229  {
230  if (ec != boost::asio::error::operation_aborted)
231  test_.log << what << ": " << ec.message() << std::endl;
232  acceptor_.close();
233  }
234  }
235 
236  void
238  {
239  if (ec)
240  return fail("accept", ec);
241  auto const p =
242  std::make_shared<Connection>(server_, std::move(socket_));
243  server_.add(p);
244  p->run();
245  acceptor_.async_accept(
246  socket_,
247  bind_executor(
248  strand_,
249  std::bind(
252  std::placeholders::_1)));
253  }
254  };
255 
256  struct Connection : Child, std::enable_shared_from_this<Connection>
257  {
264  boost::asio::streambuf buf_;
265 
266  Connection(Server& server, socket_type&& socket)
267  : Child(server)
268  , server_(server)
269  , test_(server_.test_)
270  , socket_(std::move(socket))
274  {
275  }
276 
277  void
278  close() override
279  {
280  if (!strand_.running_in_this_thread())
281  return post(
282  strand_,
284  if (socket_.is_open())
285  {
286  socket_.close();
287  timer_.cancel();
288  }
289  }
290 
291  void
292  run()
293  {
294  timer_.expires_from_now(std::chrono::seconds(3));
295  timer_.async_wait(bind_executor(
296  strand_,
297  std::bind(
300  std::placeholders::_1)));
301  stream_.async_handshake(
302  stream_type::server,
303  bind_executor(
304  strand_,
305  std::bind(
308  std::placeholders::_1)));
309  }
310 
311  void
312  fail(std::string const& what, error_code ec)
313  {
314  if (socket_.is_open())
315  {
316  if (ec != boost::asio::error::operation_aborted)
317  test_.log << "[server] " << what << ": " << ec.message()
318  << std::endl;
319  socket_.close();
320  timer_.cancel();
321  }
322  }
323 
324  void
326  {
327  if (ec == boost::asio::error::operation_aborted)
328  return;
329  if (ec)
330  return fail("timer", ec);
331  test_.log << "[server] timeout" << std::endl;
332  socket_.close();
333  }
334 
335  void
337  {
338  if (ec)
339  return fail("handshake", ec);
340 #if 1
341  boost::asio::async_read_until(
342  stream_,
343  buf_,
344  "\n",
345  bind_executor(
346  strand_,
347  std::bind(
350  std::placeholders::_1,
351  std::placeholders::_2)));
352 #else
353  close();
354 #endif
355  }
356 
357  void
358  on_read(error_code ec, std::size_t bytes_transferred)
359  {
360  if (ec == boost::asio::error::eof)
361  {
362  server_.test_.log << "[server] read: EOF" << std::endl;
363  return stream_.async_shutdown(bind_executor(
364  strand_,
365  std::bind(
368  std::placeholders::_1)));
369  }
370  if (ec)
371  return fail("read", ec);
372 
373  buf_.commit(bytes_transferred);
374  buf_.consume(bytes_transferred);
375  write(buf_, "BYE\n");
376  boost::asio::async_write(
377  stream_,
378  buf_.data(),
379  bind_executor(
380  strand_,
381  std::bind(
384  std::placeholders::_1,
385  std::placeholders::_2)));
386  }
387 
388  void
389  on_write(error_code ec, std::size_t bytes_transferred)
390  {
391  buf_.consume(bytes_transferred);
392  if (ec)
393  return fail("write", ec);
394  stream_.async_shutdown(bind_executor(
395  strand_,
396  std::bind(
399  std::placeholders::_1)));
400  }
401 
402  void
404  {
405  if (ec)
406  return fail("shutdown", ec);
407  socket_.close();
408  timer_.cancel();
409  }
410  };
411 
412  public:
413  explicit Server(short_read_test& test) : test_(test)
414  {
415  auto const p = std::make_shared<Acceptor>(*this);
416  add(p);
417  p->run();
418  }
419 
421  {
422  close();
423  wait();
424  }
425 
426  endpoint_type const&
427  endpoint() const
428  {
429  return endpoint_;
430  }
431  };
432 
433  //--------------------------------------------------------------------------
434  class Client : public Base
435 
436  {
437  private:
439 
440  struct Connection : Child, std::enable_shared_from_this<Connection>
441  {
448  boost::asio::streambuf buf_;
450 
451  Connection(Client& client, endpoint_type const& ep)
452  : Child(client)
453  , client_(client)
454  , test_(client_.test_)
459  , ep_(ep)
460  {
461  }
462 
463  void
464  close() override
465  {
466  if (!strand_.running_in_this_thread())
467  return post(
468  strand_,
470  if (socket_.is_open())
471  {
472  socket_.close();
473  timer_.cancel();
474  }
475  }
476 
477  void
478  run(endpoint_type const& ep)
479  {
480  timer_.expires_from_now(std::chrono::seconds(3));
481  timer_.async_wait(bind_executor(
482  strand_,
483  std::bind(
486  std::placeholders::_1)));
487  socket_.async_connect(
488  ep,
489  bind_executor(
490  strand_,
491  std::bind(
494  std::placeholders::_1)));
495  }
496 
497  void
498  fail(std::string const& what, error_code ec)
499  {
500  if (socket_.is_open())
501  {
502  if (ec != boost::asio::error::operation_aborted)
503  test_.log << "[client] " << what << ": " << ec.message()
504  << std::endl;
505  socket_.close();
506  timer_.cancel();
507  }
508  }
509 
510  void
512  {
513  if (ec == boost::asio::error::operation_aborted)
514  return;
515  if (ec)
516  return fail("timer", ec);
517  test_.log << "[client] timeout";
518  socket_.close();
519  }
520 
521  void
523  {
524  if (ec)
525  return fail("connect", ec);
526  stream_.async_handshake(
527  stream_type::client,
528  bind_executor(
529  strand_,
530  std::bind(
533  std::placeholders::_1)));
534  }
535 
536  void
538  {
539  if (ec)
540  return fail("handshake", ec);
541  write(buf_, "HELLO\n");
542 
543 #if 1
544  boost::asio::async_write(
545  stream_,
546  buf_.data(),
547  bind_executor(
548  strand_,
549  std::bind(
552  std::placeholders::_1,
553  std::placeholders::_2)));
554 #else
555  stream_.async_shutdown(bind_executor(
556  strand_,
557  std::bind(
560  std::placeholders::_1)));
561 #endif
562  }
563 
564  void
565  on_write(error_code ec, std::size_t bytes_transferred)
566  {
567  buf_.consume(bytes_transferred);
568  if (ec)
569  return fail("write", ec);
570 #if 1
571  boost::asio::async_read_until(
572  stream_,
573  buf_,
574  "\n",
575  bind_executor(
576  strand_,
577  std::bind(
580  std::placeholders::_1,
581  std::placeholders::_2)));
582 #else
583  stream_.async_shutdown(bind_executor(
584  strand_,
585  std::bind(
588  std::placeholders::_1)));
589 #endif
590  }
591 
592  void
593  on_read(error_code ec, std::size_t bytes_transferred)
594  {
595  if (ec)
596  return fail("read", ec);
597  buf_.commit(bytes_transferred);
598  stream_.async_shutdown(bind_executor(
599  strand_,
600  std::bind(
603  std::placeholders::_1)));
604  }
605 
606  void
608  {
609  if (ec)
610  return fail("shutdown", ec);
611  socket_.close();
612  timer_.cancel();
613  }
614  };
615 
616  public:
617  Client(short_read_test& test, endpoint_type const& ep) : test_(test)
618  {
619  auto const p = std::make_shared<Connection>(*this, ep);
620  add(p);
621  p->run(ep);
622  }
623 
625  {
626  close();
627  wait();
628  }
629  };
630 
631 public:
633  : work_(io_context_.get_executor())
634  , thread_(std::thread([this]() {
635  beast::setCurrentThreadName("io_context");
636  this->io_context_.run();
637  }))
639  {
640  }
641 
643  {
644  work_.reset();
645  thread_.join();
646  }
647 
648  void
649  run() override
650  {
651  Server s(*this);
652  Client c(*this, s.endpoint());
653  c.wait();
654  pass();
655  }
656 };
657 
658 BEAST_DEFINE_TESTSUITE(short_read, overlay, ripple);
659 
660 } // namespace ripple
ripple::short_read_test::Client::Client
Client(short_read_test &test, endpoint_type const &ep)
Definition: short_read_test.cpp:617
ripple::short_read_test::Base::mutex_
std::mutex mutex_
Definition: short_read_test.cpp:106
ripple::short_read_test::Client::Connection::fail
void fail(std::string const &what, error_code ec)
Definition: short_read_test.cpp:498
ripple::short_read_test::Client::Connection::timer_
timer_type timer_
Definition: short_read_test.cpp:447
ripple::short_read_test
Definition: short_read_test.cpp:50
std::bind
T bind(T... args)
ripple::short_read_test::Server::Connection
Definition: short_read_test.cpp:256
std::string
STL class.
ripple::short_read_test::Server
Definition: short_read_test.cpp:169
std::shared_ptr< boost::asio::ssl::context >
ripple::short_read_test::Client::Connection::on_handshake
void on_handshake(error_code ec)
Definition: short_read_test.cpp:537
ripple::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(AccountTxPaging, app, ripple)
utility
ripple::short_read_test::Server::Acceptor::Acceptor
Acceptor(Server &server)
Definition: short_read_test.cpp:183
ripple::short_read_test::Client::~Client
~Client()
Definition: short_read_test.cpp:624
ripple::short_read_test::Server::Acceptor::strand_
strand_type strand_
Definition: short_read_test.cpp:181
ripple::short_read_test::Client::Connection::test_
short_read_test & test_
Definition: short_read_test.cpp:443
functional
ripple::short_read_test::Server::Acceptor::close
void close() override
Definition: short_read_test.cpp:203
ripple::short_read_test::timer_type
boost::asio::basic_waitable_timer< std::chrono::steady_clock > timer_type
Definition: short_read_test.cpp:56
ripple::short_read_test::Server::Connection::on_handshake
void on_handshake(error_code ec)
Definition: short_read_test.cpp:336
std::vector::reserve
T reserve(T... args)
ripple::short_read_test::Server::Acceptor::on_accept
void on_accept(error_code ec)
Definition: short_read_test.cpp:237
ripple::short_read_test::Server::Connection::fail
void fail(std::string const &what, error_code ec)
Definition: short_read_test.cpp:312
std::vector
STL class.
ripple::short_read_test::error_code
boost::system::error_code error_code
Definition: short_read_test.cpp:60
std::string::size
T size(T... args)
ripple::short_read_test::work_
std::optional< boost::asio::executor_work_guard< boost::asio::executor > > work_
Definition: short_read_test.cpp:66
ripple::make_SSLContext
std::shared_ptr< boost::asio::ssl::context > make_SSLContext(std::string const &cipherList)
Create a self-signed SSL context that allows anonymous Diffie Hellman.
Definition: make_SSLContext.cpp:400
ripple::short_read_test::thread_
std::thread thread_
Definition: short_read_test.cpp:67
ripple::short_read_test::Client::Connection::on_timer
void on_timer(error_code ec)
Definition: short_read_test.cpp:511
ripple::short_read_test::endpoint_type
boost::asio::ip::tcp::endpoint endpoint_type
Definition: short_read_test.cpp:61
std::chrono::seconds
ripple::short_read_test::Client::test_
short_read_test & test_
Definition: short_read_test.cpp:438
ripple::short_read_test::Server::Acceptor::test_
short_read_test & test_
Definition: short_read_test.cpp:178
ripple::short_read_test::Client::Connection::stream_
stream_type stream_
Definition: short_read_test.cpp:445
ripple::short_read_test::socket_type
boost::asio::ip::tcp::socket socket_type
Definition: short_read_test.cpp:58
std::lock_guard
STL class.
ripple::short_read_test::Base::remove
void remove(Child *child)
Definition: short_read_test.cpp:126
ripple::short_read_test::Base::Child
Definition: short_read_test.cpp:86
ripple::from_string
bool from_string(RangeSet< T > &rs, std::string const &s)
Convert the given styled string to a RangeSet.
Definition: RangeSet.h:123
ripple::short_read_test::context_
std::shared_ptr< boost::asio::ssl::context > context_
Definition: short_read_test.cpp:68
ripple::short_read_test::Base::~Base
~Base()
Definition: short_read_test.cpp:112
ripple::short_read_test::Server::Connection::Connection
Connection(Server &server, socket_type &&socket)
Definition: short_read_test.cpp:266
ripple::short_read_test::strand_type
boost::asio::io_context::strand strand_type
Definition: short_read_test.cpp:54
ripple::short_read_test::Server::Acceptor
Definition: short_read_test.cpp:175
std::optional::reset
T reset(T... args)
ripple::short_read_test::Base::cond_
std::condition_variable cond_
Definition: short_read_test.cpp:107
ripple::short_read_test::Client::Connection::on_connect
void on_connect(error_code ec)
Definition: short_read_test.cpp:522
ripple::short_read_test::Base::Child::base_
Base & base_
Definition: short_read_test.cpp:89
ripple::short_read_test::Server::Connection::on_write
void on_write(error_code ec, std::size_t bytes_transferred)
Definition: short_read_test.cpp:389
ripple::short_read_test::Server::Acceptor::server_
Server & server_
Definition: short_read_test.cpp:177
ripple::short_read_test::Server::endpoint_
endpoint_type endpoint_
Definition: short_read_test.cpp:173
ripple::short_read_test::Server::Connection::server_
Server & server_
Definition: short_read_test.cpp:258
std::enable_shared_from_this< Acceptor >::shared_from_this
T shared_from_this(T... args)
ripple::short_read_test::Server::Acceptor::acceptor_
acceptor_type acceptor_
Definition: short_read_test.cpp:179
thread
ripple::short_read_test::Server::Connection::timer_
timer_type timer_
Definition: short_read_test.cpp:263
ripple::short_read_test::Server::Connection::socket_
socket_type socket_
Definition: short_read_test.cpp:260
ripple::short_read_test::Server::Connection::close
void close() override
Definition: short_read_test.cpp:278
ripple::short_read_test::Client::Connection::client_
Client & client_
Definition: short_read_test.cpp:442
std::unique_lock
STL class.
ripple::short_read_test::write
static void write(Streambuf &sb, std::string const &s)
Definition: short_read_test.cpp:72
ripple::short_read_test::Base::add
void add(std::shared_ptr< Child > const &child)
Definition: short_read_test.cpp:119
std::enable_shared_from_this
ripple::short_read_test::Base::Child::Child
Child(Base &base)
Definition: short_read_test.cpp:92
ripple::short_read_test::Server::Acceptor::run
void run()
Definition: short_read_test.cpp:213
ripple::short_read_test::Server::endpoint
endpoint_type const & endpoint() const
Definition: short_read_test.cpp:427
ripple::short_read_test::Server::Connection::on_shutdown
void on_shutdown(error_code ec)
Definition: short_read_test.cpp:403
ripple::short_read_test::Client::Connection::on_read
void on_read(error_code ec, std::size_t bytes_transferred)
Definition: short_read_test.cpp:593
ripple::short_read_test::Base::Child::~Child
virtual ~Child()
Definition: short_read_test.cpp:96
ripple::short_read_test::Client::Connection
Definition: short_read_test.cpp:440
std::condition_variable::wait
T wait(T... args)
ripple::short_read_test::Client::Connection::run
void run(endpoint_type const &ep)
Definition: short_read_test.cpp:478
ripple::short_read_test::Base::closed_
bool closed_
Definition: short_read_test.cpp:109
std::map
STL class.
memory
ripple::short_read_test::Server::Server
Server(short_read_test &test)
Definition: short_read_test.cpp:413
ripple::short_read_test::Client::Connection::on_shutdown
void on_shutdown(error_code ec)
Definition: short_read_test.cpp:607
std::condition_variable::notify_one
T notify_one(T... args)
ripple::short_read_test::Client::Connection::on_write
void on_write(error_code ec, std::size_t bytes_transferred)
Definition: short_read_test.cpp:565
ripple::short_read_test::Client::Connection::buf_
boost::asio::streambuf buf_
Definition: short_read_test.cpp:448
ripple::short_read_test::address_type
boost::asio::ip::address address_type
Definition: short_read_test.cpp:62
ripple::short_read_test::~short_read_test
~short_read_test()
Definition: short_read_test.cpp:642
ripple::short_read_test::Server::Acceptor::fail
void fail(std::string const &what, error_code ec)
Definition: short_read_test.cpp:226
beast::setCurrentThreadName
void setCurrentThreadName(std::string_view name)
Changes the name of the caller thread.
Definition: CurrentThreadName.cpp:119
std::vector::emplace_back
T emplace_back(T... args)
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::short_read_test::Client::Connection::ep_
endpoint_type const & ep_
Definition: short_read_test.cpp:449
ripple::short_read_test::Server::Acceptor::socket_
socket_type socket_
Definition: short_read_test.cpp:180
ripple::short_read_test::Base::list_
std::map< Child *, std::weak_ptr< Child > > list_
Definition: short_read_test.cpp:108
ripple::short_read_test::Client::Connection::close
void close() override
Definition: short_read_test.cpp:464
std::endl
T endl(T... args)
ripple::short_read_test::Server::Connection::buf_
boost::asio::streambuf buf_
Definition: short_read_test.cpp:264
ripple::short_read_test::acceptor_type
boost::asio::ip::tcp::acceptor acceptor_type
Definition: short_read_test.cpp:57
ripple::short_read_test::Server::~Server
~Server()
Definition: short_read_test.cpp:420
std
STL namespace.
cassert
ripple::short_read_test::Server::Connection::strand_
strand_type strand_
Definition: short_read_test.cpp:262
condition_variable
ripple::short_read_test::Server::Connection::on_read
void on_read(error_code ec, std::size_t bytes_transferred)
Definition: short_read_test.cpp:358
ripple::short_read_test::Base::wait
void wait()
Definition: short_read_test.cpp:159
ripple::short_read_test::run
void run() override
Definition: short_read_test.cpp:649
ripple::short_read_test::Client::Connection::Connection
Connection(Client &client, endpoint_type const &ep)
Definition: short_read_test.cpp:451
optional
std::mutex
STL class.
std::size_t
ripple::short_read_test::io_context_type
boost::asio::io_context io_context_type
Definition: short_read_test.cpp:53
ripple::short_read_test::Server::test_
short_read_test & test_
Definition: short_read_test.cpp:172
ripple::short_read_test::Client
Definition: short_read_test.cpp:434
ripple::short_read_test::Server::Connection::on_timer
void on_timer(error_code ec)
Definition: short_read_test.cpp:325
ripple::short_read_test::Base::Child::close
virtual void close()=0
ripple::short_read_test::Base::close
void close()
Definition: short_read_test.cpp:135
ripple::short_read_test::short_read_test
short_read_test()
Definition: short_read_test.cpp:632
ripple::short_read_test::Client::Connection::strand_
strand_type strand_
Definition: short_read_test.cpp:446
ripple::short_read_test::Base
Definition: short_read_test.cpp:83
std::string::data
T data(T... args)
ripple::short_read_test::io_context_
io_context_type io_context_
Definition: short_read_test.cpp:64
ripple::short_read_test::Server::Connection::run
void run()
Definition: short_read_test.cpp:292
ripple::short_read_test::stream_type
boost::asio::ssl::stream< socket_type & > stream_type
Definition: short_read_test.cpp:59
ripple::short_read_test::Server::Connection::test_
short_read_test & test_
Definition: short_read_test.cpp:259
ripple::short_read_test::Server::Connection::stream_
stream_type stream_
Definition: short_read_test.cpp:261
std::thread::join
T join(T... args)
ripple::short_read_test::Client::Connection::socket_
socket_type socket_
Definition: short_read_test.cpp:444
beast
Definition: base_uint.h:654