accept_server.h
1 // Copyright 2018, Beeri 15. All rights reserved.
2 // Author: Roman Gershman (romange@gmail.com)
3 //
4 
5 #pragma once
6 
7 #include <tuple>
8 
9 #include <boost/asio/ip/tcp.hpp>
10 #include <boost/asio/signal_set.hpp>
11 
12 #include "util/asio/connection_handler.h"
13 #include "util/fibers/fibers_ext.h"
14 
15 namespace util {
16 
17 class IoContextPool;
18 class IoContext;
19 
20 class AcceptServer {
21  public:
22  typedef ::boost::asio::io_context io_context;
23 
24  explicit AcceptServer(IoContextPool* pool);
25  ~AcceptServer();
26 
27  void Run();
28 
29  // Does not wait for the server to stop.
30  // You need to run Wait() to wait for proper shutdown.
31  void Stop(bool wait = false) {
32  // No need to close acceptor because signals.cancel will trigger its callback that
33  // will close it anyway.
34  signals_.cancel();
35  if (wait)
36  Wait();
37  }
38 
39  void Wait();
40 
41  // Returns the port number to which the listener was bound.
42  unsigned short AddListener(unsigned short port, ListenerInterface* cf);
43 
44  void TriggerOnBreakSignal(std::function<void()> f) { on_break_hook_ = std::move(f); }
45 
46  private:
47  using acceptor = ::boost::asio::ip::tcp::acceptor;
48  using endpoint = ::boost::asio::ip::tcp::endpoint;
49  struct ListenerWrapper;
50 
51  void AcceptInIOThread(ListenerWrapper* listener);
52 
53  // Should really be std::expected or std::experimental::fundamental_v3::expected
54  // when upgrade the compiler.
55  typedef std::tuple<ConnectionHandler*, ::boost::system::error_code>
56  AcceptResult;
57 
58  AcceptResult AcceptConnection(ListenerWrapper* listener);
59 
60  IoContextPool* pool_;
61 
62  struct ListenerWrapper {
63  IoContext& io_context;
64  ::boost::asio::ip::tcp::acceptor acceptor;
65  ListenerInterface* listener;
66  unsigned short port;
67 
68  ListenerWrapper(const endpoint& ep, IoContext* io_context,
69  ListenerInterface* si);
70  };
71 
72  ::boost::asio::signal_set signals_;
74  std::vector<ListenerWrapper> listeners_;
75 
76  // Called if a termination signal has been caught (SIGTERM/SIGINT).
77  std::function<void()> on_break_hook_;
78  bool was_run_ = false;
79 };
80 
81 } // namespace util
Abstracts away connections implementation and their life-cycle.
A pool of IoContext objects, representing and managing CPU resources of the system.