Virtual Testbed
Ship dynamics simulator for extreme conditions
client.hh
1 #ifndef VTESTBED_SERVER_CLIENT_HH
2 #define VTESTBED_SERVER_CLIENT_HH
3 
4 #include <chrono>
5 #include <mutex>
6 
7 #include <unistdx/base/log_message>
8 #include <unistdx/io/poller>
9 #include <unistdx/net/socket>
10 
11 #include <vtestbed/core/testbed.hh>
12 #include <vtestbed/server/macros.hh>
13 #include <vtestbed/server/remote_client.hh>
14 
15 namespace vtb {
16 
17  namespace srv {
18 
19  template <class T>
20  class Client {
21 
22  private:
25  typedef clock_type::duration duration;
26  typedef clock_type::time_point time_point;
30 
31  private:
32  client_type _client;
33  sys::event_poller _poller;
34  testbed_type _testbed;
35  mutex_type _mutex;
36  bool _verbose = false;
38  duration _timeout = std::chrono::seconds(7);
39 
40  public:
41 
42  inline explicit
43  Client(const sys::socket_address& address):
44  _client(sys::socket(), address, false)
45  {}
46 
47  template <class Handler>
48  void
49  run(Handler handler) {
50  connect();
51  while (true) {
52  _poller.wait(_mutex);
53  for (const sys::epoll_event& ev : _poller) {
54  if (ev.fd() == _client.socket().fd()) {
55  if (ev.in()) {
56  _client.process(ev, _testbed);
57  handler.on_receive(_testbed);
58  }
59  if (ev.hup()) {
60  this->info("disconnect from _", _client.address());
61  _poller.erase(ev);
62  return;
63  }
64  }
65  }
66  if (_client.handshake()) {
67  handler.on_handshake(_client);
68  }
69  _client.flush();
70  }
71  }
72 
73  void
74  connect() {
75  this->info("connect to _", _client.address());
76  try {
77  _client.socket().connect(_client.address());
78  #if defined(UNISTDX_HAVE_TCP_USER_TIMEOUT)
79  VTB_WARN(_client.socket().set_user_timeout(_timeout));
80  #endif
81  } catch (const sys::bad_call& err) {
82  if (err.errc() != std::errc::operation_in_progress) {
83  throw;
84  }
85  }
86  _poller.emplace(_client.socket().fd(), sys::event::in);
87  _poller.notify_one();
88  }
89 
90  inline void
91  verbose(bool rhs) {
92  _verbose = rhs;
93  }
94 
95  inline bool
96  verbose() const noexcept {
97  return _verbose;
98  }
99 
101  inline testbed_type&
102  testbed() noexcept {
103  return _testbed;
104  }
105 
107  inline const testbed_type&
108  testbed() const noexcept {
109  return _testbed;
110  }
111 
112  inline void
113  push(const testbed_type& testbed) {
114  lock_type lock(_mutex);
115  _client.push(testbed);
116  _poller.notify_one();
117  }
118 
119  inline const client_type&
120  client() const noexcept {
121  return _client;
122  }
123 
124  inline client_type&
125  client() noexcept {
126  return _client;
127  }
128 
129  private:
130 
131  template <class ... Args>
132  inline void
133  info(const Args& ... args) {
134  sys::log_message("client", args ...);
135  }
136 
137  };
138 
139  }
140 
141 }
142 
143 #endif // vim:filetype=cpp
const testbed_type & testbed() const noexcept
Virtual testbed object received from the server.
Definition: client.hh:108
testbed_type & testbed() noexcept
Virtual testbed object received from the server.
Definition: client.hh:102
Main namespace.
Definition: convert.hh:9