73#define _WIN32_WINNT 0x0A00
77#define _WINSOCK_DEPRECATED_NO_WARNINGS
78#define ASIO_STANDALONE
80#include <asio/ts/buffer.hpp>
81#include <asio/ts/internet.hpp>
101 template <
typename T>
117 os <<
"ID:" << int(msg.
header.id) <<
" Size:" << msg.
header.size;
128 template<
typename DataType>
132 static_assert(std::is_standard_layout<DataType>::value,
"Data is too complex to be pushed into vector");
135 size_t i = msg.
body.size();
138 msg.
body.resize(msg.
body.size() +
sizeof(DataType));
141 std::memcpy(msg.
body.data() + i, &data,
sizeof(DataType));
151 template<
typename DataType>
155 static_assert(std::is_standard_layout<DataType>::value,
"Data is too complex to be pulled from vector");
158 size_t i = msg.
body.size() -
sizeof(DataType);
161 std::memcpy(&data, msg.
body.data() + i,
sizeof(DataType));
180 template <
typename T>
183 template <
typename T>
186 std::shared_ptr<connection<T>>
remote =
nullptr;
226 auto t = std::move(
deqQueue.front());
235 auto t = std::move(
deqQueue.back());
244 deqQueue.emplace_back(std::move(item));
254 deqQueue.emplace_front(std::move(item));
303 class connection :
public std::enable_shared_from_this<connection<T>>
327 m_nHandshakeOut = uint64_t(std::chrono::system_clock::now().time_since_epoch().count());
379 asio::async_connect(
m_socket, endpoints,
380 [
this](std::error_code ec, asio::ip::tcp::endpoint endpoint)
427 if (!bWritingMessage)
444 [
this](std::error_code ec, std::size_t length)
452 if (m_qMessagesOut.front().body.size() > 0)
461 m_qMessagesOut.pop_front();
465 if (!m_qMessagesOut.empty())
477 std::cout <<
"[" << id <<
"] Write Header Fail.\n";
489 asio::async_write(m_socket, asio::buffer(m_qMessagesOut.front().body.data(), m_qMessagesOut.front().body.size()),
490 [
this](std::error_code ec, std::size_t length)
496 m_qMessagesOut.pop_front();
500 if (!m_qMessagesOut.empty())
508 std::cout <<
"[" << id <<
"] Write Body Fail.\n";
522 asio::async_read(m_socket, asio::buffer(&m_msgTemporaryIn.header,
sizeof(message_header<T>)),
523 [
this](std::error_code ec, std::size_t length)
529 if (m_msgTemporaryIn.header.size > 0)
533 m_msgTemporaryIn.body.resize(m_msgTemporaryIn.header.size);
540 AddToIncomingMessageQueue();
547 std::cout <<
"[" << id <<
"] Read Header Fail.\n";
559 asio::async_read(m_socket, asio::buffer(m_msgTemporaryIn.body.data(), m_msgTemporaryIn.body.size()),
560 [
this](std::error_code ec, std::size_t length)
566 AddToIncomingMessageQueue();
571 std::cout <<
"[" << id <<
"] Read Body Fail.\n";
578 uint64_t scramble(uint64_t nInput)
580 uint64_t out = nInput ^ 0xDEADBEEFC0DECAFE;
581 out = (out & 0xF0F0F0F0F0F0F0) >> 4 | (out & 0x0F0F0F0F0F0F0F) << 4;
582 return out ^ 0xC0DEFACE12345678;
586 void WriteValidation()
588 asio::async_write(m_socket, asio::buffer(&m_nHandshakeOut,
sizeof(uint64_t)),
589 [
this](std::error_code ec, std::size_t length)
595 if (m_nOwnerType == owner::client)
607 asio::async_read(m_socket, asio::buffer(&m_nHandshakeIn,
sizeof(uint64_t)),
608 [
this, server](std::error_code ec, std::size_t length)
612 if (m_nOwnerType == owner::server)
617 if (m_nHandshakeIn == m_nHandshakeCheck)
620 std::cout <<
"Client Validated" << std::endl;
621 server->OnClientValidated(this->shared_from_this());
629 std::cout <<
"Client Disconnected (Fail Validation)" << std::endl;
636 m_nHandshakeOut = scramble(m_nHandshakeIn);
645 std::cout <<
"Client Disconnected (ReadValidation)" << std::endl;
652 void AddToIncomingMessageQueue()
656 if(m_nOwnerType == owner::server)
657 m_qMessagesIn.push_back({ this->shared_from_this(), m_msgTemporaryIn });
659 m_qMessagesIn.push_back({
nullptr, m_msgTemporaryIn });
689 uint64_t m_nHandshakeOut = 0;
690 uint64_t m_nHandshakeIn = 0;
691 uint64_t m_nHandshakeCheck = 0;
694 bool m_bValidHandshake =
false;
695 bool m_bConnectionEstablished =
false;
702 template <
typename T>
717 bool Connect(
const std::string& host,
const uint16_t port)
722 asio::ip::tcp::resolver resolver(m_context);
723 asio::ip::tcp::resolver::results_type endpoints = resolver.resolve(host, std::to_string(port));
726 m_connection = std::make_unique<connection<T>>(
connection<T>::owner::client, m_context, asio::ip::tcp::socket(m_context), m_qMessagesIn);
729 m_connection->ConnectToServer(endpoints);
732 thrContext = std::thread([
this]() { m_context.run(); });
734 catch (std::exception& e)
736 std::cerr <<
"Client Exception: " << e.what() <<
"\n";
749 m_connection->Disconnect();
755 if (thrContext.joinable())
759 m_connection.release();
766 return m_connection->IsConnected();
776 m_connection->Send(msg);
782 return m_qMessagesIn;
805 : m_asioAcceptor(m_asioContext, asio::ip::tcp::endpoint(asio::ip::tcp::v4(), port))
826 WaitForClientConnection();
829 m_threadContext = std::thread([
this]() { m_asioContext.run(); });
831 catch (std::exception& e)
834 std::cerr <<
"[SERVER] Exception: " << e.what() <<
"\n";
838 std::cout <<
"[SERVER] Started!\n";
846 m_asioContext.stop();
849 if (m_threadContext.joinable()) m_threadContext.join();
852 std::cout <<
"[SERVER] Stopped!\n";
861 m_asioAcceptor.async_accept(
862 [
this](std::error_code ec, asio::ip::tcp::socket socket)
868 std::cout <<
"[SERVER] New Connection: " << socket.remote_endpoint() <<
"\n";
871 std::shared_ptr<connection<T>> newconn =
873 m_asioContext, std::move(socket), m_qMessagesIn);
878 if (OnClientConnect(newconn))
881 m_deqConnections.push_back(std::move(newconn));
885 m_deqConnections.back()->ConnectToClient(
this, nIDCounter++);
887 std::cout <<
"[" << m_deqConnections.back()->GetID() <<
"] Connection Approved\n";
891 std::cout <<
"[-----] Connection Denied\n";
900 std::cout <<
"[SERVER] New Connection Error: " << ec.message() <<
"\n";
905 WaitForClientConnection();
913 if (client && client->IsConnected())
923 OnClientDisconnect(client);
929 m_deqConnections.erase(
930 std::remove(m_deqConnections.begin(), m_deqConnections.end(), client), m_deqConnections.end());
937 bool bInvalidClientExists =
false;
940 for (
auto& client : m_deqConnections)
943 if (client && client->IsConnected())
946 if(client != pIgnoreClient)
953 OnClientDisconnect(client);
957 bInvalidClientExists =
true;
963 if (bInvalidClientExists)
964 m_deqConnections.erase(
965 std::remove(m_deqConnections.begin(), m_deqConnections.end(),
nullptr), m_deqConnections.end());
969 void Update(
size_t nMaxMessages = -1,
bool bWait =
false)
971 if (bWait) m_qMessagesIn.wait();
975 size_t nMessageCount = 0;
976 while (nMessageCount < nMaxMessages && !m_qMessagesIn.empty())
979 auto msg = m_qMessagesIn.pop_front();
982 OnMessage(msg.remote, msg.msg);
1033 uint32_t nIDCounter = 10000;
Definition olcPGEX_Network.h:704
std::thread thrContext
Definition olcPGEX_Network.h:789
bool Connect(const std::string &host, const uint16_t port)
Definition olcPGEX_Network.h:717
tsqueue< owned_message< T > > & Incoming()
Definition olcPGEX_Network.h:780
void Disconnect()
Definition olcPGEX_Network.h:743
bool IsConnected()
Definition olcPGEX_Network.h:763
asio::io_context m_context
Definition olcPGEX_Network.h:787
virtual ~client_interface()
Definition olcPGEX_Network.h:709
std::unique_ptr< connection< T > > m_connection
Definition olcPGEX_Network.h:791
client_interface()
Definition olcPGEX_Network.h:706
void Send(const message< T > &msg)
Definition olcPGEX_Network.h:773
Definition olcPGEX_Network.h:304
void Send(const message< T > &msg)
Definition olcPGEX_Network.h:415
uint32_t GetID() const
Definition olcPGEX_Network.h:345
uint64_t m_nHandshakeOut
Definition olcPGEX_Network.h:689
void StartListening()
Definition olcPGEX_Network.h:407
uint64_t m_nHandshakeIn
Definition olcPGEX_Network.h:690
tsqueue< owned_message< T > > & m_qMessagesIn
Definition olcPGEX_Network.h:679
uint32_t id
Definition olcPGEX_Network.h:697
void ConnectToClient(olc::net::server_interface< T > *server, uint32_t uid=0)
Definition olcPGEX_Network.h:351
bool IsConnected() const
Definition olcPGEX_Network.h:401
connection(owner parent, asio::io_context &asioContext, asio::ip::tcp::socket socket, tsqueue< owned_message< T > > &qIn)
Definition olcPGEX_Network.h:317
void ConnectToServer(const asio::ip::tcp::resolver::results_type &endpoints)
Definition olcPGEX_Network.h:373
virtual ~connection()
Definition olcPGEX_Network.h:340
owner
Definition olcPGEX_Network.h:309
asio::ip::tcp::socket m_socket
Definition olcPGEX_Network.h:669
message< T > m_msgTemporaryIn
Definition olcPGEX_Network.h:683
void Disconnect()
Definition olcPGEX_Network.h:395
asio::io_context & m_asioContext
Definition olcPGEX_Network.h:672
uint64_t m_nHandshakeCheck
Definition olcPGEX_Network.h:691
owner m_nOwnerType
Definition olcPGEX_Network.h:686
tsqueue< message< T > > m_qMessagesOut
Definition olcPGEX_Network.h:676
Definition olcPGEX_Network.h:801
void MessageClient(std::shared_ptr< connection< T > > client, const message< T > &msg)
Definition olcPGEX_Network.h:910
void Update(size_t nMaxMessages=-1, bool bWait=false)
Definition olcPGEX_Network.h:969
asio::io_context m_asioContext
Definition olcPGEX_Network.h:1026
virtual bool OnClientConnect(std::shared_ptr< connection< T > > client)
Definition olcPGEX_Network.h:993
void WaitForClientConnection()
Definition olcPGEX_Network.h:856
virtual void OnClientValidated(std::shared_ptr< connection< T > > client)
Definition olcPGEX_Network.h:1012
std::deque< std::shared_ptr< connection< T > > > m_deqConnections
Definition olcPGEX_Network.h:1023
std::thread m_threadContext
Definition olcPGEX_Network.h:1027
asio::ip::tcp::acceptor m_asioAcceptor
Definition olcPGEX_Network.h:1030
virtual ~server_interface()
Definition olcPGEX_Network.h:810
virtual void OnClientDisconnect(std::shared_ptr< connection< T > > client)
Definition olcPGEX_Network.h:999
virtual void OnMessage(std::shared_ptr< connection< T > > client, message< T > &msg)
Definition olcPGEX_Network.h:1005
server_interface(uint16_t port)
Definition olcPGEX_Network.h:804
bool Start()
Definition olcPGEX_Network.h:817
tsqueue< owned_message< T > > m_qMessagesIn
Definition olcPGEX_Network.h:1020
void MessageAllClients(const message< T > &msg, std::shared_ptr< connection< T > > pIgnoreClient=nullptr)
Definition olcPGEX_Network.h:935
void Stop()
Definition olcPGEX_Network.h:843
Definition olcPGEX_Network.h:201
void wait()
Definition olcPGEX_Network.h:281
std::condition_variable cvBlocking
Definition olcPGEX_Network.h:293
std::deque< T > deqQueue
Definition olcPGEX_Network.h:292
std::mutex muxQueue
Definition olcPGEX_Network.h:291
void push_back(const T &item)
Definition olcPGEX_Network.h:241
void clear()
Definition olcPGEX_Network.h:275
bool empty()
Definition olcPGEX_Network.h:261
std::mutex muxBlocking
Definition olcPGEX_Network.h:294
T pop_back()
Definition olcPGEX_Network.h:232
virtual ~tsqueue()
Definition olcPGEX_Network.h:205
tsqueue(const tsqueue< T > &)=delete
const T & back()
Definition olcPGEX_Network.h:216
size_t count()
Definition olcPGEX_Network.h:268
void push_front(const T &item)
Definition olcPGEX_Network.h:251
const T & front()
Definition olcPGEX_Network.h:209
T pop_front()
Definition olcPGEX_Network.h:223
Definition olcPixelGameEngine.h:593
@ T
Definition olcPixelGameEngine.h:974
Definition olcPGEX_Network.h:103
friend std::ostream & operator<<(std::ostream &os, const message< T > &msg)
Definition olcPGEX_Network.h:115
size_t size() const
Definition olcPGEX_Network.h:109
std::vector< uint8_t > body
Definition olcPGEX_Network.h:106
message_header< T > header
Definition olcPGEX_Network.h:105
friend message< T > & operator>>(message< T > &msg, DataType &data)
Definition olcPGEX_Network.h:152
Definition olcPGEX_Network.h:185
friend std::ostream & operator<<(std::ostream &os, const owned_message< T > &msg)
Definition olcPGEX_Network.h:190
message< T > msg
Definition olcPGEX_Network.h:187
std::shared_ptr< connection< T > > remote
Definition olcPGEX_Network.h:186