Added conversion from Handshake to NetworkMessage and vice versa

Added a new ConnectionCode - Close
TcpServer: AddToClientsList and AllocateID are now called add_to_clients_list and allocate_id respectively and are now private, removed SendHandshake method - we now use SendMessage method and the HandshakeToNetworkMessage method in the Handshake class
Added a new method to Utility::StringConverter - FromString
Changed NetworkMessage conversions to allow Handshake conversions
NetworkMessage: if subject is 1 then the NetworkMessage is a handshake
I may be missing something but im going to check it
I may be overcomplicating this but i want to make it as simple as possible xD
This commit is contained in:
xX-TheDoctor-Xx
2016-08-18 15:08:51 +01:00
parent 2314e862b1
commit 9d1c518610
16 changed files with 118 additions and 95 deletions

View File

@ -1,2 +1,4 @@
id -1 is server / valid message if other parameters are valid as well
id -2 is invalid network message
NetworkMessage: subject 1 is reserved for handshake validation

View File

@ -134,7 +134,7 @@
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<AdditionalIncludeDirectories>F:\VoidNet\include;F:\VoidNet\src</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..\include;..\..\src</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>

View File

@ -233,7 +233,8 @@ enum DistributionType
enum ConnectionCode
{
Accept,
Reject
Reject,
Close
};
enum InternalTags

View File

@ -6,6 +6,7 @@
#endif
#include "Defs.hpp"
#include "NetworkMessage.hpp"
#include <vector>
@ -17,6 +18,8 @@ struct Handshake
static const std::vector<byte> &EncodeHandshake(const Handshake &handshake);
static Handshake &DecodeHandshake(const std::vector<byte> &bytes);
static const NetworkMessage &HandshakeToNetworkMessage(const Handshake &handshake);
static const Handshake &NetworkMessageToHandshake(const NetworkMessage &message);
uint16 id;
byte con_code;

View File

@ -19,13 +19,10 @@ struct TcpServer
void Shutdown();
uint16 AllocateID();
void AddToClientsList(TcpClient &client);
bool StartServer(bool accept_connections); // if accept_connections is false the user must call the funcion AcceptConnections()
void AcceptConnections();
void SendMessage(const NetworkMessage &message);
void SendHandshake(const Handshake &handshake);
void RejectConnection(TcpClient &client);
void AcceptConnection(uint16 client);
@ -44,6 +41,10 @@ private:
static void process_client_messages(TcpServer *server, TcpClient &client);
static void accept_connections(TcpServer *server);
void add_to_clients_list(TcpClient &client);
uint16 allocate_id();
void shutdown_internal();
bool initialize(uint16 port = default_server_port);

View File

@ -56,6 +56,8 @@ struct Utility
static const std::string &ToString(int64 value);
static const std::string &ToString(const std::vector<byte> &bytes);
static const std::vector<byte> &FromString(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 &Trim(std::string &str, char ch);

View File

@ -9,6 +9,8 @@
struct VoidNetServer
{
void StartServer(uint16 port);
void StopServer();
private:
TcpServer server;
};

View File

@ -24,8 +24,9 @@ const std::vector<byte>& Handshake::EncodeHandshake(const Handshake & handshake)
std::vector<byte> id = Utility::BitConverter::FromUint16(handshake.id);
std::vector<byte> con_mode = Utility::BitConverter::FromUint8(handshake.con_code);
handshake_bytes.insert(handshake_bytes.end(), id.begin(), id.end());
handshake_bytes.insert(handshake_bytes.end(), con_mode.begin(), con_mode.end());
handshake_bytes.emplace_back(Utility::BitConverter::FromUint8(1));
handshake_bytes.emplace_back(id.begin(), id.end());
handshake_bytes.emplace_back(con_mode.begin(), con_mode.end());
return handshake_bytes;
}
@ -34,8 +35,25 @@ Handshake & Handshake::DecodeHandshake(const std::vector<byte>& bytes)
{
Handshake handshake;
handshake.id = Utility::BitConverter::ToUint16(bytes);
handshake.con_code = Utility::BitConverter::ToUint8(bytes, 2);
handshake.id = Utility::BitConverter::ToUint16(bytes, 1);
handshake.con_code = Utility::BitConverter::ToUint8(bytes, 3);
return handshake;
}
const NetworkMessage & Handshake::HandshakeToNetworkMessage(const Handshake & handshake)
{
NetworkMessage message;
message.sender = handshake.id;
message.tag = handshake.con_code;
message.subject = 1;
return message;
}
const Handshake & Handshake::NetworkMessageToHandshake(const NetworkMessage & message)
{
Handshake handshake;
handshake.id = message.sender;
handshake.con_code = message.tag;
return handshake;
}

View File

@ -1,6 +1,7 @@
#include "NetworkMessage.hpp"
#include "Utility.hpp"
#include "Serializer.hpp"
#include "Handshake.hpp"
#include <vector>
@ -28,6 +29,8 @@ const NetworkBuffer &NetworkMessage::EncodeMessage(const NetworkMessage &message
{
NetworkBuffer net_buffer;
if (message.subject != 1)
{
std::vector<byte> sender = Utility::BitConverter::FromUint16(message.sender);
std::vector<byte> distribution_mode = Utility::BitConverter::FromUint8(message.distribution_mode);
std::vector<byte> destination_id = Utility::BitConverter::FromUint16(message.destination_id);
@ -37,23 +40,37 @@ const NetworkBuffer &NetworkMessage::EncodeMessage(const NetworkMessage &message
if (message.data != nullptr)
data = Serializer::to_bytes(message.data);
net_buffer.body.insert(net_buffer.body.end(), sender.begin(), sender.end());
net_buffer.body.insert(net_buffer.body.end(), distribution_mode.begin(), distribution_mode.end());
net_buffer.body.insert(net_buffer.body.end(), destination_id.begin(), destination_id.end());
net_buffer.body.insert(net_buffer.body.end(), tag.begin(), tag.end());
net_buffer.body.insert(net_buffer.body.end(), subject.begin(), subject.end());
net_buffer.body.emplace_back(Utility::BitConverter::FromInt8(0));
net_buffer.body.emplace_back(sender.begin(), sender.end());
net_buffer.body.emplace_back(distribution_mode.begin(), distribution_mode.end());
net_buffer.body.emplace_back(destination_id.begin(), destination_id.end());
net_buffer.body.emplace_back(tag.begin(), tag.end());
net_buffer.body.emplace_back(subject.begin(), subject.end());
if (message.data != nullptr && data.size() > 0)
net_buffer.body.insert(net_buffer.body.end(), data.begin(), data.end());
net_buffer.body.emplace_back(data.begin(), data.end());
net_buffer.header = Utility::BitConverter::FromInt32(sender.size() + distribution_mode.size() + destination_id.size() +
tag.size() + subject.size() + data.size());
net_buffer.valid = true;
}
else
{
std::vector<byte> handshake_bytes = Handshake::EncodeHandshake(Handshake::NetworkMessageToHandshake(message));
net_buffer.header = Utility::BitConverter::FromInt32(handshake_bytes.size());
net_buffer.body = handshake_bytes;
}
return net_buffer;
}
return NetworkBuffer();
}
const NetworkMessage &NetworkMessage::DecodeMessage(const NetworkBuffer &buffer)
{
if (buffer.valid)
{
byte type = buffer.body[0];
switch (type)
{
case 0:
{
NetworkMessage message;
message.sender = Utility::BitConverter::ToUint16(buffer.body, 1);
@ -62,25 +79,30 @@ const NetworkMessage &NetworkMessage::DecodeMessage(const NetworkBuffer &buffer)
message.tag = buffer.body[6];
message.subject = Utility::BitConverter::ToUint8(buffer.body, 7);
message.valid = message.sender != -2 && message.tag != CONNECT && message.tag != DISCONNECT;
if (Utility::BitConverter::ToInt32(buffer.header) < 9)
return message;
byte version = buffer.body[0];
switch (version)
{
case 0:
{
void *object;
object = Serializer::from_bytes(buffer.body, object);
return message;
}
case 1:
{
NetworkMessage message;
message.sender = Utility::BitConverter::ToUint16(buffer.body, 1);
message.tag = Utility::BitConverter::ToUint8(buffer.body, 3);
message.subject = 1;
message.valid = message.sender != -2 && (message.tag == DISCONNECT || message.tag == CONNECT || message.tag == ConnectionCode::Accept ||
message.tag == ConnectionCode::Close || message.tag == ConnectionCode::Reject);
return message;
break;
}
default:
{
//version not supported
//type not supported
throw std::runtime_error("NetworkMessage - Decoding version not supported");
}
}
return message;
}
return NetworkMessage();
}

View File

@ -56,10 +56,13 @@ void TcpClient::receive_data(TcpClient *client)
NetworkMessage message(client->ReceiveMessage());
if (message.valid)
{
if (message.tag == CONNECT) // some user has connected
if (message.subject == 1) // its a handshake
{
if (message.tag == CONNECT) // some user has connected - not us, never
std::async(std::launch::async, client->OnConnect, message.sender);
else if (message.tag == DISCONNECT) // some user has disconnected
else if (message.tag == DISCONNECT || message.tag == ConnectionCode::Close) // some user has disconnected
std::async(std::launch::async, client->OnDisconnect, message.sender);
}
else
std::async(std::launch::async, client->OnMessage, message.sender, message.tag, message.subject, message.data); // we received data
}

View File

@ -53,11 +53,8 @@ TcpClient::~TcpClient()
void TcpClient::Shutdown()
{
NetworkMessage message;
message.sender = id;
message.distribution_mode = Server;
message.tag = DISCONNECT;
SendMessage(message);
Handshake handshake(id, Close, Server);
SendMessage(Handshake::HandshakeToNetworkMessage(handshake));
uint16 code = closesocket(tcp_socket);
if (code == SOCKET_ERROR)
{
@ -82,14 +79,13 @@ bool TcpClient::Connect()
if (connect_code == SOCKET_ERROR)
return false;
NetworkBuffer buffer(receive_data_array());
if (buffer.valid)
NetworkMessage message(receive_data_array());
if (message.valid && message.subject == 1)
{
Handshake handshake = Handshake::DecodeHandshake(buffer.body);
if (handshake.con_code == ConnectionCode::Accept)
if (message.tag == ConnectionCode::Accept)
{
receive = true;
OnConnect(handshake.id);
OnConnect(message.sender);
return true;
}
}

View File

@ -33,10 +33,13 @@ void TcpServer::Shutdown()
}
void TcpServer::AcceptConnections()
{
if (!running)
{
running = true;
std::async(std::launch::async, &accept_connections, this);
}
}
void TcpServer::process_client_messages(TcpServer *server, TcpClient & client)
{
@ -109,36 +112,7 @@ void TcpServer::SendMessage(const NetworkMessage & message)
}
}
void TcpServer::SendHandshake(const Handshake & handshake)
{
switch (handshake.distribution_mode)
{
case AllAndMe: // this will send the message to EVERYONE including the user that sent it
{
for (std::vector<TcpClient>::iterator it = clients.begin(); it != clients.end(); ++it)
{
TcpClient client = *it;
client.SendBytes(Handshake::EncodeHandshake(handshake));
}
break;
}
case ID: // this will send the message to a specific id
{
for (std::vector<TcpClient>::iterator it = clients.begin(); it != clients.end(); ++it)
{
TcpClient client = *it;
if (handshake.id == client.GetID())
{
client.SendBytes(Handshake::EncodeHandshake(handshake));
break;
}
}
break;
}
}
}
uint16 TcpServer::AllocateID() // this function is only used in the AddToClientsList function
uint16 TcpServer::allocate_id() // this function is only used in the AddToClientsList function
{
for (uint16 i = 1; i < max_connections; ++i)
{
@ -159,9 +133,9 @@ uint16 TcpServer::AllocateID() // this function is only used in the AddToClients
return 0;
}
void TcpServer::AddToClientsList(TcpClient & client_socket)
void TcpServer::add_to_clients_list(TcpClient & client_socket)
{
uint16 id = AllocateID();
uint16 id = allocate_id();
if (id > 0)
{
client_socket.SetID(id);
@ -179,14 +153,13 @@ void TcpServer::AddToClientsList(TcpClient & client_socket)
void TcpServer::RejectConnection(TcpClient &client)
{
Handshake handshake(client.GetID(), ConnectionCode::Reject, ID);
client.SendBytes(Handshake::EncodeHandshake(handshake));
CloseSocket(client);
SendMessage(Handshake::HandshakeToNetworkMessage(handshake));
}
void TcpServer::AcceptConnection(uint16 id)
{
Handshake handshake(id, ConnectionCode::Accept, AllAndMe);
SendHandshake(handshake);
SendMessage(Handshake::HandshakeToNetworkMessage(handshake));
}
void TcpServer::CloseSocket(TcpClient & client)

View File

@ -185,10 +185,10 @@ void Utility::ConfigReader::ReadConfig(const std::string & file_name)
return;
std::fstream file;
file.open(file_name);
if (file.is_open)
if (file.is_open())
{
longlong file_lenght = file.gcount();
char *content = new char[file_lenght]();
char *content = new char[static_cast<uint32>(file_lenght)]();
file.read(content, file_lenght);
file_content = std::string(content);
}