diff --git a/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/CL.command.1.tlog b/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/CL.command.1.tlog
index aee5b93..81ec6bd 100644
Binary files a/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/CL.command.1.tlog and b/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/CL.command.1.tlog differ
diff --git a/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/CL.read.1.tlog b/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/CL.read.1.tlog
index a9af9a2..9611acb 100644
Binary files a/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/CL.read.1.tlog and b/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/CL.read.1.tlog differ
diff --git a/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/CL.write.1.tlog b/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/CL.write.1.tlog
index 7bfdec6..83f3455 100644
Binary files a/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/CL.write.1.tlog and b/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/CL.write.1.tlog differ
diff --git a/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/Lib-link.write.1.tlog b/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/Lib-link.write.1.tlog
index 47d98bc..844b0b5 100644
Binary files a/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/Lib-link.write.1.tlog and b/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/Lib-link.write.1.tlog differ
diff --git a/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/Lib.read.1.tlog b/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/Lib.read.1.tlog
index 3ab96a9..ed0af5f 100644
Binary files a/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/Lib.read.1.tlog and b/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/Lib.read.1.tlog differ
diff --git a/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/lib.command.1.tlog b/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/lib.command.1.tlog
index 0e35fa9..5b549a6 100644
Binary files a/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/lib.command.1.tlog and b/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/lib.command.1.tlog differ
diff --git a/VoidNetVS/VoidNetVS/VoidNetVS.vcxproj b/VoidNetVS/VoidNetVS/VoidNetVS.vcxproj
index c11f398..d95fb5e 100644
--- a/VoidNetVS/VoidNetVS/VoidNetVS.vcxproj
+++ b/VoidNetVS/VoidNetVS/VoidNetVS.vcxproj
@@ -30,7 +30,6 @@
-
diff --git a/VoidNetVS/VoidNetVS/VoidNetVS.vcxproj.filters b/VoidNetVS/VoidNetVS/VoidNetVS.vcxproj.filters
index 4c911af..2f6aa11 100644
--- a/VoidNetVS/VoidNetVS/VoidNetVS.vcxproj.filters
+++ b/VoidNetVS/VoidNetVS/VoidNetVS.vcxproj.filters
@@ -39,9 +39,6 @@
include
-
- include
-
include
diff --git a/include/Defs.hpp b/include/Defs.hpp
index 7da81c1..a770c77 100644
--- a/include/Defs.hpp
+++ b/include/Defs.hpp
@@ -167,7 +167,8 @@ typedef unsigned long long uint64;
#endif // compiler data type defenitions
-const uint16 default_port = 60250;
+const uint16 default_client_port = 60250;
+const uint16 default_server_port = 61250;
enum DistributionType
{
@@ -178,4 +179,10 @@ enum DistributionType
ID,
};
+enum ConnectionCode
+{
+ Accept = 0,
+ Reject
+};
+
#endif // DEFS_HPP
\ No newline at end of file
diff --git a/include/NetworkMessage.hpp b/include/NetworkMessage.hpp
index ca9f8d3..5a1c9a8 100644
--- a/include/NetworkMessage.hpp
+++ b/include/NetworkMessage.hpp
@@ -29,8 +29,8 @@ struct NetworkMessage
bool valid = false;
private:
- const NetworkMessage &NetworkMessage::DecodeMessageHeader(const NetworkBuffer &buffer);
- void *DecodeMessageData(const NetworkBuffer &buffer);
+ const NetworkMessage &decode_message_header(const NetworkBuffer &buffer);
+ void *decode_message_data(const NetworkBuffer &buffer);
NetworkBuffer buffer;
};
diff --git a/include/TcpClient.hpp b/include/TcpClient.hpp
index 6ef6c08..cdd6948 100644
--- a/include/TcpClient.hpp
+++ b/include/TcpClient.hpp
@@ -16,8 +16,9 @@
class TcpClient
{
public:
- TcpClient();
- TcpClient(const std::string &ip, uint16 port = default_port);
+ TcpClient(const SOCKET &socket);
+ TcpClient(const std::string &ip);
+ TcpClient(const std::string &ip, uint16 port = default_client_port);
~TcpClient();
const std::string &GetIP();
@@ -26,9 +27,13 @@ public:
uint16 GetPort();
void SetPort(uint16 port);
+ uint16 GetID();
+ void SetID(uint16 id);
+
bool Connect();
void ReceiveMessages();
+ const NetworkMessage &ReceiveMessage();
void SendMessage(const NetworkMessage &message);
std::function OnDisconnect;
@@ -36,11 +41,12 @@ public:
std::function OnMessage;
private:
- const NetworkBuffer &ReceiveDataArray();
- static void ReceiveData(TcpClient *client);
- static void SendNetworkMessage(const NetworkMessage &message, TcpClient *client);
- bool Initialize(const std::string &ip, uint16 port = default_port);
+ const NetworkBuffer &receive_data_array();
+ static void receive_data(TcpClient *client);
+ static void send_network_message(const NetworkMessage &message, TcpClient *client);
+ bool initialize(const std::string &ip, uint16 port = default_client_port);
+ uint16 id = 0;
std::string ip;
uint16 port = 0;
bool initialized = false;
@@ -49,7 +55,6 @@ private:
#ifdef _MSC_VER
SOCKET tcp_socket = INVALID_SOCKET;
struct addrinfo *result = nullptr;
- struct addrinfo *ptr = nullptr;
struct addrinfo hints;
#endif
};
diff --git a/include/TcpServer.hpp b/include/TcpServer.hpp
index 5209748..caf6eb1 100644
--- a/include/TcpServer.hpp
+++ b/include/TcpServer.hpp
@@ -3,6 +3,60 @@
#ifdef _MSC_VER
#pragma once
-#endif
+#endif
+
+#include "Defs.hpp"
+#include "TcpClient.hpp"
+
+#include
+
+#ifdef _MSC_VER
+#undef SendMessage
+#endif
+
+class TcpServer
+{
+public:
+ TcpServer();
+ TcpServer(uint16 port = default_server_port);
+ ~TcpServer();
+
+ uint16 AllocateID();
+ void AddToClientsList(const TcpClient &client);
+ bool StartServer(bool accept_connections);
+ void AcceptConnections();
+ void SendMessage(const NetworkMessage &message);
+
+ void RejectConnection(TcpClient &client);
+
+ std::function OnMessage;
+
+private:
+ static void process_message(TcpServer *server, const NetworkMessage &message);
+ static void process_client_received_data(TcpServer *server);
+ static void accept_connections(TcpServer *server);
+ bool initialize(uint16 port = default_server_port);
+
+ bool initialized = false;
+ bool running = false;
+
+ uint16 max_connections = 0;
+
+ std::vector clients;
+
+#ifdef _MSC_VER
+ SOCKET socket = INVALID_SOCKET;
+ struct addrinfo *result = nullptr;
+ struct addrinfo hints;
+#endif
+};
+
+#ifdef _MSC_VER
+#ifdef UNICODE
+#define SendMessage SendMessageW
+#else
+#define SendMessage SendMessageA
+#endif // !UNICODE
+#endif
#endif
diff --git a/include/VoidNetClient.hpp b/include/VoidNetClient.hpp
index effcda5..54baa39 100644
--- a/include/VoidNetClient.hpp
+++ b/include/VoidNetClient.hpp
@@ -18,7 +18,7 @@
struct VoidNetClientAPI
{
- static bool Connect(const std::string &ip, uint16 port = default_port);
+ static bool Connect(const std::string &ip, uint16 port = default_client_port);
static void Disconnect();
static void SendMessageToServer(byte tag, byte subject, void *data);
@@ -32,7 +32,7 @@ struct VoidNetClientAPI
static void Receive();
private:
- static void ProcessAllData();
+ static void process_all_data();
static TcpClient *client;
static uint16 id;
diff --git a/src/NetworkMessage.cpp b/src/NetworkMessage.cpp
index 2824f72..ad45585 100644
--- a/src/NetworkMessage.cpp
+++ b/src/NetworkMessage.cpp
@@ -53,12 +53,12 @@ const NetworkBuffer &NetworkMessage::EncodeMessage(const NetworkMessage &message
const NetworkMessage &NetworkMessage::DecodeMessage(const NetworkBuffer &buffer)
{
- NetworkMessage message = DecodeMessageHeader(buffer);
- message.data = DecodeMessageData(buffer);
+ NetworkMessage message = decode_message_header(buffer);
+ message.data = decode_message_data(buffer);
return message;
}
-void *NetworkMessage::DecodeMessageData(const NetworkBuffer &buffer)
+void *NetworkMessage::decode_message_data(const NetworkBuffer &buffer)
{
if (buffer.body_size < 9)
return nullptr;
@@ -78,7 +78,7 @@ void *NetworkMessage::DecodeMessageData(const NetworkBuffer &buffer)
}
}
-const NetworkMessage &NetworkMessage::DecodeMessageHeader(const NetworkBuffer &buffer)
+const NetworkMessage &NetworkMessage::decode_message_header(const NetworkBuffer &buffer)
{
sender = Utility::BitConverter::ToUint16(buffer.body, 1);
distribution_mode = buffer.body[3];
diff --git a/src/TcpClientWindows.cpp b/src/TcpClientWindows.cpp
index 0e35cf2..f4e84bc 100644
--- a/src/TcpClientWindows.cpp
+++ b/src/TcpClientWindows.cpp
@@ -10,7 +10,7 @@
#undef SendMessage
-bool TcpClient::Initialize(const std::string &ip, uint16 port)
+bool TcpClient::initialize(const std::string &ip, uint16 port)
{
if (ip.size() == 0 || std::count(ip.begin(), ip.end(), '.') != 4)
return false;
@@ -30,8 +30,7 @@ bool TcpClient::Initialize(const std::string &ip, uint16 port)
return false;
}
- ptr = result;
- tcp_socket = ::socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
+ tcp_socket = ::socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (tcp_socket == INVALID_SOCKET)
{
@@ -42,17 +41,23 @@ bool TcpClient::Initialize(const std::string &ip, uint16 port)
return false;
}
- initialized = true;
- return true;
+ return initialized = true;
}
-TcpClient::TcpClient() : port(default_port)
+TcpClient::TcpClient(const SOCKET & socket)
{
+ tcp_socket = socket;
+}
+
+TcpClient::TcpClient(const std::string &ip) : port(default_client_port)
+{
+ initialize(ip);
}
TcpClient::TcpClient(const std::string &ip, uint16 port) :
ip(ip), port(port)
{
+ initialize(ip, port);
}
TcpClient::~TcpClient()
@@ -60,7 +65,6 @@ TcpClient::~TcpClient()
freeaddrinfo(result);
WSACleanup();
Utility::Delete(result);
- Utility::Delete(ptr);
}
const std::string &TcpClient::GetIP()
@@ -83,6 +87,16 @@ void TcpClient::SetPort(uint16 port)
this->port = port;
}
+uint16 TcpClient::GetID()
+{
+ return id;
+}
+
+void TcpClient::SetID(uint16 id)
+{
+ this->id = id;
+}
+
bool TcpClient::Connect()
{
if (!initialized)
@@ -91,17 +105,17 @@ bool TcpClient::Connect()
return false;
if (port == 0)
return false;
- if (Initialize(ip, port) != true)
+ if (initialize(ip, port) != true)
return false;
}
- uint16 connect_code = ::connect(tcp_socket, ptr->ai_addr, ptr->ai_addrlen);
+ uint16 connect_code = ::connect(tcp_socket, result->ai_addr, result->ai_addrlen);
if (connect_code == SOCKET_ERROR)
return false;
receive = true;
return true;
}
-const NetworkBuffer &TcpClient::ReceiveDataArray()
+const NetworkBuffer &TcpClient::receive_data_array()
{
NetworkBuffer buffer;
@@ -122,11 +136,11 @@ const NetworkBuffer &TcpClient::ReceiveDataArray()
return buffer;
}
-void TcpClient::ReceiveData(TcpClient *client)
+void TcpClient::receive_data(TcpClient *client)
{
while (client->receive)
{
- NetworkMessage message(client->ReceiveDataArray());
+ NetworkMessage message(client->receive_data_array());
if (message.valid)
{
if (message.tag == CONNECT) // some user has connected
@@ -141,10 +155,15 @@ void TcpClient::ReceiveData(TcpClient *client)
void TcpClient::ReceiveMessages()
{
- std::async(std::launch::async, &ReceiveData, this);
+ std::async(std::launch::async, &receive_data, this);
}
-void TcpClient::SendNetworkMessage(const NetworkMessage &message, TcpClient *client)
+const NetworkMessage & TcpClient::ReceiveMessage()
+{
+ return receive_data_array();
+}
+
+void TcpClient::send_network_message(const NetworkMessage &message, TcpClient *client)
{
NetworkBuffer buffer = message.EncodeMessage(message);
int32 bytes_sent = send(client->tcp_socket, reinterpret_cast(buffer.body), buffer.body_size, 0);
@@ -156,5 +175,5 @@ void TcpClient::SendNetworkMessage(const NetworkMessage &message, TcpClient *cli
void TcpClient::SendMessage(const NetworkMessage &message)
{
- std::async(std::launch::async, &SendNetworkMessage, message, this);
-}
\ No newline at end of file
+ std::async(std::launch::async, &send_network_message, message, this);
+}
diff --git a/src/TcpServerWindows.cpp b/src/TcpServerWindows.cpp
index 261319a..8aea990 100644
--- a/src/TcpServerWindows.cpp
+++ b/src/TcpServerWindows.cpp
@@ -1 +1,231 @@
-#include "TcpClient.hpp"
\ No newline at end of file
+#include "TcpServer.hpp"
+#include "Config.hpp"
+#include "Utility.hpp"
+
+#include
+#include
+#include
+
+#undef SendMessage
+
+bool TcpServer::initialize(uint16 port)
+{
+ ZeroMemory(&hints, sizeof(hints));
+ hints.ai_family = AF_INET;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+ hints.ai_flags = AI_PASSIVE;
+
+ uint16 code = getaddrinfo(0, std::to_string(port).c_str(), &hints, &result);
+ if (code != 0)
+ {
+ if (Config::GetUsingConsole())
+ std::cerr << WSAGetLastError() << std::endl; // display more info
+ WSACleanup();
+ return false;
+ }
+
+ socket = ::socket(result->ai_family, result->ai_socktype, result->ai_protocol);
+
+ if (socket == INVALID_SOCKET)
+ {
+ if (Config::GetUsingConsole())
+ std::cerr << WSAGetLastError() << std::endl; // display more info
+ freeaddrinfo(result);
+ WSACleanup();
+ return false;
+ }
+
+ code = bind(socket, result->ai_addr, result->ai_addrlen);
+ if (code == SOCKET_ERROR)
+ {
+ if (Config::GetUsingConsole())
+ std::cerr << WSAGetLastError() << std::endl; // display more info
+ freeaddrinfo(result);
+ closesocket(socket);
+ WSACleanup();
+ return false;
+ }
+
+ freeaddrinfo(result);
+ return initialized = true;
+}
+
+TcpServer::TcpServer()
+{
+ initialize(); // initialize with the default port
+}
+
+TcpServer::TcpServer(uint16 port)
+{
+ initialize(port);
+}
+
+TcpServer::~TcpServer()
+{
+ freeaddrinfo(result);
+ WSACleanup();
+ Utility::Delete(result);
+}
+
+bool TcpServer::StartServer(bool accept_connections)
+{
+ if (listen(socket, SOMAXCONN) == SOCKET_ERROR)
+ {
+ if (Config::GetUsingConsole())
+ std::cerr << WSAGetLastError() << std::endl;
+ closesocket(socket);
+ WSACleanup();
+ return false;
+ }
+
+ if (accept_connections)
+ AcceptConnections();
+
+ return true;
+}
+
+void TcpServer::AcceptConnections()
+{
+ running = true;
+ std::async(std::launch::async, &accept_connections, this);
+}
+
+void TcpServer::accept_connections(TcpServer *server)
+{
+ std::async(std::launch::async, &process_client_received_data, server);
+ while (server->running)
+ {
+ SOCKET client_socket = accept(server->socket, 0, 0);
+ if (client_socket == INVALID_SOCKET)
+ {
+ if (Config::GetUsingConsole())
+ std::cerr << WSAGetLastError() << std::endl;
+ closesocket(server->socket);
+ WSACleanup();
+ server->running = false;
+ break;
+ }
+
+ server->AddToClientsList(TcpClient(client_socket));
+ }
+}
+
+void TcpServer::process_client_received_data(TcpServer *server)
+{
+ while (server->running) // we only process the data if we are receiving connections,
+ {
+ for (std::vector::iterator it = server->clients.begin(); it != server->clients.end(); ++it)
+ {
+ TcpClient client = *it;
+ NetworkMessage message(client.ReceiveMessage());
+ std::async(std::launch::async, &process_message, server, message); // we start an async task so that we dont bottleneck the receiver
+ }
+ }
+}
+
+void TcpServer::process_message(TcpServer * server, const NetworkMessage & message)
+{
+ if (message.valid)
+ server->SendMessage(message);
+}
+
+void TcpServer::SendMessage(const NetworkMessage & message)
+{
+ switch (message.distribution_mode)
+ {
+ case All: // this will send the message to all except the user that sent it
+ {
+ for (std::vector::iterator it = clients.begin(); it != clients.end(); ++it)
+ {
+ TcpClient client = *it;
+ if (message.sender != client.GetID())
+ client.SendMessage(message);
+ }
+ OnMessage(message);
+ break;
+ }
+ case AllAndMe: // this will send the message to EVERYONE including the user that sent it
+ {
+ for (std::vector::iterator it = clients.begin(); it != clients.end(); ++it)
+ {
+ TcpClient client = *it;
+ client.SendMessage(message);
+ }
+ OnMessage(message);
+ break;
+ }
+ case Server: // this will only send the message to the server
+ {
+ OnMessage(message);
+ break;
+ }
+ case Others: // this will send the message to others, excluding server and the user that sent it
+ {
+ for (std::vector::iterator it = clients.begin(); it != clients.end(); ++it)
+ {
+ TcpClient client = *it;
+ client.SendMessage(message);
+ }
+ break;
+ }
+ case ID: // this will send the message to a specific id
+ {
+ for (std::vector::iterator it = clients.begin(); it != clients.end(); ++it)
+ {
+ TcpClient client = *it;
+ if (message.sender == client.GetID())
+ {
+ client.SendMessage(message);
+ break;
+ }
+ }
+ break;
+ }
+ }
+}
+
+uint16 TcpServer::AllocateID() // this function is only used in the AddToClientsList function
+{
+ for (uint16 i = 1; i < max_connections; ++i)
+ {
+ bool flag = true;
+ for (std::vector::iterator it = clients.begin(); it != clients.end(); ++it)
+ {
+ if ((*it).GetID() == i)
+ {
+ flag = false;
+ break;
+ }
+ }
+
+ if (flag)
+ return i;
+ }
+ return 0;
+}
+
+void TcpServer::AddToClientsList(const TcpClient & client_socket)
+{
+ TcpClient client(client_socket);
+ uint16 id = AllocateID();
+ if (id > 0)
+ {
+ client.SetID(id);
+ clients.emplace_back(client);
+ }
+ else
+ {
+ if (Config::GetUsingConsole())
+ std::cout << "No available ID's" << std::endl;
+ RejectConnection(client);
+ }
+}
+
+void TcpServer::RejectConnection(TcpClient &client)
+{
+ NetworkMessage message;
+ message.sender = -1;
+ message.tag = Reject; // 0 for rejected connection
+ client.SendMessage(message);
+}
\ No newline at end of file
diff --git a/src/VoidNetClient.cpp b/src/VoidNetClient.cpp
index a443b0b..391acf7 100644
--- a/src/VoidNetClient.cpp
+++ b/src/VoidNetClient.cpp
@@ -2,6 +2,8 @@
#include "Utility.hpp"
#include "Tags.hpp"
+#include
+
#undef SendMessage
bool VoidNetClientAPI::Connect(const std::string &ip, uint16 port)
@@ -50,11 +52,10 @@ void VoidNetClientAPI::SendMessage(byte distribution_mode, uint16 destination_id
void VoidNetClientAPI::Receive()
{
- receive_thread = std::thread(ProcessAllData);
- receive_thread.detach();
+ std::async(std::launch::async, &process_all_data);
}
-void VoidNetClientAPI::ProcessAllData()
+void VoidNetClientAPI::process_all_data()
{
client->ReceiveMessages();
}