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 -1 is server / valid message if other parameters are valid as well
id -2 is invalid network message id -2 is invalid network message
NetworkMessage: subject 1 is reserved for handshake validation

View File

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

View File

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

View File

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

View File

@ -19,13 +19,10 @@ struct TcpServer
void Shutdown(); 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() 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); void SendMessage(const NetworkMessage &message);
void SendHandshake(const Handshake &handshake);
void RejectConnection(TcpClient &client); void RejectConnection(TcpClient &client);
void AcceptConnection(uint16 client); void AcceptConnection(uint16 client);
@ -44,6 +41,10 @@ private:
static void process_client_messages(TcpServer *server, TcpClient &client); static void process_client_messages(TcpServer *server, TcpClient &client);
static void accept_connections(TcpServer *server); static void accept_connections(TcpServer *server);
void add_to_clients_list(TcpClient &client);
uint16 allocate_id();
void shutdown_internal(); void shutdown_internal();
bool initialize(uint16 port = default_server_port); 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(int64 value);
static const std::string &ToString(const std::vector<byte> &bytes); 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 &ToString(const std::vector<byte> &bytes, uint16 start_index = 0, uint16 lenght = 0);
static const std::string &Trim(std::string &str, char ch); static const std::string &Trim(std::string &str, char ch);

View File

@ -9,6 +9,8 @@
struct VoidNetServer struct VoidNetServer
{ {
void StartServer(uint16 port);
void StopServer();
private: private:
TcpServer server; 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> id = Utility::BitConverter::FromUint16(handshake.id);
std::vector<byte> con_mode = Utility::BitConverter::FromUint8(handshake.con_code); std::vector<byte> con_mode = Utility::BitConverter::FromUint8(handshake.con_code);
handshake_bytes.insert(handshake_bytes.end(), id.begin(), id.end()); handshake_bytes.emplace_back(Utility::BitConverter::FromUint8(1));
handshake_bytes.insert(handshake_bytes.end(), con_mode.begin(), con_mode.end()); handshake_bytes.emplace_back(id.begin(), id.end());
handshake_bytes.emplace_back(con_mode.begin(), con_mode.end());
return handshake_bytes; return handshake_bytes;
} }
@ -34,8 +35,25 @@ Handshake & Handshake::DecodeHandshake(const std::vector<byte>& bytes)
{ {
Handshake handshake; Handshake handshake;
handshake.id = Utility::BitConverter::ToUint16(bytes); handshake.id = Utility::BitConverter::ToUint16(bytes, 1);
handshake.con_code = Utility::BitConverter::ToUint8(bytes, 2); handshake.con_code = Utility::BitConverter::ToUint8(bytes, 3);
return handshake; 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 "NetworkMessage.hpp"
#include "Utility.hpp" #include "Utility.hpp"
#include "Serializer.hpp" #include "Serializer.hpp"
#include "Handshake.hpp"
#include <vector> #include <vector>
@ -28,6 +29,8 @@ const NetworkBuffer &NetworkMessage::EncodeMessage(const NetworkMessage &message
{ {
NetworkBuffer net_buffer; NetworkBuffer net_buffer;
if (message.subject != 1)
{
std::vector<byte> sender = Utility::BitConverter::FromUint16(message.sender); std::vector<byte> sender = Utility::BitConverter::FromUint16(message.sender);
std::vector<byte> distribution_mode = Utility::BitConverter::FromUint8(message.distribution_mode); std::vector<byte> distribution_mode = Utility::BitConverter::FromUint8(message.distribution_mode);
std::vector<byte> destination_id = Utility::BitConverter::FromUint16(message.destination_id); 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) if (message.data != nullptr)
data = Serializer::to_bytes(message.data); data = Serializer::to_bytes(message.data);
net_buffer.body.insert(net_buffer.body.end(), sender.begin(), sender.end()); net_buffer.body.emplace_back(Utility::BitConverter::FromInt8(0));
net_buffer.body.insert(net_buffer.body.end(), distribution_mode.begin(), distribution_mode.end()); net_buffer.body.emplace_back(sender.begin(), sender.end());
net_buffer.body.insert(net_buffer.body.end(), destination_id.begin(), destination_id.end()); net_buffer.body.emplace_back(distribution_mode.begin(), distribution_mode.end());
net_buffer.body.insert(net_buffer.body.end(), tag.begin(), tag.end()); net_buffer.body.emplace_back(destination_id.begin(), destination_id.end());
net_buffer.body.insert(net_buffer.body.end(), subject.begin(), subject.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) 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() + net_buffer.header = Utility::BitConverter::FromInt32(sender.size() + distribution_mode.size() + destination_id.size() +
tag.size() + subject.size() + data.size()); tag.size() + subject.size() + data.size());
net_buffer.valid = true; 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(); return NetworkBuffer();
} }
const NetworkMessage &NetworkMessage::DecodeMessage(const NetworkBuffer &buffer) const NetworkMessage &NetworkMessage::DecodeMessage(const NetworkBuffer &buffer)
{ {
if (buffer.valid) if (buffer.valid)
{
byte type = buffer.body[0];
switch (type)
{
case 0:
{ {
NetworkMessage message; NetworkMessage message;
message.sender = Utility::BitConverter::ToUint16(buffer.body, 1); 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.tag = buffer.body[6];
message.subject = Utility::BitConverter::ToUint8(buffer.body, 7); message.subject = Utility::BitConverter::ToUint8(buffer.body, 7);
message.valid = message.sender != -2 && message.tag != CONNECT && message.tag != DISCONNECT; message.valid = message.sender != -2 && message.tag != CONNECT && message.tag != DISCONNECT;
if (Utility::BitConverter::ToInt32(buffer.header) < 9) if (Utility::BitConverter::ToInt32(buffer.header) < 9)
return message; return message;
byte version = buffer.body[0];
switch (version)
{
case 0:
{
void *object; void *object;
object = Serializer::from_bytes(buffer.body, 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: default:
{ {
//version not supported //type not supported
throw std::runtime_error("NetworkMessage - Decoding version not supported"); throw std::runtime_error("NetworkMessage - Decoding version not supported");
} }
} }
return message;
} }
return NetworkMessage(); return NetworkMessage();
} }

View File

@ -56,10 +56,13 @@ void TcpClient::receive_data(TcpClient *client)
NetworkMessage message(client->ReceiveMessage()); NetworkMessage message(client->ReceiveMessage());
if (message.valid) 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); 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); std::async(std::launch::async, client->OnDisconnect, message.sender);
}
else else
std::async(std::launch::async, client->OnMessage, message.sender, message.tag, message.subject, message.data); // we received data 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() void TcpClient::Shutdown()
{ {
NetworkMessage message; Handshake handshake(id, Close, Server);
message.sender = id; SendMessage(Handshake::HandshakeToNetworkMessage(handshake));
message.distribution_mode = Server;
message.tag = DISCONNECT;
SendMessage(message);
uint16 code = closesocket(tcp_socket); uint16 code = closesocket(tcp_socket);
if (code == SOCKET_ERROR) if (code == SOCKET_ERROR)
{ {
@ -82,14 +79,13 @@ bool TcpClient::Connect()
if (connect_code == SOCKET_ERROR) if (connect_code == SOCKET_ERROR)
return false; return false;
NetworkBuffer buffer(receive_data_array()); NetworkMessage message(receive_data_array());
if (buffer.valid) if (message.valid && message.subject == 1)
{ {
Handshake handshake = Handshake::DecodeHandshake(buffer.body); if (message.tag == ConnectionCode::Accept)
if (handshake.con_code == ConnectionCode::Accept)
{ {
receive = true; receive = true;
OnConnect(handshake.id); OnConnect(message.sender);
return true; return true;
} }
} }

View File

@ -33,10 +33,13 @@ void TcpServer::Shutdown()
} }
void TcpServer::AcceptConnections() void TcpServer::AcceptConnections()
{
if (!running)
{ {
running = true; running = true;
std::async(std::launch::async, &accept_connections, this); std::async(std::launch::async, &accept_connections, this);
} }
}
void TcpServer::process_client_messages(TcpServer *server, TcpClient & client) 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) uint16 TcpServer::allocate_id() // this function is only used in the AddToClientsList function
{
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
{ {
for (uint16 i = 1; i < max_connections; ++i) 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; 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) if (id > 0)
{ {
client_socket.SetID(id); client_socket.SetID(id);
@ -179,14 +153,13 @@ void TcpServer::AddToClientsList(TcpClient & client_socket)
void TcpServer::RejectConnection(TcpClient &client) void TcpServer::RejectConnection(TcpClient &client)
{ {
Handshake handshake(client.GetID(), ConnectionCode::Reject, ID); Handshake handshake(client.GetID(), ConnectionCode::Reject, ID);
client.SendBytes(Handshake::EncodeHandshake(handshake)); SendMessage(Handshake::HandshakeToNetworkMessage(handshake));
CloseSocket(client);
} }
void TcpServer::AcceptConnection(uint16 id) void TcpServer::AcceptConnection(uint16 id)
{ {
Handshake handshake(id, ConnectionCode::Accept, AllAndMe); Handshake handshake(id, ConnectionCode::Accept, AllAndMe);
SendHandshake(handshake); SendMessage(Handshake::HandshakeToNetworkMessage(handshake));
} }
void TcpServer::CloseSocket(TcpClient & client) void TcpServer::CloseSocket(TcpClient & client)

View File

@ -185,10 +185,10 @@ void Utility::ConfigReader::ReadConfig(const std::string & file_name)
return; return;
std::fstream file; std::fstream file;
file.open(file_name); file.open(file_name);
if (file.is_open) if (file.is_open())
{ {
longlong file_lenght = file.gcount(); 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.read(content, file_lenght);
file_content = std::string(content); file_content = std::string(content);
} }