diff --git a/TODO b/TODO index d2032d8..3c5137c 100644 --- a/TODO +++ b/TODO @@ -1,13 +1,14 @@ initialization code for other operating systems - currently VoidNet only supports windows initialization code for tcp client and tcp server for other operating systems - currently windows only -handle SendNetworkMessage errors for windows -handle ReceiveDataArray errors for windows revamped BitConverter class new StringConverter class +IPUtil class for other os's -maybe i should implement error codes +maybe i should implement error codes and exceptions plugin system - idk how im going to implement it yet -maybe i should use virtual methods for the server and client, maybe... \ No newline at end of file +maybe i should use virtual methods for the server and client, maybe... + +TcpServer::SendMessage rework \ No newline at end of file diff --git a/VoidNetVS/VoidNetVS/VoidNetVS.vcxproj b/VoidNetVS/VoidNetVS/VoidNetVS.vcxproj index e4924d7..4cad46f 100644 --- a/VoidNetVS/VoidNetVS/VoidNetVS.vcxproj +++ b/VoidNetVS/VoidNetVS/VoidNetVS.vcxproj @@ -29,6 +29,7 @@ + @@ -44,17 +45,9 @@ - - true - - - true - - - true - + diff --git a/VoidNetVS/VoidNetVS/VoidNetVS.vcxproj.filters b/VoidNetVS/VoidNetVS/VoidNetVS.vcxproj.filters index 3d76a3a..cc7daca 100644 --- a/VoidNetVS/VoidNetVS/VoidNetVS.vcxproj.filters +++ b/VoidNetVS/VoidNetVS/VoidNetVS.vcxproj.filters @@ -48,14 +48,14 @@ include + + include + src - - src - src @@ -74,9 +74,6 @@ src - - src - src @@ -92,7 +89,7 @@ src - + src diff --git a/include/Defs.hpp b/include/Defs.hpp index dd405ee..ec596ab 100644 --- a/include/Defs.hpp +++ b/include/Defs.hpp @@ -243,6 +243,6 @@ enum InternalTags DisconnectTag = 255, }; -#define IS_HANDSHAKE(name) name.subject == 1 && (name.tag == DisconnectTag || name.tag == ConnectTag || name.tag == Accept || name.tag == Close || name.tag == Reject) +#define IS_HANDSHAKE(name) name.subject == 1 || (name.tag == DisconnectTag || name.tag == ConnectTag || name.tag == Accept || name.tag == Close || name.tag == Reject) #endif // DEFS_HPP \ No newline at end of file diff --git a/include/Init.hpp b/include/Init.hpp index 45e0bd4..af477b4 100644 --- a/include/Init.hpp +++ b/include/Init.hpp @@ -10,8 +10,16 @@ struct Initialization { - static bool initialize(); + static bool Initialize(); + +#ifdef _MSC_VER + const WSADATA &GetData(); +#endif + +private: +#ifdef _MSC_VER static WSADATA wsa_data; +#endif }; #endif \ No newline at end of file diff --git a/include/TcpClient.hpp b/include/TcpClient.hpp index fc86d8b..c6d8766 100644 --- a/include/TcpClient.hpp +++ b/include/TcpClient.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #ifdef _MSC_VER #pragma once @@ -39,18 +40,24 @@ struct TcpClient //this is a more manual method with no callbacks const NetworkMessage &ReceiveMessage(); - void SendMessage(const NetworkMessage &message); - void SendBytes(const std::vector &bytes); - void SendBytes(byte *bytes, uint32 lenght); + + std::future SendMessage(const NetworkMessage &message); + bool SendBytes(const std::vector &bytes); + bool SendBytes(byte *bytes, uint32 lenght); void SetOnDisconnectCallback(void (*func)(uint16)); void SetOnConnectCallback(void (*func)(uint16)); void SetOnMessageCallback(void (*func)(uint16, byte, byte, void*)); + static const TcpClient &DefaultTcpClient(); + private: + TcpClient(); + const NetworkBuffer &receive_data_array(); static void receive_data(TcpClient *client); - static void send_network_message(const NetworkMessage &message, TcpClient *client); + static bool send_network_message(const NetworkMessage &message, TcpClient *client); + bool initialize(const std::string &ip, uint16 port = default_client_port); uint16 id = -2; @@ -63,11 +70,9 @@ private: std::function OnConnect; std::function OnMessage; -#ifdef _MSC_VER SOCKET tcp_socket = INVALID_SOCKET; struct addrinfo *result = nullptr; struct addrinfo hints; -#endif }; #endif \ No newline at end of file diff --git a/include/TcpServer.hpp b/include/TcpServer.hpp index f4bd958..16f877e 100644 --- a/include/TcpServer.hpp +++ b/include/TcpServer.hpp @@ -22,7 +22,7 @@ struct TcpServer bool StartServer(bool accept_connections); // if accept_connections is false the user must call the funcion AcceptConnections() void AcceptConnections(); - void SendMessage(const NetworkMessage &message); + bool SendMessage(const NetworkMessage &message); void RejectConnection(TcpClient &client); void AcceptConnection(uint16 client); @@ -56,11 +56,9 @@ private: std::vector clients; -#ifdef _MSC_VER SOCKET server_tcp_socket = INVALID_SOCKET; struct addrinfo *result = nullptr; struct addrinfo hints; -#endif }; #endif diff --git a/include/UdpClient.hpp b/include/UdpClient.hpp index 1c34328..d239e57 100644 --- a/include/UdpClient.hpp +++ b/include/UdpClient.hpp @@ -9,11 +9,49 @@ #include "NetworkMessage.hpp" #include +#include #include +#include struct UdpClient { - + UdpClient(const SOCKET &socket); + UdpClient(const std::string &ip); + UdpClient(const std::string &ip, uint16 = default_client_port); + ~UdpClient(); + + void Shutdown(); + + const std::string &GetIP(); + void SetIP(const std::string &ip); + + uint16 GetPort(); + void SetPort(uint16 port); + + uint16 GetID(); + void SetID(uint16 id); + + std::future SendMessage(const NetworkMessage &message); + bool SendBytes(const std::vector &bytes); + bool SendBytes(byte *bytes, uint32 lenght); + +private: + bool initialize(const std::string &ip, uint16 port = default_client_port); + + static bool send_network_message(const NetworkMessage &message, UdpClient *client); + + uint16 id = -2; + + std::string ip; + uint16 port = 0; + bool initialized = false; + bool receive = false; + + std::function OnDisconnect; + std::function OnConnect; + std::function OnMessage; + + SOCKET udp_socket = INVALID_SOCKET; }; #endif diff --git a/include/UdpServer.hpp b/include/UdpServer.hpp new file mode 100644 index 0000000..7ab44b2 --- /dev/null +++ b/include/UdpServer.hpp @@ -0,0 +1,34 @@ +#ifndef UDP_SERVER_HPP +#define UDP_SERVER_HPP + +#ifdef _MSC_VER +#pragma once +#endif + +#include "Defs.hpp" +#include "UdpClient.hpp" + +#include +#include + +struct UdpServer +{ +private: + bool initialize(uint16 port = default_server_port); + + uint16 allocate_id(); + + void shutdown_internal(); + + bool initialized = false; + bool running = false; + + uint16 max_connections = 0; + + std::vector clients; + + SOCKET server_udp_socket = INVALID_SOCKET; + struct sockaddr_in server; +}; + +#endif \ No newline at end of file diff --git a/include/Utility.hpp b/include/Utility.hpp index b4978a3..13759cd 100644 --- a/include/Utility.hpp +++ b/include/Utility.hpp @@ -56,6 +56,15 @@ struct Utility static const std::string &ToString(int64 value); static const std::string &ToString(const std::vector &bytes); + static uint8 ToUint8(const std::string &str); + static uint16 ToUint16(const std::string &str); + static uint32 ToUint32(const std::string &str); + static uint64 ToUint64(const std::string &str); + static int8 ToInt8(const std::string &str); + static int16 ToInt16(const std::string &str); + static int32 ToInt32(const std::string &str); + static int64 ToInt64(const std::string &str); + static const std::vector &ToBytes(const std::string &str); static const std::string &ToString(const std::vector &bytes, uint16 start_index = 0, uint16 lenght = 0); @@ -64,6 +73,11 @@ struct Utility static std::vector Split(const std::string &str, const std::string &delimiter); }; + struct IPUtil + { + static bool ValidIPV4(const std::string &ip); + }; + struct ConfigReader { void ReadConfig(const std::string &file_name); diff --git a/src/InitWindows.cpp b/src/InitWindows.cpp index 8c9565a..18b8dd4 100644 --- a/src/InitWindows.cpp +++ b/src/InitWindows.cpp @@ -3,7 +3,7 @@ #include -bool Initialization::initialize() +bool Initialization::Initialize() { uint16 code = WSAStartup(MAKEWORD(2, 2), &wsa_data); if (code != 0) @@ -13,4 +13,9 @@ bool Initialization::initialize() return false; } return true; +} + +const WSADATA &Initialization::GetData() +{ + return wsa_data; } \ No newline at end of file diff --git a/src/TcpClient.cpp b/src/TcpClient.cpp index 091e7f8..b9b6b06 100644 --- a/src/TcpClient.cpp +++ b/src/TcpClient.cpp @@ -1,8 +1,12 @@ #include "TcpClient.hpp" #include "NetworkBuffer.hpp" +#include "Utility.hpp" +#include "Config.hpp" +#include "Handshake.hpp" #include #include +#include TcpClient::TcpClient(const std::string &ip) : port(default_client_port) { @@ -56,7 +60,7 @@ void TcpClient::receive_data(TcpClient *client) { if (message.tag == ConnectTag) // some user has connected - not us, never std::async(std::launch::async, client->OnConnect, message.sender); - else if (message.tag == DisconnectTag || message.tag == Close) // some user has disconnected + else if (message.tag == DisconnectTag || message.tag == Close) // some user has disconnected, it can be us std::async(std::launch::async, client->OnDisconnect, message.sender); } else @@ -75,9 +79,9 @@ const NetworkMessage & TcpClient::ReceiveMessage() return receive_data_array(); } -void TcpClient::SendMessage(const NetworkMessage &message) +std::future TcpClient::SendMessage(const NetworkMessage &message) { - std::async(std::launch::async, &send_network_message, message, this); + return std::async(std::launch::async, &send_network_message, message, this); } void TcpClient::SetOnDisconnectCallback(void(*func)(uint16)) @@ -95,6 +99,146 @@ void TcpClient::SetOnMessageCallback(void(*func)(uint16, byte, byte, void*)) OnMessage = func; } -#ifdef _MSC_VER -#include "TcpClientWindows.cpp" -#endif \ No newline at end of file +const TcpClient & TcpClient::DefaultTcpClient() +{ + return TcpClient(); +} + +TcpClient::TcpClient(const SOCKET & socket) +{ + tcp_socket = socket; +} + +bool TcpClient::initialize(const std::string &ip, uint16 port) +{ + if (Utility::IPUtil::ValidIPV4(ip) || port == 0) + return false; + ZeroMemory(&hints, sizeof(hints)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + uint16 code = getaddrinfo(ip.c_str(), std::to_string(port).c_str(), &hints, &result); + if (code != 0) + { + if (Config::GetUsingConsole()) + std::cerr << code << std::endl; // display more info + WSACleanup(); + return false; + } + + tcp_socket = socket(result->ai_family, result->ai_socktype, result->ai_protocol); + + if (tcp_socket == INVALID_SOCKET) + { + if (Config::GetUsingConsole()) + std::cerr << WSAGetLastError() << std::endl; // display more info + freeaddrinfo(result); + WSACleanup(); + return false; + } + + return initialized = true; +} + +TcpClient::~TcpClient() +{ + freeaddrinfo(result); + WSACleanup(); + Utility::Delete(result); +} + +void TcpClient::Shutdown() +{ + Handshake handshake(id, Close, Server); + SendMessage(Handshake::HandshakeToNetworkMessage(handshake)); + uint16 code = closesocket(tcp_socket); + if (code == SOCKET_ERROR) + { + if (Config::GetUsingConsole()) + std::cerr << WSAGetLastError() << std::endl; // display more info + } + + WSACleanup(); +} + +bool TcpClient::Connect() +{ + if (!initialized) + { + if (ip.size() == 0 || std::count(ip.begin(), ip.end(), '.') != 4 && port == 0 && !initialize(ip, port)) + return false; + } + else return false; + + uint16 connect_code = connect(tcp_socket, result->ai_addr, result->ai_addrlen); + if (connect_code == SOCKET_ERROR) + return false; + + NetworkMessage message(receive_data_array()); + if (IS_HANDSHAKE(message)) + { + if (message.tag == Accept) + { + receive = true; + OnConnect(message.sender); + return true; + } + } + return false; +} + +bool TcpClient::DataAvailable(int32 &size) +{ + return ioctlsocket(tcp_socket, FIONREAD, reinterpret_cast(size)) != NO_ERROR && size > 0; +} + +const NetworkBuffer &TcpClient::receive_data_array() +{ + NetworkBuffer buffer; + + int32 temp; + if (DataAvailable(temp) && temp > sizeof(int32)) + { + byte *header = new byte[sizeof(int32)](); + if (recv(tcp_socket, reinterpret_cast(header), sizeof(int32), 0) != sizeof(int32)) + return NetworkBuffer(); + buffer.header = std::vector(header, header + sizeof(int32)); + } + else + return NetworkBuffer(); + + int32 body_size = Utility::BitConverter::ToInt32(buffer.header); + byte *body = new byte[body_size](); + int16 received_bytes = recv(tcp_socket, reinterpret_cast(body), body_size, 0); + if (received_bytes == SOCKET_ERROR || received_bytes != body_size || WSAGetLastError() != 0) + return NetworkBuffer(); + + buffer.body = std::vector(body, body + body_size); + buffer.valid = true; + + return buffer; +} + +bool TcpClient::send_network_message(const NetworkMessage &message, TcpClient *client) +{ + NetworkBuffer buffer = NetworkMessage::EncodeMessage(message); + int32 lenght = Utility::BitConverter::ToInt32(buffer.header); + int32 bytes_sent = send(client->tcp_socket, reinterpret_cast(buffer.body.data()), lenght, 0); + return bytes_sent == SOCKET_ERROR || bytes_sent != lenght || WSAGetLastError() != 0; +} + +bool TcpClient::SendBytes(const std::vector& bytes) +{ + int32 bytes_sent = send(tcp_socket, reinterpret_cast(bytes.data()), bytes.size(), 0); + if (bytes_sent == SOCKET_ERROR || bytes_sent != bytes.size() || WSAGetLastError() != 0) + { + //something went wrong couldnt send anything/some data + } +} + +bool TcpClient::SendBytes(byte * bytes, uint32 size) +{ + int32 bytes_sent = send(tcp_socket, reinterpret_cast(bytes), size, 0); + return bytes_sent == SOCKET_ERROR || bytes_sent != size || WSAGetLastError() != 0; +} \ No newline at end of file diff --git a/src/TcpClientWindows.cpp b/src/TcpClientWindows.cpp deleted file mode 100644 index 525d46d..0000000 --- a/src/TcpClientWindows.cpp +++ /dev/null @@ -1,156 +0,0 @@ -#include "TcpClient.hpp" -#include "Utility.hpp" -#include "Config.hpp" -#include "Handshake.hpp" - -#include - -TcpClient::TcpClient(const SOCKET & socket) -{ - tcp_socket = socket; -} - -bool TcpClient::initialize(const std::string &ip, uint16 port) -{ - if (ip.size() == 0 || std::count(ip.begin(), ip.end(), '.') != 4 || port == 0) - return false; - ZeroMemory(&hints, sizeof(hints)); - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - - uint16 code = getaddrinfo(ip.c_str(), std::to_string(port).c_str(), &hints, &result); - if (code != 0) - { - if (Config::GetUsingConsole()) - std::cerr << code << std::endl; // display more info - WSACleanup(); - return false; - } - - tcp_socket = ::socket(result->ai_family, result->ai_socktype, result->ai_protocol); - - if (tcp_socket == INVALID_SOCKET) - { - if (Config::GetUsingConsole()) - std::cerr << WSAGetLastError() << std::endl; // display more info - freeaddrinfo(result); - WSACleanup(); - return false; - } - - return initialized = true; -} - -TcpClient::~TcpClient() -{ - freeaddrinfo(result); - WSACleanup(); - Utility::Delete(result); -} - -void TcpClient::Shutdown() -{ - Handshake handshake(id, Close, Server); - SendMessage(Handshake::HandshakeToNetworkMessage(handshake)); - uint16 code = closesocket(tcp_socket); - if (code == SOCKET_ERROR) - { - if (Config::GetUsingConsole()) - std::cerr << WSAGetLastError() << std::endl; // display more info - } - - closesocket(tcp_socket); - WSACleanup(); -} - -bool TcpClient::Connect() -{ - if (!initialized) - { - if (ip.size() == 0 || std::count(ip.begin(), ip.end(), '.') != 4 && port == 0 && !initialize(ip, port)) - return false; - } - else return false; - - uint16 connect_code = connect(tcp_socket, result->ai_addr, result->ai_addrlen); - if (connect_code == SOCKET_ERROR) - return false; - - NetworkMessage message(receive_data_array()); - if (IS_HANDSHAKE(message)) - { - if (message.tag == Accept) - { - receive = true; - OnConnect(message.sender); - return true; - } - } - return false; -} - -bool TcpClient::DataAvailable(int32 &size) -{ - return ioctlsocket(tcp_socket, FIONREAD, reinterpret_cast(size)) != NO_ERROR && size > 0; -} - -const NetworkBuffer &TcpClient::receive_data_array() -{ - NetworkBuffer buffer; - - int32 temp; - if (DataAvailable(temp) && temp > sizeof(int32)) - { - byte *header = new byte[sizeof(int32)](); - if (recv(tcp_socket, reinterpret_cast(header), sizeof(int32), 0) != sizeof(int32)) - //invalid header - return NetworkBuffer(); - buffer.header = std::vector(header, header + sizeof(int32)); - } - else - return NetworkBuffer(); - - int32 body_size = Utility::BitConverter::ToInt32(buffer.header); - byte *body = new byte[body_size](); - int16 received_bytes = recv(tcp_socket, reinterpret_cast(body), body_size, 0); - if (received_bytes == SOCKET_ERROR || received_bytes != body_size || WSAGetLastError() != 0) - { - //there was a problem receiving the body of the message or theres no body to receive - return NetworkBuffer(); - } - - buffer.body = std::vector(body, body + body_size); - buffer.valid = true; - - return buffer; -} - -void TcpClient::send_network_message(const NetworkMessage &message, TcpClient *client) -{ - NetworkBuffer buffer = NetworkMessage::EncodeMessage(message); - int32 lenght = Utility::BitConverter::ToInt32(buffer.header); - int32 bytes_sent = send(client->tcp_socket, reinterpret_cast(buffer.body.data()), lenght, 0); - if (bytes_sent == SOCKET_ERROR || bytes_sent != lenght || WSAGetLastError() != 0) - { - //something went wrong couldnt send anything/some data - } -} - -void TcpClient::SendBytes(const std::vector& bytes) -{ - int32 bytes_sent = send(tcp_socket, reinterpret_cast(bytes.data()), bytes.size(), 0); - if (bytes_sent == SOCKET_ERROR || bytes_sent != bytes.size() || WSAGetLastError() != 0) - { - //something went wrong couldnt send anything/some data - } -} - -void TcpClient::SendBytes(byte * bytes, uint32 size) -{ - int32 bytes_sent = send(tcp_socket, reinterpret_cast(bytes), size, 0); - if (bytes_sent == SOCKET_ERROR || bytes_sent != size || WSAGetLastError() != 0) - { - //something went wrong couldnt send anything/some data - } -} \ No newline at end of file diff --git a/src/TcpServer.cpp b/src/TcpServer.cpp index 31a990b..836ce43 100644 --- a/src/TcpServer.cpp +++ b/src/TcpServer.cpp @@ -1,18 +1,22 @@ #include "TcpServer.hpp" #include "Config.hpp" #include "Handshake.hpp" +#include "Utility.hpp" +#include #include #include TcpServer::TcpServer() { initialize(); // initialize with the default port + clients = std::vector(max_connections); } TcpServer::TcpServer(uint16 port) { initialize(port); + clients = std::vector(max_connections); } TcpServer::~TcpServer() @@ -51,7 +55,7 @@ void TcpServer::process_client_messages(TcpServer *server, TcpClient & client) } } -void TcpServer::SendMessage(const NetworkMessage & message) +bool TcpServer::SendMessage(const NetworkMessage & message) { switch (message.distribution_mode) { @@ -65,7 +69,6 @@ void TcpServer::SendMessage(const NetworkMessage & message) } for (uint16 i = 0; i < OnMessageFunctions.size(); i++) OnMessageFunctions[i](message); - break; } case AllAndMe: // this will send the message to EVERYONE including the user that sent it { @@ -76,7 +79,6 @@ void TcpServer::SendMessage(const NetworkMessage & message) } for (uint16 i = 0; i < OnMessageFunctions.size(); i++) OnMessageFunctions[i](message); - break; } case Server: // this will only send the message to the server { @@ -84,7 +86,6 @@ void TcpServer::SendMessage(const NetworkMessage & message) CloseSocket(message.sender); for (uint16 i = 0; i < OnMessageFunctions.size(); i++) OnMessageFunctions[i](message); - break; } case Others: // this will send the message to others, excluding server and the user that sent it { @@ -94,7 +95,6 @@ void TcpServer::SendMessage(const NetworkMessage & message) if (message.sender != client.GetID()) client.SendMessage(message); } - break; } case ID: // this will send the message to a specific id { @@ -102,12 +102,9 @@ void TcpServer::SendMessage(const NetworkMessage & message) { TcpClient client = *it; if (message.sender == client.GetID()) - { client.SendMessage(message); - break; - } } - break; + return false; } } } @@ -190,7 +187,7 @@ const TcpClient & TcpServer::GetClientByID(uint16 id) if (client.GetID() == id) return client; } - return TcpClient(); + return TcpClient::DefaultTcpClient(); } void TcpServer::SetMaxConnections(uint16 value) @@ -203,6 +200,91 @@ uint16 TcpServer::GetMaxConnections() return max_connections; } -#ifdef _MSC_VER -#include "TcpServerWindows.cpp" -#endif \ No newline at end of file +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; + } + + server_tcp_socket = ::socket(result->ai_family, result->ai_socktype, result->ai_protocol); + + if (server_tcp_socket == INVALID_SOCKET) + { + if (Config::GetUsingConsole()) + std::cerr << WSAGetLastError() << std::endl; // display more info + freeaddrinfo(result); + WSACleanup(); + return false; + } + + code = bind(server_tcp_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(server_tcp_socket); + WSACleanup(); + return false; + } + + freeaddrinfo(result); + return initialized = true; +} + +bool TcpServer::StartServer(bool accept_connections) +{ + if (listen(server_tcp_socket, SOMAXCONN) == SOCKET_ERROR) + { + if (Config::GetUsingConsole()) + std::cerr << WSAGetLastError() << std::endl; + closesocket(server_tcp_socket); + WSACleanup(); + return false; + } + + if (accept_connections) + AcceptConnections(); + + return true; +} + +void TcpServer::accept_connections(TcpServer *server) +{ + while (server->running) + { + SOCKET client_socket = accept(server->server_tcp_socket, 0, 0); + if (client_socket == INVALID_SOCKET) + { + if (Config::GetUsingConsole()) + std::cerr << WSAGetLastError() << std::endl; + closesocket(server->server_tcp_socket); + WSACleanup(); + server->running = false; // if we cant accept a connection idk if we should stop the server or not mh + break; + } + + TcpClient client(client_socket); + server->add_to_clients_list(client); + + std::async(std::launch::async, &process_client_messages, server, client); + } +} + +void TcpServer::shutdown_internal() +{ + freeaddrinfo(result); + WSACleanup(); + Utility::Delete(result); +} \ No newline at end of file diff --git a/src/TcpServerWindows.cpp b/src/TcpServerWindows.cpp deleted file mode 100644 index 24fbd70..0000000 --- a/src/TcpServerWindows.cpp +++ /dev/null @@ -1,96 +0,0 @@ -#include "TcpServer.hpp" -#include "Config.hpp" -#include "Utility.hpp" - -#include -#include -#include - -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; - } - - server_tcp_socket = ::socket(result->ai_family, result->ai_socktype, result->ai_protocol); - - if (server_tcp_socket == INVALID_SOCKET) - { - if (Config::GetUsingConsole()) - std::cerr << WSAGetLastError() << std::endl; // display more info - freeaddrinfo(result); - WSACleanup(); - return false; - } - - code = bind(server_tcp_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(server_tcp_socket); - WSACleanup(); - return false; - } - - freeaddrinfo(result); - return initialized = true; -} - -bool TcpServer::StartServer(bool accept_connections) -{ - if (listen(server_tcp_socket, SOMAXCONN) == SOCKET_ERROR) - { - if (Config::GetUsingConsole()) - std::cerr << WSAGetLastError() << std::endl; - closesocket(server_tcp_socket); - WSACleanup(); - return false; - } - - if (accept_connections) - AcceptConnections(); - - return true; -} - -void TcpServer::accept_connections(TcpServer *server) -{ - while (server->running) - { - SOCKET client_socket = accept(server->server_tcp_socket, 0, 0); - if (client_socket == INVALID_SOCKET) - { - if (Config::GetUsingConsole()) - std::cerr << WSAGetLastError() << std::endl; - closesocket(server->server_tcp_socket); - WSACleanup(); - server->running = false; // if we cant accept a connection idk if we should stop the server or not mh - break; - } - - TcpClient client(client_socket); - server->add_to_clients_list(client); - - std::async(std::launch::async, &process_client_messages, server, client); - } -} - -void TcpServer::shutdown_internal() -{ - freeaddrinfo(result); - WSACleanup(); - Utility::Delete(result); -} \ No newline at end of file diff --git a/src/UdpClient.cpp b/src/UdpClient.cpp index 7b8cb80..3e4dbd9 100644 --- a/src/UdpClient.cpp +++ b/src/UdpClient.cpp @@ -1,5 +1,105 @@ #include "UdpClient.hpp" +#include "Handshake.hpp" +#include "Config.hpp" -#ifdef _MSC_VER -#include "UdpClientWindows.cpp" -#endif \ No newline at end of file +#include + +#include + +UdpClient::UdpClient(const std::string & ip) +{ + initialize(ip); +} + +UdpClient::UdpClient(const std::string & ip, uint16) +{ + initialize(ip, port); +} + +uint16 UdpClient::GetPort() +{ + return port; +} + +void UdpClient::SetPort(uint16 port) +{ + this->port = port; +} + +uint16 UdpClient::GetID() +{ + return id; +} + +void UdpClient::SetID(uint16 id) +{ + this->id = id; +} + +std::future UdpClient::SendMessage(const NetworkMessage & message) +{ + return std::async(std::launch::async, &send_network_message, message, this); +} + +const std::string &UdpClient::GetIP() +{ + return ip; +} + +void UdpClient::SetIP(const std::string & ip) +{ + this->ip = ip; +} + +UdpClient::UdpClient(const SOCKET & socket) +{ + udp_socket = socket; +} + +bool UdpClient::initialize(const std::string &ip, uint16 port) +{ + if (Utility::IPUtil::ValidIPV4(ip) || port == 0) + return false; + + udp_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + + if (udp_socket == INVALID_SOCKET) + { + WSACleanup(); + return false; + } +} + +UdpClient::~UdpClient() +{ + WSACleanup(); +} + +void UdpClient::Shutdown() +{ + Handshake handshake(id, Close, Server); + SendMessage(Handshake::HandshakeToNetworkMessage(handshake)); + uint16 code = closesocket(udp_socket); + if (code == SOCKET_ERROR) + { + if (Config::GetUsingConsole()) + std::cerr << WSAGetLastError() << std::endl; // display more info + } + + WSACleanup(); +} + +bool UdpClient::SendBytes(const std::vector &bytes) +{ + +} + +bool UdpClient::SendBytes(byte *bytes, uint32 lenght) +{ + +} + +bool UdpClient::send_network_message(const NetworkMessage &message, UdpClient *client) +{ + +} \ No newline at end of file diff --git a/src/UdpClientWindows.cpp b/src/UdpClientWindows.cpp deleted file mode 100644 index 8c55758..0000000 --- a/src/UdpClientWindows.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "UdpClient.hpp" diff --git a/src/UdpServer.cpp b/src/UdpServer.cpp new file mode 100644 index 0000000..c513de6 --- /dev/null +++ b/src/UdpServer.cpp @@ -0,0 +1,57 @@ +#include "UdpServer.hpp" +#include "Utility.hpp" + +uint16 UdpServer::allocate_id() +{ + for (uint16 i = 1; i < max_connections; ++i) + { + bool flag = true; + for (std::vector::iterator it = clients.begin(); it != clients.end(); ++it) + { + UdpClient client = *it; + if (client.GetID() == i) + { + flag = false; + break; + } + } + + if (flag) + return i; + } + return 0; +} + +bool UdpServer::initialize(uint16 port) +{ + server_udp_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + + if (server_udp_socket == INVALID_SOCKET) + { + WSACleanup(); + return false; + } + + memset(&server, '\0', sizeof(struct sockaddr_in)); + + server.sin_family = AF_INET; + server.sin_port = htons(port); + + server.sin_addr.S_un.S_un_b.s_b1 = 0; + server.sin_addr.S_un.S_un_b.s_b2 = 0; + server.sin_addr.S_un.S_un_b.s_b3 = 0; + server.sin_addr.S_un.S_un_b.s_b4 = 0; + + if (bind(server_udp_socket, reinterpret_cast(&server), sizeof(struct sockaddr_in)) == -1) + { + closesocket(server_udp_socket); + WSACleanup(); + return false; + } + return initialized = true; +} + +void UdpServer::shutdown_internal() +{ + WSACleanup(); +} \ No newline at end of file diff --git a/src/Utility.cpp b/src/Utility.cpp index dd67a24..588724c 100644 --- a/src/Utility.cpp +++ b/src/Utility.cpp @@ -162,6 +162,46 @@ const std::string & Utility::StringConverter::ToString(const std::vector& return std::string(); } +uint8 Utility::StringConverter::ToUint8(const std::string & str) +{ + return uint8(); +} + +uint16 Utility::StringConverter::ToUint16(const std::string & str) +{ + return uint16(); +} + +uint32 Utility::StringConverter::ToUint32(const std::string & str) +{ + return uint32(); +} + +uint64 Utility::StringConverter::ToUint64(const std::string & str) +{ + return uint64(); +} + +int8 Utility::StringConverter::ToInt8(const std::string & str) +{ + return int8(); +} + +int16 Utility::StringConverter::ToInt16(const std::string & str) +{ + return int16(); +} + +int32 Utility::StringConverter::ToInt32(const std::string & str) +{ + return int32(); +} + +int64 Utility::StringConverter::ToInt64(const std::string & str) +{ + return int64(); +} + const std::vector& Utility::StringConverter::ToBytes(const std::string & str) { return std::vector(); @@ -224,3 +264,17 @@ const std::string & Utility::ConfigReader::operator[](const std::string &key) { return nodes.at(key); } + +bool Utility::IPUtil::ValidIPV4(const std::string & ip) +{ + std::vector splitted_address = Utility::StringConverter::Split(ip, "."); + if (splitted_address.size() != 4) + return false; + uint8 a1 = Utility::StringConverter::ToUint8(splitted_address[0]); + uint8 a2 = Utility::StringConverter::ToUint8(splitted_address[1]); + uint8 a3 = Utility::StringConverter::ToUint8(splitted_address[2]); + uint8 a4 = Utility::StringConverter::ToUint8(splitted_address[3]); + + return a1 != 0 && a2 != 0 && a3 != 0 && a4 != 0 && + a1 != 255 && a2 != 255 && a3 != 255 && a4 != 255; +} diff --git a/src/VoidNetClient.cpp b/src/VoidNetClient.cpp index 0357647..44f5963 100644 --- a/src/VoidNetClient.cpp +++ b/src/VoidNetClient.cpp @@ -37,17 +37,15 @@ void VoidNetClientAPI::SendMessageToAllAndMe(byte tag, byte subject, void *data) void VoidNetClientAPI::SendMessage(byte distribution_mode, uint16 destination_id, byte tag, byte subject, void *data) { - if (tag != ConnectTag && tag != DisconnectTag) - { - NetworkMessage message; - message.tag = tag; - message.subject = subject; - message.data = data; - message.distribution_mode = distribution_mode; - message.sender = id; - message.destination_id = destination_id; + NetworkMessage message; + message.tag = tag; + message.subject = subject; + message.data = data; + message.distribution_mode = distribution_mode; + message.sender = id; + message.destination_id = destination_id; + if (!IS_HANDSHAKE(message)) tcp_client.SendMessage(message); - } } void VoidNetClientAPI::Receive()