Updated TODO list

Removed windows specific files since the code is the same for linux
UdpClient: added basic methods to interact with the variables of that class, added initialization and started with sending and receiving messages
UdpServer: added initialization and basic variables
Utility: added a bunch of methods to the StringConverter utility class
VoidNetClientAPI: SendMessage now checks if message is not an handshake
This commit is contained in:
xX-TheDoctor-Xx
2016-09-08 00:36:45 +01:00
parent 74d9d5db87
commit 3e97c0da6d
20 changed files with 593 additions and 318 deletions

7
TODO
View File

@ -1,13 +1,14 @@
initialization code for other operating systems - currently VoidNet only supports windows 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 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 revamped BitConverter class
new StringConverter 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 plugin system - idk how im going to implement it yet
maybe i should use virtual methods for the server and client, maybe... maybe i should use virtual methods for the server and client, maybe...
TcpServer::SendMessage rework

View File

@ -29,6 +29,7 @@
<ClInclude Include="..\..\include\TcpClient.hpp" /> <ClInclude Include="..\..\include\TcpClient.hpp" />
<ClInclude Include="..\..\include\TcpServer.hpp" /> <ClInclude Include="..\..\include\TcpServer.hpp" />
<ClInclude Include="..\..\include\UdpClient.hpp" /> <ClInclude Include="..\..\include\UdpClient.hpp" />
<ClInclude Include="..\..\include\UdpServer.hpp" />
<ClInclude Include="..\..\include\Utility.hpp" /> <ClInclude Include="..\..\include\Utility.hpp" />
<ClInclude Include="..\..\include\VoidNetClient.hpp" /> <ClInclude Include="..\..\include\VoidNetClient.hpp" />
<ClInclude Include="..\..\include\VoidNetServer.hpp" /> <ClInclude Include="..\..\include\VoidNetServer.hpp" />
@ -44,17 +45,9 @@
<ClCompile Include="..\..\src\NetworkMessage.cpp" /> <ClCompile Include="..\..\src\NetworkMessage.cpp" />
<ClCompile Include="..\..\src\Serializer.cpp" /> <ClCompile Include="..\..\src\Serializer.cpp" />
<ClCompile Include="..\..\src\TcpClient.cpp" /> <ClCompile Include="..\..\src\TcpClient.cpp" />
<ClCompile Include="..\..\src\TcpClientWindows.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\TcpServer.cpp" /> <ClCompile Include="..\..\src\TcpServer.cpp" />
<ClCompile Include="..\..\src\TcpServerWindows.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\UdpClient.cpp" /> <ClCompile Include="..\..\src\UdpClient.cpp" />
<ClCompile Include="..\..\src\UdpClientWindows.cpp"> <ClCompile Include="..\..\src\UdpServer.cpp" />
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\Utility.cpp" /> <ClCompile Include="..\..\src\Utility.cpp" />
<ClCompile Include="..\..\src\VoidNetClient.cpp" /> <ClCompile Include="..\..\src\VoidNetClient.cpp" />
</ItemGroup> </ItemGroup>

View File

@ -48,14 +48,14 @@
<ClInclude Include="..\..\include\UdpClient.hpp"> <ClInclude Include="..\..\include\UdpClient.hpp">
<Filter>include</Filter> <Filter>include</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\include\UdpServer.hpp">
<Filter>include</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="..\..\src\Init.cpp"> <ClCompile Include="..\..\src\Init.cpp">
<Filter>src</Filter> <Filter>src</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\TcpClientWindows.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\..\src\Utility.cpp"> <ClCompile Include="..\..\src\Utility.cpp">
<Filter>src</Filter> <Filter>src</Filter>
</ClCompile> </ClCompile>
@ -74,9 +74,6 @@
<ClCompile Include="..\..\src\VoidNetClient.cpp"> <ClCompile Include="..\..\src\VoidNetClient.cpp">
<Filter>src</Filter> <Filter>src</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\TcpServerWindows.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\..\src\TcpServer.cpp"> <ClCompile Include="..\..\src\TcpServer.cpp">
<Filter>src</Filter> <Filter>src</Filter>
</ClCompile> </ClCompile>
@ -92,7 +89,7 @@
<ClCompile Include="..\..\src\UdpClient.cpp"> <ClCompile Include="..\..\src\UdpClient.cpp">
<Filter>src</Filter> <Filter>src</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\UdpClientWindows.cpp"> <ClCompile Include="..\..\src\UdpServer.cpp">
<Filter>src</Filter> <Filter>src</Filter>
</ClCompile> </ClCompile>
</ItemGroup> </ItemGroup>

View File

@ -243,6 +243,6 @@ enum InternalTags
DisconnectTag = 255, 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 #endif // DEFS_HPP

View File

@ -10,8 +10,16 @@
struct Initialization struct Initialization
{ {
static bool initialize(); static bool Initialize();
#ifdef _MSC_VER
const WSADATA &GetData();
#endif
private:
#ifdef _MSC_VER
static WSADATA wsa_data; static WSADATA wsa_data;
#endif
}; };
#endif #endif

View File

@ -7,6 +7,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <functional> #include <functional>
#include <future>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma once #pragma once
@ -39,18 +40,24 @@ struct TcpClient
//this is a more manual method with no callbacks //this is a more manual method with no callbacks
const NetworkMessage &ReceiveMessage(); const NetworkMessage &ReceiveMessage();
void SendMessage(const NetworkMessage &message);
void SendBytes(const std::vector<byte> &bytes); std::future<bool> SendMessage(const NetworkMessage &message);
void SendBytes(byte *bytes, uint32 lenght); bool SendBytes(const std::vector<byte> &bytes);
bool SendBytes(byte *bytes, uint32 lenght);
void SetOnDisconnectCallback(void (*func)(uint16)); void SetOnDisconnectCallback(void (*func)(uint16));
void SetOnConnectCallback(void (*func)(uint16)); void SetOnConnectCallback(void (*func)(uint16));
void SetOnMessageCallback(void (*func)(uint16, byte, byte, void*)); void SetOnMessageCallback(void (*func)(uint16, byte, byte, void*));
static const TcpClient &DefaultTcpClient();
private: private:
TcpClient();
const NetworkBuffer &receive_data_array(); const NetworkBuffer &receive_data_array();
static void receive_data(TcpClient *client); 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); bool initialize(const std::string &ip, uint16 port = default_client_port);
uint16 id = -2; uint16 id = -2;
@ -63,11 +70,9 @@ private:
std::function<void(uint16)> OnConnect; std::function<void(uint16)> OnConnect;
std::function<void(uint16, byte, byte, void*)> OnMessage; std::function<void(uint16, byte, byte, void*)> OnMessage;
#ifdef _MSC_VER
SOCKET tcp_socket = INVALID_SOCKET; SOCKET tcp_socket = INVALID_SOCKET;
struct addrinfo *result = nullptr; struct addrinfo *result = nullptr;
struct addrinfo hints; struct addrinfo hints;
#endif
}; };
#endif #endif

View File

@ -22,7 +22,7 @@ struct TcpServer
bool StartServer(bool accept_connections); // if accept_connections is false the user must call the funcion AcceptConnections() bool StartServer(bool accept_connections); // if accept_connections is false the user must call the funcion AcceptConnections()
void AcceptConnections(); void AcceptConnections();
void SendMessage(const NetworkMessage &message); bool SendMessage(const NetworkMessage &message);
void RejectConnection(TcpClient &client); void RejectConnection(TcpClient &client);
void AcceptConnection(uint16 client); void AcceptConnection(uint16 client);
@ -56,11 +56,9 @@ private:
std::vector<TcpClient> clients; std::vector<TcpClient> clients;
#ifdef _MSC_VER
SOCKET server_tcp_socket = INVALID_SOCKET; SOCKET server_tcp_socket = INVALID_SOCKET;
struct addrinfo *result = nullptr; struct addrinfo *result = nullptr;
struct addrinfo hints; struct addrinfo hints;
#endif
}; };
#endif #endif

View File

@ -9,11 +9,49 @@
#include "NetworkMessage.hpp" #include "NetworkMessage.hpp"
#include <string> #include <string>
#include <vector>
#include <functional> #include <functional>
#include <future>
struct UdpClient 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<bool> SendMessage(const NetworkMessage &message);
bool SendBytes(const std::vector<byte> &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<void(uint16)> OnDisconnect;
std::function<void(uint16)> OnConnect;
std::function<void(uint16, byte, byte, void*)> OnMessage;
SOCKET udp_socket = INVALID_SOCKET;
}; };
#endif #endif

34
include/UdpServer.hpp Normal file
View File

@ -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 <string>
#include <vector>
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<UdpClient> clients;
SOCKET server_udp_socket = INVALID_SOCKET;
struct sockaddr_in server;
};
#endif

View File

@ -56,6 +56,15 @@ struct Utility
static const std::string &ToString(int64 value); static const std::string &ToString(int64 value);
static const std::string &ToString(const std::vector<byte> &bytes); static const std::string &ToString(const std::vector<byte> &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<byte> &ToBytes(const std::string &str); static const std::vector<byte> &ToBytes(const std::string &str);
static const std::string &ToString(const std::vector<byte> &bytes, uint16 start_index = 0, uint16 lenght = 0); static const std::string &ToString(const std::vector<byte> &bytes, uint16 start_index = 0, uint16 lenght = 0);
@ -64,6 +73,11 @@ struct Utility
static std::vector<std::string> Split(const std::string &str, const std::string &delimiter); static std::vector<std::string> Split(const std::string &str, const std::string &delimiter);
}; };
struct IPUtil
{
static bool ValidIPV4(const std::string &ip);
};
struct ConfigReader struct ConfigReader
{ {
void ReadConfig(const std::string &file_name); void ReadConfig(const std::string &file_name);

View File

@ -3,7 +3,7 @@
#include <iostream> #include <iostream>
bool Initialization::initialize() bool Initialization::Initialize()
{ {
uint16 code = WSAStartup(MAKEWORD(2, 2), &wsa_data); uint16 code = WSAStartup(MAKEWORD(2, 2), &wsa_data);
if (code != 0) if (code != 0)
@ -14,3 +14,8 @@ bool Initialization::initialize()
} }
return true; return true;
} }
const WSADATA &Initialization::GetData()
{
return wsa_data;
}

View File

@ -1,8 +1,12 @@
#include "TcpClient.hpp" #include "TcpClient.hpp"
#include "NetworkBuffer.hpp" #include "NetworkBuffer.hpp"
#include "Utility.hpp"
#include "Config.hpp"
#include "Handshake.hpp"
#include <string> #include <string>
#include <future> #include <future>
#include <iostream>
TcpClient::TcpClient(const std::string &ip) : port(default_client_port) 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 if (message.tag == ConnectTag) // some user has connected - not us, never
std::async(std::launch::async, client->OnConnect, message.sender); 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); std::async(std::launch::async, client->OnDisconnect, message.sender);
} }
else else
@ -75,9 +79,9 @@ const NetworkMessage & TcpClient::ReceiveMessage()
return receive_data_array(); return receive_data_array();
} }
void TcpClient::SendMessage(const NetworkMessage &message) std::future<bool> 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)) void TcpClient::SetOnDisconnectCallback(void(*func)(uint16))
@ -95,6 +99,146 @@ void TcpClient::SetOnMessageCallback(void(*func)(uint16, byte, byte, void*))
OnMessage = func; OnMessage = func;
} }
#ifdef _MSC_VER const TcpClient & TcpClient::DefaultTcpClient()
#include "TcpClientWindows.cpp" {
#endif 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<u_long*>(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<char*>(header), sizeof(int32), 0) != sizeof(int32))
return NetworkBuffer();
buffer.header = std::vector<byte>(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<char*>(body), body_size, 0);
if (received_bytes == SOCKET_ERROR || received_bytes != body_size || WSAGetLastError() != 0)
return NetworkBuffer();
buffer.body = std::vector<byte>(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<char*>(buffer.body.data()), lenght, 0);
return bytes_sent == SOCKET_ERROR || bytes_sent != lenght || WSAGetLastError() != 0;
}
bool TcpClient::SendBytes(const std::vector<byte>& bytes)
{
int32 bytes_sent = send(tcp_socket, reinterpret_cast<const char*>(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<const char*>(bytes), size, 0);
return bytes_sent == SOCKET_ERROR || bytes_sent != size || WSAGetLastError() != 0;
}

View File

@ -1,156 +0,0 @@
#include "TcpClient.hpp"
#include "Utility.hpp"
#include "Config.hpp"
#include "Handshake.hpp"
#include <iostream>
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<u_long*>(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<char*>(header), sizeof(int32), 0) != sizeof(int32))
//invalid header
return NetworkBuffer();
buffer.header = std::vector<byte>(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<char*>(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<byte>(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<char*>(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<byte>& bytes)
{
int32 bytes_sent = send(tcp_socket, reinterpret_cast<const char*>(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<const char*>(bytes), size, 0);
if (bytes_sent == SOCKET_ERROR || bytes_sent != size || WSAGetLastError() != 0)
{
//something went wrong couldnt send anything/some data
}
}

View File

@ -1,18 +1,22 @@
#include "TcpServer.hpp" #include "TcpServer.hpp"
#include "Config.hpp" #include "Config.hpp"
#include "Handshake.hpp" #include "Handshake.hpp"
#include "Utility.hpp"
#include <string>
#include <future> #include <future>
#include <iostream> #include <iostream>
TcpServer::TcpServer() TcpServer::TcpServer()
{ {
initialize(); // initialize with the default port initialize(); // initialize with the default port
clients = std::vector<TcpClient>(max_connections);
} }
TcpServer::TcpServer(uint16 port) TcpServer::TcpServer(uint16 port)
{ {
initialize(port); initialize(port);
clients = std::vector<TcpClient>(max_connections);
} }
TcpServer::~TcpServer() 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) switch (message.distribution_mode)
{ {
@ -65,7 +69,6 @@ void TcpServer::SendMessage(const NetworkMessage & message)
} }
for (uint16 i = 0; i < OnMessageFunctions.size(); i++) for (uint16 i = 0; i < OnMessageFunctions.size(); i++)
OnMessageFunctions[i](message); OnMessageFunctions[i](message);
break;
} }
case AllAndMe: // this will send the message to EVERYONE including the user that sent it 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++) for (uint16 i = 0; i < OnMessageFunctions.size(); i++)
OnMessageFunctions[i](message); OnMessageFunctions[i](message);
break;
} }
case Server: // this will only send the message to the server case Server: // this will only send the message to the server
{ {
@ -84,7 +86,6 @@ void TcpServer::SendMessage(const NetworkMessage & message)
CloseSocket(message.sender); CloseSocket(message.sender);
for (uint16 i = 0; i < OnMessageFunctions.size(); i++) for (uint16 i = 0; i < OnMessageFunctions.size(); i++)
OnMessageFunctions[i](message); OnMessageFunctions[i](message);
break;
} }
case Others: // this will send the message to others, excluding server and the user that sent it 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()) if (message.sender != client.GetID())
client.SendMessage(message); client.SendMessage(message);
} }
break;
} }
case ID: // this will send the message to a specific id case ID: // this will send the message to a specific id
{ {
@ -102,12 +102,9 @@ void TcpServer::SendMessage(const NetworkMessage & message)
{ {
TcpClient client = *it; TcpClient client = *it;
if (message.sender == client.GetID()) if (message.sender == client.GetID())
{
client.SendMessage(message); client.SendMessage(message);
break;
} }
} return false;
break;
} }
} }
} }
@ -190,7 +187,7 @@ const TcpClient & TcpServer::GetClientByID(uint16 id)
if (client.GetID() == id) if (client.GetID() == id)
return client; return client;
} }
return TcpClient(); return TcpClient::DefaultTcpClient();
} }
void TcpServer::SetMaxConnections(uint16 value) void TcpServer::SetMaxConnections(uint16 value)
@ -203,6 +200,91 @@ uint16 TcpServer::GetMaxConnections()
return max_connections; return max_connections;
} }
#ifdef _MSC_VER bool TcpServer::initialize(uint16 port)
#include "TcpServerWindows.cpp" {
#endif 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);
}

View File

@ -1,96 +0,0 @@
#include "TcpServer.hpp"
#include "Config.hpp"
#include "Utility.hpp"
#include <string>
#include <iostream>
#include <future>
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);
}

View File

@ -1,5 +1,105 @@
#include "UdpClient.hpp" #include "UdpClient.hpp"
#include "Handshake.hpp"
#include "Config.hpp"
#ifdef _MSC_VER #include <iostream>
#include "UdpClientWindows.cpp"
#endif #include <future>
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<bool> 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<byte> &bytes)
{
}
bool UdpClient::SendBytes(byte *bytes, uint32 lenght)
{
}
bool UdpClient::send_network_message(const NetworkMessage &message, UdpClient *client)
{
}

View File

@ -1 +0,0 @@
#include "UdpClient.hpp"

57
src/UdpServer.cpp Normal file
View File

@ -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<UdpClient>::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<struct sockaddr*>(&server), sizeof(struct sockaddr_in)) == -1)
{
closesocket(server_udp_socket);
WSACleanup();
return false;
}
return initialized = true;
}
void UdpServer::shutdown_internal()
{
WSACleanup();
}

View File

@ -162,6 +162,46 @@ const std::string & Utility::StringConverter::ToString(const std::vector<byte>&
return std::string(); 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<byte>& Utility::StringConverter::ToBytes(const std::string & str) const std::vector<byte>& Utility::StringConverter::ToBytes(const std::string & str)
{ {
return std::vector<byte>(); return std::vector<byte>();
@ -224,3 +264,17 @@ const std::string & Utility::ConfigReader::operator[](const std::string &key)
{ {
return nodes.at(key); return nodes.at(key);
} }
bool Utility::IPUtil::ValidIPV4(const std::string & ip)
{
std::vector<std::string> 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;
}

View File

@ -37,8 +37,6 @@ void VoidNetClientAPI::SendMessageToAllAndMe(byte tag, byte subject, void *data)
void VoidNetClientAPI::SendMessage(byte distribution_mode, uint16 destination_id, 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; NetworkMessage message;
message.tag = tag; message.tag = tag;
message.subject = subject; message.subject = subject;
@ -46,8 +44,8 @@ void VoidNetClientAPI::SendMessage(byte distribution_mode, uint16 destination_id
message.distribution_mode = distribution_mode; message.distribution_mode = distribution_mode;
message.sender = id; message.sender = id;
message.destination_id = destination_id; message.destination_id = destination_id;
if (!IS_HANDSHAKE(message))
tcp_client.SendMessage(message); tcp_client.SendMessage(message);
}
} }
void VoidNetClientAPI::Receive() void VoidNetClientAPI::Receive()