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:
7
TODO
7
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...
|
||||
|
||||
TcpServer::SendMessage rework
|
||||
@ -29,6 +29,7 @@
|
||||
<ClInclude Include="..\..\include\TcpClient.hpp" />
|
||||
<ClInclude Include="..\..\include\TcpServer.hpp" />
|
||||
<ClInclude Include="..\..\include\UdpClient.hpp" />
|
||||
<ClInclude Include="..\..\include\UdpServer.hpp" />
|
||||
<ClInclude Include="..\..\include\Utility.hpp" />
|
||||
<ClInclude Include="..\..\include\VoidNetClient.hpp" />
|
||||
<ClInclude Include="..\..\include\VoidNetServer.hpp" />
|
||||
@ -44,17 +45,9 @@
|
||||
<ClCompile Include="..\..\src\NetworkMessage.cpp" />
|
||||
<ClCompile Include="..\..\src\Serializer.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\TcpServerWindows.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\UdpClient.cpp" />
|
||||
<ClCompile Include="..\..\src\UdpClientWindows.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\UdpServer.cpp" />
|
||||
<ClCompile Include="..\..\src\Utility.cpp" />
|
||||
<ClCompile Include="..\..\src\VoidNetClient.cpp" />
|
||||
</ItemGroup>
|
||||
|
||||
@ -48,14 +48,14 @@
|
||||
<ClInclude Include="..\..\include\UdpClient.hpp">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\UdpServer.hpp">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\Init.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\TcpClientWindows.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\Utility.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
@ -74,9 +74,6 @@
|
||||
<ClCompile Include="..\..\src\VoidNetClient.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\TcpServerWindows.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\TcpServer.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
@ -92,7 +89,7 @@
|
||||
<ClCompile Include="..\..\src\UdpClient.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\UdpClientWindows.cpp">
|
||||
<ClCompile Include="..\..\src\UdpServer.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
|
||||
@ -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
|
||||
@ -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
|
||||
@ -7,6 +7,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <future>
|
||||
|
||||
#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<byte> &bytes);
|
||||
void SendBytes(byte *bytes, uint32 lenght);
|
||||
|
||||
std::future<bool> SendMessage(const NetworkMessage &message);
|
||||
bool SendBytes(const std::vector<byte> &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<void(uint16)> OnConnect;
|
||||
std::function<void(uint16, byte, byte, void*)> OnMessage;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
SOCKET tcp_socket = INVALID_SOCKET;
|
||||
struct addrinfo *result = nullptr;
|
||||
struct addrinfo hints;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -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<TcpClient> clients;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
SOCKET server_tcp_socket = INVALID_SOCKET;
|
||||
struct addrinfo *result = nullptr;
|
||||
struct addrinfo hints;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@ -9,11 +9,49 @@
|
||||
#include "NetworkMessage.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <future>
|
||||
|
||||
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
|
||||
|
||||
34
include/UdpServer.hpp
Normal file
34
include/UdpServer.hpp
Normal 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
|
||||
@ -56,6 +56,15 @@ struct Utility
|
||||
static const std::string &ToString(int64 value);
|
||||
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::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);
|
||||
};
|
||||
|
||||
struct IPUtil
|
||||
{
|
||||
static bool ValidIPV4(const std::string &ip);
|
||||
};
|
||||
|
||||
struct ConfigReader
|
||||
{
|
||||
void ReadConfig(const std::string &file_name);
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
bool Initialization::initialize()
|
||||
bool Initialization::Initialize()
|
||||
{
|
||||
uint16 code = WSAStartup(MAKEWORD(2, 2), &wsa_data);
|
||||
if (code != 0)
|
||||
@ -14,3 +14,8 @@ bool Initialization::initialize()
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const WSADATA &Initialization::GetData()
|
||||
{
|
||||
return wsa_data;
|
||||
}
|
||||
@ -1,8 +1,12 @@
|
||||
#include "TcpClient.hpp"
|
||||
#include "NetworkBuffer.hpp"
|
||||
#include "Utility.hpp"
|
||||
#include "Config.hpp"
|
||||
#include "Handshake.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <future>
|
||||
#include <iostream>
|
||||
|
||||
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<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))
|
||||
@ -95,6 +99,146 @@ void TcpClient::SetOnMessageCallback(void(*func)(uint16, byte, byte, void*))
|
||||
OnMessage = func;
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include "TcpClientWindows.cpp"
|
||||
#endif
|
||||
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<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;
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
@ -1,18 +1,22 @@
|
||||
#include "TcpServer.hpp"
|
||||
#include "Config.hpp"
|
||||
#include "Handshake.hpp"
|
||||
#include "Utility.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <future>
|
||||
#include <iostream>
|
||||
|
||||
TcpServer::TcpServer()
|
||||
{
|
||||
initialize(); // initialize with the default port
|
||||
clients = std::vector<TcpClient>(max_connections);
|
||||
}
|
||||
|
||||
TcpServer::TcpServer(uint16 port)
|
||||
{
|
||||
initialize(port);
|
||||
clients = std::vector<TcpClient>(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
|
||||
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);
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
@ -1,5 +1,105 @@
|
||||
#include "UdpClient.hpp"
|
||||
#include "Handshake.hpp"
|
||||
#include "Config.hpp"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include "UdpClientWindows.cpp"
|
||||
#endif
|
||||
#include <iostream>
|
||||
|
||||
#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)
|
||||
{
|
||||
|
||||
}
|
||||
@ -1 +0,0 @@
|
||||
#include "UdpClient.hpp"
|
||||
57
src/UdpServer.cpp
Normal file
57
src/UdpServer.cpp
Normal 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();
|
||||
}
|
||||
@ -162,6 +162,46 @@ const std::string & Utility::StringConverter::ToString(const std::vector<byte>&
|
||||
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)
|
||||
{
|
||||
return std::vector<byte>();
|
||||
@ -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<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;
|
||||
}
|
||||
|
||||
@ -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)
|
||||
{
|
||||
if (tag != ConnectTag && tag != DisconnectTag)
|
||||
{
|
||||
NetworkMessage message;
|
||||
message.tag = tag;
|
||||
message.subject = subject;
|
||||
@ -46,8 +44,8 @@ void VoidNetClientAPI::SendMessage(byte distribution_mode, uint16 destination_id
|
||||
message.distribution_mode = distribution_mode;
|
||||
message.sender = id;
|
||||
message.destination_id = destination_id;
|
||||
if (!IS_HANDSHAKE(message))
|
||||
tcp_client.SendMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
void VoidNetClientAPI::Receive()
|
||||
|
||||
Reference in New Issue
Block a user