aegis.cpp
 All Classes Functions Variables Typedefs Enumerations Enumerator Friends Pages
shard.hpp
1 //
2 // shard.hpp
3 // *********
4 //
5 // Copyright (c) 2019 Sharon W (sharon at aegis dot gg)
6 //
7 // Distributed under the MIT License. (See accompanying file LICENSE)
8 //
9 
10 #pragma once
11 
12 #include "aegis/config.hpp"
13 #include "aegis/utility.hpp"
14 #include "aegis/fwd.hpp"
15 #include <memory>
16 #include <map>
17 #include <string>
18 #include <chrono>
19 #include <stdint.h>
20 #include <asio/io_context.hpp>
21 #ifdef WIN32
22 # include "aegis/push.hpp"
23 #endif
24 #include <websocketpp/config/asio_client.hpp>
25 #include <websocketpp/common/connection_hdl.hpp>
26 #include <websocketpp/client.hpp>
27 #ifdef WIN32
28 # include "aegis/pop.hpp"
29 #endif
30 #include <spdlog/fmt/fmt.h>
31 #include "aegis/zstr/zstr.hpp"
32 #include "aegis/gateway/objects/presence.hpp"
33 #include "aegis/gateway/objects/activity.hpp"
34 
35 namespace aegis
36 {
37 
38 namespace shards
39 {
40 
42 class shard
43 {
44 public:
46  using connection_ptr = websocketpp::client<websocketpp::config::asio_tls_client>::connection_type::ptr;
47 
49  AEGIS_DECL shard(asio::io_context & _io, websocketpp::client<websocketpp::config::asio_tls_client> & _ws, int32_t id);
50 
52  AEGIS_DECL void do_reset(shard_status _status = shard_status::closed) noexcept;
53 
55 
58  int64_t get_sequence() const noexcept
59  {
60  return _sequence;
61  }
62 
64 
68  int32_t get_id() const noexcept
69  {
70  return _id;
71  }
72 
74 
77  AEGIS_DECL bool is_connected() const noexcept;
78 
80 
83  AEGIS_DECL bool is_online() const noexcept;
84 
86 
90  AEGIS_DECL void send(const std::string & payload, websocketpp::frame::opcode::value op = websocketpp::frame::opcode::text);
91 
93  AEGIS_DECL void send_now(const std::string & payload, websocketpp::frame::opcode::value op = websocketpp::frame::opcode::text);
94 
96 
99  std::string get_transfer_str() const noexcept
100  {
101  return utility::format_bytes(transfer_bytes);
102  }
103 
105 
110  std::string get_transfer_u_str() const noexcept
111  {
112  return utility::format_bytes(transfer_bytes_u);
113  }
114 
117 
120  uint64_t get_transfer() const noexcept
121  {
122  return transfer_bytes;
123  }
124 
127 
130  uint64_t get_transfer_u() const noexcept
131  {
132  return transfer_bytes_u;
133  }
134 
136  struct
137  {
138  int64_t messages;
139  int64_t presence_changes;
140  int64_t reconnects;
141  } counters = { 0,0,0 };
142 
144  AEGIS_DECL void connect();
145 
147 
150  AEGIS_DECL std::string uptime_str() const noexcept
151  {
152  return utility::uptime_str(_ready_time);
153  }
154 
156 
159  int64_t uptime() const noexcept
160  {
161  return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - _ready_time).count();
162  }
163 
164  void set_heartbeat(std::function<void(const asio::error_code &, const std::chrono::milliseconds, shard *)> fnkeepalive)
165  {
166  keepalivefunc = fnkeepalive;
167  }
168 
169  AEGIS_DECL void start_heartbeat(int32_t heartbeat) noexcept;
170 
171 #if defined(AEGIS_DEBUG_HISTORY)
172  std::deque<std::tuple<std::chrono::steady_clock::time_point, std::string>> debug_messages;
173 #endif
174  asio::steady_timer keepalivetimer;
175  asio::steady_timer delayedauth;
176  asio::steady_timer write_timer;
177 
178  std::queue<std::tuple<std::string, websocketpp::frame::opcode::value>> write_queue;
179 
180  int32_t heartbeattime;
181 
182  std::chrono::steady_clock::time_point heartbeat_ack;
183  std::chrono::steady_clock::time_point lastheartbeat;
184  std::chrono::steady_clock::time_point lastwsevent;
185  std::chrono::steady_clock::time_point last_status_time;
186  std::chrono::steady_clock::time_point _ready_time;
187  std::chrono::steady_clock::time_point last_ws_write;
188  std::chrono::steady_clock::time_point connect_time;
189  std::chrono::steady_clock::time_point closing_time;
190 
191  shard_status connection_state;
192  std::string session_id;
193  std::function<void(const asio::error_code &, const std::chrono::milliseconds, shard *)> keepalivefunc;
194 
195  void set_sequence(int64_t seq) noexcept
196  {
197  _sequence = seq;
198  }
199 
200  void set_id(int32_t shard_id) noexcept
201  {
202  _id = shard_id;
203  }
204 
205  connection_ptr get_connection() noexcept
206  {
207  return _connection;
208  }
209 
210  const std::vector<std::string> & get_trace() const noexcept
211  {
212  return _trace;
213  }
214 
216 
223  AEGIS_DECL void update_presence(const std::string& text, gateway::objects::activity::activity_type type = gateway::objects::activity::Game, gateway::objects::presence::user_status status = gateway::objects::presence::Online);
224 
225 
226 private:
227  friend class shard_mgr;
228  friend class aegis::core;
229 
230  bool state_valid()
231  {
232  if (_connection == nullptr || _strand == nullptr)
233  return false;
234  return true;
235  }
236 
237  AEGIS_DECL void process_writes(const asio::error_code & ec);
238  AEGIS_DECL void _reset();
239  AEGIS_DECL void set_connected();
240 
241  connection_ptr _connection;
242 
243  int64_t _sequence;
244  int32_t _id;
245 
246  asio::io_context & _io_context;
247 
249  uint64_t transfer_bytes;
250 
252  uint64_t transfer_bytes_u;
253 
254  websocketpp::client<websocketpp::config::asio_tls_client> & _websocket;
255 
256  std::stringstream ws_buffer;
257  std::unique_ptr<zstr::istream> zlib_ctx;
258 
259  // Websocket++ socket connection
260  websocketpp::connection_hdl hdl;
261  std::vector<std::string> _trace;
262  std::shared_ptr<asio::io_context::strand> _strand;
263 
264  heartbeat_status _heartbeat_status = heartbeat_status::normal;
265 };
266 
267 }
268 
269 }
270 
271 #if defined(AEGIS_HEADER_ONLY)
272 #include "aegis/shards/impl/shard.cpp"
273 #endif
std::string get_transfer_u_str() const noexcept
Returns a formatted string of uncompressed bytes received since library start.
Definition: shard.hpp:110
int64_t uptime() const noexcept
Return shard uptime as {days hours minutes seconds}.
Definition: shard.hpp:159
int32_t get_id() const noexcept
Gets the id of the shard in the master list.
Definition: shard.hpp:68
Primary class for managing a bot interface.
Definition: core.hpp:157
void do_reset(shard_status _status=shard_status::closed) noexcept
Resets connection, heartbeat, and timer related objects to allow reconnection.
Definition: shard.cpp:39
void update_presence(const std::string &text, gateway::objects::activity::activity_type type=gateway::objects::activity::Game, gateway::objects::presence::user_status status=gateway::objects::presence::Online)
Update presence on this shard.
Definition: shard.cpp:248
struct aegis::shards::shard::@0 counters
Contains counters of valued objects and events.
shard(asio::io_context &_io, websocketpp::client< websocketpp::config::asio_tls_client > &_ws, int32_t id)
Constructs a shard object for connecting to the websocket gateway and tracking timers.
Definition: shard.cpp:24
void connect()
Open websocket connection.
Definition: shard.cpp:101
void send_now(const std::string &payload, websocketpp::frame::opcode::value op=websocketpp::frame::opcode::text)
Send message over the websocket synchronously.
Definition: shard.cpp:208
bool is_connected() const noexcept
Check if this shard has an active connection or is a connecting state.
Definition: shard.cpp:154
void send(const std::string &payload, websocketpp::frame::opcode::value op=websocketpp::frame::opcode::text)
Send a message to this shard's websocket connection asynchronously.
Definition: shard.cpp:196
uint64_t get_transfer() const noexcept
Definition: shard.hpp:120
std::string uptime_str() const noexcept
Return shard uptime as {days hours minutes seconds}.
Definition: shard.hpp:150
std::string get_transfer_str() const noexcept
Returns a formatted string of bytes received since library start.
Definition: shard.hpp:99
uint64_t get_transfer_u() const noexcept
Definition: shard.hpp:130
Tracks websocket shards and their connections.
Definition: shard.hpp:42
websocketpp::client< websocketpp::config::asio_tls_client >::connection_type::ptr connection_ptr
Type of a pointer to the Websocket++ TLS connection.
Definition: shard.hpp:46
bool is_online() const noexcept
Check if this shard is ready to interact with the gateway.
Definition: shard.cpp:165
int64_t get_sequence() const noexcept
Get this shard's websocket message sequence counter.
Definition: shard.hpp:58