Botcraft 1.21.4
Loading...
Searching...
No Matches
NetworkManager.cpp
Go to the documentation of this file.
1#include <functional>
2#include <optional>
3
8#if USE_COMPRESSION
10#endif
13#if PROTOCOL_VERSION > 758 /* > 1.18.2 */
15#endif
16
17
20
21using namespace ProtocolCraft;
22
23namespace Botcraft
24{
25 NetworkManager::NetworkManager(const std::string& address, const std::string& login, const bool force_microsoft_auth, const std::vector<Handler*>& handlers)
26 {
27 com = nullptr;
28
29 // Online mode with Microsoft login flow
30 if (login.empty() || force_microsoft_auth)
31 {
32 authentifier = std::make_shared<Authentifier>();
33 if (!authentifier->AuthMicrosoft(login))
34 {
35 throw std::runtime_error("Error trying to authenticate on Mojang server using Microsoft auth flow");
36 }
37 name = authentifier->GetPlayerDisplayName();
38 }
39 // Online mode false
40 else
41 {
42 authentifier = nullptr;
43 name = login;
44 }
45
46 compression = -1;
47 AddHandler(this);
48 for (Handler* p : handlers)
49 {
50 AddHandler(p);
51 }
52
53 state = ConnectionState::Handshake;
54
55 //Start the thread to process the incoming packets
57
58 com = std::make_shared<TCP_Com>(address, std::bind(&NetworkManager::OnNewRawData, this, std::placeholders::_1));
59
60 // Wait for the communication to be ready before sending any data
62 return com->IsInitialized();
63 }, 500, 0);
64
65 std::shared_ptr<ServerboundClientIntentionPacket> handshake_msg = std::make_shared<ServerboundClientIntentionPacket>();
66 handshake_msg->SetProtocolVersion(PROTOCOL_VERSION);
67 handshake_msg->SetHostName(com->GetIp());
68 handshake_msg->SetPort(com->GetPort());
69 handshake_msg->SetIntention(static_cast<int>(ConnectionState::Login));
70 Send(handshake_msg);
71
72 state = ConnectionState::Login;
73
74 std::shared_ptr<ServerboundHelloPacket> loginstart_msg = std::make_shared<ServerboundHelloPacket>();
75#if PROTOCOL_VERSION < 759 /* < 1.19 */
76 loginstart_msg->SetGameProfile(name);
77#else
78 loginstart_msg->SetName_(name);
79 if (authentifier)
80 {
81#if PROTOCOL_VERSION < 761 /* < 1.19.3 */
83 key.SetTimestamp(authentifier->GetKeyTimestamp());
84 key.SetKey(Utilities::RSAToBytes(authentifier->GetPublicKey()));
85 key.SetSignature(Utilities::DecodeBase64(authentifier->GetKeySignature()));
86
87 loginstart_msg->SetPublicKey(key);
88#else
90#endif
91#if PROTOCOL_VERSION > 759 /* > 1.19 */
92 loginstart_msg->SetProfileId(authentifier->GetPlayerUUID());
93#endif
94 }
95#endif
96 Send(loginstart_msg);
97 }
98
99 NetworkManager::NetworkManager(const ConnectionState constant_connection_state)
100 {
101 state = constant_connection_state;
102 compression = -1;
103 }
104
109
111 {
112 state = ConnectionState::None;
113
114 if (com)
115 {
116 com->close();
117 }
118
119 process_condition.notify_all();
120
121 if (m_thread_process.joinable())
122 {
123 m_thread_process.join();
124 }
125 compression = -1;
126
127 com.reset();
128 }
129
131 {
132 subscribed.push_back(h);
133 }
134
135 void NetworkManager::Send(const std::shared_ptr<Message> msg)
136 {
137 if (com)
138 {
139 std::lock_guard<std::mutex> lock(mutex_send);
140 std::vector<unsigned char> msg_data;
141 msg_data.reserve(256);
142 msg->Write(msg_data);
143 if (compression == -1)
144 {
145 com->SendPacket(msg_data);
146 }
147 else
148 {
149#ifdef USE_COMPRESSION
150 if (msg_data.size() < compression)
151 {
152 msg_data.insert(msg_data.begin(), 0x00);
153 com->SendPacket(msg_data);
154 }
155 else
156 {
157 std::vector<unsigned char> compressed_msg;
158 compressed_msg.reserve(msg_data.size() + 5);
159 WriteData<VarInt>(static_cast<int>(msg_data.size()), compressed_msg);
160 std::vector<unsigned char> compressed_data = Compress(msg_data);
161 compressed_msg.insert(compressed_msg.end(), compressed_data.begin(), compressed_data.end());
162 com->SendPacket(compressed_msg);
163 }
164#else
165 throw std::runtime_error("Program compiled without ZLIB. Cannot send compressed message");
166#endif
167 }
168 }
169 }
170
172 {
173 return state;
174 }
175
176 const std::string& NetworkManager::GetMyName() const
177 {
178 return name;
179 }
180
181 void NetworkManager::SendChatMessage(const std::string& message)
182 {
183#if PROTOCOL_VERSION > 758 /* > 1.18.2 */
184 if (message[0] == '/')
185 {
186 LOG_INFO("You're trying to send a message starting with '/'. Use SendChatCommand instead if you want the server to interprete it as a command.");
187 }
188#endif
189
190 std::shared_ptr<ServerboundChatPacket> chat_message = std::make_shared<ServerboundChatPacket>();
191 chat_message->SetMessage(message);
192#if PROTOCOL_VERSION > 758 /* > 1.18.2 */
193#if PROTOCOL_VERSION < 761 /* < 1.19.3 */
194 chat_message->SetSignedPreview(false);
195#endif
196 if (authentifier)
197 {
198 long long int salt, timestamp;
199 std::vector<unsigned char> signature;
200#if PROTOCOL_VERSION == 759 /* 1.19 */
201 // 1.19
202 signature = authentifier->GetMessageSignature(message, salt, timestamp);
203#elif PROTOCOL_VERSION == 760 /* 1.19.1/2 */
204 // 1.19.1 and 1.19.2
205 LastSeenMessagesUpdate last_seen_update;
206 {
207 std::scoped_lock<std::mutex> lock_messages(chat_context.GetMutex());
208 last_seen_update = chat_context.GetLastSeenMessagesUpdate();
209 signature = authentifier->GetMessageSignature(message, chat_context.GetLastSignature(), last_seen_update.GetLastSeen(), salt, timestamp);
210 // Update last signature with current one for the next message
211 chat_context.SetLastSignature(signature);
212 }
213 chat_message->SetLastSeenMessages(last_seen_update);
214#else
215 // 1.19.3+
216 const auto [signatures, updates] = chat_context.GetLastSeenMessagesUpdate();
217 const int current_message_sent_index = message_sent_index++;
218 signature = authentifier->GetMessageSignature(message, current_message_sent_index, chat_session_uuid, signatures, salt, timestamp);
219 chat_message->SetLastSeenMessages(updates);
220#endif
221 if (signature.empty())
222 {
223 throw std::runtime_error("Empty chat message signature.");
224 }
225 chat_message->SetTimestamp(timestamp);
226
227#if PROTOCOL_VERSION < 760 /* < 1.19.1 */
228 SaltSignature salt_signature;
229 salt_signature.SetSalt(salt);
230 salt_signature.SetSignature(signature);
231
232 chat_message->SetSaltSignature(salt_signature);
233#else
234 chat_message->SetSalt(salt);
235 chat_message->SetSignature(signature);
236#endif
237 }
238 // Offline mode, empty signature
239 else
240 {
241 chat_message->SetTimestamp(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count());
242 }
243#endif
244 Send(chat_message);
245 }
246
247 void NetworkManager::SendChatCommand(const std::string& command)
248 {
249#if PROTOCOL_VERSION > 765 /* > 1.20.4 */
250 if (authentifier == nullptr)
251 {
252 std::shared_ptr<ServerboundChatCommandPacket> chat_command = std::make_shared<ServerboundChatCommandPacket>();
253 chat_command->SetCommand(command);
254 Send(chat_command);
255 return;
256 }
257#endif
258#if PROTOCOL_VERSION > 758 /* > 1.18.2 */
259#if PROTOCOL_VERSION > 765 /* > 1.20.4 */
260 std::shared_ptr<ServerboundChatCommandSignedPacket> chat_command = std::make_shared<ServerboundChatCommandSignedPacket>();
261#else
262 std::shared_ptr<ServerboundChatCommandPacket> chat_command = std::make_shared<ServerboundChatCommandPacket>();
263#endif
264 chat_command->SetCommand(command);
265 chat_command->SetTimestamp(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count());
266#if PROTOCOL_VERSION > 759 /* > 1.19 */
267 std::mt19937 rnd(static_cast<unsigned int>(std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count()));
268 chat_command->SetSalt(std::uniform_int_distribution<long long int>(std::numeric_limits<long long int>::min(), std::numeric_limits<long long int>::max())(rnd));
269#endif
270#if PROTOCOL_VERSION < 761 /* < 1.19.3 */
271 chat_command->SetSignedPreview(false);
272#endif
273#if PROTOCOL_VERSION == 760 /* 1.19.1/2 */
274 LastSeenMessagesUpdate last_seen_update;
275 if (authentifier)
276 {
277 std::scoped_lock<std::mutex> lock_messages(chat_context.GetMutex());
278 last_seen_update = chat_context.GetLastSeenMessagesUpdate();
279 }
280 chat_command->SetLastSeenMessages(last_seen_update);
281#elif PROTOCOL_VERSION > 760 /* > 1.19.2 */
282 const auto [signatures, updates] = chat_context.GetLastSeenMessagesUpdate();
283 chat_command->SetLastSeenMessages(updates);
284#endif
285 // TODO: when this shouldn't be empty? Can't find a situation where it's filled with something
286 chat_command->SetArgumentSignatures({});
287#else
288 std::shared_ptr<ServerboundChatPacket> chat_command = std::make_shared<ServerboundChatPacket>();
289 chat_command->SetMessage("/" + command);
290#endif
291 Send(chat_command);
292 }
293
295 {
296 return m_thread_process.get_id();
297 }
298
300 {
301 Logger::GetInstance().RegisterThread("NetworkPacketProcessing - " + name);
302 try
303 {
304 while (state != ConnectionState::None)
305 {
306 {
307 std::unique_lock<std::mutex> lck(mutex_process);
308 process_condition.wait(lck);
309 }
310 while (!packets_to_process.empty())
311 {
312 std::vector<unsigned char> packet;
313 { // process_guard scope
314 std::lock_guard<std::mutex> process_guard(mutex_process);
315 if (!packets_to_process.empty())
316 {
317 packet = packets_to_process.front();
318 packets_to_process.pop();
319 }
320 }
321 if (packet.size() > 0)
322 {
323 if (compression == -1)
324 {
325 ProcessPacket(packet);
326 }
327 else
328 {
329#ifdef USE_COMPRESSION
330 size_t length = packet.size();
331 ReadIterator iter = packet.begin();
332 int data_length = ReadData<VarInt>(iter, length);
333
334 //Packet not compressed
335 if (data_length == 0)
336 {
337 //Erase the first 0
338 packet.erase(packet.begin());
339 ProcessPacket(packet);
340 }
341 //Packet compressed
342 else
343 {
344 const int size_varint = static_cast<int>(packet.size() - length);
345
346 std::vector<unsigned char> uncompressed_msg = Decompress(packet, size_varint);
347 ProcessPacket(uncompressed_msg);
348 }
349#else
350 throw std::runtime_error("Program compiled without USE_COMPRESSION. Cannot read compressed message");
351#endif
352 }
353 }
354 }
355 }
356 }
357 catch (const std::exception& e)
358 {
359 LOG_FATAL("Exception:\n" << e.what());
360 throw;
361 }
362 catch (...)
363 {
364 LOG_FATAL("Unknown exception");
365 throw;
366 }
367 }
368
369 void NetworkManager::ProcessPacket(const std::vector<unsigned char>& packet)
370 {
371 if (packet.empty())
372 {
373 return;
374 }
375
376 std::vector<unsigned char>::const_iterator packet_iterator = packet.begin();
377 size_t length = packet.size();
378
379 const int packet_id = ReadData<VarInt>(packet_iterator, length);
380
381 std::shared_ptr<Message> msg = CreateClientboundMessage(state, packet_id);
382
383 if (msg)
384 {
385 try
386 {
387 msg->Read(packet_iterator, length);
388 }
389 catch (const std::exception&)
390 {
391 LOG_FATAL("Parsing exception while parsing message \"" << msg->GetName() << '"');
392 throw;
393 }
394 for (size_t i = 0; i < subscribed.size(); i++)
395 {
396 msg->Dispatch(subscribed[i]);
397 }
398 }
399 }
400
401 void NetworkManager::OnNewRawData(const std::vector<unsigned char>& packet)
402 {
403 {
404 std::unique_lock<std::mutex> lck(mutex_process);
405 packets_to_process.push(packet);
406 }
407 process_condition.notify_all();
408 }
409
410
412 {
413 compression = msg.GetCompressionThreshold();
414 }
415
416#if PROTOCOL_VERSION < 768 /* < 1.21.2 */
417 void NetworkManager::Handle(ClientboundGameProfilePacket& msg)
418#else
420#endif
421 {
422#if PROTOCOL_VERSION < 764 /* < 1.20.2 */
423 state = ConnectionState::Play;
424#else
425 state = ConnectionState::Configuration;
426 std::shared_ptr<ServerboundLoginAcknowledgedPacket> login_ack_msg = std::make_shared<ServerboundLoginAcknowledgedPacket>();
427 Send(login_ack_msg);
428#endif
429 }
430
432 {
433 if (authentifier == nullptr)
434 {
435 throw std::runtime_error("Authentication asked while no valid account has been provided, make sure to connect with a valid Microsoft Account, or to a server with online-mode=false");
436 }
437
438#ifdef USE_ENCRYPTION
439 std::shared_ptr<AESEncrypter> encrypter = std::make_shared<AESEncrypter>();
440
441 std::vector<unsigned char> raw_shared_secret;
442 std::vector<unsigned char> encrypted_shared_secret;
443
444#if PROTOCOL_VERSION < 759 /* < 1.19 */
445 std::vector<unsigned char> encrypted_nonce;
446 encrypter->Init(msg.GetPublicKey(), msg.GetNonce(),
447 raw_shared_secret, encrypted_nonce, encrypted_shared_secret);
448#elif PROTOCOL_VERSION < 761 /* < 1.19.3 */
449 std::vector<unsigned char> salted_nonce_signature;
450 long long int salt;
451 encrypter->Init(msg.GetPublicKey(), msg.GetNonce(), authentifier->GetPrivateKey(),
452 raw_shared_secret, encrypted_shared_secret,
453 salt, salted_nonce_signature);
454#else
455 std::vector<unsigned char> encrypted_challenge;
456 encrypter->Init(msg.GetPublicKey(), msg.GetChallenge(),
457 raw_shared_secret, encrypted_shared_secret,
458 encrypted_challenge);
459#endif
460
461 authentifier->JoinServer(msg.GetServerId(), raw_shared_secret, msg.GetPublicKey());
462
463 std::shared_ptr<ServerboundKeyPacket> response_msg = std::make_shared<ServerboundKeyPacket>();
464 response_msg->SetKeyBytes(encrypted_shared_secret);
465
466#if PROTOCOL_VERSION < 759 /* < 1.19 */
467 // Pre-1.19 behaviour, send encrypted nonce
468 response_msg->SetNonce(encrypted_nonce);
469#elif PROTOCOL_VERSION < 761 /* < 1.19.3 */
470 // 1.19, 1.19.1, 1.19.2 behaviour, send salted nonce signature
471 SaltSignature salt_signature;
472 salt_signature.SetSalt(salt);
473 salt_signature.SetSignature(salted_nonce_signature);
474 response_msg->SetSaltSignature(salt_signature);
475#else
476 // 1.19.3+ behaviour, send encrypted challenge
477 response_msg->SetEncryptedChallenge(encrypted_challenge);
478#endif
479
480 Send(response_msg);
481
482 // Enable encryption from now on
483 com->SetEncrypter(encrypter);
484#else
485 throw std::runtime_error("Your version of botcraft doesn't support encryption. Either run your server with online-mode=false or recompile botcraft");
486#endif
487 }
488
490 {
491 std::shared_ptr<ServerboundKeepAlivePacket> keep_alive_msg = std::make_shared<ServerboundKeepAlivePacket>();
492 keep_alive_msg->SetId_(msg.GetId_());
493 Send(keep_alive_msg);
494 }
495
496#if PROTOCOL_VERSION > 754 /* > 1.16.5 */
498 {
499 std::shared_ptr<ServerboundPongPacket> pong_msg = std::make_shared<ServerboundPongPacket>();
500 pong_msg->SetId_(msg.GetId_());
501 Send(pong_msg);
502 }
503#endif
504
505#if PROTOCOL_VERSION > 340 /* > 1.12.2 */
507 {
508 // Vanilla like response when asked by fabric API
509 // Not implemented in fabric before December 05 2020,
510 // so not necessary before version 1.16.4
511#if PROTOCOL_VERSION > 753 /* > 1.16.3 */
512 if (msg.GetIdentifier().GetFull() == "fabric-networking-api-v1:early_registration")
513 {
514#if PROTOCOL_VERSION < 764 /* < 1.20.2 */
515 std::shared_ptr<ServerboundCustomQueryPacket> custom_query_anwser = std::make_shared<ServerboundCustomQueryPacket>();
516 custom_query_anwser->SetTransactionId(msg.GetTransactionId());
517 custom_query_anwser->SetData(std::nullopt);
518#else
519 std::shared_ptr<ServerboundCustomQueryAnswerPacket> custom_query_anwser = std::make_shared<ServerboundCustomQueryAnswerPacket>();
520 custom_query_anwser->SetTransactionId(msg.GetTransactionId());
521 custom_query_anwser->SetPayload(std::nullopt);
522#endif
523 Send(custom_query_anwser);
524 return;
525 }
526#endif
527 }
528#endif
529
530#if PROTOCOL_VERSION > 759 /* > 1.19 */
532 {
533#if PROTOCOL_VERSION < 761 /* < 1.19.3 */
534 chat_context.AddSeenMessage(msg.GetMessage_().GetHeaderSignature(), msg.GetMessage_().GetSignedHeader().GetSender());
535#else
536 if (msg.GetSignature().has_value())
537 {
538 std::scoped_lock<std::mutex> lock_messages(chat_context.GetMutex());
539
540 chat_context.AddSeenMessage(std::vector<unsigned char>(msg.GetSignature().value().begin(), msg.GetSignature().value().end()));
541
542 if (chat_context.GetOffset() > 64)
543 {
544 std::shared_ptr<ServerboundChatAckPacket> ack_msg = std::make_shared<ServerboundChatAckPacket>();
545 ack_msg->SetOffset(chat_context.GetAndResetOffset());
546 Send(ack_msg);
547 }
548 }
549#endif
550 }
551
552#if PROTOCOL_VERSION < 761 /* < 1.19.3 */
553 void NetworkManager::Handle(ClientboundPlayerChatHeaderPacket& msg)
554 {
555 chat_context.AddSeenMessage(msg.GetHeaderSignature(), msg.GetHeader().GetSender());
556 }
557#endif
558#endif
559
560#if PROTOCOL_VERSION > 760 /* > 1.19.2 */
562 {
563 if (authentifier)
564 {
565 std::shared_ptr<ServerboundChatSessionUpdatePacket> chat_session_msg = std::make_shared<ServerboundChatSessionUpdatePacket>();
566 RemoteChatSessionData chat_session_data;
567
569 key.SetTimestamp(authentifier->GetKeyTimestamp());
570 key.SetKey(Utilities::RSAToBytes(authentifier->GetPublicKey()));
571 key.SetSignature(Utilities::DecodeBase64(authentifier->GetKeySignature()));
572
573 chat_session_data.SetProfilePublicKey(key);
575 std::mt19937 rnd = std::mt19937(static_cast<unsigned int>(std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count()));
576 std::uniform_int_distribution<int> distrib(std::numeric_limits<unsigned char>::min(), std::numeric_limits<unsigned char>::max());
577 for (size_t i = 0; i < chat_session_uuid.size(); ++i)
578 {
579 chat_session_uuid[i] = static_cast<unsigned char>(distrib(rnd));
580 }
581 chat_session_data.SetUuid(chat_session_uuid);
582
583 chat_session_msg->SetChatSession(chat_session_data);
584 Send(chat_session_msg);
585 }
586 }
587#endif
588
589#if PROTOCOL_VERSION > 763 /* > 1.20.1 */
591 {
592 state = ConnectionState::Play;
593 std::shared_ptr<ServerboundFinishConfigurationPacket> finish_config_msg = std::make_shared<ServerboundFinishConfigurationPacket>();
594 Send(finish_config_msg);
595 }
596
598 {
599 std::shared_ptr<ServerboundKeepAliveConfigurationPacket> keep_alive_msg = std::make_shared<ServerboundKeepAliveConfigurationPacket>();
600 keep_alive_msg->SetId_(msg.GetId_());
601 Send(keep_alive_msg);
602 }
603
605 {
606 std::shared_ptr<ServerboundPongConfigurationPacket> pong_msg = std::make_shared<ServerboundPongConfigurationPacket>();
607 pong_msg->SetId_(msg.GetId_());
608 Send(pong_msg);
609 }
610
612 {
613 state = ConnectionState::Configuration;
614 std::shared_ptr<ServerboundConfigurationAcknowledgedPacket> config_ack_msg = std::make_shared<ServerboundConfigurationAcknowledgedPacket>();
615 Send(config_ack_msg);
616 }
617
619 {
620 chunk_batch_start_time = std::chrono::steady_clock::now();
621 }
622
624 {
625 using count_return = decltype(std::declval<std::chrono::milliseconds>().count());
626 const count_return time_elapsed_ms = std::max(static_cast<count_return>(1), std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - chunk_batch_start_time).count());
627 std::shared_ptr<ServerboundChunkBatchReceivedPacket> chunk_per_tick_msg = std::make_shared<ServerboundChunkBatchReceivedPacket>();
628 // Ask as many chunks as we can process in one tick (50 ms)
629 chunk_per_tick_msg->SetDesiredChunksPerTick(msg.GetBatchSize() * 50.0f / time_elapsed_ms);
630 Send(chunk_per_tick_msg);
631 }
632#endif
633
634#if PROTOCOL_VERSION > 765 /* > 1.20.4 */
636 {
637 std::shared_ptr<ServerboundSelectKnownPacksPacket> select_known_packs = std::make_shared<ServerboundSelectKnownPacksPacket>();
638 // Datapacks are not supported by Botcraft
639 select_known_packs->SetKnownPacks({});
640
641 Send(select_known_packs);
642
643 }
644#endif
645}
#define LOG_INFO(osstream)
Definition Logger.hpp:43
#define LOG_FATAL(osstream)
Definition Logger.hpp:46
void AddSeenMessage(const std::vector< unsigned char > &signature)
std::pair< std::vector< std::vector< unsigned char > >, ProtocolCraft::LastSeenMessagesUpdate > GetLastSeenMessagesUpdate()
Get both a vector of previous messages signatures and the LastSeenMessagesUpdate object.
void RegisterThread(const std::string &name)
Register the current thread in the map.
Definition Logger.cpp:104
static Logger & GetInstance()
Definition Logger.cpp:36
std::condition_variable process_condition
void AddHandler(ProtocolCraft::Handler *h)
std::thread::id GetProcessingThreadId() const
void SendChatCommand(const std::string &command)
virtual void Handle(ProtocolCraft::ClientboundLoginCompressionPacket &msg) override
void SendChatMessage(const std::string &message)
LastSeenMessagesTracker chat_context
void Send(const std::shared_ptr< ProtocolCraft::Message > msg)
std::shared_ptr< TCP_Com > com
std::chrono::steady_clock::time_point chunk_batch_start_time
const std::string & GetMyName() const
std::shared_ptr< Authentifier > authentifier
const ProtocolCraft::ConnectionState GetConnectionState() const
std::vector< ProtocolCraft::Handler * > subscribed
NetworkManager(const std::string &address, const std::string &login, const bool force_microsoft_auth, const std::vector< ProtocolCraft::Handler * > &handlers={})
std::atomic< int > message_sent_index
ProtocolCraft::ConnectionState state
void ProcessPacket(const std::vector< unsigned char > &packet)
std::queue< std::vector< unsigned char > > packets_to_process
ProtocolCraft::UUID chat_session_uuid
void OnNewRawData(const std::vector< unsigned char > &packet)
std::vector< unsigned char > RSAToBytes(const std::string &s)
std::vector< unsigned char > DecodeBase64(const std::string &s)
bool WaitForCondition(const std::function< bool()> &condition, const long long int timeout_ms=0, const long long int check_interval_ms=10)
std::vector< unsigned char > Decompress(const std::vector< unsigned char > &compressed, const int start=0)
std::vector< unsigned char > Compress(const std::vector< unsigned char > &raw)
std::array< unsigned char, 16 > UUID
std::shared_ptr< Message > CreateClientboundMessage(const ConnectionState state, const int id)
std::vector< unsigned char >::const_iterator ReadIterator