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(); }