fiber_socket.h
1 // Copyright 2020, Beeri 15. All rights reserved.
2 // Author: Roman Gershman (romange@gmail.com)
3 //
4 
5 #pragma once
6 
7 #include <liburing/io_uring.h>
8 
9 // for tcp::endpoint. Consider introducing our own.
10 #include <boost/asio/buffer.hpp>
11 #include <boost/asio/ip/tcp.hpp>
12 
13 #include "absl/base/attributes.h"
14 #include "util/sync_stream_interface.h"
15 
16 namespace util {
17 namespace uring {
18 
19 class Proactor;
20 
22  FiberSocket(const FiberSocket&) = delete;
23  void operator=(const FiberSocket&) = delete;
24 
25  explicit FiberSocket(int fd) : fd_(fd) {
26  }
27 
28  public:
29  using native_handle_type = int;
30  using endpoint_type = ::boost::asio::ip::tcp::endpoint;
31  using error_code = std::error_code;
32  using expected_size_t = nonstd::expected<size_t, error_code>;
33 
34  FiberSocket() : fd_(-1), p_(nullptr) {
35  }
36 
37  FiberSocket(FiberSocket&& other) noexcept : fd_(other.fd_), p_(other.p_) {
38  other.fd_ = -1;
39  other.p_ = nullptr;
40  }
41 
42  virtual ~FiberSocket();
43 
44  FiberSocket& operator=(FiberSocket&& other) noexcept;
45 
46  // sock_opts are the bit mask of sockopt values shifted left, i.e.
47  // (1 << SO_REUSEADDR) | (1 << SO_DONTROUTE), for example.
48  ABSL_MUST_USE_RESULT error_code Listen(unsigned port, unsigned backlog,
49  uint32_t sock_opts_mask = 0);
50 
51  ABSL_MUST_USE_RESULT error_code Accept(FiberSocket* peer);
52 
53  ABSL_MUST_USE_RESULT error_code Connect(const endpoint_type& ep);
54 
55  ABSL_MUST_USE_RESULT error_code Shutdown(int how);
56 
57  ABSL_MUST_USE_RESULT error_code Close();
58 
59  // Really need here expected.
60  expected_size_t Send(const iovec* ptr, size_t len) override;
61 
62  expected_size_t Send(const boost::asio::const_buffer& b) {
63  iovec v{const_cast<void*>(b.data()), b.size()};
64  return Send(&v, 1);
65  }
66 
67  expected_size_t Recv(iovec* ptr, size_t len) override;
68 
69  expected_size_t Recv(const boost::asio::mutable_buffer& mb) {
70  iovec v{mb.data(), mb.size()};
71  return Recv(&v, 1);
72  }
73 
74  native_handle_type native_handle() const {
75  return fd_ & FD_MASK;
76  }
77 
79  void Detach() {
80  fd_ = -1;
81  }
82 
83  endpoint_type LocalEndpoint() const;
84  endpoint_type RemoteEndpoint() const;
85 
87  // just that the file descriptor is valid and its state is open.
88  bool IsOpen() const {
89  return fd_ >= 0 && (fd_ & IS_SHUTDOWN) == 0;
90  }
91 
92  void set_proactor(Proactor* p) { p_ = p;}
93 
94  Proactor* proactor() { return p_; }
95 
96  static bool IsConnClosed(const error_code& ec) {
97  return (ec == std::errc::connection_aborted) || (ec == std::errc::connection_reset);
98  }
99 
100  private:
101  // Gives me 512M descriptors.
102  enum { FD_MASK = 0x1fffffff };
103  enum { IS_SHUTDOWN = 0x20000000 };
104 
105  int32_t fd_;
106 
107  // We must reference proactor in each socket so that we could support write_some/read_some
108  // with predefined interfance and be compliant with SyncWriteStream/SyncReadStream concepts.
109  Proactor* p_;
110 };
111 
112 } // namespace uring
113 } // namespace util
bool IsOpen() const
IsOpen does not promise that the socket is TCP connected or live,.
Definition: fiber_socket.h:88
void Detach()
Removes the ownership over file descriptor. Use with caution.
Definition: fiber_socket.h:79