From 5f13265c5d7692470d98d9f9dfef0e2a0f6c6915 Mon Sep 17 00:00:00 2001 From: TheDoctor Date: Mon, 21 Oct 2019 00:27:21 +0100 Subject: [PATCH] Update NetworkMessage->GetData fixed Plugin -> Splitted message types PluginManager is now thread safe TcpConnection added list of events Properly handling disconnection now Fixed bug in Socket with error translation It crashes when it exits, i think it has something to do with shared ptrs or something --- include/VoidNet_HL/NetworkMessage.hpp | 4 +- include/VoidNet_HL/Plugin/Plugin.hpp | 27 +++++- include/VoidNet_HL/Plugin/PluginManager.hpp | 9 ++ include/VoidNet_HL/TcpConnection.hpp | 41 ++++++-- include/VoidNet_HL/TcpConnectionHandler.hpp | 1 - include/VoidNet_LL/Cookies.hpp | 1 + include/VoidNet_LL/Enums.hpp | 4 +- include/VoidNet_LL/Headers.hpp | 1 + include/VoidNet_LL/Socket.hpp | 2 +- src/VoidNet_HL/Plugin/PluginManager.cpp | 4 + src/VoidNet_HL/TcpConnection.cpp | 61 ++++++------ src/VoidNet_HL/TcpConnectionHandler.cpp | 101 +++++++++++--------- src/VoidNet_HL/main.cpp | 62 +++++++++--- src/VoidNet_LL/Response.cpp | 2 + src/VoidNet_LL/Socket.cpp | 10 +- 15 files changed, 223 insertions(+), 107 deletions(-) diff --git a/include/VoidNet_HL/NetworkMessage.hpp b/include/VoidNet_HL/NetworkMessage.hpp index a5c3053..f1e2e75 100644 --- a/include/VoidNet_HL/NetworkMessage.hpp +++ b/include/VoidNet_HL/NetworkMessage.hpp @@ -89,7 +89,9 @@ namespace std::net template T *GetData() const { - return (T*)m_data; + if (m_data) + return (T*)m_data; + else return nullptr; } }; } \ No newline at end of file diff --git a/include/VoidNet_HL/Plugin/Plugin.hpp b/include/VoidNet_HL/Plugin/Plugin.hpp index bd69568..145b7de 100644 --- a/include/VoidNet_HL/Plugin/Plugin.hpp +++ b/include/VoidNet_HL/Plugin/Plugin.hpp @@ -1,6 +1,8 @@ #pragma once #include +#include +#include namespace std::net { @@ -11,6 +13,29 @@ namespace std::net { } - virtual void HandleMessage(const NetworkMessage& msg) = 0; + void HandleMessage(const NetworkMessage& msg) + { + if (msg.GetTag() == (uint32_t)InternalTags::Disconnect) + { + OnDisconnect(*(msg.GetData())); + } + else if (msg.GetTag() == (uint32_t)InternalTags::Connect) + { + OnNewConnection(msg.GetSenderID(), msg.GetData()); + } + else if (msg.GetTag() == (uint32_t)InternalTags::AssignID) + { + OnConnection(); + } + else + { + OnDataReceived(msg.GetSenderID(), msg.GetDistributionMode(), msg.GetDestinationID(), msg.GetTag(), msg.GetData()); + } + } + + virtual void OnDisconnect(string) abstract; + virtual void OnNewConnection(uint32_t, void*) abstract; + virtual void OnConnection() abstract; + virtual void OnDataReceived(uint32_t, DistributionMode, uint32_t, uint32_t, void*) abstract; }; } \ No newline at end of file diff --git a/include/VoidNet_HL/Plugin/PluginManager.hpp b/include/VoidNet_HL/Plugin/PluginManager.hpp index c2ddb6b..b5b57dd 100644 --- a/include/VoidNet_HL/Plugin/PluginManager.hpp +++ b/include/VoidNet_HL/Plugin/PluginManager.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include "VoidNet_HL/Plugin/Plugin.hpp" @@ -14,16 +15,24 @@ namespace std::net void HandleMessage(const NetworkMessage& msg) { + m_pluginsMutex.lock(); + for (size_t i = 0; i < m_plugins.size(); i++) m_plugins.at(i)->HandleMessage(msg); + + m_pluginsMutex.unlock(); } void AddPlugin(Plugin* p) { + m_pluginsMutex.lock(); m_plugins.emplace_back(p); + m_pluginsMutex.unlock(); } private: vector m_plugins; + + mutex m_pluginsMutex; }; } \ No newline at end of file diff --git a/include/VoidNet_HL/TcpConnection.hpp b/include/VoidNet_HL/TcpConnection.hpp index 1ee59b6..8bcba46 100644 --- a/include/VoidNet_HL/TcpConnection.hpp +++ b/include/VoidNet_HL/TcpConnection.hpp @@ -21,30 +21,55 @@ namespace std::net bool Connect(IPAddress addr); + bool Disconnect(); + template - void SendMessage(DistributionMode mode, uint32_t destinationId, uint32_t tag, void *data) + bool SendMessage(DistributionMode mode, uint32_t destinationId, uint32_t tag, void *data) { NetworkMessage msg(m_id, mode, destinationId, tag, data, sizeof(T)); - sendMessage(msg); + return sendMessage(msg); } - void SendMessage(DistributionMode mode, uint32_t destinationId, uint32_t tag) + bool SendMessage(DistributionMode mode, uint32_t destinationId, uint32_t tag) { NetworkMessage msg(m_id, mode, destinationId, tag, nullptr, 0); - sendMessage(msg); + return sendMessage(msg); } void ReceiveData(); - function DataReceivedEvent; - function DisconnectedEvent; - function NewConnectionEvent; - function OnConnectionEvent; + bool IsConnected; private: bool sendMessage(const NetworkMessage &msg); shared_ptr m_client; uint32_t m_id; + + vector> m_onDataReceived; + vector> m_onDisconnect; + vector> m_onNewConnection; + vector> m_onConnection; + + public: + void operator+=(const function &rhs) + { + m_onDataReceived.push_back(rhs); + } + + void operator+=(const function& rhs) + { + m_onDisconnect.push_back(rhs); + } + + void operator+=(const function & rhs) + { + m_onNewConnection.push_back(rhs); + } + + void operator+=(const function& rhs) + { + m_onConnection.push_back(rhs); + } }; } \ No newline at end of file diff --git a/include/VoidNet_HL/TcpConnectionHandler.hpp b/include/VoidNet_HL/TcpConnectionHandler.hpp index a23dba3..cf51906 100644 --- a/include/VoidNet_HL/TcpConnectionHandler.hpp +++ b/include/VoidNet_HL/TcpConnectionHandler.hpp @@ -47,7 +47,6 @@ namespace std::net uint32_t m_maxConnections = 0; thread m_receiveThread; - thread m_sendThread; atomic_bool m_run; diff --git a/include/VoidNet_LL/Cookies.hpp b/include/VoidNet_LL/Cookies.hpp index ab3b8ad..b59cb27 100644 --- a/include/VoidNet_LL/Cookies.hpp +++ b/include/VoidNet_LL/Cookies.hpp @@ -3,6 +3,7 @@ #pragma once #include +#include namespace std::net { diff --git a/include/VoidNet_LL/Enums.hpp b/include/VoidNet_LL/Enums.hpp index 7675fed..2e0b454 100644 --- a/include/VoidNet_LL/Enums.hpp +++ b/include/VoidNet_LL/Enums.hpp @@ -81,8 +81,8 @@ namespace std::net enum class SocketType { Unknown = -1, - Datagram = 2, - Streaming = 1, + Datagram = 2, //SOCK_DGRAM + Streaming = 1, //SOCK_STREAM }; enum class SocketProtocol diff --git a/include/VoidNet_LL/Headers.hpp b/include/VoidNet_LL/Headers.hpp index c9337af..09ced5e 100644 --- a/include/VoidNet_LL/Headers.hpp +++ b/include/VoidNet_LL/Headers.hpp @@ -3,6 +3,7 @@ #pragma once #include +#include namespace std::net { diff --git a/include/VoidNet_LL/Socket.hpp b/include/VoidNet_LL/Socket.hpp index a38aacb..ca44cef 100644 --- a/include/VoidNet_LL/Socket.hpp +++ b/include/VoidNet_LL/Socket.hpp @@ -21,7 +21,7 @@ namespace std::net init(); } - virtual ~Socket() { Close(); } + virtual ~Socket() { } public: diff --git a/src/VoidNet_HL/Plugin/PluginManager.cpp b/src/VoidNet_HL/Plugin/PluginManager.cpp index 298349c..ca5c9d0 100644 --- a/src/VoidNet_HL/Plugin/PluginManager.cpp +++ b/src/VoidNet_HL/Plugin/PluginManager.cpp @@ -10,5 +10,9 @@ namespace std::net PluginManager::~PluginManager() { + for (size_t i = 0; i < m_plugins.size(); i++) + { + delete m_plugins[i]; + } } } \ No newline at end of file diff --git a/src/VoidNet_HL/TcpConnection.cpp b/src/VoidNet_HL/TcpConnection.cpp index 012f21e..7872529 100644 --- a/src/VoidNet_HL/TcpConnection.cpp +++ b/src/VoidNet_HL/TcpConnection.cpp @@ -6,33 +6,9 @@ namespace std::net { - void received(uint32_t, DistributionMode, uint32_t, uint32_t, void*) - { - std::cout << "received" << std::endl; - } - - void disconnected(std::string s) - { - std::cout << s << std::endl; - } - - void new_connection(uint32_t, void*) - { - std::cout << "new client connection" << std::endl; - } - - void on_connect() - { - std::cout << "i connected" << std::endl; - } - TcpConnection::TcpConnection() : m_client(new TcpClient()) { - DataReceivedEvent = received; - DisconnectedEvent = disconnected; - NewConnectionEvent = new_connection; - OnConnectionEvent = on_connect; } TcpConnection::TcpConnection(TcpClient * client) @@ -52,7 +28,12 @@ namespace std::net bool TcpConnection::Connect(IPAddress addr) { - return m_client->Connect(addr); + return IsConnected = m_client->Connect(addr); + } + + bool TcpConnection::Disconnect() + { + return SendMessage(DistributionMode::AllAndServer, 0, (uint32_t)InternalTags::Disconnect); } bool TcpConnection::sendMessage(const NetworkMessage & msg) @@ -79,25 +60,39 @@ namespace std::net if (message.GetTag() == (uint32_t)InternalTags::Disconnect) { - if (DisconnectedEvent) - DisconnectedEvent(*(message.GetData())); + for (size_t i = 0; i < m_onDisconnect.size(); i++) + { + //string* msgStr = message.GetData(); + m_onDisconnect[i](""); + } + + IsConnected = false; + m_client->Close(); } else if (message.GetTag() == (uint32_t)InternalTags::Connect) { - if (NewConnectionEvent) - NewConnectionEvent(message.GetSenderID(), message.GetData()); + for (size_t i = 0; i < m_onNewConnection.size(); i++) + { + m_onNewConnection[i](message.GetSenderID(), message.GetData()); + } } else if (message.GetTag() == (uint32_t)InternalTags::AssignID) { m_id = *(message.GetData()); - if (OnConnectionEvent) - OnConnectionEvent(); + for (size_t i = 0; i < m_onConnection.size(); i++) + { + m_onConnection[i](); + } + + IsConnected = true; } else { - if (DataReceivedEvent) - DataReceivedEvent(message.GetSenderID(), message.GetDistributionMode(), message.GetDestinationID(), message.GetTag(), message.GetData()); + for (size_t i = 0; i < m_onDataReceived.size(); i++) + { + m_onDataReceived[i](message.GetSenderID(), message.GetDistributionMode(), message.GetDestinationID(), message.GetTag(), message.GetData()); + } } } } diff --git a/src/VoidNet_HL/TcpConnectionHandler.cpp b/src/VoidNet_HL/TcpConnectionHandler.cpp index 39dd140..b6e548f 100644 --- a/src/VoidNet_HL/TcpConnectionHandler.cpp +++ b/src/VoidNet_HL/TcpConnectionHandler.cpp @@ -7,6 +7,7 @@ #include "VoidNet_LL/TcpListener.hpp" #include +#include namespace std::net { @@ -112,62 +113,76 @@ namespace std::net void TcpConnectionHandler::HandleConnections() { - int res = poll(m_pollFds.data(), m_pollFds.size(), -1); - - if (res < 0) + try { - //poll error - } + int res = poll(m_pollFds.data(), m_pollFds.size(), 5); - //should never timeout because its infinite (negative) - //if (res == 0) - //{ - //timeout - //} - - for (int i = 0; i < m_pollFds.size(); i++) - { - if (m_pollFds.at(i).revents == 0 || m_pollFds[i].revents != POLLRDNORM) - continue; - - if (m_pollFds.at(i).fd == m_listenerPtr->m_socket->GetNativeSocket()) + if (res < 0) { - TcpClient *c = m_listenerPtr->AcceptClient(); - if (c) - { - shared_ptr connection = make_shared(c); - AddClient(connection); - break; - } + //poll error } - else // not the listening socket + + //should never timeout because its infinite (negative) + //if (res == 0) + //{ + //timeout + //} + + for (int i = 0; i < m_pollFds.size(); i++) { - SOCKET c = m_pollFds.at(i).fd; - - byte* header = new byte[sizeof(NetworkHeader)](); - - int32_t read; - if ((read = recv(c, (char*)header, sizeof(NetworkHeader), 0)) != sizeof(NetworkHeader)) + if (m_pollFds.at(i).revents == 0 || m_pollFds[i].revents != POLLRDNORM) continue; - NetworkHeader net_header(*(NetworkHeader*)(header)); - byte *buffer = new byte[net_header.Size](); - - read = recv(c, (char*)buffer, net_header.Size - 4, 0); - if ((read) == net_header.Size - 4) + if (m_pollFds.at(i).fd == m_listenerPtr->m_socket->GetNativeSocket()) { - NetworkMessage msg; - msg.DeserializeWithoutHeader(buffer, net_header.Size); + TcpClient* c = m_listenerPtr->AcceptClient(); + if (c) + { + shared_ptr connection = make_shared(c); + AddClient(connection); + break; + } + } + else // not the listening socket + { + SOCKET c = m_pollFds.at(i).fd; - if (msg.GetTag() == (uint32_t)InternalTags::Disconnect) - // i? or i+1 - m_pollFds.erase(m_pollFds.begin() + i); + byte* header = new byte[sizeof(NetworkHeader)](); - // put this in a separate thread - HandleMessage(msg); + int32_t read; + if ((read = recv(c, (char*)header, sizeof(NetworkHeader), 0)) != sizeof(NetworkHeader)) + continue; + + NetworkHeader net_header(*(NetworkHeader*)(header)); + byte* buffer = new byte[net_header.Size](); + + read = recv(c, (char*)buffer, net_header.Size - 4, 0); + if ((read) == net_header.Size - 4) + { + NetworkMessage msg; + msg.DeserializeWithoutHeader(buffer, net_header.Size); + + // put this in a separate thread + HandleMessage(msg); + + if (msg.GetTag() == (uint32_t)InternalTags::Disconnect) + { + for (size_t k = 0; k < m_list.size(); i++) + { + if (m_list[k]->m_id == msg.GetSenderID()) + { + std::shared_ptr c = m_list[k]; + c->m_client->Close(); + m_list.erase(m_list.begin() + k); + } + } + m_pollFds.erase(m_pollFds.begin() + i); + } + } } } } + catch (void*) {} } void TcpConnectionHandler::HandleMessage(const NetworkMessage &msg) diff --git a/src/VoidNet_HL/main.cpp b/src/VoidNet_HL/main.cpp index 7416165..81cc455 100644 --- a/src/VoidNet_HL/main.cpp +++ b/src/VoidNet_HL/main.cpp @@ -11,31 +11,65 @@ class Plugin : public std::net::Plugin { - virtual void HandleMessage(const std::net::NetworkMessage& message) override - { - std::cout << "asd" << std::endl; - } + }; +void dsfg(uint32_t, std::net::DistributionMode, uint32_t, uint32_t, void*) +{ + +} + +std::net::TcpConnection *con = new std::net::TcpConnection(); + +void onData(uint32_t, std::net::DistributionMode, uint32_t, uint32_t, void*) +{ + std::cout << "ondata" << std::endl; +} + +void onDisconnect(std::string) +{ + std::cout << "ondisconnect" << std::endl; +} + +void onconnect() +{ + std::cout << "onconnect" << std::endl; + con->Disconnect(); +} + int main() { - std::net::Initialize(); - std::net::Server server(1); - server.AddPlugin(new Plugin()); - server.Start(); - - std::net::TcpConnection con; - con.Connect(std::net::IPAddress("127.0.0.1")); + std::net::Server *server = new std::net::Server(1); + //server.AddPlugin(new Plugin()); + server->Start(); - bool sent = false; + //con->Connect(std::net::IPAddress("127.0.0.1")); - while (con) // 8% of my cpu + //bool sent = false; + + //con += onData; + //con += onDisconnect; + //con += onconnect; + + /*while (con.IsConnected) // 8% of my cpu { con.ReceiveData(); if (!sent) { sent = true; - con.SendMessage(std::net::DistributionMode::Server, 0, 1); + //con.SendMessage(std::net::DistributionMode::AllAndServer, 0, 1); } + }*/ + + try + + { + server->Stop(); + delete server; } + catch (void* e) + { + std::cout << "asd" << std::endl; + } + getchar(); } \ No newline at end of file diff --git a/src/VoidNet_LL/Response.cpp b/src/VoidNet_LL/Response.cpp index 15cadba..1875e78 100644 --- a/src/VoidNet_LL/Response.cpp +++ b/src/VoidNet_LL/Response.cpp @@ -3,6 +3,8 @@ #include "VoidNet_LL/Response.hpp" #include "VoidNet_LL/Parse.hpp" +#include + namespace std::net { static ParseResult ParseStatus(const char* str) diff --git a/src/VoidNet_LL/Socket.cpp b/src/VoidNet_LL/Socket.cpp index b4faa71..209b8b4 100644 --- a/src/VoidNet_LL/Socket.cpp +++ b/src/VoidNet_LL/Socket.cpp @@ -1,10 +1,13 @@ #include "VoidNet_LL/Socket.hpp" #include "VoidNet_LL/IPAddress.hpp" +#include namespace std::net { void Socket::init() { + Initialize(); + if (GetSocketType() == SocketType::Unknown) throw invalid_argument("Unknown socket type"); @@ -55,11 +58,11 @@ namespace std::net bool Socket::Connect(const IPAddress& addr) { sockaddr_in addr_in = addr.ToCAddr(); - int32_t Return = connect(m_socket, (sockaddr*)&addr_in, sizeof(sockaddr_in)); - SocketErrors Error = TranslateErrorCode(Return); + int32_t retValue = connect(m_socket, (sockaddr*)&addr_in, sizeof(sockaddr_in)); + SocketErrors error = TranslateErrorCode(retValue); // "would block" is not an error - return ((Error == SocketErrors::SE_NO_ERROR) || (Error == SocketErrors::SE_EWOULDBLOCK)); + return ((error == SocketErrors::SE_NO_ERROR) || (error == SocketErrors::SE_EWOULDBLOCK)); } bool Socket::WaitForPendingConnection(bool& hasPendingConnection, chrono::milliseconds t) @@ -421,6 +424,7 @@ namespace std::net return SocketErrors::SE_EINVAL; #else + code = WSAGetLastError(); // handle the generic -1 error if (code == SOCKET_ERROR) {