diff --git a/HLAPI/HLAPI/HLAPI.vcxproj b/HLAPI/HLAPI/HLAPI.vcxproj
new file mode 100644
index 0000000..2ba64fb
--- /dev/null
+++ b/HLAPI/HLAPI/HLAPI.vcxproj
@@ -0,0 +1,154 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 16.0
+ {989D0F55-C4B9-44D2-AD2B-DD7E1AAABFC1}
+ HLAPI
+ 10.0.17763.0
+
+
+
+ Application
+ true
+ v142
+ MultiByte
+
+
+ Application
+ false
+ v142
+ true
+ MultiByte
+
+
+ Application
+ true
+ v141
+ MultiByte
+
+
+ Application
+ false
+ v142
+ true
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Level3
+ Disabled
+ true
+ true
+ D:\VoidNet\include\HLAPI;D:\VoidNet\include
+ stdcpplatest
+
+
+ Console
+ D:\VoidNet\VoidNetVS\x64\Debug\VoidNetVS.lib;WS2_32.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+ Disabled
+ true
+ true
+
+
+ Console
+
+
+
+
+ Level3
+ MaxSpeed
+ true
+ true
+ true
+ true
+
+
+ Console
+ true
+ true
+
+
+
+
+ Level3
+ MaxSpeed
+ true
+ true
+ true
+ true
+
+
+ Console
+ true
+ true
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HLAPI/HLAPI/HLAPI.vcxproj.filters b/HLAPI/HLAPI/HLAPI.vcxproj.filters
new file mode 100644
index 0000000..60bef89
--- /dev/null
+++ b/HLAPI/HLAPI/HLAPI.vcxproj.filters
@@ -0,0 +1,72 @@
+
+
+
+
+ {a941a71f-2121-4d2f-87f9-58bcadbeb98b}
+
+
+ {1c087ed8-3cca-4254-836f-10fb70fda154}
+
+
+
+
+ include
+
+
+ include
+
+
+ include
+
+
+ include
+
+
+ include
+
+
+ include
+
+
+ include
+
+
+ include
+
+
+ include
+
+
+ include
+
+
+ include
+
+
+ include
+
+
+
+
+ src
+
+
+ src
+
+
+ src
+
+
+ src
+
+
+ src
+
+
+ src
+
+
+ src
+
+
+
\ No newline at end of file
diff --git a/TestsVS/Tests/Tests.cpp b/TestsVS/Tests/Tests.cpp
index c73c4dc..aa098d5 100644
--- a/TestsVS/Tests/Tests.cpp
+++ b/TestsVS/Tests/Tests.cpp
@@ -1,4 +1,4 @@
-#include "Utility.hpp"
+#include "Util.hpp"
#include
diff --git a/VoidNetVS/VoidNetVS.sln b/VoidNetVS/VoidNetVS.sln
index aabb269..a340f35 100644
--- a/VoidNetVS/VoidNetVS.sln
+++ b/VoidNetVS/VoidNetVS.sln
@@ -1,12 +1,14 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 14
-VisualStudioVersion = 14.0.25123.0
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.29326.143
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VoidNetVS", "VoidNetVS\VoidNetVS.vcxproj", "{5172321E-CCB0-4A77-9F3D-FAAF0084F434}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Tests", "..\TestsVS\Tests\Tests.vcxproj", "{41663B22-3949-4570-9AB5-309363EAD56F}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HLAPI", "..\HLAPI\HLAPI\HLAPI.vcxproj", "{989D0F55-C4B9-44D2-AD2B-DD7E1AAABFC1}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@@ -31,8 +33,19 @@ Global
{41663B22-3949-4570-9AB5-309363EAD56F}.Release|x64.Build.0 = Release|x64
{41663B22-3949-4570-9AB5-309363EAD56F}.Release|x86.ActiveCfg = Release|Win32
{41663B22-3949-4570-9AB5-309363EAD56F}.Release|x86.Build.0 = Release|Win32
+ {989D0F55-C4B9-44D2-AD2B-DD7E1AAABFC1}.Debug|x64.ActiveCfg = Debug|x64
+ {989D0F55-C4B9-44D2-AD2B-DD7E1AAABFC1}.Debug|x64.Build.0 = Debug|x64
+ {989D0F55-C4B9-44D2-AD2B-DD7E1AAABFC1}.Debug|x86.ActiveCfg = Debug|Win32
+ {989D0F55-C4B9-44D2-AD2B-DD7E1AAABFC1}.Debug|x86.Build.0 = Debug|Win32
+ {989D0F55-C4B9-44D2-AD2B-DD7E1AAABFC1}.Release|x64.ActiveCfg = Release|x64
+ {989D0F55-C4B9-44D2-AD2B-DD7E1AAABFC1}.Release|x64.Build.0 = Release|x64
+ {989D0F55-C4B9-44D2-AD2B-DD7E1AAABFC1}.Release|x86.ActiveCfg = Release|Win32
+ {989D0F55-C4B9-44D2-AD2B-DD7E1AAABFC1}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {30B0A8A0-814A-40F1-99DB-799D6ABB368C}
+ EndGlobalSection
EndGlobal
diff --git a/VoidNetVS/VoidNetVS/VoidNetVS.vcxproj b/VoidNetVS/VoidNetVS/VoidNetVS.vcxproj
index 8caf10b..5331e04 100644
--- a/VoidNetVS/VoidNetVS/VoidNetVS.vcxproj
+++ b/VoidNetVS/VoidNetVS/VoidNetVS.vcxproj
@@ -124,7 +124,7 @@
Disabled
true
../../include
- stdcpp17
+ stdcpplatest
_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)
diff --git a/include/HLAPI/BitConverter.hpp b/include/HLAPI/BitConverter.hpp
new file mode 100644
index 0000000..9984841
--- /dev/null
+++ b/include/HLAPI/BitConverter.hpp
@@ -0,0 +1,33 @@
+#pragma once
+
+// i want to use bitshifting but i red in stackoverflow that casting doesnt generate overhead
+// now ive hit a wall
+// casting vs bitshifting
+
+#include
+#include
+
+namespace std
+{
+ class BitConverter
+ {
+ public:
+ template
+ inline static uint8_t *ToBytes(T value)
+ {
+ uint8_t *data = new uint8_t[sizeof(T)]();
+ memcpy(data, &value, sizeof(T));
+ return data;
+ }
+
+ template
+ inline static T FromBytes(uint8_t *data)
+ {
+ if (!data)
+ throw std::invalid_argument("cant have null parameter -> BitConverter::FromBytes");
+ T value;
+ memcpy(&value, data, sizeof(T));
+ return value;
+ }
+ };
+}
\ No newline at end of file
diff --git a/include/HLAPI/DataReceivedEvent.hpp b/include/HLAPI/DataReceivedEvent.hpp
new file mode 100644
index 0000000..b758432
--- /dev/null
+++ b/include/HLAPI/DataReceivedEvent.hpp
@@ -0,0 +1,27 @@
+#pragma once
+
+#include "NetworkMessage.hpp"
+
+namespace std::net
+{
+ class DataReceivedEvent
+ {
+ public:
+ inline DataReceivedEvent(const NetworkMessage &msg)
+ {
+ SenderID = msg.GetSenderID();
+ DistributionMode = msg.GetDistributionMode();
+ DestinationID = msg.GetDestinationID();
+ Tag = msg.GetTag();
+ Data = msg.GetData();
+ }
+
+ public:
+ uint32_t SenderID;
+ DistributionMode DistributionMode;
+ uint32_t DestinationID;
+ uint32_t Tag;
+
+ void *Data;
+ };
+}
\ No newline at end of file
diff --git a/include/HLAPI/DisconnectedEvent.hpp b/include/HLAPI/DisconnectedEvent.hpp
new file mode 100644
index 0000000..b8943db
--- /dev/null
+++ b/include/HLAPI/DisconnectedEvent.hpp
@@ -0,0 +1,36 @@
+#pragma once
+
+#include
+
+namespace std::net
+{
+ class DisconnectedEvent // can be processed by client and server
+ {
+ private:
+ DisconnectedEvent();
+
+ public:
+ inline DisconnectedEvent(uint32_t id, char *reason, int32_t reason_id)
+ : m_reason(reason)
+ , m_clientID(id)
+ , m_reasonID(reason_id)
+ {
+ }
+
+ inline DisconnectedEvent(uint32_t id, const std::string &reason, int32_t reason_id)
+ : m_reason(reason)
+ , m_clientID(id)
+ , m_reasonID(reason_id)
+ {
+ }
+
+ inline const std::string &GetReason() const { return m_reason; }
+ inline int32_t GetReasonID() const { return m_reasonID; }
+ inline uint32_t GetID() const { return m_clientID; }
+
+ private:
+ std::string m_reason;
+ int32_t m_reasonID;
+ uint32_t m_clientID;
+ };
+}
\ No newline at end of file
diff --git a/include/HLAPI/InternalTags.hpp b/include/HLAPI/InternalTags.hpp
new file mode 100644
index 0000000..f5f7690
--- /dev/null
+++ b/include/HLAPI/InternalTags.hpp
@@ -0,0 +1,10 @@
+#pragma once
+
+#include
+
+enum class InternalTags : uint32_t
+{
+ Disconnect = 0xFFFFFFFF,
+ Connect = 0xFFFFFFFE,
+ AssignID = 0xFFFFFFFD
+};
\ No newline at end of file
diff --git a/include/HLAPI/MessageQueue.hpp b/include/HLAPI/MessageQueue.hpp
new file mode 100644
index 0000000..decfe76
--- /dev/null
+++ b/include/HLAPI/MessageQueue.hpp
@@ -0,0 +1,43 @@
+#pragma once
+
+#include
+#include
+
+#include "NetworkMessage.hpp"
+
+#include "NewConnectionEvent.hpp"
+#include "DisconnectedEvent.hpp"
+#include "DataReceivedEvent.hpp"
+
+namespace std::net
+{
+ class MessageQueue
+ {
+ public:
+ MessageQueue()
+ {
+ }
+
+ void EnqueueMessageToSend(const NetworkMessage &msg);
+
+ void EnqueueMessageReceived(const NetworkMessage &msg);
+ void EnqueueDisconnection(const NetworkMessage &msg);
+ void EnqueueConnection(const NetworkMessage &msg);
+
+ NetworkMessage DequeueMessageToSend();
+
+ uint32_t SendSize();
+
+ private:
+ std::deque m_messagesToSend;
+
+ std::deque m_connectionEvents;
+ std::deque m_disconnectedEvents;
+ std::deque m_dataReceivedEvents;
+
+ std::mutex m_sendMutex;
+ std::mutex m_receivedMutex;
+ std::mutex m_disconnectMutex;
+ std::mutex m_connectionMutex;
+ };
+}
\ No newline at end of file
diff --git a/include/HLAPI/NetworkHeader.hpp b/include/HLAPI/NetworkHeader.hpp
new file mode 100644
index 0000000..f7ea01d
--- /dev/null
+++ b/include/HLAPI/NetworkHeader.hpp
@@ -0,0 +1,12 @@
+#pragma once
+
+#include
+
+namespace std::net
+{
+ class NetworkHeader
+ {
+ public:
+ uint32_t Size;
+ };
+}
\ No newline at end of file
diff --git a/include/HLAPI/NetworkMessage.hpp b/include/HLAPI/NetworkMessage.hpp
new file mode 100644
index 0000000..a4459da
--- /dev/null
+++ b/include/HLAPI/NetworkMessage.hpp
@@ -0,0 +1,95 @@
+#pragma once
+
+#include "NetworkHeader.hpp"
+#include "BitConverter.hpp"
+
+#include
+#include
+
+namespace std::net
+{
+ enum class DistributionMode : uint8_t
+ {
+ ID,
+ Others,
+ OthersAndServer,
+ All,
+ AllAndMe,
+ Server
+ };
+
+ class NetworkMessage
+ {
+ public:
+ NetworkMessage()
+ {
+ }
+
+ NetworkMessage(uint32_t sender, DistributionMode mode, uint32_t destinationId, uint32_t tag, void *data, uint32_t dataSize)
+ : m_senderID(sender)
+ , m_distributionMode(mode)
+ , m_destinationID(destinationId)
+ , m_tag(tag)
+ , m_data(data)
+ , m_dataSize(dataSize)
+ {
+ }
+
+ uint32_t GetSenderID() const;
+ DistributionMode GetDistributionMode() const;
+ uint32_t GetDestinationID() const;
+ uint32_t GetTag() const;
+
+ private:
+ uint32_t m_senderID = 0;
+ DistributionMode m_distributionMode = DistributionMode::All;
+ uint32_t m_destinationID = 0;
+ uint32_t m_tag = 0;
+
+ void *m_data = 0;
+ uint32_t m_dataSize = 0;
+
+ public:
+ template
+ void SetData(T *data)
+ {
+ m_data = data;
+ m_dataSize = sizeof(T);
+ }
+
+ template
+ uint8_t * SerializeData(uint32_t &size)
+ {
+ int32_t sizeOfNetHeader = sizeof(NetworkHeader);
+
+ NetworkHeader header;
+ header.Size = 13 + sizeOfNetHeader + sizeof(T);
+
+ uint8_t *bytes = new uint8_t[header.Size];
+ memcpy(bytes, &header, sizeOfNetHeader);
+
+ uint8_t *sender = BitConverter::ToBytes(m_senderID); // 4
+ uint8_t *destination = BitConverter::ToBytes(m_destinationID); // 4
+ uint8_t *tag = BitConverter::ToBytes(m_tag); // 4
+
+ memcpy(bytes + sizeOfNetHeader, sender, 4);
+ bytes[sizeOfNetHeader + 4] = (uint8_t)m_distributionMode;
+ memcpy(bytes + sizeOfNetHeader + 5, destination, 4);
+ memcpy(bytes + sizeOfNetHeader + 9, tag, 4);
+
+ memcpy(bytes + 13 + sizeOfNetHeader, m_data, sizeof(T));
+
+ size = header.Size;
+ return bytes;
+ }
+
+ uint8_t *SerializeData(uint32_t &size);
+ void Deserialize(uint8_t *data, uint32_t size);
+
+ template
+ T *GetData() const
+ {
+ return (T*)m_data;
+ }
+ };
+}
\ No newline at end of file
diff --git a/include/HLAPI/NewConnectionEvent.hpp b/include/HLAPI/NewConnectionEvent.hpp
new file mode 100644
index 0000000..3a3ea37
--- /dev/null
+++ b/include/HLAPI/NewConnectionEvent.hpp
@@ -0,0 +1,18 @@
+#pragma once
+
+namespace std::net
+{
+ class NewConnectionEvent
+ {
+ public:
+ inline NewConnectionEvent(uint32_t id, void *data)
+ : m_id(id)
+ , m_data(data)
+ {
+ }
+
+ private:
+ uint32_t m_id;
+ void *m_data;
+ };
+}
\ No newline at end of file
diff --git a/include/HLAPI/Server.hpp b/include/HLAPI/Server.hpp
new file mode 100644
index 0000000..fc644d0
--- /dev/null
+++ b/include/HLAPI/Server.hpp
@@ -0,0 +1,26 @@
+#pragma once
+
+#include
+
+#include
+
+namespace std::net
+{
+ class TcpServer;
+
+ class MessageQueue;
+
+ class Server
+ {
+ public:
+ Server(uint32_t max_connections = 20, uint16_t port = DEFAULT_SERVER_PORT);
+
+ void Start();
+ void Stop();
+
+ private:
+ std::shared_ptr m_tcpServer;
+
+ std::shared_ptr m_queue;
+ };
+}
\ No newline at end of file
diff --git a/include/HLAPI/TcpConnection.hpp b/include/HLAPI/TcpConnection.hpp
new file mode 100644
index 0000000..0225a25
--- /dev/null
+++ b/include/HLAPI/TcpConnection.hpp
@@ -0,0 +1,40 @@
+#pragma once
+
+#include
+
+#include "TcpClient.hpp"
+
+#include "NetworkMessage.hpp"
+
+namespace std::net
+{
+ class TcpConnection
+ {
+ public:
+ friend class TcpConnectionHandler;
+
+ TcpConnection(TcpClient *client);
+
+ std::shared_ptr GetClient();
+ uint32_t GetID();
+ void SetID(uint32_t id);
+
+ template
+ void SendMessage(DistributionMode mode, uint32_t destinationId, uint32_t tag, void *data)
+ {
+ NetworkMessage msg(m_id, mode, destinationId, tag, data, sizeof(T));
+ }
+
+ void ReceiveData();
+
+ std::function DataReceivedEvent;
+ std::function DisconnectedEvent;
+ std::function NewConnectionEvent;
+
+ private:
+ bool sendMessage(NetworkMessage &msg);
+
+ std::shared_ptr m_client;
+ uint32_t m_id;
+ };
+}
\ No newline at end of file
diff --git a/include/HLAPI/TcpConnectionHandler.hpp b/include/HLAPI/TcpConnectionHandler.hpp
new file mode 100644
index 0000000..aa666be
--- /dev/null
+++ b/include/HLAPI/TcpConnectionHandler.hpp
@@ -0,0 +1,63 @@
+#pragma once
+
+#include
+#include
+#include
+
+#include
+#include
+
+//#include
+
+namespace std::net
+{
+ class MessageQueue;
+ class TcpConnection;
+ class Server;
+
+ namespace sockets
+ {
+ class TcpListener;
+ }
+}
+
+namespace std::net
+{
+ class TcpConnectionHandler
+ {
+ friend class std::net::Server;
+
+ public:
+ TcpConnectionHandler(std::shared_ptr listener_ptr);
+ ~TcpConnectionHandler();
+
+ void Start();
+ void Stop();
+ void AddClient(std::shared_ptr &c);
+ void SetMaxConnections(uint32_t max_connections);
+
+ uint32_t GetAvailableID();
+
+ private:
+ void HandleReceiveMsgAndConns();
+ void HandleSend();
+
+ void HandleReceiveMsgAndConnsThreaded();
+ void HandleSendThreaded();
+
+ private:
+ std::vector> m_list;
+ std::mutex m_listMutex;
+
+ uint32_t m_maxConnections;
+
+ std::thread m_receiveThread;
+ std::thread m_sendThread;
+
+ std::atomic_bool m_run;
+
+ std::shared_ptr m_queue;
+
+ std::shared_ptr m_listenerPtr;
+ };
+}
\ No newline at end of file
diff --git a/include/HLAPI/TcpServer.hpp b/include/HLAPI/TcpServer.hpp
new file mode 100644
index 0000000..8128000
--- /dev/null
+++ b/include/HLAPI/TcpServer.hpp
@@ -0,0 +1,31 @@
+#pragma once
+
+#include
+
+#include "TcpListener.hpp"
+
+namespace std::net
+{
+ class Server;
+ class TcpConnectionHandler;
+
+ class TcpServer
+ {
+ friend class std::net::Server;
+
+ public:
+ TcpServer(uint32_t max_connections, uint16_t port = DEFAULT_SERVER_PORT);
+
+ void Start();
+ void Stop();
+
+ private:
+ std::shared_ptr listener;
+ uint32_t m_maxConnections;
+ uint16_t m_port;
+
+ std::atomic_bool m_run;
+
+ std::shared_ptr m_connectionHandler;
+ };
+}
\ No newline at end of file
diff --git a/src/HLAPI/MessageQueue.cpp b/src/HLAPI/MessageQueue.cpp
new file mode 100644
index 0000000..6b18e5f
--- /dev/null
+++ b/src/HLAPI/MessageQueue.cpp
@@ -0,0 +1,52 @@
+#include "MessageQueue.hpp"
+
+namespace std::net
+{
+ void MessageQueue::EnqueueMessageToSend(const NetworkMessage & msg)
+ {
+ m_sendMutex.lock();
+ m_messagesToSend.emplace_back(msg);
+ m_sendMutex.unlock();
+ }
+
+ void MessageQueue::EnqueueMessageReceived(const NetworkMessage & msg)
+ {
+ m_receivedMutex.lock();
+ DataReceivedEvent ev(msg);
+ m_dataReceivedEvents.push_back(ev);
+ m_receivedMutex.unlock();
+ }
+
+ void MessageQueue::EnqueueDisconnection(const NetworkMessage & msg)
+ {
+ m_disconnectMutex.lock();
+ //std::unique_ptr ev(((NetworkMessage)msg).GetData());
+ //m_disconnectedEvents.push_back(*(ev.get()));
+ m_disconnectMutex.unlock();
+ }
+
+ void MessageQueue::EnqueueConnection(const NetworkMessage & msg)
+ {
+ m_connectionMutex.lock();
+ NewConnectionEvent ev(msg.GetSenderID(), msg.GetData());
+ m_connectionEvents.push_back(ev);
+ m_connectionMutex.unlock();
+ }
+
+ NetworkMessage MessageQueue::DequeueMessageToSend()
+ {
+ m_sendMutex.lock();
+ NetworkMessage msg = m_messagesToSend.front();
+ m_messagesToSend.erase(m_messagesToSend.begin() + 1);
+ m_sendMutex.unlock();
+ return msg;
+ }
+
+ uint32_t MessageQueue::SendSize()
+ {
+ m_sendMutex.lock();
+ uint32_t size = m_messagesToSend.size();
+ m_sendMutex.unlock();
+ return size;
+ }
+}
\ No newline at end of file
diff --git a/src/HLAPI/NetworkMessage.cpp b/src/HLAPI/NetworkMessage.cpp
new file mode 100644
index 0000000..42c968c
--- /dev/null
+++ b/src/HLAPI/NetworkMessage.cpp
@@ -0,0 +1,63 @@
+#include "NetworkMessage.hpp"
+
+namespace std::net
+{
+ uint32_t NetworkMessage::GetSenderID() const
+ {
+ return m_senderID;
+ }
+
+ DistributionMode NetworkMessage::GetDistributionMode() const
+ {
+ return m_distributionMode;
+ }
+
+ uint32_t NetworkMessage::GetDestinationID() const
+ {
+ return m_destinationID;
+ }
+
+ uint32_t NetworkMessage::GetTag() const
+ {
+ return m_tag;
+ }
+
+ uint8_t *NetworkMessage::SerializeData(uint32_t &size)
+ {
+ int32_t sizeOfNetHeader = sizeof(NetworkHeader);
+
+ NetworkHeader header;
+ header.Size = 13 + sizeOfNetHeader + m_dataSize;
+
+ uint8_t *bytes = new uint8_t[header.Size];
+ memcpy(bytes, &header, sizeOfNetHeader);
+
+ uint8_t *sender = BitConverter::ToBytes(m_senderID); // 4
+ uint8_t *destination = BitConverter::ToBytes(m_destinationID); // 4
+ uint8_t *tag = BitConverter::ToBytes(m_tag); // 4
+
+ memcpy(bytes + sizeOfNetHeader, sender, 4);
+ bytes[sizeOfNetHeader + 4] = (uint8_t)m_distributionMode;
+ memcpy(bytes + sizeOfNetHeader + 5, destination, 4);
+ memcpy(bytes + sizeOfNetHeader + 9, tag, 4);
+
+ memcpy(bytes + 13 + sizeOfNetHeader, m_data, m_dataSize);
+
+ size = header.Size;
+ return bytes;
+ }
+
+ void NetworkMessage::Deserialize(uint8_t *data, uint32_t size)
+ {
+ NetworkHeader buffer;
+ uint32_t sizeOfNetHeader = sizeof(NetworkHeader);
+ memcpy(&(buffer), data, sizeOfNetHeader);
+
+ memcpy(&(m_senderID), data + 4 + sizeOfNetHeader, 4);
+ m_distributionMode = (DistributionMode)data[8 + sizeOfNetHeader];
+ memcpy(&(m_destinationID), data + 5 + sizeOfNetHeader, 4);
+ memcpy(&(m_tag), data + 9 + sizeOfNetHeader, 4);
+
+ m_data = data + 13 + sizeOfNetHeader;
+ }
+}
\ No newline at end of file
diff --git a/src/HLAPI/Server.cpp b/src/HLAPI/Server.cpp
new file mode 100644
index 0000000..99d3888
--- /dev/null
+++ b/src/HLAPI/Server.cpp
@@ -0,0 +1,25 @@
+#include "Server.hpp"
+
+#include "MessageQueue.hpp"
+#include "TcpServer.hpp"
+//#include "UdpServer.hpp
+
+namespace std::net
+{
+ Server::Server(uint32_t max_connections, uint16_t port)
+ {
+ m_tcpServer = std::make_shared(max_connections, port);
+ m_queue = std::make_shared();
+ //m_tcpServer->m_connectionHandler->m_queue = m_queue;
+ }
+
+ void Server::Start()
+ {
+ m_tcpServer->Start();
+ }
+
+ void Server::Stop()
+ {
+ m_tcpServer->Stop();
+ }
+}
\ No newline at end of file
diff --git a/src/HLAPI/TcpConnection.cpp b/src/HLAPI/TcpConnection.cpp
new file mode 100644
index 0000000..490f1c1
--- /dev/null
+++ b/src/HLAPI/TcpConnection.cpp
@@ -0,0 +1,72 @@
+#include "TcpConnection.hpp"
+
+#include "InternalTags.hpp"
+
+namespace std::net
+{
+ TcpConnection::TcpConnection(TcpClient * client)
+ : m_client(client)
+ {
+ }
+
+ std::shared_ptr TcpConnection::GetClient()
+ {
+ return m_client;
+ }
+
+ uint32_t TcpConnection::GetID()
+ {
+ return m_id;
+ }
+
+ void TcpConnection::SetID(uint32_t id)
+ {
+ m_id = id;
+ }
+
+ bool TcpConnection::sendMessage(NetworkMessage & msg)
+ {
+ uint32_t size;
+ uint8_t *data = msg.SerializeData(size);
+ int32_t sent;
+ return m_client->Send(data, size, sent);
+ }
+
+ void TcpConnection::ReceiveData()
+ {
+ std::unique_ptr header(new uint8_t[sizeof(NetworkHeader*)]());
+
+ int32_t read;
+ if (!m_client->Recv(header.get(), sizeof(NetworkHeader*), read))
+ return;
+
+ if (read == sizeof(NetworkHeader*))
+ {
+ std::unique_ptr net_header((NetworkHeader*)header.get());
+
+ std::unique_ptr buffer(new uint8_t[net_header->Size]());
+ int32_t read;
+ if (!m_client->Recv(buffer.get(), net_header->Size, read))
+ {
+ if (read != net_header->Size)
+ return; // wrong message?
+
+ NetworkMessage msg;
+ msg.Deserialize(buffer.get(), net_header->Size);
+
+ if (msg.GetTag() == (uint32_t)InternalTags::Disconnect)
+ {
+ //DisconnectedEvent(msg.m_senderID, );
+ }
+ else if (msg.GetTag() == (uint32_t)InternalTags::Connect)
+ NewConnectionEvent(msg.GetSenderID(), msg.GetData());
+ else
+ DataReceivedEvent(msg.GetSenderID(), msg.GetDistributionMode(), msg.GetDestinationID(), msg.GetTag(), msg.GetData());
+ }
+ }
+ else // wrong message
+ {
+ return;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/HLAPI/TcpConnectionHandler.cpp b/src/HLAPI/TcpConnectionHandler.cpp
new file mode 100644
index 0000000..5278c0c
--- /dev/null
+++ b/src/HLAPI/TcpConnectionHandler.cpp
@@ -0,0 +1,306 @@
+#include "TcpConnectionHandler.hpp"
+
+#include "DisconnectedEvent.hpp"
+#include "NewConnectionEvent.hpp"
+#include "InternalTags.hpp"
+
+#include "NetworkMessage.hpp"
+#include "MessageQueue.hpp"
+#include "TcpConnection.hpp"
+#include "TcpListener.hpp"
+
+#include
+
+namespace std::net
+{
+ TcpConnectionHandler::TcpConnectionHandler(std::shared_ptr listener_ptr)
+ : m_run(false)
+ , m_listenerPtr(listener_ptr)
+ , m_queue(new MessageQueue())
+ {
+ }
+
+ TcpConnectionHandler::~TcpConnectionHandler()
+ {
+ m_run.exchange(false);
+ }
+
+ void TcpConnectionHandler::Start()
+ {
+ m_run.exchange(true);
+ std::thread receive_thread(&TcpConnectionHandler::HandleReceiveMsgAndConnsThreaded, this);
+ m_receiveThread.swap(receive_thread);
+
+ //std::thread send_thread(&TcpConnectionHandler::HandleSendThreaded, this);
+ //m_sendThread.swap(send_thread);
+ }
+
+ void TcpConnectionHandler::Stop()
+ {
+ m_run.exchange(false);
+ }
+
+ void TcpConnectionHandler::AddClient(std::shared_ptr &c)
+ {
+ uint32_t id = GetAvailableID();
+ if (id == -1)
+ {
+ // this can be handled just by the server
+ // what if the server owner wants to know if a user wanted to join but couldnt
+ DisconnectedEvent disconnected_event(id, "Server Full", -1);
+ std::shared_ptr client = c->GetClient();
+ /*int32_t size = 0;
+ uint8_t *buffer = disconnected_event.Serialize(size);
+ int32_t sent = 0;
+ client->Send(buffer, size, sent);*/
+ client->Close();
+ }
+
+ c->SetID(id);
+
+ uint32_t *id_ptr = &id;
+
+ NetworkMessage msg(0, DistributionMode::ID, id, (uint32_t)InternalTags::AssignID, id_ptr, sizeof(id_ptr));
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(50));
+
+ uint32_t serialized_size;
+ uint8_t *serialized_data = msg.SerializeData(serialized_size);
+ int32_t sent;
+ if (!c->GetClient()->Send(serialized_data, serialized_size, sent))
+ {
+ //couldnt send
+ return;
+ }
+
+ m_listMutex.lock();
+ m_list.push_back(c);
+ m_listMutex.unlock();
+
+ m_queue->EnqueueConnection(msg);
+ }
+
+ uint32_t TcpConnectionHandler::GetAvailableID()
+ {
+ for (int i = 1; i <= m_maxConnections; i++)
+ {
+ bool flag = true;
+ m_listMutex.lock();
+ for (int k = 0; k < m_list.size(); k++)
+ {
+ if (m_list.at(k)->GetID() == i)
+ flag = false;
+ }
+ m_listMutex.unlock();
+
+ if (flag)
+ return i;
+ }
+
+ //throw OutOfRangeException("Out of IDs to allocate - clients = max connections", "NewConnectionEventPool");
+ return -1;
+ }
+
+ void TcpConnectionHandler::SetMaxConnections(uint32_t max_connections)
+ {
+ m_maxConnections = max_connections;
+ }
+
+ void TcpConnectionHandler::HandleReceiveMsgAndConns()
+ {
+ // https://www.ibm.com/support/knowledgecenter/en/ssw_i5_54/rzab6/poll.htm
+ std::vector poll_fds;
+ pollfd master_fd;
+ master_fd.fd = m_listenerPtr->m_socket->GetNativeSocket();
+ master_fd.events = POLLRDNORM;
+ poll_fds.emplace_back(master_fd);
+
+ for (size_t i = 0; i < m_list.size(); i++)
+ {
+ pollfd client_fd;
+ client_fd.fd = m_list.at(i)->m_client->m_socket->GetNativeSocket();
+ client_fd.events = POLLRDNORM;
+ poll_fds.emplace_back(client_fd);
+ }
+
+ int res = poll(poll_fds.data(), poll_fds.size(), -1);
+
+ if (res < 0)
+ {
+ //poll error
+ }
+
+ //should never timeout because its infinite (negative)
+ //if (res == 0)
+ //{
+ //timeout
+ //}
+
+ for (int i = 0; i < poll_fds.size(); i++)
+ {
+ if (poll_fds.at(i).revents == 0)
+ continue;
+
+ if (poll_fds[i].revents != POLLRDNORM)
+ {
+ continue;
+ }
+ if (poll_fds.at(i).fd == m_listenerPtr->m_socket->GetNativeSocket())
+ {
+ TcpClient *c = m_listenerPtr->AcceptClient();
+ if (c)
+ {
+ std::shared_ptr connection = std::make_shared(c);
+ AddClient(connection);
+ break;
+ }
+ }
+ else // not the listening socket
+ {
+ SOCKET c = poll_fds.at(i).fd;
+ std::unique_ptr header(new uint8_t[sizeof(NetworkHeader*)]());
+
+ int32_t read;
+ if ((read = recv(c, (char*)header.get(), sizeof(NetworkHeader*), 0)) != sizeof(NetworkHeader*))
+ continue;
+
+ std::unique_ptr net_header((NetworkHeader*)header.get());
+ std::unique_ptr buffer(new uint8_t[net_header->Size]());
+
+ if ((read = recv(c, (char*)buffer.get(), net_header->Size, 0)) == net_header->Size)
+ {
+ NetworkMessage msg;
+ msg.Deserialize(buffer.get(), net_header->Size);
+
+ if (msg.GetTag() == (uint32_t)InternalTags::Disconnect)
+ m_queue->EnqueueDisconnection(msg);
+ else if (msg.GetTag() == (uint32_t)InternalTags::Connect)
+ m_queue->EnqueueConnection(msg);
+ else
+ m_queue->EnqueueMessageReceived(msg);
+ }
+ else
+ continue;
+ }
+ }
+ }
+
+ void TcpConnectionHandler::HandleSend()
+ {
+ if (m_queue->SendSize() > 0)
+ {
+ NetworkMessage msg = m_queue->DequeueMessageToSend();
+
+ uint32_t size;
+ std::unique_ptr data(msg.SerializeData(size));
+
+ if (msg.GetDistributionMode() == DistributionMode::Others)
+ {
+ m_listMutex.lock();
+ for (int i = 0; i < m_list.size(); i++)
+ {
+ std::shared_ptr c = m_list.at(i);
+ if (c->GetID() != msg.GetSenderID())
+ {
+ int32_t sent;
+ if (!c->GetClient()->Send(data.get(), size, sent))
+ {
+ // it failed - retry? or just disconnect right in the first try
+ }
+ }
+ }
+ m_listMutex.unlock();
+ }
+ else if (msg.GetDistributionMode() == DistributionMode::OthersAndServer)
+ {
+ m_listMutex.lock();
+ for (int i = 0; i < m_list.size(); i++)
+ {
+ std::shared_ptr c = m_list.at(i);
+ if (c->GetID() != msg.GetSenderID())
+ {
+ int32_t sent;
+ if (!c->GetClient()->Send(data.get(), size, sent))
+ {
+ // it failed - retry? or just disconnect right in the first try
+ }
+ }
+ }
+ m_listMutex.unlock();
+
+ //handle to plugins too
+ }
+ else if (msg.GetDistributionMode() == DistributionMode::ID)
+ {
+ m_listMutex.lock();
+ for (int i = 0; i < m_list.size(); i++)
+ {
+ std::shared_ptr c = m_list.at(i);
+ if (c->GetID() == msg.GetSenderID())
+ {
+ int32_t sent;
+ if (!c->GetClient()->Send(data.get(), size, sent))
+ {
+ // it failed - retry? or just disconnect right in the first try
+ }
+ }
+ }
+ m_listMutex.unlock();
+ }
+ else if (msg.GetDistributionMode() == DistributionMode::All)
+ {
+ m_listMutex.lock();
+ for (int i = 0; i < m_list.size(); i++)
+ {
+ std::shared_ptr c = m_list.at(i);
+
+ int32_t sent;
+ if (!c->GetClient()->Send(data.get(), size, sent))
+ {
+ // it failed - retry? or just disconnect right in the first try
+ }
+ }
+ m_listMutex.unlock();
+ }
+ else if (msg.GetDistributionMode() == DistributionMode::AllAndMe)
+ {
+ m_listMutex.lock();
+ for (int i = 0; i < m_list.size(); i++)
+ {
+ std::shared_ptr c = m_list.at(i);
+
+ int32_t sent;
+ if (!c->GetClient()->Send(data.get(), size, sent))
+ {
+ // it failed - retry? or just disconnect right in the first try
+ }
+ }
+ m_listMutex.unlock();
+
+ //handle to plugins too
+ }
+ else if (msg.GetDistributionMode() == DistributionMode::Server)
+ {
+ //handle just in plugins
+ }
+ }
+ }
+
+ void TcpConnectionHandler::HandleReceiveMsgAndConnsThreaded()
+ {
+ while (m_run.load())
+ {
+ HandleReceiveMsgAndConns();
+ std::this_thread::sleep_for(std::chrono::milliseconds(5));
+ }
+ }
+
+ void TcpConnectionHandler::HandleSendThreaded()
+ {
+ while (m_run.load())
+ {
+ HandleSend();
+ std::this_thread::sleep_for(std::chrono::milliseconds(5));
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/HLAPI/TcpServer.cpp b/src/HLAPI/TcpServer.cpp
new file mode 100644
index 0000000..778f451
--- /dev/null
+++ b/src/HLAPI/TcpServer.cpp
@@ -0,0 +1,33 @@
+#include "TcpServer.hpp"
+
+#include "TcpConnection.hpp"
+#include "TcpSocketBuilder.hpp"
+#include "TcpClient.hpp"
+#include "TcpConnectionHandler.hpp"
+
+namespace std::net
+{
+ TcpServer::TcpServer(uint32_t max_connections, uint16_t port)
+ : m_maxConnections(max_connections)
+ , m_port(port)
+ , m_run(false)
+ {
+ if (max_connections == 0 || port == 0)
+ throw std::invalid_argument("TcpServer::TcpServer()");
+
+ listener = std::shared_ptr(TcpSocketBuilder().AsReusable().Bind(IPAddress(0, 0, 0, 0, port)).Listening().BuildListener().release());
+ m_connectionHandler = std::make_shared(listener);
+ m_connectionHandler->SetMaxConnections(max_connections);
+ }
+
+ void TcpServer::Start()
+ {
+ m_run = true;
+ m_connectionHandler->Start();
+ }
+
+ void TcpServer::Stop()
+ {
+ m_run.exchange(false);
+ }
+}
\ No newline at end of file
diff --git a/src/HLAPI/main.cpp b/src/HLAPI/main.cpp
new file mode 100644
index 0000000..ac90fc3
--- /dev/null
+++ b/src/HLAPI/main.cpp
@@ -0,0 +1,58 @@
+#include "Init.hpp"
+#include "Server.hpp"
+#include "BitConverter.hpp"
+#include "TcpClient.hpp"
+#include "InternalTags.hpp"
+#include "NetworkMessage.hpp"
+
+#include
+
+int main()
+{
+ std::net::Initialize();
+ std::net::Server server(100);
+ server.Start();
+
+ std::net::TcpClient client;
+ std::net::IPAddress ip("127.0.0.1");
+ client.Connect(ip);
+
+ std::net::TcpClient client2;
+ client2.Connect(ip);
+
+ while (true)
+ {
+ uint32_t data_size;
+ while (client.HasPendingData(data_size))
+ {
+ std::net::NetworkMessage message;
+
+ uint8_t *bytes = new uint8_t[data_size]();
+
+ int32_t read;
+ client.Recv(bytes, data_size, read);
+
+ message.Deserialize(bytes, data_size);
+
+ uint32_t id = std::BitConverter::FromBytes((uint8_t*)(message.GetData()));
+ if (message.GetTag() == (uint32_t)InternalTags::AssignID)
+ std::cout << id << std::endl;
+ }
+
+ while (client2.HasPendingData(data_size))
+ {
+ std::net::NetworkMessage message2;
+
+ uint8_t* bytes2 = new uint8_t[data_size]();
+
+ int32_t read2;
+ client2.Recv(bytes2, data_size, read2);
+
+ message2.Deserialize(bytes2, data_size);
+
+ uint32_t id2 = std::BitConverter::FromBytes((uint8_t*)(message2.GetData()));
+ if (message2.GetTag() == (uint32_t)InternalTags::AssignID)
+ std::cout << id2 << std::endl;
+ }
+ }
+}
\ No newline at end of file