diff --git a/DEV_INFO b/DEV_INFO
new file mode 100644
index 0000000..ee5e530
--- /dev/null
+++ b/DEV_INFO
@@ -0,0 +1,5 @@
+id -1 is server / valid message if other parameters are valid as well
+id -2 is invalid network message
+
+
+currently working on: TcpClient::SendMessage
\ No newline at end of file
diff --git a/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/CL.command.1.tlog b/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/CL.command.1.tlog
index cf2b1b3..f06a63f 100644
Binary files a/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/CL.command.1.tlog and b/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/CL.command.1.tlog differ
diff --git a/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/CL.read.1.tlog b/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/CL.read.1.tlog
index 3c4f5f0..72e3d43 100644
Binary files a/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/CL.read.1.tlog and b/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/CL.read.1.tlog differ
diff --git a/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/CL.write.1.tlog b/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/CL.write.1.tlog
index f8ea4cf..bfd30b5 100644
Binary files a/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/CL.write.1.tlog and b/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/CL.write.1.tlog differ
diff --git a/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/Lib-link.write.1.tlog b/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/Lib-link.write.1.tlog
index 1670021..bd81a63 100644
Binary files a/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/Lib-link.write.1.tlog and b/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/Lib-link.write.1.tlog differ
diff --git a/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/Lib.read.1.tlog b/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/Lib.read.1.tlog
index 0d32cf9..d1d9bcb 100644
Binary files a/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/Lib.read.1.tlog and b/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/Lib.read.1.tlog differ
diff --git a/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/lib.command.1.tlog b/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/lib.command.1.tlog
index 724e276..3e3d46b 100644
Binary files a/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/lib.command.1.tlog and b/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/lib.command.1.tlog differ
diff --git a/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/unsuccessfulbuild b/VoidNetVS/VoidNetVS/Release/VoidNetVS.tlog/unsuccessfulbuild
deleted file mode 100644
index e69de29..0000000
diff --git a/VoidNetVS/VoidNetVS/VoidNetVS.vcxproj b/VoidNetVS/VoidNetVS/VoidNetVS.vcxproj
index 1314c09..788028c 100644
--- a/VoidNetVS/VoidNetVS/VoidNetVS.vcxproj
+++ b/VoidNetVS/VoidNetVS/VoidNetVS.vcxproj
@@ -27,6 +27,7 @@
+
@@ -41,9 +42,12 @@
+
+
+
diff --git a/VoidNetVS/VoidNetVS/VoidNetVS.vcxproj.filters b/VoidNetVS/VoidNetVS/VoidNetVS.vcxproj.filters
index 6e2ac58..11506fe 100644
--- a/VoidNetVS/VoidNetVS/VoidNetVS.vcxproj.filters
+++ b/VoidNetVS/VoidNetVS/VoidNetVS.vcxproj.filters
@@ -45,6 +45,9 @@
include
+
+ include
+
@@ -74,8 +77,15 @@
src
+
+ src
+
+
+ src
+
+
\ No newline at end of file
diff --git a/include/Callbacks.hpp b/include/Callbacks.hpp
index bd3a456..e751357 100644
--- a/include/Callbacks.hpp
+++ b/include/Callbacks.hpp
@@ -8,10 +8,14 @@
#include "Defs.hpp"
#include "Serializer.hpp"
+/*Client Callbacks begin*/
+
void OnMessage(uint16 sender, uint16 tag, uint16 subject, void *data);
void OnDisconnect(uint16 id);
void OnConnect(uint16 id);
+/*Client Callbacks end*/
+
#endif
\ No newline at end of file
diff --git a/include/Defs.hpp b/include/Defs.hpp
index 1822fd7..0a47b54 100644
--- a/include/Defs.hpp
+++ b/include/Defs.hpp
@@ -185,11 +185,12 @@ enum VoidCode
enum DistributionType
{
All,
+ AllAndMe,
Server,
Others,
ID,
Reply,
Custom,
-}
+};
#endif // DEFS_HPP
\ No newline at end of file
diff --git a/include/NetworkMessage.hpp b/include/NetworkMessage.hpp
index 0f59eb2..ca9f8d3 100644
--- a/include/NetworkMessage.hpp
+++ b/include/NetworkMessage.hpp
@@ -15,20 +15,22 @@ struct NetworkMessage
NetworkMessage(uint16 sender, byte distribution_mode, uint16 destination_id, byte tag, uint16 subject, NetworkBuffer buffer);
~NetworkMessage();
- const NetworkMessage &EncodeMessage();
+ static const NetworkBuffer &EncodeMessage(const NetworkMessage &message);
const NetworkMessage &NetworkMessage::DecodeMessage(const NetworkBuffer &buffer);
- const NetworkMessage &NetworkMessage::DecodeMessageHeader(const NetworkBuffer &buffer);
- void *DecodeMessageData(const NetworkBuffer &buffer);
- uint16 sender;
- uint16 destination_id;
+ uint16 sender = -2;
byte distribution_mode;
- uint16 tag;
+ uint16 destination_id;
+ byte tag;
uint16 subject;
void *data;
+
+ bool valid = false;
private:
+ const NetworkMessage &NetworkMessage::DecodeMessageHeader(const NetworkBuffer &buffer);
+ void *DecodeMessageData(const NetworkBuffer &buffer);
NetworkBuffer buffer;
};
diff --git a/include/Serializer.hpp b/include/Serializer.hpp
index 58a740a..989470d 100644
--- a/include/Serializer.hpp
+++ b/include/Serializer.hpp
@@ -6,11 +6,12 @@
#endif
#include "Defs.hpp"
+#include
struct Serializer
{
template static const std::vector &to_bytes(const T &object);
- template static const T &from_bytes(byte *bytes, T &object);
+ template static const T& from_bytes(byte *bytes, T& object);
};
#endif
\ No newline at end of file
diff --git a/src/Tags.hpp b/include/Tags.hpp
similarity index 78%
rename from src/Tags.hpp
rename to include/Tags.hpp
index 154ef10..482d99d 100644
--- a/src/Tags.hpp
+++ b/include/Tags.hpp
@@ -5,7 +5,7 @@
#pragma once
#endif
-enum InternalTags : uint16
+enum InternalTags
{
CONNECT = 65534,
DISCONNECT = 65535,
diff --git a/include/TcpClient.hpp b/include/TcpClient.hpp
index aff0048..1d890a8 100644
--- a/include/TcpClient.hpp
+++ b/include/TcpClient.hpp
@@ -3,6 +3,7 @@
#include "Defs.hpp"
#include "NetworkMessage.hpp"
+#include "ThreadPool.hpp"
#include
@@ -10,6 +11,8 @@
#pragma once
#endif
+#undef SendMessage
+
class TcpClient
{
public:
@@ -27,21 +30,30 @@ public:
NetworkBuffer ReceiveDataArray();
const NetworkMessage &ReceiveData();
- bool SendData(const NetworkMessage &message);
+ VoidCode SendMessage(const NetworkMessage &message);
private:
+ static VoidCode SendNetworkMessage(const NetworkMessage &message, TcpClient *client);
VoidCode Initialize(const std::string &ip, uint16 port = default_port);
std::string ip;
uint16 port = 0;
bool initialized;
+ ThreadPool thread_pool;
+
#ifdef _MSC_VER
- SOCKET socket = INVALID_SOCKET;
+ SOCKET tcp_socket = INVALID_SOCKET;
struct addrinfo *result = nullptr;
struct addrinfo *ptr = nullptr;
struct addrinfo hints;
#endif
};
+#ifdef UNICODE
+#define SendMessage SendMessageW
+#else
+#define SendMessage SendMessageA
+#endif // !UNICODE
+
#endif
\ No newline at end of file
diff --git a/include/ThreadPool.hpp b/include/ThreadPool.hpp
new file mode 100644
index 0000000..6cfc0be
--- /dev/null
+++ b/include/ThreadPool.hpp
@@ -0,0 +1,33 @@
+#ifndef THREAD_POOL_HPP
+#define THREAD_POOL_HPP
+
+#ifdef _MSC_VER
+#pragma once
+#endif
+
+#include
+#include
+#include
+#include
+#include
+
+class ThreadPool
+{
+public:
+ ThreadPool(int threads);
+ ~ThreadPool();
+ void Enqueue(std::function f);
+ void Shutdown();
+ const ThreadPool &operator=(ThreadPool &pool);
+
+private:
+ std::vector threadPool;
+ std::queue> tasks;
+ std::mutex tasksMutex;
+ std::condition_variable condition;
+ bool terminate;
+ bool stopped;
+ void Invoke();
+};
+
+#endif
\ No newline at end of file
diff --git a/include/VoidNetClient.hpp b/include/VoidNetClient.hpp
index 7a74481..c425648 100644
--- a/include/VoidNetClient.hpp
+++ b/include/VoidNetClient.hpp
@@ -11,5 +11,41 @@
#include "Callbacks.hpp"
#include "NetworkBuffer.hpp"
#include "NetworkMessage.hpp"
+#include "ThreadPool.hpp"
+
+#include
+#include
+
+#undef SendMessage
+
+struct VoidNetClientAPI
+{
+ static bool Connect(const std::string &ip, uint16 port = default_port);
+ static void Disconnect();
+
+ static bool SendMessageToServer(byte tag, byte subject, void *data);
+ static bool SendMessageToID(uint16 id, byte tag, byte subject, void *data);
+ static bool SendMessageToOthers(byte tag, byte subject, void *data);
+ static bool SendMessageToAll(byte tag, byte subject, void *data);
+ static bool SendMessageToAllAndMe(byte tag, byte subject, void *data);
+
+ static bool SendMessage(byte distribution_mode, uint16 destination_id, byte tag, byte subject, void *data);
+
+ static void Receive();
+
+private:
+ static void ProcessAllData();
+
+ static TcpClient *client;
+ static uint16 id;
+ static std::thread receive_thread;
+ static bool receive;
+};
+
+#ifdef UNICODE
+#define SendMessage SendMessageW
+#else
+#define SendMessage SendMessageA
+#endif // !UNICODE
#endif
diff --git a/src/NetworkMessage.cpp b/src/NetworkMessage.cpp
index 6b79e2b..c81ef15 100644
--- a/src/NetworkMessage.cpp
+++ b/src/NetworkMessage.cpp
@@ -1,6 +1,8 @@
#include "NetworkMessage.hpp"
#include "Utility.hpp"
#include "Serializer.hpp"
+#include "Tags.hpp"
+
#include
NetworkMessage::NetworkMessage()
@@ -12,13 +14,41 @@ NetworkMessage::NetworkMessage(uint16 sender, byte distribution_mode, uint16 des
{
}
+NetworkMessage::NetworkMessage(const NetworkBuffer &buffer)
+{
+ *this = DecodeMessage(buffer);
+}
+
NetworkMessage::~NetworkMessage()
{
}
-const NetworkMessage &NetworkMessage::EncodeMessage()
+const NetworkBuffer &NetworkMessage::EncodeMessage(const NetworkMessage &message)
{
- return NetworkMessage();
+ NetworkBuffer buffer;
+ uint16 size = buffer.body_size + 1;
+ byte *encoded_message = new byte[size]();
+ buffer.body_size = size;
+
+ byte *encoded_sender = &encoded_message[1];
+ encoded_sender = Utility::BitConverter::FromUint16(message.sender);
+
+ encoded_message[3] = message.distribution_mode;
+
+ byte *encoded_destination_id = &encoded_message[4];
+ encoded_destination_id = Utility::BitConverter::FromUint16(message.destination_id);
+
+ encoded_message[6] = message.tag;
+
+ byte *encoded_subject = &encoded_message[7];
+ encoded_subject = Utility::BitConverter::FromUint16(message.subject);
+
+ byte *encoded_data = &encoded_message[9];
+ std::vector serialized_data = Serializer::to_bytes(message.data);
+ encoded_data = &serialized_data[0];
+
+ buffer.body = encoded_message;
+ return buffer;
}
const NetworkMessage &NetworkMessage::DecodeMessage(const NetworkBuffer &buffer)
@@ -38,7 +68,7 @@ void *NetworkMessage::DecodeMessageData(const NetworkBuffer &buffer)
case 0:
{
void *object;
- return Serializer::from_bytes(buffer.body, object);
+ return Serializer::from_bytes(buffer.body + 9, object);
}
default:
{
@@ -50,6 +80,12 @@ void *NetworkMessage::DecodeMessageData(const NetworkBuffer &buffer)
const NetworkMessage &NetworkMessage::DecodeMessageHeader(const NetworkBuffer &buffer)
{
- return NetworkMessage(Utility::BitConverter::ToUint16(buffer.body, 1), buffer.body[3], Utility::BitConverter::ToUint16(buffer.body, 4),
- buffer.body[6], Utility::BitConverter::ToUint16(buffer.body, 7), buffer);
+ sender = Utility::BitConverter::ToUint16(buffer.body, 1);
+ distribution_mode = buffer.body[3];
+ destination_id = Utility::BitConverter::ToUint16(buffer.body, 4);
+ tag = buffer.body[6];
+ subject = Utility::BitConverter::ToUint16(buffer.body, 7);
+ this->buffer = buffer;
+ valid = sender != -2 && tag != CONNECT && tag != DISCONNECT;
+ return *this;
}
diff --git a/src/Serializer.cpp b/src/Serializer.cpp
index 7a877c6..4505087 100644
--- a/src/Serializer.cpp
+++ b/src/Serializer.cpp
@@ -1,7 +1,5 @@
#include "Serializer.hpp"
-#include
-
template const std::vector &Serializer::to_bytes(const T& object)
{
std::vector bytes;
@@ -13,7 +11,7 @@ template const std::vector &Serializer::to_bytes(const T& obje
return bytes;
}
-template T& Serializer::from_bytes(byte *bytes, T& object)
+template const T& Serializer::from_bytes(byte *bytes, T& object)
{
static_assert(std::is_trivially_copyable::value, "not a TriviallyCopyable type");
diff --git a/src/TcpClientWindows.cpp b/src/TcpClientWindows.cpp
index 7dd1b33..eb367da 100644
--- a/src/TcpClientWindows.cpp
+++ b/src/TcpClientWindows.cpp
@@ -7,6 +7,8 @@
#include
+#undef SendMessage
+
VoidCode TcpClient::Initialize(const std::string &ip, uint16 port)
{
if (ip.size() == 0 || std::count(ip.begin(), ip.end(), '.') != 4)
@@ -28,9 +30,9 @@ VoidCode TcpClient::Initialize(const std::string &ip, uint16 port)
}
ptr = result;
- socket = ::socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
+ tcp_socket = ::socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
- if (socket == INVALID_SOCKET)
+ if (tcp_socket == INVALID_SOCKET)
{
if (Config::GetUsingConsole())
std::cerr << WSAGetLastError() << std::endl; // display more info
@@ -43,12 +45,12 @@ VoidCode TcpClient::Initialize(const std::string &ip, uint16 port)
return VOID_SUCCESS;
}
-TcpClient::TcpClient()
+TcpClient::TcpClient() : port(default_port), thread_pool(50)
{
}
TcpClient::TcpClient(const std::string &ip, uint16 port) :
- ip(ip), port(port)
+ ip(ip), port(port), thread_pool(50)
{
}
@@ -92,7 +94,7 @@ VoidCode TcpClient::Connect()
if (code != VOID_SUCCESS)
return code;
}
- uint16 connect_code = ::connect(socket, ptr->ai_addr, ptr->ai_addrlen);
+ uint16 connect_code = ::connect(tcp_socket, ptr->ai_addr, ptr->ai_addrlen);
if (connect_code == SOCKET_ERROR)
return VOID_COULDNT_CONNECT;
}
@@ -101,16 +103,19 @@ NetworkBuffer TcpClient::ReceiveDataArray()
{
NetworkBuffer buffer;
- if (recv(socket, reinterpret_cast(buffer.body_size), 4, 0) != 4 || WSAGetLastError() != 0)
+ int32 header_received = recv(tcp_socket, reinterpret_cast(buffer.body_size), 4, 0);
+
+ if (header_received != 4 || WSAGetLastError() != 0) // this header is completely unrelated to the network message header - this header is the body size of the network message
{
- // there was a problem receiving the body size of the message
+ // there was a problem receiving the body size of the message or theres no header to receive
return NetworkBuffer();
}
buffer.body = new byte[buffer.body_size]();
- if (recv(socket, reinterpret_cast(buffer.body), buffer.body_size, 0) != buffer.body_size || WSAGetLastError() != 0)
+ int32 body_received = recv(tcp_socket, reinterpret_cast(buffer.body), buffer.body_size, 0);
+ if (body_received != buffer.body_size || WSAGetLastError() != 0)
{
- //there was a problem receiving the body of the message
+ //there was a problem receiving the body of the message or theres no body to receive
return NetworkBuffer();
}
@@ -119,8 +124,7 @@ NetworkBuffer TcpClient::ReceiveDataArray()
const NetworkMessage &TcpClient::ReceiveData()
{
- NetworkBuffer received_data = ReceiveDataArray();
- NetworkMessage message = NetworkMessage(received_data);
+ NetworkMessage message(ReceiveDataArray());
if (message.tag == CONNECT)
OnConnect(message.sender);
else if (message.tag == DISCONNECT)
@@ -130,7 +134,16 @@ const NetworkMessage &TcpClient::ReceiveData()
return message;
}
-bool TcpClient::SendData(const NetworkMessage &message)
+VoidCode TcpClient::SendNetworkMessage(const NetworkMessage &message, TcpClient *client)
{
- return false;
+ NetworkBuffer buffer = message.EncodeMessage(message);
+ int32 sent_bytes = send(client->tcp_socket, reinterpret_cast(buffer.body), buffer.body_size, 0);
}
+
+VoidCode TcpClient::SendMessage(const NetworkMessage &message)
+{
+ thread_pool.Enqueue([]()
+ {
+ //SendNetworkMessage(message, this);
+ });
+}
\ No newline at end of file
diff --git a/src/ThreadPool.cpp b/src/ThreadPool.cpp
new file mode 100644
index 0000000..3d59a85
--- /dev/null
+++ b/src/ThreadPool.cpp
@@ -0,0 +1,57 @@
+#include "ThreadPool.hpp"
+
+ThreadPool::ThreadPool(int threads) :
+ terminate(false),
+ stopped(false)
+{
+ for (int i = 0; i < threads; i++)
+ threadPool.emplace_back(std::thread(&ThreadPool::Invoke, this));
+}
+
+void ThreadPool::Enqueue(std::function f)
+{
+ std::unique_lock lock(tasksMutex);
+ tasks.push(f);
+ condition.notify_one();
+}
+
+void ThreadPool::Invoke() {
+
+ std::function task;
+ while (true)
+ {
+ std::unique_lock lock(tasksMutex);
+ condition.wait(lock, [this] { return !tasks.empty() || terminate; });
+ if (terminate && tasks.empty())
+ {
+ return;
+ }
+ task = tasks.front();
+ tasks.pop();
+ task();
+ }
+}
+
+void ThreadPool::Shutdown()
+{
+ std::unique_lock lock(tasksMutex);
+ terminate = true;
+ condition.notify_all();
+
+ for (std::thread &thread : threadPool)
+ thread.join();
+
+ threadPool.empty();
+ stopped = true;
+}
+
+const ThreadPool &ThreadPool::operator=(ThreadPool &pool)
+{
+ return pool;
+}
+
+ThreadPool::~ThreadPool()
+{
+ if (!stopped)
+ Shutdown();
+}
\ No newline at end of file
diff --git a/src/VoidNetClient.cpp b/src/VoidNetClient.cpp
new file mode 100644
index 0000000..9ddc1f0
--- /dev/null
+++ b/src/VoidNetClient.cpp
@@ -0,0 +1,79 @@
+#include "VoidNetClient.hpp"
+#include "Utility.hpp"
+#include "Tags.hpp"
+
+#undef SendMessage
+
+bool VoidNetClientAPI::Connect(const std::string &ip, uint16 port)
+{
+ client->SetIP(ip);
+ client->SetPort(port);
+ return client->Connect() == VOID_SUCCESS;
+}
+
+bool VoidNetClientAPI::SendMessageToServer(byte tag, byte subject, void *data)
+{
+ return SendMessage(Server, 0, tag, subject, data);
+}
+
+bool VoidNetClientAPI::SendMessageToID(uint16 destination_id, byte tag, byte subject, void *data)
+{
+ return SendMessage(ID, destination_id, tag, subject, data);
+}
+
+bool VoidNetClientAPI::SendMessageToOthers(byte tag, byte subject, void *data)
+{
+ return SendMessage(Others, 0, tag, subject, data);
+}
+
+bool VoidNetClientAPI::SendMessageToAll(byte tag, byte subject, void *data)
+{
+ return SendMessage(All, 0, tag, subject, data);
+}
+
+bool VoidNetClientAPI::SendMessageToAllAndMe(byte tag, byte subject, void *data)
+{
+ return SendMessage(AllAndMe, 0, tag, subject, data);
+}
+
+bool VoidNetClientAPI::SendMessage(byte distribution_mode, uint16 destination_id, byte tag, byte subject, void *data)
+{
+ NetworkMessage message;
+ message.tag = tag;
+ message.subject = subject;
+ message.data = data;
+ message.distribution_mode = distribution_mode;
+ message.sender = id;
+ message.destination_id = destination_id;
+ return client->SendMessage(message) == VOID_SUCCESS;
+}
+
+void VoidNetClientAPI::Receive()
+{
+ receive_thread = std::thread(ProcessAllData);
+ receive_thread.detach();
+}
+
+void VoidNetClientAPI::ProcessAllData()
+{
+ while (receive)
+ {
+ NetworkMessage message = client->ReceiveDataArray();
+ if (message.valid)
+ {
+ if (message.tag == CONNECT)
+ OnConnect(message.sender);
+ else if (message.tag == DISCONNECT)
+ OnDisconnect(message.sender);
+ else
+ OnMessage(message.sender, message.tag, message.subject, message.data);
+ }
+ }
+}
+
+void VoidNetClientAPI::Disconnect()
+{
+ Utility::Delete(client);
+ receive = false;
+ receive_thread.join();
+}