From 6fa7872a6d61943d1ed484a0427aab29f0959426 Mon Sep 17 00:00:00 2001 From: xX-TheDoctor-Xx Date: Fri, 22 Jul 2016 00:32:53 +0100 Subject: [PATCH] Added Connection Codes Private methods dont have capital letters and are words are separated by underscores Added id's to TcpClient's class Removed ptr from TcpClient and Server Worked on TcpServer Theres now a default server port Added ReceiveMessage function to TcpClient to receive only 1 message Fixed VoidNetClientAPI Receive function --- .../Release/VoidNetVS.tlog/CL.command.1.tlog | Bin 5346 -> 5934 bytes .../Release/VoidNetVS.tlog/CL.read.1.tlog | Bin 189710 -> 219862 bytes .../Release/VoidNetVS.tlog/CL.write.1.tlog | Bin 4848 -> 6394 bytes .../VoidNetVS.tlog/Lib-link.write.1.tlog | Bin 1074 -> 950 bytes .../Release/VoidNetVS.tlog/Lib.read.1.tlog | Bin 2470 -> 2220 bytes .../Release/VoidNetVS.tlog/lib.command.1.tlog | Bin 1522 -> 1338 bytes VoidNetVS/VoidNetVS/VoidNetVS.vcxproj | 1 - VoidNetVS/VoidNetVS/VoidNetVS.vcxproj.filters | 3 - include/Defs.hpp | 9 +- include/NetworkMessage.hpp | 4 +- include/TcpClient.hpp | 19 +- include/TcpServer.hpp | 56 ++++- include/VoidNetClient.hpp | 4 +- src/NetworkMessage.cpp | 8 +- src/TcpClientWindows.cpp | 51 ++-- src/TcpServerWindows.cpp | 232 +++++++++++++++++- src/VoidNetClient.cpp | 7 +- 17 files changed, 353 insertions(+), 41 deletions(-) diff --git a/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/CL.command.1.tlog b/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/CL.command.1.tlog index aee5b9382bb5c6406e9cc4e6e2fa05cd56145248..81ec6bd45c7f66d31db0b810c5e01995084e15e4 100644 GIT binary patch delta 83 zcmaE)xlV7xESAm7xHFh0rwA!+mSg|G2xK@--oU1|`2fosHuhi!SB4;lu+8gP7?}h^ a7@Qdb7@$HRiOmmr3z;VG5mAHa1Tp}2Z5fFG delta 57 zcmZ3d_egWYESAYR+-jQ}1U@is&f)&UvUveZ64T~&LM}{`ML3l<*KmGd1Tvf^bBL=! HI6wvfeZdp{ diff --git a/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/CL.read.1.tlog b/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/CL.read.1.tlog index a9af9a2cb4fc9a1c308a7388e9a01803aa203648..9611acb60b851391b63feb3b2cf20fc723e8ecb9 100644 GIT binary patch delta 178 zcmeA>#eHon?}RhkYjhd^lyBd_%~X@tcxLMv#%((6!3?epK@4FNAF5BBz#$mI;LH%f z02KqtOz+iYbcZS0tbak?c=Cf;YSYi@GP-P6NMuwpo0uRm*^W_dy51i~zR3+HUDFRF zGqO#;W6#tx{lQd5mg(E(F?MY)n#uTzX}Z&V#;)lNbAi&YW-xYakD9|6!89>}ZTqG9 WjQ6sq>l87mO|(+m{;7mXrT_pz4nZvd delta 573 zcmcb%mACH{_k=UeF88;)+-KaTGyRr56VJwbugbTZwJ=$vZ9Y*^lQuo?6_Z-MGlLaF z3`01BCxah@3xhw96%6FNGxz}6P7IDf+LIv)NQVGvf1sKepu9gr5SZ@=REOZZFt{?f z0abOt-Yx&y@^H=qF_Kf(g>Cg*VSO=9MnT*Ia?Ie~+3vJS^CbfufmG5%m=hw7iK&mF&6fqNd~FQF delta 111 zcmexm_(64p7tiDb4!+3~1VkoxNd!$kAQCb;k3($o9Z?XQ56BjnyoQ@=at)ip14e3NrH`6e-Q F0RX#eCF}qI 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 47d98bc991256338087c75d9f60522e2519d4871..844b0b5daa2f4602b0709dc1ffcfb7cfd0ad3569 100644 GIT binary patch delta 36 qcmdnQv5kF$7~|w`jC`9XF?um_2Q#=b1Tlnx$jO3Ck(2$Hp8x>Fe+m%* delta 72 zcmdnSzKLUl7^A2sgCBz@LkL4Sko044VekjCf+y=Urf*hZ^kS5BX7B+@xB{gxl|)Xy H#PkFJ6@?FK diff --git a/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/Lib.read.1.tlog b/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/Lib.read.1.tlog index 3ab96a92d7daf616f812cbb6afe74b788adeeabb..ed0af5f9ec315ada75c9affdb01fc09c500754de 100644 GIT binary patch delta 77 zcmZ1`yhd - 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(); }