asio_stream_adapter.h
1 // Copyright 2020, Beeri 15. All rights reserved.
2 // Author: Roman Gershman (romange@gmail.com)
3 //
4 
5 #pragma once
6 
7 #include <boost/asio/detail/buffer_sequence_adapter.hpp>
8 #include <boost/system/error_code.hpp>
9 #include "util/sync_stream_interface.h"
10 
11 namespace util {
12 
13 template <typename Socket = SyncStreamInterface> class AsioStreamAdapter {
14  Socket& s_;
15 
16  public:
17  using error_code = ::boost::system::error_code;
18 
19  explicit AsioStreamAdapter(Socket& s) : s_(s) {
20  }
21 
22  // Read/Write functions should be called from IoContext thread.
23  // (fiber) SyncRead interface:
24  // https://www.boost.org/doc/libs/1_69_0/doc/html/boost_asio/reference/SyncReadStream.html
25  template <typename MBS> size_t read_some(const MBS& bufs, error_code& ec);
26 
27  // To calm SyncReadStream compile-checker we provide exception-enabled
28  // interface without implementing it.
29  template <typename MBS> size_t read_some(const MBS& bufs);
30 
31  // SyncWrite interface:
32  // https://www.boost.org/doc/libs/1_69_0/doc/html/boost_asio/reference/SyncWriteStream.html
33  template <typename BS> size_t write_some(const BS& bufs, error_code& ec);
34 
35  // To calm SyncWriteStream compile-checker we provide exception-enabled
36  // interface without implementing it.
37  template <typename BS> size_t write_some(const BS& bufs);
38 };
39 
40 template <typename Socket>
41 template <typename MBS>
42 size_t AsioStreamAdapter<Socket>::read_some(const MBS& bufs, error_code& ec) {
43  using badapter = ::boost::asio::detail::buffer_sequence_adapter<
44  boost::asio::mutable_buffer, const MBS&>;
45  badapter bsa(bufs);
46 
47  auto res = s_.Recv(bsa.buffers(), bsa.count());
48  if (res)
49  return res.value();
50  ec = error_code(std::move(res.error()).value(), boost::system::system_category());
51 
52  return 0;
53 }
54 
55 template <typename Socket>
56 template <typename BS>
57 size_t AsioStreamAdapter<Socket>::write_some(const BS& bufs, error_code& ec) {
58  using badapter =
59  ::boost::asio::detail::buffer_sequence_adapter<boost::asio::const_buffer,
60  const BS&>;
61  badapter bsa(bufs);
62 
63  std::error_code lec;
64  auto res = s_.Send(bsa.buffers(), bsa.count());
65  if (res) {
66  return res.value();
67  }
68  ec = error_code(std::move(res.error()).value(), boost::system::system_category());
69 
70  return 0;
71 }
72 
73 } // namespace util