From e133791369e565c954b0aa690708d1838b211630 Mon Sep 17 00:00:00 2001 From: Jocke Date: Wed, 3 Feb 2016 10:28:15 +0100 Subject: [PATCH 01/18] WIP Reliable Message --- include/Engine/Network/Client.h | 2 +- include/Engine/Network/HybridClient.h | 14 ++++++++++++++ include/Engine/Network/TCPClient.h | 7 +++++++ include/Game/Game.h | 2 +- src/Engine/Network/HybridClient.cpp | 12 ++++++++++++ src/Engine/Network/Server.cpp | 2 +- src/Engine/Network/TCPClient.cpp | 0 src/Game/Game.cpp | 2 +- src/Tests/CollisionTest.cpp | 2 +- src/Tests/HealthSystemTest.cpp | 4 ++-- 10 files changed, 40 insertions(+), 7 deletions(-) create mode 100644 include/Engine/Network/HybridClient.h create mode 100644 include/Engine/Network/TCPClient.h create mode 100644 src/Engine/Network/HybridClient.cpp create mode 100644 src/Engine/Network/TCPClient.cpp diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index 4f1baa67..4397dd41 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -29,7 +29,7 @@ public: ~Client(); void Start(World* world, EventBroker* eventBroker) override; void Update() override; -private: +protected: // Assio UDP logic boost::asio::ip::udp::endpoint m_ReceiverEndpoint; boost::asio::io_service m_IOService; diff --git a/include/Engine/Network/HybridClient.h b/include/Engine/Network/HybridClient.h new file mode 100644 index 00000000..7573ad87 --- /dev/null +++ b/include/Engine/Network/HybridClient.h @@ -0,0 +1,14 @@ +#ifndef HybridClient_h__ +#define HybridClient_h__ + +#include "Client.h" + + +class HybridClient : public Client +{ +public: + HybridClient(ConfigFile* config); + ~HybridClient(); +}; + +#endif \ No newline at end of file diff --git a/include/Engine/Network/TCPClient.h b/include/Engine/Network/TCPClient.h new file mode 100644 index 00000000..d342641b --- /dev/null +++ b/include/Engine/Network/TCPClient.h @@ -0,0 +1,7 @@ +#ifndef TCPClient_h__ +#define TCPClient_h__ + + + + +#endif \ No newline at end of file diff --git a/include/Game/Game.h b/include/Game/Game.h index fab10a49..ccca080e 100644 --- a/include/Game/Game.h +++ b/include/Game/Game.h @@ -25,7 +25,7 @@ #include #include "Network/Network.h" #include "Network/Server.h" -#include "Network/Client.h" +#include "Network/HybridClient.h" // Sound #include "Sound/SoundSystem.h" diff --git a/src/Engine/Network/HybridClient.cpp b/src/Engine/Network/HybridClient.cpp new file mode 100644 index 00000000..798ff578 --- /dev/null +++ b/src/Engine/Network/HybridClient.cpp @@ -0,0 +1,12 @@ +#include "Network/HybridClient.h" + + +HybridClient::HybridClient(ConfigFile * config) : Client(config) +{ + +} + +HybridClient::~HybridClient() +{ + +} diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index 30676d80..a94acd39 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -271,7 +271,7 @@ void Server::parseOnInputCommand(Packet& packet) e.PlayerID = player; // Set correct player id e.Value = packet.ReadPrimitive(); m_EventBroker->Publish(e); - //LOG_INFO("Server::parseOnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID); + LOG_INFO("Server::parseOnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID); } } } diff --git a/src/Engine/Network/TCPClient.cpp b/src/Engine/Network/TCPClient.cpp new file mode 100644 index 00000000..e69de29b diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index ef51aca6..7ce66710 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -169,7 +169,7 @@ void Game::networkFunction() bool isServer = m_Config->Get("Networking.IsServer", false); if (!isServer) { m_IsClientOrServer = true; - m_ClientOrServer = new Client(m_Config); + m_ClientOrServer = new HybridClient(m_Config); } if (isServer) { m_IsClientOrServer = true; diff --git a/src/Tests/CollisionTest.cpp b/src/Tests/CollisionTest.cpp index 67b6ce19..6cb6c88b 100644 --- a/src/Tests/CollisionTest.cpp +++ b/src/Tests/CollisionTest.cpp @@ -29,7 +29,7 @@ void RayTest(std::string fileName) { Ray ray(glm::vec3(-50, 0, 0), glm::vec3(1, 0, 0)); //using a - here, else we have to init the renderingsystem + //here, else we have to init the renderingsystem ResourceManager::RegisterType("RawModel"); auto unitBox = ResourceManager::Load(fileName); BOOST_REQUIRE(unitBox != nullptr); diff --git a/src/Tests/HealthSystemTest.cpp b/src/Tests/HealthSystemTest.cpp index bdd9ba4b..6540c0e3 100644 --- a/src/Tests/HealthSystemTest.cpp +++ b/src/Tests/HealthSystemTest.cpp @@ -69,8 +69,8 @@ GameHealthSystemTest::GameHealthSystemTest() m_EventBroker->Publish(e3); //damage player with 50 Events::PlayerDamage e; - e.DamageAmount = 50.0f; - e.PlayerDamagedID = healthsID; + // e.DamageAmount = 50.0f; +// e.PlayerDamagedID = healthsID; m_EventBroker->Publish(e); //heal some other player with 40 Events::PlayerHealthPickup e2; From 9232b24a7be77aec148c79309356af2da75bb214 Mon Sep 17 00:00:00 2001 From: Jocke Date: Thu, 4 Feb 2016 15:49:04 +0100 Subject: [PATCH 02/18] WIP Reliable message --- include/Engine/Network/Client.h | 13 +- include/Engine/Network/HybridClient.h | 10 ++ include/Engine/Network/HybridServer.h | 30 ++++ include/Engine/Network/PlayerDefinition.h | 3 + include/Engine/Network/Server.h | 35 ++-- include/Engine/Network/TCPClient.h | 16 ++ include/Engine/Network/TCPServer.h | 37 ++++ include/Game/Game.h | 4 +- src/Engine/Network/Client.cpp | 59 +----- src/Engine/Network/HybridClient.cpp | 56 +++++- src/Engine/Network/HybridServer.cpp | 203 +++++++++++++++++++++ src/Engine/Network/Server.cpp | 208 +--------------------- src/Engine/Network/TCPClient.cpp | 48 +++++ src/Engine/Network/TCPServer.cpp | 148 +++++++++++++++ src/Game/Game.cpp | 4 +- 15 files changed, 580 insertions(+), 294 deletions(-) create mode 100644 include/Engine/Network/HybridServer.h create mode 100644 include/Engine/Network/TCPServer.h create mode 100644 src/Engine/Network/HybridServer.cpp create mode 100644 src/Engine/Network/TCPServer.cpp diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index 4397dd41..1c445cac 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -30,11 +30,9 @@ public: void Start(World* world, EventBroker* eventBroker) override; void Update() override; protected: - // Assio UDP logic - boost::asio::ip::udp::endpoint m_ReceiverEndpoint; - boost::asio::io_service m_IOService; - boost::asio::ip::udp::socket m_Socket; - + // Save for children + std::string address; + int port = 0; // Sending message to server logic int bytesRead = -1; char readBuf[INPUTSIZE] = { 0 }; @@ -68,9 +66,8 @@ protected: std::vector m_InputCommandBuffer; // Private member functions - void readFromServer(); - int receive(char* data); - void send(Packet& packet); + virtual void send(Packet& packet) = 0; + virtual void readFromServer() = 0; void connect(); void disconnect(); void parseMessageType(Packet& packet); diff --git a/include/Engine/Network/HybridClient.h b/include/Engine/Network/HybridClient.h index 7573ad87..8c9d1a68 100644 --- a/include/Engine/Network/HybridClient.h +++ b/include/Engine/Network/HybridClient.h @@ -9,6 +9,16 @@ class HybridClient : public Client public: HybridClient(ConfigFile* config); ~HybridClient(); + void Start(World* world, EventBroker* eventBroker); +private: + // Assio UDP logic + boost::asio::ip::udp::endpoint m_ReceiverEndpoint; + boost::asio::io_service m_IOService; + boost::asio::ip::udp::socket m_Socket; + + void readFromServer(); + int receive(char * data); + void send(Packet & packet); }; #endif \ No newline at end of file diff --git a/include/Engine/Network/HybridServer.h b/include/Engine/Network/HybridServer.h new file mode 100644 index 00000000..95a9ffde --- /dev/null +++ b/include/Engine/Network/HybridServer.h @@ -0,0 +1,30 @@ +#ifndef HybridServer_h__ +#define HybridServer_h__ + +#include "Server.h" +#include + +class HybridServer : public Server +{ +public: + HybridServer(); + ~HybridServer(); +private: + // UDP logic + boost::asio::io_service m_IOService; + std::unique_ptr m_Socket; + + void readFromClients(); + void parseClientPing(); + void parsePing(); + void parseDisconnect(); + void parseConnect(Packet & packet); + void parseOnInputCommand(Packet & packet); + void parsePlayerTransform(Packet & packet); + void send(Packet & packet, PlayerDefinition & playerDefinition); + void send(Packet & packet); + int receive(char * data); + PlayerID GetPlayerIDFromEndpoint(boost::asio::ip::udp::endpoint endpoint); +}; + +#endif \ No newline at end of file diff --git a/include/Engine/Network/PlayerDefinition.h b/include/Engine/Network/PlayerDefinition.h index 863948b3..3a3dd122 100644 --- a/include/Engine/Network/PlayerDefinition.h +++ b/include/Engine/Network/PlayerDefinition.h @@ -2,6 +2,7 @@ #define PlayerDefinition_h__ #include #include "../Core/Entity.h" +#include struct PlayerDefinition { ::EntityID EntityID = EntityID_Invalid; @@ -9,6 +10,8 @@ struct PlayerDefinition { boost::asio::ip::udp::endpoint Endpoint; unsigned int PacketID; std::clock_t StopTime; + // use for tcp connections + boost::shared_ptr TCPSocket; }; #endif diff --git a/include/Engine/Network/Server.h b/include/Engine/Network/Server.h index 11f983a9..2926558f 100644 --- a/include/Engine/Network/Server.h +++ b/include/Engine/Network/Server.h @@ -5,7 +5,6 @@ #include #include -#include #include "Network/MessageType.h" #include "Network/PlayerDefinition.h" @@ -18,7 +17,6 @@ #include "Core/EPlayerSpawned.h" #include "Core/EEntityDeleted.h" #include "Core/EComponentDeleted.h" - class Server : public Network { public: @@ -26,12 +24,9 @@ public: ~Server(); void Start(World* m_world, EventBroker *eventBroker) override; void Update() override; -private: - // UDP logic - boost::asio::ip::udp::endpoint m_ReceiverEndpoint; - boost::asio::io_service m_IOService; - boost::asio::ip::udp::socket m_Socket; - +protected: + template + T m_ReceiverEndpoint; // Sending messages to client logic std::map m_ConnectedPlayers; // HACK: Fix INPUTSIZE @@ -41,12 +36,12 @@ private: std::clock_t previousePingMessage = std::clock(); std::clock_t previousSnapshotMessage = std::clock(); std::clock_t timOutTimer = std::clock(); + // How often we send messages (milliseconds) int pingIntervalMs; int snapshotInterval; int checkTimeOutInterval = 100; int m_NextPlayerID = 0; - //Timers std::clock_t m_StartPingTime; @@ -59,10 +54,7 @@ private: PacketID m_PreviousPacketID = 0; // Private member functions - int receive(char* data); - void readFromClients(); - void send(PlayerID player, Packet& packet); - void send(Packet& packet); + //int receive(char* data); void broadcast(Packet& packet); void sendSnapshot(); void addChildrenToPacket(Packet& packet, EntityID entityID); @@ -70,15 +62,18 @@ private: void checkForTimeOuts(); void disconnect(PlayerID playerID); void parseMessageType(Packet& packet); - void parseOnInputCommand(Packet& packet); void parseOnPlayerDamage(Packet& packet); - void parseConnect(Packet& packet); - void parseDisconnect(); - void parseClientPing(); - void parsePing(); void identifyPacketLoss(); void kick(PlayerID player); - PlayerID GetPlayerIDFromEndpoint(boost::asio::ip::udp::endpoint endpoint); + // Pure virtual functions + virtual void parseOnInputCommand(Packet& packet) = 0; + virtual void readFromClients() = 0; + virtual void send(Packet& packet, PlayerDefinition & playerDefinition) = 0; + virtual void send(Packet& packet) = 0; + virtual void parseConnect(Packet& packet) = 0; + virtual void parseDisconnect() = 0; + virtual void parseClientPing() = 0; + virtual void parsePing() = 0; // Debug event EventRelay m_EInputCommand; bool OnInputCommand(const Events::InputCommand& e); @@ -88,7 +83,7 @@ private: bool OnEntityDeleted(const Events::EntityDeleted& e); EventRelay m_EComponentDeleted; bool OnComponentDeleted(const Events::ComponentDeleted& e); - void parsePlayerTransform(Packet& packet); + virtual void parsePlayerTransform(Packet& packet) = 0; }; #endif diff --git a/include/Engine/Network/TCPClient.h b/include/Engine/Network/TCPClient.h index d342641b..14415eef 100644 --- a/include/Engine/Network/TCPClient.h +++ b/include/Engine/Network/TCPClient.h @@ -1,7 +1,23 @@ #ifndef TCPClient_h__ #define TCPClient_h__ +#include "Client.h" +class TCPClient : public Client +{ +public: + TCPClient(ConfigFile* config); + ~TCPClient(); + void Start(World* world, EventBroker* eventBroker); +private: + // Assio TCP logic + boost::asio::ip::tcp::endpoint m_Endpoint; + boost::asio::io_service m_IOService; + boost::shared_ptr m_Socket; + void readFromServer(); + int receive(char * data); + void send(Packet & packet); +}; #endif \ No newline at end of file diff --git a/include/Engine/Network/TCPServer.h b/include/Engine/Network/TCPServer.h new file mode 100644 index 00000000..23f6d666 --- /dev/null +++ b/include/Engine/Network/TCPServer.h @@ -0,0 +1,37 @@ +#ifndef TCPServer_h__ +#define TCPServer_h__ + +#include "Server.h" + +class TCPServer : public Server +{ +public: + TCPServer(); + ~TCPServer(); + +private: + // TCP logic + boost::asio::ip::udp::endpoint m_ReceiverEndpoint; + boost::asio::io_service m_IOService; + std::unique_ptr acceptor; + boost::shared_ptr lastReceivedSocket; + + void Start(World* world, EventBroker* eventBroker); + void readFromClients(); + void acceptNewConnections(); + void handle_accept(boost::shared_ptr socket, const boost::system::error_code & error); + void parseDisconnect(); + void parseConnect(Packet & packet); + ///// Implement method to get which player it was + void parseClientPing(); + void parsePing(); + void parseOnInputCommand(Packet & packet); + void parsePlayerTransform(Packet & packet); + ///////////////////////// + void send(Packet & packet, PlayerDefinition & playerDefinition); + void send(Packet & packet); + int receive(char * data, boost::asio::ip::tcp::socket& socket); + PlayerID GetPlayerIDFromEndpoint(boost::asio::ip::udp::endpoint endpoint); +}; + +#endif \ No newline at end of file diff --git a/include/Game/Game.h b/include/Game/Game.h index 85d0190c..060f97f4 100644 --- a/include/Game/Game.h +++ b/include/Game/Game.h @@ -26,8 +26,10 @@ // Network #include #include "Network/Network.h" -#include "Network/Server.h" +#include "Network/HybridServer.h" #include "Network/HybridClient.h" +#include "Network/TCPClient.h" +#include "Network/TCPServer.h" // Sound #include "Sound/SoundSystem.h" diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 6c43cc8b..6f9519d5 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -1,9 +1,6 @@ #include "Network/Client.h" -using namespace boost::asio::ip; - - -Client::Client(ConfigFile* config) : m_Socket(m_IOService) +Client::Client(ConfigFile* config) { Network::initialize(); @@ -12,13 +9,11 @@ Client::Client(ConfigFile* config) : m_Socket(m_IOService) // Init timer m_TimeSinceSentInputs = std::clock(); // Default is local host - std::string address = config->Get("Networking.Address", "127.0.0.1"); - int port = config->Get("Networking.Port", 27666); - m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string(address), port); + address = config->Get("Networking.Address", "127.0.0.1"); + port = config->Get("Networking.Port", 27666); // Set up network stream m_PlayerName = config->Get("Networking.Name", "Raptorcopter"); m_SendInputIntervalMs = config->Get("Networking.SendInputIntervalMs", 33); - } Client::~Client() @@ -33,8 +28,6 @@ void Client::Start(World* world, EventBroker* eventBroker) EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &Client::OnInputCommand); EVENT_SUBSCRIBE_MEMBER(m_EPlayerDamage, &Client::OnPlayerDamage); EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &Client::OnPlayerSpawned); - - m_Socket.connect(m_ReceiverEndpoint); LOG_INFO("I am client. BIP BOP"); } @@ -54,17 +47,6 @@ void Client::Update() Network::Update(); } -void Client::readFromServer() -{ - while (m_Socket.available()) { - bytesRead = receive(readBuf); - if (bytesRead > 0) { - Packet packet(readBuf, bytesRead); - parseMessageType(packet); - } - } -} - void Client::parseMessageType(Packet& packet) { int messageType = packet.ReadPrimitive(); @@ -258,40 +240,6 @@ void Client::parseSnapshot(Packet& packet) } } -int Client::receive(char* data) -{ - boost::system::error_code error; - - int bytesReceived = m_Socket.receive_from(boost - ::asio::buffer((void*)data, INPUTSIZE), - m_ReceiverEndpoint, - 0, error); - // Network Debug data - if (isReadingData) { - m_NetworkData.TotalDataReceived += bytesReceived; - m_NetworkData.DataReceivedThisInterval += bytesReceived; - m_NetworkData.AmountOfMessagesReceived++; - } - if (error) { - //LOG_ERROR("receive: %s", error.message().c_str()); - } - return bytesReceived; -} - -void Client::send(Packet& packet) -{ - m_Socket.send_to(boost::asio::buffer( - packet.Data(), - packet.Size()), - m_ReceiverEndpoint, 0); - // Network Debug data - if (isReadingData) { - m_NetworkData.TotalDataSent += packet.Size(); - m_NetworkData.DataSentThisInterval += packet.Size(); - m_NetworkData.AmountOfMessagesSent++; - } -} - void Client::connect() { Packet packet(MessageType::Connect, m_SendPacketID); @@ -457,7 +405,6 @@ void Client::insertIntoServerClientMaps(EntityID serverEntityID, EntityID client { m_ServerIDToClientID.insert(std::make_pair(serverEntityID, clientEntityID)); m_ClientIDToServerID.insert(std::make_pair(clientEntityID, serverEntityID)); - } void Client::deleteFromServerClientMaps(EntityID serverEntityID, EntityID clientEntityID) diff --git a/src/Engine/Network/HybridClient.cpp b/src/Engine/Network/HybridClient.cpp index 798ff578..fd0b6649 100644 --- a/src/Engine/Network/HybridClient.cpp +++ b/src/Engine/Network/HybridClient.cpp @@ -1,12 +1,64 @@ #include "Network/HybridClient.h" +using namespace boost::asio::ip; -HybridClient::HybridClient(ConfigFile * config) : Client(config) +HybridClient::HybridClient(ConfigFile * config) : Client(config), m_Socket(m_IOService) { - + m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string(address), port); } HybridClient::~HybridClient() { } + +void HybridClient::Start(World* world, EventBroker* eventBroker) +{ + Client::Start(world, eventBroker); + m_Socket.connect(m_ReceiverEndpoint); +} + +void HybridClient::readFromServer() +{ + while (m_Socket.available()) { + bytesRead = receive(readBuf); + if (bytesRead > 0) { + Packet packet(readBuf, bytesRead); + parseMessageType(packet); + } + } +} + +int HybridClient::receive(char* data) +{ + boost::system::error_code error; + + int bytesReceived = m_Socket.receive_from(boost + ::asio::buffer((void*)data, INPUTSIZE), + m_ReceiverEndpoint, + 0, error); + // Network Debug data + if (isReadingData) { + m_NetworkData.TotalDataReceived += bytesReceived; + m_NetworkData.DataReceivedThisInterval += bytesReceived; + m_NetworkData.AmountOfMessagesReceived++; + } + if (error) { + //LOG_ERROR("receive: %s", error.message().c_str()); + } + return bytesReceived; +} + +void HybridClient::send(Packet& packet) +{ + m_Socket.send_to(boost::asio::buffer( + packet.Data(), + packet.Size()), + m_ReceiverEndpoint, 0); + // Network Debug data + if (isReadingData) { + m_NetworkData.TotalDataSent += packet.Size(); + m_NetworkData.DataSentThisInterval += packet.Size(); + m_NetworkData.AmountOfMessagesSent++; + } +} \ No newline at end of file diff --git a/src/Engine/Network/HybridServer.cpp b/src/Engine/Network/HybridServer.cpp new file mode 100644 index 00000000..e4142725 --- /dev/null +++ b/src/Engine/Network/HybridServer.cpp @@ -0,0 +1,203 @@ +#include "Network/HybridServer.h" + +HybridServer::HybridServer() +{ + m_Socket = std::unique_ptr(new boost::asio::ip::udp::socket(m_IOService, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 27666))); + +} + +HybridServer::~HybridServer() +{ } + + +void HybridServer::readFromClients() +{ + while (m_Socket->available()) { + try { + bytesRead = receive(readBuffer); + Packet packet(readBuffer, bytesRead); + parseMessageType(packet); + } catch (const std::exception& err) { + //LOG_ERROR("%i: Read from client crashed %s", m_PacketID, err.what()); + } + } + std::clock_t currentTime = std::clock(); + // Send snapshot + if (snapshotInterval < (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC)) { + sendSnapshot(); + previousSnapshotMessage = currentTime; + } + + // Send pings each + if (pingIntervalMs < (1000 * (currentTime - previousePingMessage) / (double)CLOCKS_PER_SEC)) { + sendPing(); + previousePingMessage = currentTime; + } + + // Time out logic + if (checkTimeOutInterval < (1000 * (currentTime - timOutTimer) / (double)CLOCKS_PER_SEC)) { + checkForTimeOuts(); + timOutTimer = currentTime; + } +} + +void HybridServer::parseClientPing() +{ + LOG_INFO("%i: Parsing ping", m_PacketID); + PlayerID player = GetPlayerIDFromEndpoint(m_ReceiverEndpoint); + if (player == -1) { + return; + } + // Return ping + Packet packet(MessageType::Ping, m_ConnectedPlayers[player].PacketID); + packet.WriteString("Ping received"); + send(packet); +} + +void HybridServer::parsePing() +{ + for (int i = 0; i < m_ConnectedPlayers.size(); i++) { + if (m_ConnectedPlayers[i].Endpoint.address() == m_ReceiverEndpoint.address()) { + m_ConnectedPlayers[i].StopTime = std::clock(); + break; + } + } +} + +void HybridServer::parseDisconnect() +{ + LOG_INFO("%i: Parsing disconnect", m_PacketID); + + for (auto& kv : m_ConnectedPlayers) { + if (kv.second.Endpoint.address() == m_ReceiverEndpoint.address() && + kv.second.Endpoint.port() == m_ReceiverEndpoint.port()) { + disconnect(kv.first); + break; + } + } +} + +void HybridServer::parseConnect(Packet& packet) +{ + LOG_INFO("Parsing connections"); + // Check if player is already connected + if (GetPlayerIDFromEndpoint(m_ReceiverEndpoint) != -1) { + return; + } + // Create a new player + PlayerDefinition pd; + pd.EntityID = 0; // Overlook this + pd.Endpoint = m_ReceiverEndpoint; + pd.Name = packet.ReadString(); + pd.PacketID = 0; + pd.StopTime = std::clock(); + m_ConnectedPlayers[m_NextPlayerID++] = pd; + LOG_INFO("Spectator \"%s\" connected on IP: %s", pd.Name.c_str(), pd.Endpoint.address().to_string().c_str()); + + // Send a message to the player that connected + Packet connnectPacket(MessageType::Connect, pd.PacketID); + send(connnectPacket); + + // Send notification that a player has connected + Packet notificationPacket(MessageType::PlayerConnected); + broadcast(notificationPacket); +} + +void HybridServer::parseOnInputCommand(Packet& packet) +{ + PlayerID player = -1; + // Check which player it was who sent the message + player = GetPlayerIDFromEndpoint(m_ReceiverEndpoint); + if (player != -1) { + while (packet.DataReadSize() < packet.Size()) { + Events::InputCommand e; + e.Command = packet.ReadString(); + e.PlayerID = player; // Set correct player id + e.Player = EntityWrapper(m_World, m_ConnectedPlayers.at(player).EntityID); + e.Value = packet.ReadPrimitive(); + m_EventBroker->Publish(e); + LOG_INFO("Server::parseOnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID); + } + } +} + +void HybridServer::parsePlayerTransform(Packet& packet) +{ + glm::vec3 position; + glm::vec3 orientation; + position.x = packet.ReadPrimitive(); + position.y = packet.ReadPrimitive(); + position.z = packet.ReadPrimitive(); + orientation.x = packet.ReadPrimitive(); + orientation.y = packet.ReadPrimitive(); + orientation.z = packet.ReadPrimitive(); + + PlayerID playerID = GetPlayerIDFromEndpoint(m_ReceiverEndpoint); + EntityWrapper player(m_World, m_ConnectedPlayers.at(playerID).EntityID); + + if (player.Valid()) { + player["Transform"]["Position"] = position; + player["Transform"]["Orientation"] = orientation; + } +} + +void HybridServer::send(Packet& packet, PlayerDefinition & playerDefinition) +{ + try { + int bytesSent = m_Socket->send_to( + boost::asio::buffer(packet.Data(), packet.Size()), + playerDefinition.Endpoint, + 0); + // Network Debug data + if (isReadingData) { + m_NetworkData.TotalDataSent += packet.Size(); + m_NetworkData.DataSentThisInterval += packet.Size(); + m_NetworkData.AmountOfMessagesSent++; + } + } catch (const boost::system::system_error& e) { + // TODO: Clean up invalid endpoints out of m_ConnectedPlayers later + playerDefinition.Endpoint = boost::asio::ip::udp::endpoint(); + } +} +// Send back to endpoint of received packet +void HybridServer::send(Packet & packet) +{ + m_Socket->send_to( + boost::asio::buffer( + packet.Data(), + packet.Size()), + m_ReceiverEndpoint, + 0); + if (isReadingData) { + // Network Debug data + m_NetworkData.TotalDataSent += packet.Size(); + m_NetworkData.DataSentThisInterval += packet.Size(); + } +} + + +int HybridServer::receive(char * data) +{ + unsigned int length = m_Socket->receive_from( + boost::asio::buffer((void*)data + , INPUTSIZE) + , m_ReceiverEndpoint, 0); + // Network Debug data + if (isReadingData) { + m_NetworkData.TotalDataReceived += length; + m_NetworkData.DataReceivedThisInterval += length; + m_NetworkData.AmountOfMessagesReceived++; + } + return length; +} + +PlayerID HybridServer::GetPlayerIDFromEndpoint(boost::asio::ip::udp::endpoint endpoint) +{ + for (auto& kv : m_ConnectedPlayers) { + if (kv.second.Endpoint.address() == endpoint.address() && + kv.second.Endpoint.port() == endpoint.port()) { + return kv.first; + } + } + return -1; +} diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index adf14413..37b2e752 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -1,19 +1,16 @@ #include "Network/Server.h" -Server::Server() : m_Socket(m_IOService, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 27666)) +Server::Server() { Network::initialize(); ConfigFile* config = ResourceManager::Load("Config.ini"); snapshotInterval = 1000 * config->Get("Networking.SnapshotInterval", 0.05); pingIntervalMs = config->Get("Networking.PingIntervalMs", 1000); - } - Server::~Server() { } - void Server::Start(World* world, EventBroker* eventBroker) { m_World = world; @@ -36,41 +33,9 @@ void Server::Update() } -void Server::readFromClients() -{ - while (m_Socket.available()) { - try { - bytesRead = receive(readBuffer); - Packet packet(readBuffer, bytesRead); - parseMessageType(packet); - } catch (const std::exception& err) { - //LOG_ERROR("%i: Read from client crashed %s", m_PacketID, err.what()); - } - } - std::clock_t currentTime = std::clock(); - // Send snapshot - if (snapshotInterval < (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC)) { - sendSnapshot(); - previousSnapshotMessage = currentTime; - } - - // Send pings each - if (pingIntervalMs < (1000 * (currentTime - previousePingMessage) / (double)CLOCKS_PER_SEC)) { - sendPing(); - previousePingMessage = currentTime; - } - - // Time out logic - if (checkTimeOutInterval < (1000 * (currentTime - timOutTimer) / (double)CLOCKS_PER_SEC)) { - checkForTimeOuts(); - timOutTimer = currentTime; - } -} - void Server::parseMessageType(Packet& packet) { int messageType = packet.ReadPrimitive(); // Read what type off message was sent from server - // Read packet ID m_PreviousPacketID = m_PacketID; // Set previous packet id m_PacketID = packet.ReadPrimitive(); //Read new packet id @@ -103,60 +68,11 @@ void Server::parseMessageType(Packet& packet) } } -int Server::receive(char * data) -{ - unsigned int length = m_Socket.receive_from( - boost::asio::buffer((void*)data - , INPUTSIZE) - , m_ReceiverEndpoint, 0); - // Network Debug data - if (isReadingData) { - m_NetworkData.TotalDataReceived += length; - m_NetworkData.DataReceivedThisInterval += length; - m_NetworkData.AmountOfMessagesReceived++; - } - return length; -} - -void Server::send(PlayerID player, Packet& packet) -{ - try { - int bytesSent = m_Socket.send_to( - boost::asio::buffer(packet.Data(), packet.Size()), - m_ConnectedPlayers[player].Endpoint, - 0); - // Network Debug data - if (isReadingData) { - m_NetworkData.TotalDataSent += packet.Size(); - m_NetworkData.DataSentThisInterval += packet.Size(); - m_NetworkData.AmountOfMessagesSent++; - } - } catch (const boost::system::system_error& e) { - // TODO: Clean up invalid endpoints out of m_ConnectedPlayers later - m_ConnectedPlayers[player].Endpoint = boost::asio::ip::udp::endpoint(); - } -} - -void Server::send(Packet & packet) -{ - m_Socket.send_to( - boost::asio::buffer( - packet.Data(), - packet.Size()), - m_ReceiverEndpoint, - 0); - if (isReadingData) { - // Network Debug data - m_NetworkData.TotalDataSent += packet.Size(); - m_NetworkData.DataSentThisInterval += packet.Size(); - } -} - void Server::broadcast(Packet& packet) { for (auto& kv : m_ConnectedPlayers) { packet.ChangePacketID(kv.second.PacketID); - send(kv.first, packet); + send(packet, kv.second); } } @@ -259,24 +175,6 @@ void Server::disconnect(PlayerID playerID) m_ConnectedPlayers.erase(playerID); } -void Server::parseOnInputCommand(Packet& packet) -{ - PlayerID player = -1; - // Check which player it was who sent the message - player = GetPlayerIDFromEndpoint(m_ReceiverEndpoint); - if (player != -1) { - while (packet.DataReadSize() < packet.Size()) { - Events::InputCommand e; - e.Command = packet.ReadString(); - e.PlayerID = player; // Set correct player id - e.Player = EntityWrapper(m_World, m_ConnectedPlayers.at(player).EntityID); - e.Value = packet.ReadPrimitive(); - m_EventBroker->Publish(e); - LOG_INFO("Server::parseOnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID); - } - } -} - void Server::parseOnPlayerDamage(Packet & packet) { Events::PlayerDamage e; @@ -286,75 +184,6 @@ void Server::parseOnPlayerDamage(Packet & packet) //LOG_DEBUG("Server::parseOnPlayerDamage: Command is %s. Value is %f. PlayerID is %i.", e.DamageAmount, e.PlayerDamagedID, e.TypeOfDamage.c_str()); } -void Server::parseConnect(Packet& packet) -{ - LOG_INFO("Parsing connections"); - // Check if player is already connected - if (GetPlayerIDFromEndpoint(m_ReceiverEndpoint) != -1) { - return; - } - for (auto& kv : m_ConnectedPlayers) { - if (kv.second.Endpoint.address() == m_ReceiverEndpoint.address() && - kv.second.Endpoint.port() == m_ReceiverEndpoint.port()) { - // Already connected - return; - } - } - // Create a new player - PlayerDefinition pd; - pd.EntityID = 0; // Overlook this - pd.Endpoint = m_ReceiverEndpoint; - pd.Name = packet.ReadString(); - pd.PacketID = 0; - pd.StopTime = std::clock(); - m_ConnectedPlayers[m_NextPlayerID++] = pd; - LOG_INFO("Spectator \"%s\" connected on IP: %s", pd.Name.c_str(), pd.Endpoint.address().to_string().c_str()); - - // Send a message to the player that connected - Packet connnectPacket(MessageType::Connect, pd.PacketID); - send(connnectPacket); - - // Send notification that a player has connected - Packet notificationPacket(MessageType::PlayerConnected); - broadcast(notificationPacket); -} - -void Server::parseDisconnect() -{ - LOG_INFO("%i: Parsing disconnect", m_PacketID); - - for (auto& kv : m_ConnectedPlayers) { - if (kv.second.Endpoint.address() == m_ReceiverEndpoint.address() && - kv.second.Endpoint.port() == m_ReceiverEndpoint.port()) { - disconnect(kv.first); - break; - } - } -} - -void Server::parseClientPing() -{ - LOG_INFO("%i: Parsing ping", m_PacketID); - PlayerID player = GetPlayerIDFromEndpoint(m_ReceiverEndpoint); - if (player == -1) { - return; - } - // Return ping - Packet packet(MessageType::Ping, m_ConnectedPlayers[player].PacketID); - packet.WriteString("Ping received"); - send(packet); -} - -void Server::parsePing() -{ - for (int i = 0; i < m_ConnectedPlayers.size(); i++) { - if (m_ConnectedPlayers[i].Endpoint.address() == m_ReceiverEndpoint.address()) { - m_ConnectedPlayers[i].StopTime = std::clock(); - break; - } - } -} - void Server::identifyPacketLoss() { // if no packets lost, difference should be equal to 1 @@ -371,17 +200,6 @@ void Server::kick(PlayerID player) send(packet); } -PlayerID Server::GetPlayerIDFromEndpoint(boost::asio::ip::udp::endpoint endpoint) -{ - for (auto& kv : m_ConnectedPlayers) { - if (kv.second.Endpoint.address() == endpoint.address() && - kv.second.Endpoint.port() == endpoint.port()) { - return kv.first; - } - } - return -1; -} - bool Server::OnInputCommand(const Events::InputCommand & e) { //LOG_DEBUG("Server::OnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID); @@ -408,7 +226,7 @@ bool Server::OnPlayerSpawned(const Events::PlayerSpawned & e) packet.WritePrimitive(e.Spawner.ID); // We don't send PlayerID here because it will always be set to -1 packet.WriteString(m_ConnectedPlayers[e.PlayerID].Name); - send(e.PlayerID, packet); + send(packet, m_ConnectedPlayers[e.PlayerID]); return false; } @@ -432,23 +250,3 @@ bool Server::OnComponentDeleted(const Events::ComponentDeleted & e) } return false; } - -void Server::parsePlayerTransform(Packet& packet) -{ - glm::vec3 position; - glm::vec3 orientation; - position.x = packet.ReadPrimitive(); - position.y = packet.ReadPrimitive(); - position.z = packet.ReadPrimitive(); - orientation.x = packet.ReadPrimitive(); - orientation.y = packet.ReadPrimitive(); - orientation.z = packet.ReadPrimitive(); - - PlayerID playerID = GetPlayerIDFromEndpoint(m_ReceiverEndpoint); - EntityWrapper player(m_World, m_ConnectedPlayers.at(playerID).EntityID); - - if (player.Valid()) { - player["Transform"]["Position"] = position; - player["Transform"]["Orientation"] = orientation; - } -} diff --git a/src/Engine/Network/TCPClient.cpp b/src/Engine/Network/TCPClient.cpp index e69de29b..d4909f56 100644 --- a/src/Engine/Network/TCPClient.cpp +++ b/src/Engine/Network/TCPClient.cpp @@ -0,0 +1,48 @@ +#include "Network/TCPClient.h" + +using namespace boost::asio::ip; + +TCPClient::TCPClient(ConfigFile * config) : Client(config) +{ + m_Endpoint = tcp::endpoint(boost::asio::ip::address::from_string(address), port); + m_Socket = boost::shared_ptr(new tcp::socket(m_IOService)); +} + +TCPClient::~TCPClient() +{ + +} + +void TCPClient::Start(World * world, EventBroker * eventBroker) +{ + Client::Start(world, eventBroker); + boost::system::error_code error = boost::asio::error::host_not_found; + while (error) { + m_Socket->close(); + m_Socket->connect(m_Endpoint,error); + LOG_INFO(error.message().c_str()); + } +} + +void TCPClient::readFromServer() +{ + +} + +int TCPClient::receive(char * data) +{ + return 0; +} + +void TCPClient::send(Packet & packet) +{ + m_Socket->send(boost::asio::buffer( + packet.Data(), + packet.Size())); + // Network Debug data + if (isReadingData) { + m_NetworkData.TotalDataSent += packet.Size(); + m_NetworkData.DataSentThisInterval += packet.Size(); + m_NetworkData.AmountOfMessagesSent++; + } +} diff --git a/src/Engine/Network/TCPServer.cpp b/src/Engine/Network/TCPServer.cpp new file mode 100644 index 00000000..930e7913 --- /dev/null +++ b/src/Engine/Network/TCPServer.cpp @@ -0,0 +1,148 @@ +#include "Network/TCPServer.h" +using namespace boost::asio::ip; + +TCPServer::TCPServer() +{ + acceptor = std::unique_ptr(new tcp::acceptor(m_IOService, tcp::endpoint(tcp::v4(), 27666))); +} + +TCPServer::~TCPServer() +{ + +} + +void TCPServer::Start(World* world, EventBroker* eventBroker) +{ + Server::Start(world, eventBroker); +} + +void TCPServer::readFromClients() +{ + acceptNewConnections(); + for (auto& kv : m_ConnectedPlayers) { + while (kv.second.TCPSocket->available()) { + try { + bytesRead = receive(readBuffer, *kv.second.TCPSocket); + lastReceivedSocket = kv.second.TCPSocket; + Packet packet(readBuffer, bytesRead); + parseMessageType(packet); + } catch (const std::exception& err) { + //LOG_ERROR("%i: Read from client crashed %s", m_PacketID, err.what()); + } + } + } + + std::clock_t currentTime = std::clock(); + // Send snapshot + if (snapshotInterval < (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC)) { + sendSnapshot(); + previousSnapshotMessage = currentTime; + } + + // Send pings each + if (pingIntervalMs < (1000 * (currentTime - previousePingMessage) / (double)CLOCKS_PER_SEC)) { + sendPing(); + previousePingMessage = currentTime; + } + + // Time out logic + if (checkTimeOutInterval < (1000 * (currentTime - timOutTimer) / (double)CLOCKS_PER_SEC)) { + checkForTimeOuts(); + timOutTimer = currentTime; + } +} + +void TCPServer::acceptNewConnections() +{ + boost::shared_ptr newSocket = boost::shared_ptr(new tcp::socket(m_IOService)); + m_IOService.poll(); + acceptor->async_accept(*newSocket, + boost::bind(&TCPServer::handle_accept, this, newSocket, + boost::asio::placeholders::error)); +} + +void TCPServer::handle_accept(boost::shared_ptr socket, const boost::system::error_code& error) +{ + if (!error) { + // Add tcp socket to connections + PlayerDefinition pd; + pd.StopTime = std::clock(); + pd.TCPSocket = socket; + m_ConnectedPlayers[m_NextPlayerID++] = pd; + } +} +void TCPServer::parseClientPing() +{ + +} +void TCPServer::parsePing() +{ + +} +void TCPServer::parseDisconnect() +{ + +} +void TCPServer::parseConnect(Packet & packet) +{ + +} +void TCPServer::parseOnInputCommand(Packet & packet) +{ + +} +void TCPServer::parsePlayerTransform(Packet & packet) +{ + +} +void TCPServer::send(Packet & packet, PlayerDefinition & playerDefinition) +{ + try { + int bytesSent = playerDefinition.TCPSocket->send( + boost::asio::buffer(packet.Data(), packet.Size()), + 0); + // Network Debug data + if (isReadingData) { + m_NetworkData.TotalDataSent += packet.Size(); + m_NetworkData.DataSentThisInterval += packet.Size(); + m_NetworkData.AmountOfMessagesSent++; + } + } catch (const boost::system::system_error& e) { + // TODO: Clean up invalid endpoints out of m_ConnectedPlayers later + playerDefinition.Endpoint = boost::asio::ip::udp::endpoint(); + } +} + +void TCPServer::send(Packet & packet) +{ + lastReceivedSocket->send( + boost::asio::buffer( + packet.Data(), + packet.Size()), + 0); + if (isReadingData) { + // Network Debug data + m_NetworkData.TotalDataSent += packet.Size(); + m_NetworkData.DataSentThisInterval += packet.Size(); + } +} + +//boost::shared_ptr socket +int TCPServer::receive(char * data,boost::asio::ip::tcp::socket& socket) +{ + unsigned int length = socket.read_some( + boost::asio::buffer((void*)data, INPUTSIZE)); + // Network Debug data + if (isReadingData) { + m_NetworkData.TotalDataReceived += length; + m_NetworkData.DataReceivedThisInterval += length; + m_NetworkData.AmountOfMessagesReceived++; + } + return length; + +} + +PlayerID TCPServer::GetPlayerIDFromEndpoint(boost::asio::ip::udp::endpoint endpoint) +{ + return PlayerID(); +} \ No newline at end of file diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index c26510ec..969fa46c 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -181,11 +181,11 @@ void Game::networkFunction() bool isServer = m_Config->Get("Networking.IsServer", false); if (!isServer) { m_IsClientOrServer = true; - m_ClientOrServer = new HybridClient(m_Config); + m_ClientOrServer = new TCPClient(m_Config); } if (isServer) { m_IsClientOrServer = true; - m_ClientOrServer = new Server(); + m_ClientOrServer = new TCPServer(); } m_ClientOrServer->Start(m_World, m_EventBroker); From 88d7b79cd32f60a91c12ec413cf99b31da453700 Mon Sep 17 00:00:00 2001 From: Jocke Date: Fri, 5 Feb 2016 18:30:31 +0100 Subject: [PATCH 03/18] TCP and UDP Client are working for 1 connected player, more players are not tested yet --- include/Engine/Network/Client.h | 4 +- include/Engine/Network/HybridClient.h | 1 + include/Engine/Network/HybridServer.h | 7 +- include/Engine/Network/Network.h | 2 +- include/Engine/Network/Packet.h | 2 + include/Engine/Network/PlayerDefinition.h | 2 + include/Engine/Network/Server.h | 18 ++-- include/Engine/Network/TCPClient.h | 1 + include/Engine/Network/TCPServer.h | 11 --- src/Engine/Network/Client.cpp | 16 ++-- src/Engine/Network/HybridClient.cpp | 14 ++- src/Engine/Network/HybridServer.cpp | 93 ++----------------- src/Engine/Network/Packet.cpp | 9 +- src/Engine/Network/Server.cpp | 103 ++++++++++++++++++++-- src/Engine/Network/TCPClient.cpp | 61 ++++++++++--- src/Engine/Network/TCPServer.cpp | 85 ++++++++++-------- src/Game/Game.cpp | 6 +- 17 files changed, 253 insertions(+), 182 deletions(-) diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index 1c445cac..5259504b 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -35,7 +35,7 @@ protected: int port = 0; // Sending message to server logic int bytesRead = -1; - char readBuf[INPUTSIZE] = { 0 }; + char readBuffer[BUFFERSIZE] = { 0 }; // Packet loss logic PacketID m_PacketID = 0; @@ -68,7 +68,7 @@ protected: // Private member functions virtual void send(Packet& packet) = 0; virtual void readFromServer() = 0; - void connect(); + virtual void connect() = 0; void disconnect(); void parseMessageType(Packet& packet); void updateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID, const std::string& componentType); diff --git a/include/Engine/Network/HybridClient.h b/include/Engine/Network/HybridClient.h index 8c9d1a68..fb2777d4 100644 --- a/include/Engine/Network/HybridClient.h +++ b/include/Engine/Network/HybridClient.h @@ -16,6 +16,7 @@ private: boost::asio::io_service m_IOService; boost::asio::ip::udp::socket m_Socket; + void connect(); void readFromServer(); int receive(char * data); void send(Packet & packet); diff --git a/include/Engine/Network/HybridServer.h b/include/Engine/Network/HybridServer.h index 95a9ffde..f12dc660 100644 --- a/include/Engine/Network/HybridServer.h +++ b/include/Engine/Network/HybridServer.h @@ -13,18 +13,13 @@ private: // UDP logic boost::asio::io_service m_IOService; std::unique_ptr m_Socket; + boost::asio::ip::udp::endpoint m_ReceiverEndpoint; void readFromClients(); - void parseClientPing(); - void parsePing(); - void parseDisconnect(); void parseConnect(Packet & packet); - void parseOnInputCommand(Packet & packet); - void parsePlayerTransform(Packet & packet); void send(Packet & packet, PlayerDefinition & playerDefinition); void send(Packet & packet); int receive(char * data); - PlayerID GetPlayerIDFromEndpoint(boost::asio::ip::udp::endpoint endpoint); }; #endif \ No newline at end of file diff --git a/include/Engine/Network/Network.h b/include/Engine/Network/Network.h index e1e64fc1..caf55f13 100644 --- a/include/Engine/Network/Network.h +++ b/include/Engine/Network/Network.h @@ -12,7 +12,7 @@ #include #include -#define INPUTSIZE 32000 +#define BUFFERSIZE 32000 typedef unsigned int PlayerID; typedef unsigned int PacketID; diff --git a/include/Engine/Network/Packet.h b/include/Engine/Network/Packet.h index d38ddf58..b7e774c2 100644 --- a/include/Engine/Network/Packet.h +++ b/include/Engine/Network/Packet.h @@ -49,6 +49,8 @@ public: void WriteData(char* data, int sizeOfData); // Pops the first element as if it was a string. std::string ReadString(); + // Update size of packet variable in header + void UpdateSize(); char* ReadData(int SizeOfData); void ChangePacketID(unsigned int& packetID); int Size() { return m_Offset; }; diff --git a/include/Engine/Network/PlayerDefinition.h b/include/Engine/Network/PlayerDefinition.h index 3a3dd122..e4c3e5c5 100644 --- a/include/Engine/Network/PlayerDefinition.h +++ b/include/Engine/Network/PlayerDefinition.h @@ -10,6 +10,8 @@ struct PlayerDefinition { boost::asio::ip::udp::endpoint Endpoint; unsigned int PacketID; std::clock_t StopTime; + boost::asio::ip::address Address; + unsigned short Port; // use for tcp connections boost::shared_ptr TCPSocket; }; diff --git a/include/Engine/Network/Server.h b/include/Engine/Network/Server.h index 2926558f..4ff169d2 100644 --- a/include/Engine/Network/Server.h +++ b/include/Engine/Network/Server.h @@ -25,12 +25,13 @@ public: void Start(World* m_world, EventBroker *eventBroker) override; void Update() override; protected: - template - T m_ReceiverEndpoint; + // dont forget to set these in the childrens receive logic + boost::asio::ip::address m_Address; + unsigned short m_Port; // Sending messages to client logic std::map m_ConnectedPlayers; // HACK: Fix INPUTSIZE - char readBuffer[INPUTSIZE] = { 0 }; + char readBuffer[BUFFERSIZE] = { 0 }; int bytesRead = 0; // time for previouse message std::clock_t previousePingMessage = std::clock(); @@ -65,15 +66,17 @@ protected: void parseOnPlayerDamage(Packet& packet); void identifyPacketLoss(); void kick(PlayerID player); + PlayerID GetPlayerIDFromEndpoint(); + void parsePlayerTransform(Packet& packet); + void parseOnInputCommand(Packet& packet); + void parseClientPing(); + void parsePing(); + void parseDisconnect(); // Pure virtual functions - virtual void parseOnInputCommand(Packet& packet) = 0; virtual void readFromClients() = 0; virtual void send(Packet& packet, PlayerDefinition & playerDefinition) = 0; virtual void send(Packet& packet) = 0; virtual void parseConnect(Packet& packet) = 0; - virtual void parseDisconnect() = 0; - virtual void parseClientPing() = 0; - virtual void parsePing() = 0; // Debug event EventRelay m_EInputCommand; bool OnInputCommand(const Events::InputCommand& e); @@ -83,7 +86,6 @@ protected: bool OnEntityDeleted(const Events::EntityDeleted& e); EventRelay m_EComponentDeleted; bool OnComponentDeleted(const Events::ComponentDeleted& e); - virtual void parsePlayerTransform(Packet& packet) = 0; }; #endif diff --git a/include/Engine/Network/TCPClient.h b/include/Engine/Network/TCPClient.h index 14415eef..e90e049c 100644 --- a/include/Engine/Network/TCPClient.h +++ b/include/Engine/Network/TCPClient.h @@ -15,6 +15,7 @@ private: boost::asio::io_service m_IOService; boost::shared_ptr m_Socket; + void connect(); void readFromServer(); int receive(char * data); void send(Packet & packet); diff --git a/include/Engine/Network/TCPServer.h b/include/Engine/Network/TCPServer.h index 23f6d666..61e40639 100644 --- a/include/Engine/Network/TCPServer.h +++ b/include/Engine/Network/TCPServer.h @@ -8,30 +8,19 @@ class TCPServer : public Server public: TCPServer(); ~TCPServer(); - private: // TCP logic - boost::asio::ip::udp::endpoint m_ReceiverEndpoint; boost::asio::io_service m_IOService; std::unique_ptr acceptor; boost::shared_ptr lastReceivedSocket; - void Start(World* world, EventBroker* eventBroker); void readFromClients(); void acceptNewConnections(); void handle_accept(boost::shared_ptr socket, const boost::system::error_code & error); - void parseDisconnect(); void parseConnect(Packet & packet); - ///// Implement method to get which player it was - void parseClientPing(); - void parsePing(); - void parseOnInputCommand(Packet & packet); - void parsePlayerTransform(Packet & packet); - ///////////////////////// void send(Packet & packet, PlayerDefinition & playerDefinition); void send(Packet & packet); int receive(char * data, boost::asio::ip::tcp::socket& socket); - PlayerID GetPlayerIDFromEndpoint(boost::asio::ip::udp::endpoint endpoint); }; #endif \ No newline at end of file diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 6f9519d5..13efad40 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -49,6 +49,9 @@ void Client::Update() void Client::parseMessageType(Packet& packet) { + // Pop packetSize which is used by TCP Client to + // create a packet of the correct size + packet.ReadPrimitive(); int messageType = packet.ReadPrimitive(); if (messageType == -1) return; @@ -240,16 +243,9 @@ void Client::parseSnapshot(Packet& packet) } } -void Client::connect() -{ - Packet packet(MessageType::Connect, m_SendPacketID); - packet.WriteString(m_PlayerName); - m_StartPingTime = std::clock(); - send(packet); -} - void Client::disconnect() { + m_IsConnected = false; m_PreviousPacketID = 0; m_PacketID = 0; Packet packet(MessageType::Disconnect, m_SendPacketID); @@ -283,7 +279,9 @@ bool Client::OnInputCommand(const Events::InputCommand & e) m_SaveDataTimer = std::clock(); } } else { - m_InputCommandBuffer.push_back(e); + if (m_IsConnected) { + m_InputCommandBuffer.push_back(e); + } //LOG_DEBUG("Client::OnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID); return true; } diff --git a/src/Engine/Network/HybridClient.cpp b/src/Engine/Network/HybridClient.cpp index fd0b6649..eabe109b 100644 --- a/src/Engine/Network/HybridClient.cpp +++ b/src/Engine/Network/HybridClient.cpp @@ -21,9 +21,9 @@ void HybridClient::Start(World* world, EventBroker* eventBroker) void HybridClient::readFromServer() { while (m_Socket.available()) { - bytesRead = receive(readBuf); + bytesRead = receive(readBuffer); if (bytesRead > 0) { - Packet packet(readBuf, bytesRead); + Packet packet(readBuffer, bytesRead); parseMessageType(packet); } } @@ -34,7 +34,7 @@ int HybridClient::receive(char* data) boost::system::error_code error; int bytesReceived = m_Socket.receive_from(boost - ::asio::buffer((void*)data, INPUTSIZE), + ::asio::buffer((void*)data, BUFFERSIZE), m_ReceiverEndpoint, 0, error); // Network Debug data @@ -61,4 +61,12 @@ void HybridClient::send(Packet& packet) m_NetworkData.DataSentThisInterval += packet.Size(); m_NetworkData.AmountOfMessagesSent++; } +} + +void HybridClient::connect() +{ + Packet packet(MessageType::Connect, m_SendPacketID); + packet.WriteString(m_PlayerName); + m_StartPingTime = std::clock(); + send(packet); } \ No newline at end of file diff --git a/src/Engine/Network/HybridServer.cpp b/src/Engine/Network/HybridServer.cpp index e4142725..6c22bab7 100644 --- a/src/Engine/Network/HybridServer.cpp +++ b/src/Engine/Network/HybridServer.cpp @@ -15,6 +15,8 @@ void HybridServer::readFromClients() while (m_Socket->available()) { try { bytesRead = receive(readBuffer); + m_Address = m_ReceiverEndpoint.address(); + m_Port = m_ReceiverEndpoint.port(); Packet packet(readBuffer, bytesRead); parseMessageType(packet); } catch (const std::exception& err) { @@ -41,53 +43,19 @@ void HybridServer::readFromClients() } } -void HybridServer::parseClientPing() -{ - LOG_INFO("%i: Parsing ping", m_PacketID); - PlayerID player = GetPlayerIDFromEndpoint(m_ReceiverEndpoint); - if (player == -1) { - return; - } - // Return ping - Packet packet(MessageType::Ping, m_ConnectedPlayers[player].PacketID); - packet.WriteString("Ping received"); - send(packet); -} - -void HybridServer::parsePing() -{ - for (int i = 0; i < m_ConnectedPlayers.size(); i++) { - if (m_ConnectedPlayers[i].Endpoint.address() == m_ReceiverEndpoint.address()) { - m_ConnectedPlayers[i].StopTime = std::clock(); - break; - } - } -} - -void HybridServer::parseDisconnect() -{ - LOG_INFO("%i: Parsing disconnect", m_PacketID); - - for (auto& kv : m_ConnectedPlayers) { - if (kv.second.Endpoint.address() == m_ReceiverEndpoint.address() && - kv.second.Endpoint.port() == m_ReceiverEndpoint.port()) { - disconnect(kv.first); - break; - } - } -} - void HybridServer::parseConnect(Packet& packet) { LOG_INFO("Parsing connections"); // Check if player is already connected - if (GetPlayerIDFromEndpoint(m_ReceiverEndpoint) != -1) { + if (GetPlayerIDFromEndpoint() != -1) { return; } // Create a new player PlayerDefinition pd; pd.EntityID = 0; // Overlook this pd.Endpoint = m_ReceiverEndpoint; + pd.Address = m_ReceiverEndpoint.address(); + pd.Port = m_ReceiverEndpoint.port(); pd.Name = packet.ReadString(); pd.PacketID = 0; pd.StopTime = std::clock(); @@ -103,44 +71,6 @@ void HybridServer::parseConnect(Packet& packet) broadcast(notificationPacket); } -void HybridServer::parseOnInputCommand(Packet& packet) -{ - PlayerID player = -1; - // Check which player it was who sent the message - player = GetPlayerIDFromEndpoint(m_ReceiverEndpoint); - if (player != -1) { - while (packet.DataReadSize() < packet.Size()) { - Events::InputCommand e; - e.Command = packet.ReadString(); - e.PlayerID = player; // Set correct player id - e.Player = EntityWrapper(m_World, m_ConnectedPlayers.at(player).EntityID); - e.Value = packet.ReadPrimitive(); - m_EventBroker->Publish(e); - LOG_INFO("Server::parseOnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID); - } - } -} - -void HybridServer::parsePlayerTransform(Packet& packet) -{ - glm::vec3 position; - glm::vec3 orientation; - position.x = packet.ReadPrimitive(); - position.y = packet.ReadPrimitive(); - position.z = packet.ReadPrimitive(); - orientation.x = packet.ReadPrimitive(); - orientation.y = packet.ReadPrimitive(); - orientation.z = packet.ReadPrimitive(); - - PlayerID playerID = GetPlayerIDFromEndpoint(m_ReceiverEndpoint); - EntityWrapper player(m_World, m_ConnectedPlayers.at(playerID).EntityID); - - if (player.Valid()) { - player["Transform"]["Position"] = position; - player["Transform"]["Orientation"] = orientation; - } -} - void HybridServer::send(Packet& packet, PlayerDefinition & playerDefinition) { try { @@ -180,7 +110,7 @@ int HybridServer::receive(char * data) { unsigned int length = m_Socket->receive_from( boost::asio::buffer((void*)data - , INPUTSIZE) + , BUFFERSIZE) , m_ReceiverEndpoint, 0); // Network Debug data if (isReadingData) { @@ -191,13 +121,4 @@ int HybridServer::receive(char * data) return length; } -PlayerID HybridServer::GetPlayerIDFromEndpoint(boost::asio::ip::udp::endpoint endpoint) -{ - for (auto& kv : m_ConnectedPlayers) { - if (kv.second.Endpoint.address() == endpoint.address() && - kv.second.Endpoint.port() == endpoint.port()) { - return kv.first; - } - } - return -1; -} + diff --git a/src/Engine/Network/Packet.cpp b/src/Engine/Network/Packet.cpp index d40a1b32..28622611 100644 --- a/src/Engine/Network/Packet.cpp +++ b/src/Engine/Network/Packet.cpp @@ -34,6 +34,8 @@ void Packet::Init(MessageType type, unsigned int & packetID) m_ReturnDataOffset = 0; m_Offset = 0; // Create message header + // allocate memory for size of packet(only used in tcp) + Packet::WritePrimitive(0); // Add message type int messageType = static_cast(type); Packet::WritePrimitive(messageType); @@ -76,6 +78,11 @@ std::string Packet::ReadString() return returnValue; } +void Packet::UpdateSize() +{ + memcpy(m_Data, &m_Offset, sizeof(int)); +} + char * Packet::ReadData(int SizeOfData) { if (m_Offset < m_ReturnDataOffset + SizeOfData) { @@ -91,7 +98,7 @@ void Packet::ChangePacketID(unsigned int & packetID) { packetID = packetID + 1; // Overwrite old PacketID - memcpy(m_Data + sizeof(int), &packetID, sizeof(int)); + memcpy(m_Data + 2*sizeof(int), &packetID, sizeof(int)); } void Packet::resizeData() diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index 37b2e752..55f59a03 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -35,6 +35,10 @@ void Server::Update() void Server::parseMessageType(Packet& packet) { + // Pop packetSize which is used by TCP Client to + // create a packet of the correct size + packet.ReadPrimitive(); + int messageType = packet.ReadPrimitive(); // Read what type off message was sent from server // Read packet ID m_PreviousPacketID = m_PacketID; // Set previous packet id @@ -150,25 +154,38 @@ void Server::checkForTimeOuts() int startPing = 1000 * m_StartPingTime / static_cast(CLOCKS_PER_SEC); - for (int i = 0; i < m_ConnectedPlayers.size(); i++) { - if (m_ConnectedPlayers[i].Endpoint.address() != boost::asio::ip::address()) { - int stopPing = 1000 * m_ConnectedPlayers[i].StopTime / + for (auto& kv : m_ConnectedPlayers) { + if (kv.second.Address != boost::asio::ip::address()) { + int stopPing = 1000 * kv.second.StopTime / static_cast(CLOCKS_PER_SEC); if (startPing > stopPing + m_TimeoutMs) { - LOG_INFO("User %i timed out!", i); - disconnect(i); + LOG_INFO("User %i timed out!", kv.second.Name); + disconnect(kv.first); } } } } +void Server::parseDisconnect() +{ + LOG_INFO("%i: Parsing disconnect", m_PacketID); + + for (auto& kv : m_ConnectedPlayers) { + if (kv.second.Address == m_Address && + kv.second.Port == m_Port) { + disconnect(kv.first); + break; + } + } +} + void Server::disconnect(PlayerID playerID) { //broadcast("A player disconnected"); LOG_INFO("User %s disconnected/timed out", m_ConnectedPlayers[playerID].Name.c_str()); // Remove enteties and stuff (When we can remove entity, remove it and tell clients to remove the copy they have) Events::PlayerDisconnected e; - e.Entity = m_ConnectedPlayers[playerID].EntityID; + e.Entity = m_ConnectedPlayers.at(playerID).EntityID; e.PlayerID = playerID; m_EventBroker->Publish(e); @@ -250,3 +267,77 @@ bool Server::OnComponentDeleted(const Events::ComponentDeleted & e) } return false; } + + +void Server::parseClientPing() +{ + LOG_INFO("%i: Parsing ping", m_PacketID); + PlayerID player = GetPlayerIDFromEndpoint(); + if (player == -1) { + return; + } + // Return ping + Packet packet(MessageType::Ping, m_ConnectedPlayers[player].PacketID); + packet.WriteString("Ping received"); + send(packet); +} + +void Server::parsePing() +{ + for (auto& kv : m_ConnectedPlayers) { + if (kv.second.Address == m_Address && + kv.second.Port == m_Port) { + kv.second.StopTime = std::clock(); + break; + } + } +} + +void Server::parseOnInputCommand(Packet& packet) +{ + PlayerID player = -1; + // Check which player it was who sent the message + player = GetPlayerIDFromEndpoint(); + if (player != -1) { + while (packet.DataReadSize() < packet.Size()) { + Events::InputCommand e; + e.Command = packet.ReadString(); + e.PlayerID = player; // Set correct player id + e.Player = EntityWrapper(m_World, m_ConnectedPlayers.at(player).EntityID); + e.Value = packet.ReadPrimitive(); + m_EventBroker->Publish(e); + LOG_INFO("Server::parseOnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID); + } + } +} + +void Server::parsePlayerTransform(Packet& packet) +{ + glm::vec3 position; + glm::vec3 orientation; + position.x = packet.ReadPrimitive(); + position.y = packet.ReadPrimitive(); + position.z = packet.ReadPrimitive(); + orientation.x = packet.ReadPrimitive(); + orientation.y = packet.ReadPrimitive(); + orientation.z = packet.ReadPrimitive(); + + PlayerID playerID = GetPlayerIDFromEndpoint(); + EntityWrapper player(m_World, m_ConnectedPlayers.at(playerID).EntityID); + + if (player.Valid()) { + player["Transform"]["Position"] = position; + player["Transform"]["Orientation"] = orientation; + } +} + +PlayerID Server::GetPlayerIDFromEndpoint() +{ + for (auto& kv : m_ConnectedPlayers) { + if (kv.second.Address == m_Address && + kv.second.Port == m_Port) { + return kv.first; + } + } + return -1; +} \ No newline at end of file diff --git a/src/Engine/Network/TCPClient.cpp b/src/Engine/Network/TCPClient.cpp index d4909f56..3d7261b7 100644 --- a/src/Engine/Network/TCPClient.cpp +++ b/src/Engine/Network/TCPClient.cpp @@ -3,39 +3,76 @@ using namespace boost::asio::ip; TCPClient::TCPClient(ConfigFile * config) : Client(config) -{ +{ m_Endpoint = tcp::endpoint(boost::asio::ip::address::from_string(address), port); - m_Socket = boost::shared_ptr(new tcp::socket(m_IOService)); + m_Socket = boost::shared_ptr(new tcp::socket(m_IOService, m_Endpoint)); + tcp::no_delay option(true); + m_Socket->set_option(option); } TCPClient::~TCPClient() -{ +{ } void TCPClient::Start(World * world, EventBroker * eventBroker) -{ +{ Client::Start(world, eventBroker); - boost::system::error_code error = boost::asio::error::host_not_found; - while (error) { +} +void TCPClient::connect() +{ + if (!m_IsConnected) { + boost::system::error_code error = boost::asio::error::host_not_found; m_Socket->close(); - m_Socket->connect(m_Endpoint,error); + m_Socket->connect(m_Endpoint, error); LOG_INFO(error.message().c_str()); + if (!error) { + Packet packet(MessageType::Connect, m_SendPacketID); + packet.WriteString(m_PlayerName); + m_StartPingTime = std::clock(); + send(packet); + } } } - +// TODO FIX CRASH TCP CLIENT SEVER DISCONNECTS FIRST void TCPClient::readFromServer() -{ - +{ + while (m_Socket->available()) { + bytesRead = receive(readBuffer); + Packet packet(readBuffer, bytesRead); + parseMessageType(packet); + } } int TCPClient::receive(char * data) { - return 0; + boost::system::error_code error; + // Read size of packet + int bytesReceived = m_Socket->read_some(boost + ::asio::buffer((void*)data, sizeof(int)), + error); + int sizeOfPacket = 0; + memcpy(&sizeOfPacket, data, sizeof(int)); + + // Read the rest of the message + bytesReceived += m_Socket->read_some(boost + ::asio::buffer((void*)(data + bytesReceived), sizeOfPacket - bytesReceived), + error); + // Network Debug data + if (isReadingData) { + m_NetworkData.TotalDataReceived += bytesReceived; + m_NetworkData.DataReceivedThisInterval += bytesReceived; + m_NetworkData.AmountOfMessagesReceived++; + } + if (error) { + //LOG_ERROR("receive: %s", error.message().c_str()); + } + return bytesReceived; } void TCPClient::send(Packet & packet) -{ +{ + packet.UpdateSize(); m_Socket->send(boost::asio::buffer( packet.Data(), packet.Size())); diff --git a/src/Engine/Network/TCPServer.cpp b/src/Engine/Network/TCPServer.cpp index 930e7913..caf37ee8 100644 --- a/src/Engine/Network/TCPServer.cpp +++ b/src/Engine/Network/TCPServer.cpp @@ -11,11 +11,6 @@ TCPServer::~TCPServer() } -void TCPServer::Start(World* world, EventBroker* eventBroker) -{ - Server::Start(world, eventBroker); -} - void TCPServer::readFromClients() { acceptNewConnections(); @@ -24,6 +19,11 @@ void TCPServer::readFromClients() try { bytesRead = receive(readBuffer, *kv.second.TCPSocket); lastReceivedSocket = kv.second.TCPSocket; + // Get logic for mother class + boost::asio::ip::tcp::endpoint remoteEndpoint = kv.second.TCPSocket->remote_endpoint(); + m_Address = remoteEndpoint.address(); + m_Port = remoteEndpoint.port(); + // Recreate packets Packet packet(readBuffer, bytesRead); parseMessageType(packet); } catch (const std::exception& err) { @@ -63,41 +63,48 @@ void TCPServer::acceptNewConnections() void TCPServer::handle_accept(boost::shared_ptr socket, const boost::system::error_code& error) { - if (!error) { + if (!error && GetPlayerIDFromEndpoint() == -1) { // Add tcp socket to connections + boost::asio::ip::tcp::no_delay option(true); + socket->set_option(option); PlayerDefinition pd; pd.StopTime = std::clock(); pd.TCPSocket = socket; + pd.Address = socket.get()->remote_endpoint().address(); + pd.Port = socket.get()->remote_endpoint().port(); m_ConnectedPlayers[m_NextPlayerID++] = pd; } } -void TCPServer::parseClientPing() -{ -} -void TCPServer::parsePing() -{ - -} -void TCPServer::parseDisconnect() -{ - -} void TCPServer::parseConnect(Packet & packet) { + LOG_INFO("Parsing connections"); + // Check if player is already connected + PlayerID playerID = GetPlayerIDFromEndpoint(); + if(playerID = -1){ + return; + } -} -void TCPServer::parseOnInputCommand(Packet & packet) -{ + // Create a new player + m_ConnectedPlayers.at(playerID).EntityID = 0; // Overlook this + m_ConnectedPlayers.at(playerID).Name = packet.ReadString(); + m_ConnectedPlayers.at(playerID).PacketID = 0; + m_ConnectedPlayers.at(playerID).StopTime = std::clock(); + LOG_INFO("Spectator \"%s\" connected on IP: %s", m_ConnectedPlayers.at(playerID).Name.c_str(), m_ConnectedPlayers.at(playerID).Endpoint.address().to_string().c_str()); -} -void TCPServer::parsePlayerTransform(Packet & packet) -{ + // Send a message to the player that connected + Packet connnectPacket(MessageType::Connect, m_ConnectedPlayers.at(playerID).PacketID); + send(connnectPacket); + // Send notification that a player has connected + Packet notificationPacket(MessageType::PlayerConnected); + broadcast(notificationPacket); } + void TCPServer::send(Packet & packet, PlayerDefinition & playerDefinition) { try { + packet.UpdateSize(); int bytesSent = playerDefinition.TCPSocket->send( boost::asio::buffer(packet.Data(), packet.Size()), 0); @@ -115,6 +122,7 @@ void TCPServer::send(Packet & packet, PlayerDefinition & playerDefinition) void TCPServer::send(Packet & packet) { + packet.UpdateSize(); lastReceivedSocket->send( boost::asio::buffer( packet.Data(), @@ -128,21 +136,28 @@ void TCPServer::send(Packet & packet) } //boost::shared_ptr socket -int TCPServer::receive(char * data,boost::asio::ip::tcp::socket& socket) +int TCPServer::receive(char * data, boost::asio::ip::tcp::socket& socket) { - unsigned int length = socket.read_some( - boost::asio::buffer((void*)data, INPUTSIZE)); + boost::system::error_code error; + // Read size of packet + int bytesReceived = socket.read_some(boost + ::asio::buffer((void*)data, sizeof(int)), + error); + int sizeOfPacket = 0; + memcpy(&sizeOfPacket, data, sizeof(int)); + + // Read the rest of the message + bytesReceived += socket.read_some(boost + ::asio::buffer((void*)(data + bytesReceived), sizeOfPacket - bytesReceived), + error); // Network Debug data if (isReadingData) { - m_NetworkData.TotalDataReceived += length; - m_NetworkData.DataReceivedThisInterval += length; + m_NetworkData.TotalDataReceived += bytesReceived; + m_NetworkData.DataReceivedThisInterval += bytesReceived; m_NetworkData.AmountOfMessagesReceived++; } - return length; - -} - -PlayerID TCPServer::GetPlayerIDFromEndpoint(boost::asio::ip::udp::endpoint endpoint) -{ - return PlayerID(); + if (error) { + //LOG_ERROR("receive: %s", error.message().c_str()); + } + return bytesReceived; } \ No newline at end of file diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index 969fa46c..a2bde7cb 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -181,11 +181,13 @@ void Game::networkFunction() bool isServer = m_Config->Get("Networking.IsServer", false); if (!isServer) { m_IsClientOrServer = true; - m_ClientOrServer = new TCPClient(m_Config); + //m_ClientOrServer = new TCPClient(m_Config); + m_ClientOrServer = new HybridClient(m_Config); } if (isServer) { m_IsClientOrServer = true; - m_ClientOrServer = new TCPServer(); + //m_ClientOrServer = new TCPServer(); + m_ClientOrServer = new HybridServer(); } m_ClientOrServer->Start(m_World, m_EventBroker); From ba9419b342918301fc1d521bd6ef9faa8b9fef69 Mon Sep 17 00:00:00 2001 From: Jocke Date: Mon, 8 Feb 2016 14:32:00 +0100 Subject: [PATCH 04/18] Moved UDP logic from Hybrid server/client to UDP server/client. fixed bug in Server::CheckForTimeOuts. --- include/Engine/Network/HybridClient.h | 16 +--- include/Engine/Network/HybridServer.h | 15 +--- include/Engine/Network/TCPClient.h | 3 +- include/Engine/Network/TCPServer.h | 6 +- include/Engine/Network/UDPClient.h | 24 +++++ include/Engine/Network/UDPServer.h | 25 ++++++ include/Game/Game.h | 5 ++ src/Engine/Network/Client.cpp | 3 +- src/Engine/Network/HybridClient.cpp | 66 +------------- src/Engine/Network/HybridServer.cpp | 117 +----------------------- src/Engine/Network/Server.cpp | 7 +- src/Engine/Network/TCPClient.cpp | 15 ++-- src/Engine/Network/TCPServer.cpp | 2 - src/Engine/Network/UDPClient.cpp | 66 ++++++++++++++ src/Engine/Network/UDPServer.cpp | 123 ++++++++++++++++++++++++++ src/Game/Game.cpp | 8 +- 16 files changed, 271 insertions(+), 230 deletions(-) create mode 100644 include/Engine/Network/UDPClient.h create mode 100644 include/Engine/Network/UDPServer.h create mode 100644 src/Engine/Network/UDPClient.cpp create mode 100644 src/Engine/Network/UDPServer.cpp diff --git a/include/Engine/Network/HybridClient.h b/include/Engine/Network/HybridClient.h index fb2777d4..8d96bf6e 100644 --- a/include/Engine/Network/HybridClient.h +++ b/include/Engine/Network/HybridClient.h @@ -1,25 +1,13 @@ #ifndef HybridClient_h__ #define HybridClient_h__ -#include "Client.h" - - -class HybridClient : public Client +class HybridClient { public: - HybridClient(ConfigFile* config); + HybridClient(); ~HybridClient(); - void Start(World* world, EventBroker* eventBroker); private: - // Assio UDP logic - boost::asio::ip::udp::endpoint m_ReceiverEndpoint; - boost::asio::io_service m_IOService; - boost::asio::ip::udp::socket m_Socket; - void connect(); - void readFromServer(); - int receive(char * data); - void send(Packet & packet); }; #endif \ No newline at end of file diff --git a/include/Engine/Network/HybridServer.h b/include/Engine/Network/HybridServer.h index f12dc660..48d6fe63 100644 --- a/include/Engine/Network/HybridServer.h +++ b/include/Engine/Network/HybridServer.h @@ -1,25 +1,12 @@ #ifndef HybridServer_h__ #define HybridServer_h__ -#include "Server.h" -#include - -class HybridServer : public Server +class HybridServer { public: HybridServer(); ~HybridServer(); private: - // UDP logic - boost::asio::io_service m_IOService; - std::unique_ptr m_Socket; - boost::asio::ip::udp::endpoint m_ReceiverEndpoint; - - void readFromClients(); - void parseConnect(Packet & packet); - void send(Packet & packet, PlayerDefinition & playerDefinition); - void send(Packet & packet); - int receive(char * data); }; #endif \ No newline at end of file diff --git a/include/Engine/Network/TCPClient.h b/include/Engine/Network/TCPClient.h index e90e049c..b16d541d 100644 --- a/include/Engine/Network/TCPClient.h +++ b/include/Engine/Network/TCPClient.h @@ -8,12 +8,11 @@ class TCPClient : public Client public: TCPClient(ConfigFile* config); ~TCPClient(); - void Start(World* world, EventBroker* eventBroker); private: // Assio TCP logic boost::asio::ip::tcp::endpoint m_Endpoint; boost::asio::io_service m_IOService; - boost::shared_ptr m_Socket; + std::unique_ptr m_Socket; void connect(); void readFromServer(); diff --git a/include/Engine/Network/TCPServer.h b/include/Engine/Network/TCPServer.h index 61e40639..6c52d10d 100644 --- a/include/Engine/Network/TCPServer.h +++ b/include/Engine/Network/TCPServer.h @@ -13,14 +13,14 @@ private: boost::asio::io_service m_IOService; std::unique_ptr acceptor; boost::shared_ptr lastReceivedSocket; - - void readFromClients(); + void acceptNewConnections(); void handle_accept(boost::shared_ptr socket, const boost::system::error_code & error); + void readFromClients(); + int receive(char * data, boost::asio::ip::tcp::socket& socket); void parseConnect(Packet & packet); void send(Packet & packet, PlayerDefinition & playerDefinition); void send(Packet & packet); - int receive(char * data, boost::asio::ip::tcp::socket& socket); }; #endif \ No newline at end of file diff --git a/include/Engine/Network/UDPClient.h b/include/Engine/Network/UDPClient.h new file mode 100644 index 00000000..abe34b3a --- /dev/null +++ b/include/Engine/Network/UDPClient.h @@ -0,0 +1,24 @@ +#ifndef UDPClient_h__ +#define UDPClient_h__ + +#include "Client.h" + + +class UDPClient : public Client +{ +public: + UDPClient(ConfigFile* config); + ~UDPClient(); +private: + // Assio UDP logic + boost::asio::io_service m_IOService; + boost::asio::ip::udp::endpoint m_ReceiverEndpoint; + boost::asio::ip::udp::socket m_Socket; + + void connect(); + void readFromServer(); + int receive(char * data); + void send(Packet & packet); +}; + +#endif \ No newline at end of file diff --git a/include/Engine/Network/UDPServer.h b/include/Engine/Network/UDPServer.h new file mode 100644 index 00000000..22c8c3e3 --- /dev/null +++ b/include/Engine/Network/UDPServer.h @@ -0,0 +1,25 @@ +#ifndef UDPServer_h__ +#define UDPServer_h__ + +#include "Server.h" +#include + +class UDPServer : public Server +{ +public: + UDPServer(); + ~UDPServer(); +private: + // UDP logic + boost::asio::io_service m_IOService; + boost::asio::ip::udp::endpoint m_ReceiverEndpoint; + std::unique_ptr m_Socket; + + void readFromClients(); + int receive(char * data); + void parseConnect(Packet & packet); + void send(Packet & packet, PlayerDefinition & playerDefinition); + void send(Packet & packet); +}; + +#endif \ No newline at end of file diff --git a/include/Game/Game.h b/include/Game/Game.h index 060f97f4..4faf6bbf 100644 --- a/include/Game/Game.h +++ b/include/Game/Game.h @@ -26,10 +26,15 @@ // Network #include #include "Network/Network.h" +// Hybrid #include "Network/HybridServer.h" #include "Network/HybridClient.h" +// TCP #include "Network/TCPClient.h" #include "Network/TCPServer.h" +// UDP +#include "Network/UDPServer.h" +#include "Network/UDPClient.h" // Sound #include "Sound/SoundSystem.h" diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 13efad40..c7a8f0e6 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -17,7 +17,8 @@ Client::Client(ConfigFile* config) } Client::~Client() -{ } +{ +} void Client::Start(World* world, EventBroker* eventBroker) { diff --git a/src/Engine/Network/HybridClient.cpp b/src/Engine/Network/HybridClient.cpp index eabe109b..4200e8e3 100644 --- a/src/Engine/Network/HybridClient.cpp +++ b/src/Engine/Network/HybridClient.cpp @@ -1,72 +1,10 @@ #include "Network/HybridClient.h" -using namespace boost::asio::ip; -HybridClient::HybridClient(ConfigFile * config) : Client(config), m_Socket(m_IOService) -{ - m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string(address), port); +HybridClient::HybridClient() +{ } HybridClient::~HybridClient() -{ - -} - -void HybridClient::Start(World* world, EventBroker* eventBroker) -{ - Client::Start(world, eventBroker); - m_Socket.connect(m_ReceiverEndpoint); -} - -void HybridClient::readFromServer() { - while (m_Socket.available()) { - bytesRead = receive(readBuffer); - if (bytesRead > 0) { - Packet packet(readBuffer, bytesRead); - parseMessageType(packet); - } - } -} - -int HybridClient::receive(char* data) -{ - boost::system::error_code error; - - int bytesReceived = m_Socket.receive_from(boost - ::asio::buffer((void*)data, BUFFERSIZE), - m_ReceiverEndpoint, - 0, error); - // Network Debug data - if (isReadingData) { - m_NetworkData.TotalDataReceived += bytesReceived; - m_NetworkData.DataReceivedThisInterval += bytesReceived; - m_NetworkData.AmountOfMessagesReceived++; - } - if (error) { - //LOG_ERROR("receive: %s", error.message().c_str()); - } - return bytesReceived; -} - -void HybridClient::send(Packet& packet) -{ - m_Socket.send_to(boost::asio::buffer( - packet.Data(), - packet.Size()), - m_ReceiverEndpoint, 0); - // Network Debug data - if (isReadingData) { - m_NetworkData.TotalDataSent += packet.Size(); - m_NetworkData.DataSentThisInterval += packet.Size(); - m_NetworkData.AmountOfMessagesSent++; - } -} - -void HybridClient::connect() -{ - Packet packet(MessageType::Connect, m_SendPacketID); - packet.WriteString(m_PlayerName); - m_StartPingTime = std::clock(); - send(packet); } \ No newline at end of file diff --git a/src/Engine/Network/HybridServer.cpp b/src/Engine/Network/HybridServer.cpp index 6c22bab7..bfcdaee0 100644 --- a/src/Engine/Network/HybridServer.cpp +++ b/src/Engine/Network/HybridServer.cpp @@ -2,123 +2,8 @@ HybridServer::HybridServer() { - m_Socket = std::unique_ptr(new boost::asio::ip::udp::socket(m_IOService, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 27666))); - } HybridServer::~HybridServer() -{ } - - -void HybridServer::readFromClients() { - while (m_Socket->available()) { - try { - bytesRead = receive(readBuffer); - m_Address = m_ReceiverEndpoint.address(); - m_Port = m_ReceiverEndpoint.port(); - Packet packet(readBuffer, bytesRead); - parseMessageType(packet); - } catch (const std::exception& err) { - //LOG_ERROR("%i: Read from client crashed %s", m_PacketID, err.what()); - } - } - std::clock_t currentTime = std::clock(); - // Send snapshot - if (snapshotInterval < (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC)) { - sendSnapshot(); - previousSnapshotMessage = currentTime; - } - - // Send pings each - if (pingIntervalMs < (1000 * (currentTime - previousePingMessage) / (double)CLOCKS_PER_SEC)) { - sendPing(); - previousePingMessage = currentTime; - } - - // Time out logic - if (checkTimeOutInterval < (1000 * (currentTime - timOutTimer) / (double)CLOCKS_PER_SEC)) { - checkForTimeOuts(); - timOutTimer = currentTime; - } -} - -void HybridServer::parseConnect(Packet& packet) -{ - LOG_INFO("Parsing connections"); - // Check if player is already connected - if (GetPlayerIDFromEndpoint() != -1) { - return; - } - // Create a new player - PlayerDefinition pd; - pd.EntityID = 0; // Overlook this - pd.Endpoint = m_ReceiverEndpoint; - pd.Address = m_ReceiverEndpoint.address(); - pd.Port = m_ReceiverEndpoint.port(); - pd.Name = packet.ReadString(); - pd.PacketID = 0; - pd.StopTime = std::clock(); - m_ConnectedPlayers[m_NextPlayerID++] = pd; - LOG_INFO("Spectator \"%s\" connected on IP: %s", pd.Name.c_str(), pd.Endpoint.address().to_string().c_str()); - - // Send a message to the player that connected - Packet connnectPacket(MessageType::Connect, pd.PacketID); - send(connnectPacket); - - // Send notification that a player has connected - Packet notificationPacket(MessageType::PlayerConnected); - broadcast(notificationPacket); -} - -void HybridServer::send(Packet& packet, PlayerDefinition & playerDefinition) -{ - try { - int bytesSent = m_Socket->send_to( - boost::asio::buffer(packet.Data(), packet.Size()), - playerDefinition.Endpoint, - 0); - // Network Debug data - if (isReadingData) { - m_NetworkData.TotalDataSent += packet.Size(); - m_NetworkData.DataSentThisInterval += packet.Size(); - m_NetworkData.AmountOfMessagesSent++; - } - } catch (const boost::system::system_error& e) { - // TODO: Clean up invalid endpoints out of m_ConnectedPlayers later - playerDefinition.Endpoint = boost::asio::ip::udp::endpoint(); - } -} -// Send back to endpoint of received packet -void HybridServer::send(Packet & packet) -{ - m_Socket->send_to( - boost::asio::buffer( - packet.Data(), - packet.Size()), - m_ReceiverEndpoint, - 0); - if (isReadingData) { - // Network Debug data - m_NetworkData.TotalDataSent += packet.Size(); - m_NetworkData.DataSentThisInterval += packet.Size(); - } -} - - -int HybridServer::receive(char * data) -{ - unsigned int length = m_Socket->receive_from( - boost::asio::buffer((void*)data - , BUFFERSIZE) - , m_ReceiverEndpoint, 0); - // Network Debug data - if (isReadingData) { - m_NetworkData.TotalDataReceived += length; - m_NetworkData.DataReceivedThisInterval += length; - m_NetworkData.AmountOfMessagesReceived++; - } - return length; -} - - +} \ No newline at end of file diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index 55f59a03..344efba6 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -9,7 +9,6 @@ Server::Server() } Server::~Server() { - } void Server::Start(World* world, EventBroker* eventBroker) { @@ -154,16 +153,20 @@ void Server::checkForTimeOuts() int startPing = 1000 * m_StartPingTime / static_cast(CLOCKS_PER_SEC); + std::vector playersToRemove; for (auto& kv : m_ConnectedPlayers) { if (kv.second.Address != boost::asio::ip::address()) { int stopPing = 1000 * kv.second.StopTime / static_cast(CLOCKS_PER_SEC); if (startPing > stopPing + m_TimeoutMs) { LOG_INFO("User %i timed out!", kv.second.Name); - disconnect(kv.first); + playersToRemove.push_back(kv.first); } } } + for (size_t i = 0; i < playersToRemove.size(); i++) { + disconnect(playersToRemove.at(i)); + } } void Server::parseDisconnect() diff --git a/src/Engine/Network/TCPClient.cpp b/src/Engine/Network/TCPClient.cpp index 3d7261b7..545db491 100644 --- a/src/Engine/Network/TCPClient.cpp +++ b/src/Engine/Network/TCPClient.cpp @@ -5,7 +5,7 @@ using namespace boost::asio::ip; TCPClient::TCPClient(ConfigFile * config) : Client(config) { m_Endpoint = tcp::endpoint(boost::asio::ip::address::from_string(address), port); - m_Socket = boost::shared_ptr(new tcp::socket(m_IOService, m_Endpoint)); + m_Socket = std::unique_ptr(new tcp::socket(m_IOService, m_Endpoint)); tcp::no_delay option(true); m_Socket->set_option(option); } @@ -15,10 +15,6 @@ TCPClient::~TCPClient() } -void TCPClient::Start(World * world, EventBroker * eventBroker) -{ - Client::Start(world, eventBroker); -} void TCPClient::connect() { if (!m_IsConnected) { @@ -34,7 +30,7 @@ void TCPClient::connect() } } } -// TODO FIX CRASH TCP CLIENT SEVER DISCONNECTS FIRST + void TCPClient::readFromServer() { while (m_Socket->available()) { @@ -50,14 +46,14 @@ int TCPClient::receive(char * data) // Read size of packet int bytesReceived = m_Socket->read_some(boost ::asio::buffer((void*)data, sizeof(int)), - error); + error); int sizeOfPacket = 0; memcpy(&sizeOfPacket, data, sizeof(int)); // Read the rest of the message bytesReceived += m_Socket->read_some(boost ::asio::buffer((void*)(data + bytesReceived), sizeOfPacket - bytesReceived), - error); + error); // Network Debug data if (isReadingData) { m_NetworkData.TotalDataReceived += bytesReceived; @@ -73,9 +69,10 @@ int TCPClient::receive(char * data) void TCPClient::send(Packet & packet) { packet.UpdateSize(); + boost::system::error_code error; m_Socket->send(boost::asio::buffer( packet.Data(), - packet.Size())); + packet.Size()), 0, error); // Network Debug data if (isReadingData) { m_NetworkData.TotalDataSent += packet.Size(); diff --git a/src/Engine/Network/TCPServer.cpp b/src/Engine/Network/TCPServer.cpp index caf37ee8..d523bf47 100644 --- a/src/Engine/Network/TCPServer.cpp +++ b/src/Engine/Network/TCPServer.cpp @@ -8,7 +8,6 @@ TCPServer::TCPServer() TCPServer::~TCPServer() { - } void TCPServer::readFromClients() @@ -135,7 +134,6 @@ void TCPServer::send(Packet & packet) } } -//boost::shared_ptr socket int TCPServer::receive(char * data, boost::asio::ip::tcp::socket& socket) { boost::system::error_code error; diff --git a/src/Engine/Network/UDPClient.cpp b/src/Engine/Network/UDPClient.cpp new file mode 100644 index 00000000..26e895d5 --- /dev/null +++ b/src/Engine/Network/UDPClient.cpp @@ -0,0 +1,66 @@ +#include "Network/UDPClient.h" + +using namespace boost::asio::ip; + +UDPClient::UDPClient(ConfigFile * config) : Client(config), m_Socket(m_IOService) +{ + m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string(address), port); + m_Socket.connect(m_ReceiverEndpoint); +} + +UDPClient::~UDPClient() +{ +} + +void UDPClient::readFromServer() +{ + while (m_Socket.available()) { + bytesRead = receive(readBuffer); + if (bytesRead > 0) { + Packet packet(readBuffer, bytesRead); + parseMessageType(packet); + } + } +} + +int UDPClient::receive(char* data) +{ + boost::system::error_code error; + + int bytesReceived = m_Socket.receive_from(boost + ::asio::buffer((void*)data, BUFFERSIZE), + m_ReceiverEndpoint, + 0, error); + // Network Debug data + if (isReadingData) { + m_NetworkData.TotalDataReceived += bytesReceived; + m_NetworkData.DataReceivedThisInterval += bytesReceived; + m_NetworkData.AmountOfMessagesReceived++; + } + if (error) { + //LOG_ERROR("receive: %s", error.message().c_str()); + } + return bytesReceived; +} + +void UDPClient::send(Packet& packet) +{ + m_Socket.send_to(boost::asio::buffer( + packet.Data(), + packet.Size()), + m_ReceiverEndpoint, 0); + // Network Debug data + if (isReadingData) { + m_NetworkData.TotalDataSent += packet.Size(); + m_NetworkData.DataSentThisInterval += packet.Size(); + m_NetworkData.AmountOfMessagesSent++; + } +} + +void UDPClient::connect() +{ + Packet packet(MessageType::Connect, m_SendPacketID); + packet.WriteString(m_PlayerName); + m_StartPingTime = std::clock(); + send(packet); +} \ No newline at end of file diff --git a/src/Engine/Network/UDPServer.cpp b/src/Engine/Network/UDPServer.cpp new file mode 100644 index 00000000..1e62c10a --- /dev/null +++ b/src/Engine/Network/UDPServer.cpp @@ -0,0 +1,123 @@ +#include "Network/UDPServer.h" + +UDPServer::UDPServer() +{ + m_Socket = std::unique_ptr(new boost::asio::ip::udp::socket(m_IOService, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 27666))); +} + +UDPServer::~UDPServer() +{ +} + +void UDPServer::readFromClients() +{ + while (m_Socket->available()) { + try { + bytesRead = receive(readBuffer); + m_Address = m_ReceiverEndpoint.address(); + m_Port = m_ReceiverEndpoint.port(); + Packet packet(readBuffer, bytesRead); + parseMessageType(packet); + } catch (const std::exception& err) { + //LOG_ERROR("%i: Read from client crashed %s", m_PacketID, err.what()); + } + } + std::clock_t currentTime = std::clock(); + // Send snapshot + if (snapshotInterval < (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC)) { + sendSnapshot(); + previousSnapshotMessage = currentTime; + } + + // Send pings each + if (pingIntervalMs < (1000 * (currentTime - previousePingMessage) / (double)CLOCKS_PER_SEC)) { + sendPing(); + previousePingMessage = currentTime; + } + + // Time out logic + if (checkTimeOutInterval < (1000 * (currentTime - timOutTimer) / (double)CLOCKS_PER_SEC)) { + checkForTimeOuts(); + timOutTimer = currentTime; + } +} + +void UDPServer::parseConnect(Packet& packet) +{ + LOG_INFO("Parsing connections"); + // Check if player is already connected + if (GetPlayerIDFromEndpoint() != -1) { + return; + } + // Create a new player + PlayerDefinition pd; + pd.EntityID = 0; // Overlook this + pd.Endpoint = m_ReceiverEndpoint; + pd.Address = m_ReceiverEndpoint.address(); + pd.Port = m_ReceiverEndpoint.port(); + pd.Name = packet.ReadString(); + pd.PacketID = 0; + pd.StopTime = std::clock(); + m_ConnectedPlayers[m_NextPlayerID++] = pd; + LOG_INFO("Spectator \"%s\" connected on IP: %s", pd.Name.c_str(), pd.Endpoint.address().to_string().c_str()); + + // Send a message to the player that connected + Packet connnectPacket(MessageType::Connect, pd.PacketID); + send(connnectPacket); + + // Send notification that a player has connected + Packet notificationPacket(MessageType::PlayerConnected); + broadcast(notificationPacket); +} + +void UDPServer::send(Packet& packet, PlayerDefinition & playerDefinition) +{ + try { + int bytesSent = m_Socket->send_to( + boost::asio::buffer(packet.Data(), packet.Size()), + playerDefinition.Endpoint, + 0); + // Network Debug data + if (isReadingData) { + m_NetworkData.TotalDataSent += packet.Size(); + m_NetworkData.DataSentThisInterval += packet.Size(); + m_NetworkData.AmountOfMessagesSent++; + } + } catch (const boost::system::system_error& e) { + // TODO: Clean up invalid endpoints out of m_ConnectedPlayers later + playerDefinition.Endpoint = boost::asio::ip::udp::endpoint(); + } +} +// Send back to endpoint of received packet +void UDPServer::send(Packet & packet) +{ + m_Socket->send_to( + boost::asio::buffer( + packet.Data(), + packet.Size()), + m_ReceiverEndpoint, + 0); + if (isReadingData) { + // Network Debug data + m_NetworkData.TotalDataSent += packet.Size(); + m_NetworkData.DataSentThisInterval += packet.Size(); + } +} + + +int UDPServer::receive(char * data) +{ + unsigned int length = m_Socket->receive_from( + boost::asio::buffer((void*)data + , BUFFERSIZE) + , m_ReceiverEndpoint, 0); + // Network Debug data + if (isReadingData) { + m_NetworkData.TotalDataReceived += length; + m_NetworkData.DataReceivedThisInterval += length; + m_NetworkData.AmountOfMessagesReceived++; + } + return length; +} + + diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index a2bde7cb..ccbf79c9 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -181,13 +181,15 @@ void Game::networkFunction() bool isServer = m_Config->Get("Networking.IsServer", false); if (!isServer) { m_IsClientOrServer = true; + m_ClientOrServer = new UDPClient(m_Config); //m_ClientOrServer = new TCPClient(m_Config); - m_ClientOrServer = new HybridClient(m_Config); + //m_ClientOrServer = new HybridClient(m_Config); } if (isServer) { m_IsClientOrServer = true; - //m_ClientOrServer = new TCPServer(); - m_ClientOrServer = new HybridServer(); + m_ClientOrServer = new UDPServer(); + // m_ClientOrServer = new TCPServer(); + //m_ClientOrServer = new HybridServer(); } m_ClientOrServer->Start(m_World, m_EventBroker); From fccd8c64e789803aab305203137da46e3af6871d Mon Sep 17 00:00:00 2001 From: Jocke Date: Tue, 9 Feb 2016 11:43:16 +0100 Subject: [PATCH 05/18] WIP Clients are working properly, servers are not. --- include/Engine/Network/Client.h | 11 ++-- include/Engine/Network/MessageType.h | 3 +- include/Engine/Network/Network.h | 2 + include/Engine/Network/NetworkClient.h | 21 ++++++++ include/Engine/Network/NetworkServer.h | 20 +++++++ include/Engine/Network/Packet.h | 5 ++ include/Engine/Network/TCPClient.h | 25 ++++++--- include/Engine/Network/UDPClient.h | 27 ++++++---- include/Game/Game.h | 4 ++ src/Engine/Network/Client.cpp | 33 +++++++----- src/Engine/Network/Network.cpp | 15 ++++++ src/Engine/Network/NetworkClient.cpp | 0 src/Engine/Network/Packet.cpp | 41 +++++++++++---- src/Engine/Network/Server.cpp | 21 ++++++-- src/Engine/Network/TCPClient.cpp | 66 ++++++++++++----------- src/Engine/Network/TCPServer.cpp | 24 +-------- src/Engine/Network/UDPClient.cpp | 72 ++++++++++++++------------ src/Engine/Network/UDPServer.cpp | 21 +------- src/Game/Game.cpp | 32 ++++++++---- 19 files changed, 277 insertions(+), 166 deletions(-) create mode 100644 include/Engine/Network/NetworkClient.h create mode 100644 include/Engine/Network/NetworkServer.h create mode 100644 src/Engine/Network/NetworkClient.cpp diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index 5259504b..0c9608ff 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -13,6 +13,8 @@ #include "Network/Network.h" #include "Network/MessageType.h" #include "Network/PlayerDefinition.h" +#include "Network/UDPClient.h" +#include "Network/TCPClient.h" #include "Network/SnapshotDefinitions.h" #include "Core/World.h" #include "Core/EventBroker.h" @@ -35,7 +37,6 @@ protected: int port = 0; // Sending message to server logic int bytesRead = -1; - char readBuffer[BUFFERSIZE] = { 0 }; // Packet loss logic PacketID m_PacketID = 0; @@ -66,9 +67,6 @@ protected: std::vector m_InputCommandBuffer; // Private member functions - virtual void send(Packet& packet) = 0; - virtual void readFromServer() = 0; - virtual void connect() = 0; void disconnect(); void parseMessageType(Packet& packet); void updateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID, const std::string& componentType); @@ -103,6 +101,11 @@ protected: bool OnPlayerDamage(const Events::PlayerDamage& e); EventRelay m_EPlayerSpawned; bool OnPlayerSpawned(const Events::PlayerSpawned& e); + +private: + //UDPClient m_UDPClient; + //TCPClient m_TCPClient; + TCPClient m_UDPClient; }; #endif diff --git a/include/Engine/Network/MessageType.h b/include/Engine/Network/MessageType.h index 85f22649..a72f054e 100644 --- a/include/Engine/Network/MessageType.h +++ b/include/Engine/Network/MessageType.h @@ -18,7 +18,8 @@ enum class MessageType OnPlayerSpawned, EntityDeleted, ComponentDeleted, - PlayerTransform + PlayerTransform, + Invalid }; #endif diff --git a/include/Engine/Network/Network.h b/include/Engine/Network/Network.h index caf55f13..7f292b1a 100644 --- a/include/Engine/Network/Network.h +++ b/include/Engine/Network/Network.h @@ -30,6 +30,8 @@ protected: std::clock_t m_SaveDataTimer; unsigned int m_MaxConnections; unsigned int m_TimeoutMs; + void logSentData(int bytesSent); + void logReceivedData(int bytesReceived); void saveToFile(); void updateNetworkData(); void initialize(); diff --git a/include/Engine/Network/NetworkClient.h b/include/Engine/Network/NetworkClient.h new file mode 100644 index 00000000..4c623209 --- /dev/null +++ b/include/Engine/Network/NetworkClient.h @@ -0,0 +1,21 @@ +#ifndef NetworkClient_h__ +#define NetworkClient_h__ + +#include "Network/Packet.h" +#define BUFFERSIZE 32000 +typedef unsigned int PlayerID; +typedef unsigned int PacketID; + +class NetworkClient +{ +public: + virtual void Connect(std::string playerName, std::string address, int port) = 0; + virtual void Disconnect() = 0; + virtual void Receive(Packet& packet) = 0; + virtual void Send(Packet & packet) = 0; + virtual bool IsSocketAvailable() = 0; +protected: + char m_ReadBuffer[BUFFERSIZE] = { 0 }; +}; + +#endif \ No newline at end of file diff --git a/include/Engine/Network/NetworkServer.h b/include/Engine/Network/NetworkServer.h new file mode 100644 index 00000000..1586693d --- /dev/null +++ b/include/Engine/Network/NetworkServer.h @@ -0,0 +1,20 @@ +#ifndef NetworkServer_h__ +#define NetworkServer_h__ + +#include "Network/Packet.h" +#define BUFFERSIZE 32000 +typedef unsigned int PlayerID; +typedef unsigned int PacketID; + +class NetworkServer +{ +//public: +// virtual void Connect(std::string playerName, std::string address, int port) = 0; +// virtual void Disconnect() = 0; +// virtual Packet Receive() = 0; +// virtual void Send(Packet & packet) = 0; +//protected: +// char m_ReadBuffer[BUFFERSIZE] = { 0 }; +}; + +#endif \ No newline at end of file diff --git a/include/Engine/Network/Packet.h b/include/Engine/Network/Packet.h index b7e774c2..e88747b8 100644 --- a/include/Engine/Network/Packet.h +++ b/include/Engine/Network/Packet.h @@ -49,12 +49,15 @@ public: void WriteData(char* data, int sizeOfData); // Pops the first element as if it was a string. std::string ReadString(); + // Construct a packet + void ReconstructFromData(char* data, int SizeOfData); // Update size of packet variable in header void UpdateSize(); char* ReadData(int SizeOfData); void ChangePacketID(unsigned int& packetID); int Size() { return m_Offset; }; char* Data() { return m_Data; }; + MessageType GetMessageType() { return m_MessageType; }; unsigned int DataReadSize() { return m_ReturnDataOffset; } unsigned int MaxSize() { return m_MaxPacketSize; } unsigned int HeaderSize() { return m_HeaderSize; } @@ -65,7 +68,9 @@ private: int m_Offset = 0; unsigned int m_MaxPacketSize = 512; unsigned int m_HeaderSize = 0; + MessageType m_MessageType = MessageType::Invalid; void resizeData(); + void resizeData(int size); }; #endif \ No newline at end of file diff --git a/include/Engine/Network/TCPClient.h b/include/Engine/Network/TCPClient.h index b16d541d..ff10b63a 100644 --- a/include/Engine/Network/TCPClient.h +++ b/include/Engine/Network/TCPClient.h @@ -1,23 +1,32 @@ #ifndef TCPClient_h__ #define TCPClient_h__ -#include "Client.h" +#include +#include "NetworkClient.h" -class TCPClient : public Client +class TCPClient : public NetworkClient { public: - TCPClient(ConfigFile* config); + TCPClient(); ~TCPClient(); + + void Connect(std::string playerName, std::string address, int port); + void Disconnect(); + void Receive(Packet& packet); + void Send(Packet & packet); + bool IsSocketAvailable(); private: + // Assio UDP logic + //boost::asio::io_service m_IOService; + //boost::asio::ip::udp::endpoint m_ReceiverEndpoint; + //boost::shared_ptr m_Socket; // Assio TCP logic boost::asio::ip::tcp::endpoint m_Endpoint; boost::asio::io_service m_IOService; std::unique_ptr m_Socket; - - void connect(); - void readFromServer(); - int receive(char * data); - void send(Packet & packet); + int readBuffer(char* data); + PacketID m_SendPacketID = 0; + bool m_IsConnected = false; }; #endif \ No newline at end of file diff --git a/include/Engine/Network/UDPClient.h b/include/Engine/Network/UDPClient.h index abe34b3a..ca369f6b 100644 --- a/include/Engine/Network/UDPClient.h +++ b/include/Engine/Network/UDPClient.h @@ -1,24 +1,31 @@ #ifndef UDPClient_h__ #define UDPClient_h__ -#include "Client.h" +#include +#include "Network/NetworkClient.h" +//virtual void Connect(std::string address, int port) = 0; +//virtual int Receive(char * data) = 0; +//virtual void Send(Packet & packet) = 0; +//virtual void Disconnect() = 0; - -class UDPClient : public Client +class UDPClient : public NetworkClient { public: - UDPClient(ConfigFile* config); + UDPClient(); ~UDPClient(); + + void Connect(std::string playerName, std::string address, int port); + void Disconnect(); + void Receive(Packet& packet); + void Send(Packet & packet); + bool IsSocketAvailable(); private: // Assio UDP logic boost::asio::io_service m_IOService; boost::asio::ip::udp::endpoint m_ReceiverEndpoint; - boost::asio::ip::udp::socket m_Socket; - - void connect(); - void readFromServer(); - int receive(char * data); - void send(Packet & packet); + boost::shared_ptr m_Socket; + int readBuffer(char* data); + PacketID m_SendPacketID = 0; }; #endif \ No newline at end of file diff --git a/include/Game/Game.h b/include/Game/Game.h index 4faf6bbf..54b8c753 100644 --- a/include/Game/Game.h +++ b/include/Game/Game.h @@ -26,6 +26,8 @@ // Network #include #include "Network/Network.h" +// Client +#include "Network/Client.h" // Hybrid #include "Network/HybridServer.h" #include "Network/HybridClient.h" @@ -68,7 +70,9 @@ private: // Network methods void networkFunction(); Network* m_ClientOrServer; + std::unique_ptr m_Client; bool m_IsClientOrServer = false; + bool m_IsServer = false; // Sound SoundSystem* m_SoundSystem; diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index c7a8f0e6..eaacac47 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -17,8 +17,7 @@ Client::Client(ConfigFile* config) } Client::~Client() -{ -} +{ } void Client::Start(World* world, EventBroker* eventBroker) { @@ -35,17 +34,23 @@ void Client::Start(World* world, EventBroker* eventBroker) void Client::Update() { m_EventBroker->Process(); - readFromServer(); + while (m_UDPClient.IsSocketAvailable()) { + // Packet will get real data in receive + Packet packet(MessageType::Invalid); + m_UDPClient.Receive(packet); + parseMessageType(packet); + } + if (m_IsConnected) { hasServerTimedOut(); - // Don't sent 1 input in 1 packet, bunch em up. + // Don't send 1 input in 1 packet, bunch em up. if (m_SendInputIntervalMs < (1000 * (std::clock() - m_TimeSinceSentInputs) / (double)CLOCKS_PER_SEC)) { sendInputCommands(); m_TimeSinceSentInputs = std::clock(); } sendLocalPlayerTransform(); } - Network::Update(); + //Network::Update(); } void Client::parseMessageType(Packet& packet) @@ -59,7 +64,7 @@ void Client::parseMessageType(Packet& packet) // Read packet ID m_PreviousPacketID = m_PacketID; // Set previous packet id m_PacketID = packet.ReadPrimitive(); //Read new packet id - identifyPacketLoss(); + //identifyPacketLoss(); switch (static_cast(messageType)) { case MessageType::Connect: @@ -118,7 +123,7 @@ void Client::parsePing() Packet packet(MessageType::Ping, m_SendPacketID); packet.WriteString("Ping recieved"); - send(packet); + m_UDPClient.Send(packet); } void Client::parseKick() @@ -250,14 +255,14 @@ void Client::disconnect() m_PreviousPacketID = 0; m_PacketID = 0; Packet packet(MessageType::Disconnect, m_SendPacketID); - send(packet); + m_UDPClient.Send(packet); } bool Client::OnInputCommand(const Events::InputCommand & e) { if (e.Command == "ConnectToServer") { // Connect for now if (e.Value > 0) { - connect(); + m_UDPClient.Connect(m_PlayerName, address, port); } //LOG_DEBUG("Client::OnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID); return true; @@ -280,7 +285,7 @@ bool Client::OnInputCommand(const Events::InputCommand & e) m_SaveDataTimer = std::clock(); } } else { - if (m_IsConnected) { + if (m_IsConnected) { m_InputCommandBuffer.push_back(e); } //LOG_DEBUG("Client::OnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID); @@ -294,7 +299,7 @@ bool Client::OnPlayerDamage(const Events::PlayerDamage & e) Packet packet(MessageType::OnPlayerDamage, m_SendPacketID); packet.WritePrimitive(e.Damage); packet.WritePrimitive(m_ClientIDToServerID.at(e.Player.ID)); - send(packet); + m_UDPClient.Send(packet); return false; } @@ -322,7 +327,7 @@ void Client::sendLocalPlayerTransform() packet.WritePrimitive(orientation.x); packet.WritePrimitive(orientation.y); packet.WritePrimitive(orientation.z); - send(packet); + m_UDPClient.Send(packet); } void Client::identifyPacketLoss() @@ -365,7 +370,7 @@ void Client::sendInputCommands() packet.WriteString(m_InputCommandBuffer[i].Command); packet.WritePrimitive(m_InputCommandBuffer[i].Value); } - send(packet); + m_UDPClient.Send(packet); m_InputCommandBuffer.clear(); } } @@ -373,7 +378,7 @@ void Client::sendInputCommands() void Client::becomePlayer() { Packet packet = Packet(MessageType::BecomePlayer, m_SendPacketID); - send(packet); + m_UDPClient.Send(packet); } bool Client::clientServerMapsHasEntity(EntityID clientEntityID) diff --git a/src/Engine/Network/Network.cpp b/src/Engine/Network/Network.cpp index f4dcd1a2..db54a12e 100644 --- a/src/Engine/Network/Network.cpp +++ b/src/Engine/Network/Network.cpp @@ -5,6 +5,21 @@ void Network::Update() updateNetworkData(); } +void Network::logSentData(int bytesSent) +{ + +} + +void Network::logReceivedData(int bytesReceived) +{ + // Network Debug data + if (isReadingData) { + m_NetworkData.TotalDataReceived += bytesReceived; + m_NetworkData.DataReceivedThisInterval += bytesReceived; + m_NetworkData.AmountOfMessagesReceived++; + } +} + void Network::saveToFile() { std::ofstream outfile; diff --git a/src/Engine/Network/NetworkClient.cpp b/src/Engine/Network/NetworkClient.cpp new file mode 100644 index 00000000..e69de29b diff --git a/src/Engine/Network/Packet.cpp b/src/Engine/Network/Packet.cpp index 28622611..06c81b8f 100644 --- a/src/Engine/Network/Packet.cpp +++ b/src/Engine/Network/Packet.cpp @@ -37,6 +37,7 @@ void Packet::Init(MessageType type, unsigned int & packetID) // allocate memory for size of packet(only used in tcp) Packet::WritePrimitive(0); // Add message type + m_MessageType = type; int messageType = static_cast(type); Packet::WritePrimitive(messageType); Packet::WritePrimitive(packetID); @@ -58,9 +59,12 @@ void Packet::WriteString(const std::string& str) void Packet::WriteData(char * data, int sizeOfData) { + if (m_Offset + sizeOfData > m_MaxPacketSize) { //LOG_WARNING("Packet::WriteData(): Data size in packet exceeded maximum packet size. New size is %i bytes\n", m_MaxPacketSize*2); - resizeData(); + while (m_Offset + sizeOfData > m_MaxPacketSize) { + resizeData(); + } } memcpy(m_Data + m_Offset, data, sizeOfData); m_Offset += sizeOfData; @@ -78,19 +82,34 @@ std::string Packet::ReadString() return returnValue; } +void Packet::ReconstructFromData(char * data, int sizeOfData) +{ + if (sizeOfData > m_MaxPacketSize) { + // Delete our data + delete[] m_Data; + // Set new max size + m_MaxPacketSize = sizeOfData; + m_Data = new char[m_MaxPacketSize]; + // while we resized the old data container. + } + memcpy(m_Data, data, sizeOfData); + m_Offset = sizeOfData; + +} + void Packet::UpdateSize() -{ +{ memcpy(m_Data, &m_Offset, sizeof(int)); } -char * Packet::ReadData(int SizeOfData) +char * Packet::ReadData(int sizeOfData) { - if (m_Offset < m_ReturnDataOffset + SizeOfData) { + if (m_Offset < m_ReturnDataOffset + sizeOfData) { //LOG_WARNING("packet ReadData(): Oh no! You are trying to remove things outside my memory kingdom"); return nullptr; } unsigned int oldReturnDataOffset = m_ReturnDataOffset; - m_ReturnDataOffset += SizeOfData; + m_ReturnDataOffset += sizeOfData; return (m_Data + oldReturnDataOffset); } @@ -103,20 +122,24 @@ void Packet::ChangePacketID(unsigned int & packetID) void Packet::resizeData() { + resizeData(m_MaxPacketSize * 2); +} +void Packet::resizeData(int size) +{ // Allocate memory to store our data in char* holdData = new char[m_MaxPacketSize]; // Copy our data to the newly allocated memory memcpy(holdData, m_Data, m_Offset); // Increase max packet size - m_MaxPacketSize = m_MaxPacketSize * 2; + m_MaxPacketSize = size; // Delete our data - delete m_Data; - // Allocate twice the memory we had before + delete[] m_Data; + // Allocate memory m_Data = new char[m_MaxPacketSize]; // Copy our data to new location memcpy(m_Data, holdData, m_Offset); // Delete the memory allocated to hold our data // while we resized the old data container. - delete holdData; + delete[] holdData; } diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index 344efba6..fa0f1a1a 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -8,8 +8,7 @@ Server::Server() pingIntervalMs = config->Get("Networking.PingIntervalMs", 1000); } Server::~Server() -{ -} +{ } void Server::Start(World* world, EventBroker* eventBroker) { m_World = world; @@ -25,11 +24,27 @@ void Server::Start(World* world, EventBroker* eventBroker) void Server::Update() { readFromClients(); + + std::clock_t currentTime = std::clock(); + // Send snapshot + if (snapshotInterval < (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC)) { + sendSnapshot(); + previousSnapshotMessage = currentTime; + } + // Send pings each + if (pingIntervalMs < (1000 * (currentTime - previousePingMessage) / (double)CLOCKS_PER_SEC)) { + sendPing(); + previousePingMessage = currentTime; + } + // Time out logic + if (checkTimeOutInterval < (1000 * (currentTime - timOutTimer) / (double)CLOCKS_PER_SEC)) { + checkForTimeOuts(); + timOutTimer = currentTime; + } m_EventBroker->Process(); if (isReadingData) { Network::Update(); } - } void Server::parseMessageType(Packet& packet) diff --git a/src/Engine/Network/TCPClient.cpp b/src/Engine/Network/TCPClient.cpp index 545db491..42f724d0 100644 --- a/src/Engine/Network/TCPClient.cpp +++ b/src/Engine/Network/TCPClient.cpp @@ -2,46 +2,55 @@ using namespace boost::asio::ip; -TCPClient::TCPClient(ConfigFile * config) : Client(config) +TCPClient::TCPClient() { - m_Endpoint = tcp::endpoint(boost::asio::ip::address::from_string(address), port); - m_Socket = std::unique_ptr(new tcp::socket(m_IOService, m_Endpoint)); - tcp::no_delay option(true); - m_Socket->set_option(option); } TCPClient::~TCPClient() { - } -void TCPClient::connect() +void TCPClient::Connect(std::string playerName, std::string address, int port) { + if (m_Socket) { + return; + } if (!m_IsConnected) { boost::system::error_code error = boost::asio::error::host_not_found; + m_Endpoint = tcp::endpoint(boost::asio::ip::address::from_string(address), port); + m_Socket = std::unique_ptr(new tcp::socket(m_IOService, m_Endpoint)); + tcp::no_delay option(true); + m_Socket->set_option(option); m_Socket->close(); m_Socket->connect(m_Endpoint, error); LOG_INFO(error.message().c_str()); if (!error) { + m_IsConnected = true; Packet packet(MessageType::Connect, m_SendPacketID); - packet.WriteString(m_PlayerName); - m_StartPingTime = std::clock(); - send(packet); + packet.WriteString(playerName); + Send(packet); } } } -void TCPClient::readFromServer() +void TCPClient::Disconnect() +{ + +} + +void TCPClient::Receive(Packet& packet) { - while (m_Socket->available()) { - bytesRead = receive(readBuffer); - Packet packet(readBuffer, bytesRead); - parseMessageType(packet); + int bytesRead = readBuffer(m_ReadBuffer); + if (bytesRead > 0) { + packet.ReconstructFromData(m_ReadBuffer, bytesRead); } } -int TCPClient::receive(char * data) -{ +int TCPClient::readBuffer(char* data) +{ + if (!m_Socket) { + return 0; + } boost::system::error_code error; // Read size of packet int bytesReceived = m_Socket->read_some(boost @@ -54,29 +63,26 @@ int TCPClient::receive(char * data) bytesReceived += m_Socket->read_some(boost ::asio::buffer((void*)(data + bytesReceived), sizeOfPacket - bytesReceived), error); - // Network Debug data - if (isReadingData) { - m_NetworkData.TotalDataReceived += bytesReceived; - m_NetworkData.DataReceivedThisInterval += bytesReceived; - m_NetworkData.AmountOfMessagesReceived++; - } if (error) { //LOG_ERROR("receive: %s", error.message().c_str()); } return bytesReceived; } -void TCPClient::send(Packet & packet) +void TCPClient::Send(Packet & packet) { packet.UpdateSize(); boost::system::error_code error; m_Socket->send(boost::asio::buffer( packet.Data(), packet.Size()), 0, error); - // Network Debug data - if (isReadingData) { - m_NetworkData.TotalDataSent += packet.Size(); - m_NetworkData.DataSentThisInterval += packet.Size(); - m_NetworkData.AmountOfMessagesSent++; - } + //Network::logSentData(packet.Size()); } + +bool TCPClient::IsSocketAvailable() +{ + if (!m_Socket) { + return false; + } + return m_Socket->available(); +} \ No newline at end of file diff --git a/src/Engine/Network/TCPServer.cpp b/src/Engine/Network/TCPServer.cpp index d523bf47..09d2ce69 100644 --- a/src/Engine/Network/TCPServer.cpp +++ b/src/Engine/Network/TCPServer.cpp @@ -7,8 +7,7 @@ TCPServer::TCPServer() } TCPServer::~TCPServer() -{ -} +{ } void TCPServer::readFromClients() { @@ -30,25 +29,6 @@ void TCPServer::readFromClients() } } } - - std::clock_t currentTime = std::clock(); - // Send snapshot - if (snapshotInterval < (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC)) { - sendSnapshot(); - previousSnapshotMessage = currentTime; - } - - // Send pings each - if (pingIntervalMs < (1000 * (currentTime - previousePingMessage) / (double)CLOCKS_PER_SEC)) { - sendPing(); - previousePingMessage = currentTime; - } - - // Time out logic - if (checkTimeOutInterval < (1000 * (currentTime - timOutTimer) / (double)CLOCKS_PER_SEC)) { - checkForTimeOuts(); - timOutTimer = currentTime; - } } void TCPServer::acceptNewConnections() @@ -80,7 +60,7 @@ void TCPServer::parseConnect(Packet & packet) LOG_INFO("Parsing connections"); // Check if player is already connected PlayerID playerID = GetPlayerIDFromEndpoint(); - if(playerID = -1){ + if (playerID = -1) { return; } diff --git a/src/Engine/Network/UDPClient.cpp b/src/Engine/Network/UDPClient.cpp index 26e895d5..e5eafc08 100644 --- a/src/Engine/Network/UDPClient.cpp +++ b/src/Engine/Network/UDPClient.cpp @@ -2,65 +2,69 @@ using namespace boost::asio::ip; -UDPClient::UDPClient(ConfigFile * config) : Client(config), m_Socket(m_IOService) -{ - m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string(address), port); - m_Socket.connect(m_ReceiverEndpoint); +UDPClient::UDPClient() +{ } UDPClient::~UDPClient() -{ +{ } -void UDPClient::readFromServer() +void UDPClient::Connect(std::string playerName, std::string address, int port) { - while (m_Socket.available()) { - bytesRead = receive(readBuffer); - if (bytesRead > 0) { - Packet packet(readBuffer, bytesRead); - parseMessageType(packet); - } + if (m_Socket) { + return; + } + m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string(address), port); + m_Socket = boost::shared_ptr(new boost::asio::ip::udp::socket(m_IOService)); + m_Socket->connect(m_ReceiverEndpoint); + + Packet packet(MessageType::Connect, m_SendPacketID); + packet.WriteString(playerName); + Send(packet); +} + +void UDPClient::Disconnect() +{ + +} + +void UDPClient::Receive(Packet& packet) +{ + int bytesRead = readBuffer(m_ReadBuffer); + if (bytesRead > 0) { + packet.ReconstructFromData(m_ReadBuffer, bytesRead); } } -int UDPClient::receive(char* data) +int UDPClient::readBuffer(char* data) { + if (!m_Socket) { + return 0; + } boost::system::error_code error; - - int bytesReceived = m_Socket.receive_from(boost + int bytesReceived = m_Socket->receive_from(boost ::asio::buffer((void*)data, BUFFERSIZE), m_ReceiverEndpoint, 0, error); - // Network Debug data - if (isReadingData) { - m_NetworkData.TotalDataReceived += bytesReceived; - m_NetworkData.DataReceivedThisInterval += bytesReceived; - m_NetworkData.AmountOfMessagesReceived++; - } if (error) { //LOG_ERROR("receive: %s", error.message().c_str()); } return bytesReceived; } -void UDPClient::send(Packet& packet) +void UDPClient::Send(Packet& packet) { - m_Socket.send_to(boost::asio::buffer( + m_Socket->send_to(boost::asio::buffer( packet.Data(), packet.Size()), m_ReceiverEndpoint, 0); - // Network Debug data - if (isReadingData) { - m_NetworkData.TotalDataSent += packet.Size(); - m_NetworkData.DataSentThisInterval += packet.Size(); - m_NetworkData.AmountOfMessagesSent++; - } } -void UDPClient::connect() +bool UDPClient::IsSocketAvailable() { - Packet packet(MessageType::Connect, m_SendPacketID); - packet.WriteString(m_PlayerName); - m_StartPingTime = std::clock(); - send(packet); + if (!m_Socket) { + return false; + } + return m_Socket->available(); } \ No newline at end of file diff --git a/src/Engine/Network/UDPServer.cpp b/src/Engine/Network/UDPServer.cpp index 1e62c10a..41cb436c 100644 --- a/src/Engine/Network/UDPServer.cpp +++ b/src/Engine/Network/UDPServer.cpp @@ -6,8 +6,7 @@ UDPServer::UDPServer() } UDPServer::~UDPServer() -{ -} +{ } void UDPServer::readFromClients() { @@ -22,24 +21,6 @@ void UDPServer::readFromClients() //LOG_ERROR("%i: Read from client crashed %s", m_PacketID, err.what()); } } - std::clock_t currentTime = std::clock(); - // Send snapshot - if (snapshotInterval < (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC)) { - sendSnapshot(); - previousSnapshotMessage = currentTime; - } - - // Send pings each - if (pingIntervalMs < (1000 * (currentTime - previousePingMessage) / (double)CLOCKS_PER_SEC)) { - sendPing(); - previousePingMessage = currentTime; - } - - // Time out logic - if (checkTimeOutInterval < (1000 * (currentTime - timOutTimer) / (double)CLOCKS_PER_SEC)) { - checkForTimeOuts(); - timOutTimer = currentTime; - } } void UDPServer::parseConnect(Packet& packet) diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index ccbf79c9..931bb9dd 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -43,7 +43,7 @@ Game::Game(int argc, char* argv[]) 0, m_Config->Get("Video.Width", 1280), m_Config->Get("Video.Height", 720) - )); + )); m_Renderer->Initialize(); //m_Renderer->Camera()->SetFOV(glm::radians(m_Config->Get("Video.FOV", 90.f))); m_RenderFrame = new RenderFrame(); @@ -155,7 +155,11 @@ void Game::Tick() // Update network if (m_IsClientOrServer) { - m_ClientOrServer->Update(); + if (m_IsServer) + m_ClientOrServer->Update(); + else if (!m_IsServer) { + m_Client->Update(); + } } // Iterate through systems and update world! m_EventBroker->Process(); @@ -178,19 +182,25 @@ void Game::debugTick(double dt) void Game::networkFunction() { - bool isServer = m_Config->Get("Networking.IsServer", false); - if (!isServer) { + m_IsServer = m_Config->Get("Networking.IsServer", false); + if (!m_IsServer) { m_IsClientOrServer = true; - m_ClientOrServer = new UDPClient(m_Config); - //m_ClientOrServer = new TCPClient(m_Config); - //m_ClientOrServer = new HybridClient(m_Config); + m_Client = std::unique_ptr(new Client(m_Config)); + m_Client->Start(m_World, m_EventBroker); } - if (isServer) { + //if (!isServer) { + // m_IsClientOrServer = true; + // m_ClientOrServer = new UDPClient(m_Config); + // //m_ClientOrServer = new TCPClient(m_Config); + // //m_ClientOrServer = new HybridClient(m_Config); + //} + if (m_IsServer) { m_IsClientOrServer = true; - m_ClientOrServer = new UDPServer(); - // m_ClientOrServer = new TCPServer(); + // m_ClientOrServer = new UDPServer(); + m_ClientOrServer = new TCPServer(); //m_ClientOrServer = new HybridServer(); + m_ClientOrServer->Start(m_World, m_EventBroker); } - m_ClientOrServer->Start(m_World, m_EventBroker); + } \ No newline at end of file From d2ed293183bad8ae6a91b71b2d491ee1e8fc3550 Mon Sep 17 00:00:00 2001 From: Jocke Date: Tue, 9 Feb 2016 19:14:56 +0100 Subject: [PATCH 06/18] Network is now working as udp or tcp. Next step is making the hybrid. --- include/Engine/Network/NetworkServer.h | 28 +++++-- include/Engine/Network/Packet.h | 3 +- include/Engine/Network/Server.h | 22 +++-- include/Engine/Network/TCPServer.h | 24 +++--- include/Engine/Network/UDPServer.h | 22 +++-- include/Game/Game.h | 13 +-- src/Engine/Network/Packet.cpp | 8 +- src/Engine/Network/Server.cpp | 90 ++++++++++++++++++-- src/Engine/Network/TCPClient.cpp | 7 ++ src/Engine/Network/TCPServer.cpp | 109 +++++++++---------------- src/Engine/Network/UDPServer.cpp | 83 +++++-------------- src/Game/Game.cpp | 6 +- 12 files changed, 225 insertions(+), 190 deletions(-) diff --git a/include/Engine/Network/NetworkServer.h b/include/Engine/Network/NetworkServer.h index 1586693d..36544292 100644 --- a/include/Engine/Network/NetworkServer.h +++ b/include/Engine/Network/NetworkServer.h @@ -1,20 +1,32 @@ #ifndef NetworkServer_h__ #define NetworkServer_h__ - +#include #include "Network/Packet.h" +#include "Network/PlayerDefinition.h" #define BUFFERSIZE 32000 typedef unsigned int PlayerID; typedef unsigned int PacketID; class NetworkServer { -//public: -// virtual void Connect(std::string playerName, std::string address, int port) = 0; -// virtual void Disconnect() = 0; -// virtual Packet Receive() = 0; -// virtual void Send(Packet & packet) = 0; -//protected: -// char m_ReadBuffer[BUFFERSIZE] = { 0 }; +public: + virtual void AcceptNewConnections(int& nextPlayerID, std::map& connectedPlayers) = 0; + virtual void Receive(Packet & packet, PlayerDefinition & playerDefinition) = 0; + virtual void Send(Packet & packet, PlayerDefinition & playerDefinition) = 0; + virtual void Send(Packet & packet) = 0; +protected: + char m_ReadBuffer[BUFFERSIZE] = { 0 }; + //void handle_accept(boost::shared_ptr socket, const boost::system::error_code & error); + //void parseConnect(Packet & packet); + //void readFromClients(); + + //public: + // virtual void Connect(std::string playerName, std::string address, int port) = 0; + // virtual void Disconnect() = 0; + // virtual Packet Receive() = 0; + // virtual void Send(Packet & packet) = 0; + //protected: + // char m_ReadBuffer[BUFFERSIZE] = { 0 }; }; #endif \ No newline at end of file diff --git a/include/Engine/Network/Packet.h b/include/Engine/Network/Packet.h index e88747b8..2a370dc6 100644 --- a/include/Engine/Network/Packet.h +++ b/include/Engine/Network/Packet.h @@ -57,7 +57,7 @@ public: void ChangePacketID(unsigned int& packetID); int Size() { return m_Offset; }; char* Data() { return m_Data; }; - MessageType GetMessageType() { return m_MessageType; }; + MessageType GetMessageType(); unsigned int DataReadSize() { return m_ReturnDataOffset; } unsigned int MaxSize() { return m_MaxPacketSize; } unsigned int HeaderSize() { return m_HeaderSize; } @@ -68,7 +68,6 @@ private: int m_Offset = 0; unsigned int m_MaxPacketSize = 512; unsigned int m_HeaderSize = 0; - MessageType m_MessageType = MessageType::Invalid; void resizeData(); void resizeData(int size); }; diff --git a/include/Engine/Network/Server.h b/include/Engine/Network/Server.h index 4ff169d2..0a3c93c8 100644 --- a/include/Engine/Network/Server.h +++ b/include/Engine/Network/Server.h @@ -6,6 +6,8 @@ #include +#include "Network/TCPServer.h" +#include "Network/UDPServer.h" #include "Network/MessageType.h" #include "Network/PlayerDefinition.h" #include "Core/World.h" @@ -17,6 +19,7 @@ #include "Core/EPlayerSpawned.h" #include "Core/EEntityDeleted.h" #include "Core/EComponentDeleted.h" + class Server : public Network { public: @@ -49,7 +52,7 @@ protected: // Game logic World* m_World; EventBroker* m_EventBroker; - + // Packet loss logic PacketID m_PacketID = 0; PacketID m_PreviousPacketID = 0; @@ -70,13 +73,15 @@ protected: void parsePlayerTransform(Packet& packet); void parseOnInputCommand(Packet& packet); void parseClientPing(); - void parsePing(); + void parsePing(); + void parseConnect(Packet & packet, PlayerDefinition & pd); + void parseTCPConnect(Packet & packet); void parseDisconnect(); - // Pure virtual functions - virtual void readFromClients() = 0; - virtual void send(Packet& packet, PlayerDefinition & playerDefinition) = 0; - virtual void send(Packet& packet) = 0; - virtual void parseConnect(Packet& packet) = 0; + //// Pure virtual functions + //virtual void readFromClients() = 0; + //virtual void send(Packet& packet, PlayerDefinition & playerDefinition) = 0; + //virtual void send(Packet& packet) = 0; + // Debug event EventRelay m_EInputCommand; bool OnInputCommand(const Events::InputCommand& e); @@ -86,6 +91,9 @@ protected: bool OnEntityDeleted(const Events::EntityDeleted& e); EventRelay m_EComponentDeleted; bool OnComponentDeleted(const Events::ComponentDeleted& e); +private: + TCPServer m_TCPServer; + //UDPServer m_UDPServer; }; #endif diff --git a/include/Engine/Network/TCPServer.h b/include/Engine/Network/TCPServer.h index 6c52d10d..b1aa7ce0 100644 --- a/include/Engine/Network/TCPServer.h +++ b/include/Engine/Network/TCPServer.h @@ -1,26 +1,30 @@ #ifndef TCPServer_h__ #define TCPServer_h__ -#include "Server.h" +#include +#include +#include +#include "NetworkServer.h" -class TCPServer : public Server +class TCPServer : public NetworkServer { public: TCPServer(); ~TCPServer(); + void AcceptNewConnections(int& nextPlayerID, std::map& connectedPlayers); + void Receive(Packet & packet, PlayerDefinition & playerDefinition); + void Send(Packet & packet, PlayerDefinition & playerDefinition); + void Send(Packet & packet); private: // TCP logic boost::asio::io_service m_IOService; std::unique_ptr acceptor; boost::shared_ptr lastReceivedSocket; - - void acceptNewConnections(); - void handle_accept(boost::shared_ptr socket, const boost::system::error_code & error); - void readFromClients(); - int receive(char * data, boost::asio::ip::tcp::socket& socket); - void parseConnect(Packet & packet); - void send(Packet & packet, PlayerDefinition & playerDefinition); - void send(Packet & packet); + + void handle_accept(boost::shared_ptr socket, + int& nextPlayerID, std::map& connectedPlayers, + const boost::system::error_code& error); + int readBuffer(char* data, PlayerDefinition& playerDefinition); }; #endif \ No newline at end of file diff --git a/include/Engine/Network/UDPServer.h b/include/Engine/Network/UDPServer.h index 22c8c3e3..7c912a21 100644 --- a/include/Engine/Network/UDPServer.h +++ b/include/Engine/Network/UDPServer.h @@ -1,25 +1,31 @@ #ifndef UDPServer_h__ #define UDPServer_h__ -#include "Server.h" +#include "NetworkServer.h" #include +// +//virtual void AcceptNewConnections() = 0; +//virtual void Receive(Packet & packet, PlayerDefinition & playerDefinition) = 0; +//virtual void Send(Packet & packet, PlayerDefinition & playerDefinition) = 0; +//virtual void Send(Packet & packet) = 0; -class UDPServer : public Server +class UDPServer : public NetworkServer { public: UDPServer(); ~UDPServer(); + void AcceptNewConnections(int& nextPlayerID, std::map& connectedPlayers); + void Receive(Packet & packet, PlayerDefinition & playerDefinition); + //void parseConnect(Packet & packet, PlayerDefinition & playerDefinition); + void Send(Packet & packet, PlayerDefinition & playerDefinition); + void Send(Packet & packet); + bool IsSocketAvailable(); private: // UDP logic boost::asio::io_service m_IOService; boost::asio::ip::udp::endpoint m_ReceiverEndpoint; std::unique_ptr m_Socket; - - void readFromClients(); - int receive(char * data); - void parseConnect(Packet & packet); - void send(Packet & packet, PlayerDefinition & playerDefinition); - void send(Packet & packet); + int readBuffer(char* data); }; #endif \ No newline at end of file diff --git a/include/Game/Game.h b/include/Game/Game.h index 54b8c753..fb03896d 100644 --- a/include/Game/Game.h +++ b/include/Game/Game.h @@ -28,15 +28,8 @@ #include "Network/Network.h" // Client #include "Network/Client.h" -// Hybrid -#include "Network/HybridServer.h" -#include "Network/HybridClient.h" -// TCP -#include "Network/TCPClient.h" -#include "Network/TCPServer.h" -// UDP -#include "Network/UDPServer.h" -#include "Network/UDPClient.h" +// Server +#include "Network/Server.h" // Sound #include "Sound/SoundSystem.h" @@ -69,8 +62,8 @@ private: // Network methods void networkFunction(); - Network* m_ClientOrServer; std::unique_ptr m_Client; + std::unique_ptr m_Server; bool m_IsClientOrServer = false; bool m_IsServer = false; diff --git a/src/Engine/Network/Packet.cpp b/src/Engine/Network/Packet.cpp index 06c81b8f..c9e8832a 100644 --- a/src/Engine/Network/Packet.cpp +++ b/src/Engine/Network/Packet.cpp @@ -37,7 +37,6 @@ void Packet::Init(MessageType type, unsigned int & packetID) // allocate memory for size of packet(only used in tcp) Packet::WritePrimitive(0); // Add message type - m_MessageType = type; int messageType = static_cast(type); Packet::WritePrimitive(messageType); Packet::WritePrimitive(packetID); @@ -120,6 +119,13 @@ void Packet::ChangePacketID(unsigned int & packetID) memcpy(m_Data + 2*sizeof(int), &packetID, sizeof(int)); } +MessageType Packet::GetMessageType() +{ + MessageType messagType; + memcpy(&messagType, m_Data + sizeof(int), sizeof(int)); + return messagType; +} + void Packet::resizeData() { resizeData(m_MaxPacketSize * 2); diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index fa0f1a1a..de7b6e14 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -23,7 +23,35 @@ void Server::Start(World* world, EventBroker* eventBroker) void Server::Update() { - readFromClients(); + m_TCPServer.AcceptNewConnections(m_NextPlayerID, m_ConnectedPlayers); + PlayerDefinition pd; + for (auto& kv : m_ConnectedPlayers) { + while (kv.second.TCPSocket->available()) { + // Packet will get real data in receive + Packet packet(MessageType::Invalid); + m_TCPServer.Receive(packet, kv.second); + m_Address = kv.second.TCPSocket->remote_endpoint().address(); + m_Port = kv.second.TCPSocket->remote_endpoint().port(); + if (packet.GetMessageType() == MessageType::Connect) { + parseTCPConnect(packet); + } else { + parseMessageType(packet); + } + } + } + + //while (m_UDPServer.IsSocketAvailable()) { + // // Packet will get real data in receive + // Packet packet(MessageType::Invalid); + // m_UDPServer.Receive(packet, pd); + // m_Address = pd.Endpoint.address(); + // m_Port = pd.Endpoint.port(); + // if (packet.GetMessageType() == MessageType::Connect) { + // parseConnect(packet, pd); + // } else { + // parseMessageType(packet); + // } + //} std::clock_t currentTime = std::clock(); // Send snapshot @@ -60,7 +88,7 @@ void Server::parseMessageType(Packet& packet) //identifyPacketLoss(); switch (static_cast(messageType)) { case MessageType::Connect: - parseConnect(packet); + //parseConnect(packet); break; case MessageType::Ping: parsePing(); @@ -90,7 +118,7 @@ void Server::broadcast(Packet& packet) { for (auto& kv : m_ConnectedPlayers) { packet.ChangePacketID(kv.second.PacketID); - send(packet, kv.second); + m_TCPServer.Send(packet, kv.second); } } @@ -184,6 +212,56 @@ void Server::checkForTimeOuts() } } +void Server::parseConnect(Packet & packet, PlayerDefinition & pd) +{ + //LOG_INFO("Parsing connections"); + //// Check if player is already connected + //if (GetPlayerIDFromEndpoint() != -1) { + // return; + //} + //// Create a new player + //pd.EntityID = 0; // Overlook this + //pd.Address = pd.Endpoint.address(); + //pd.Port = pd.Endpoint.port(); + //pd.Name = packet.ReadString(); + //pd.PacketID = 0; + //pd.StopTime = std::clock(); + //m_ConnectedPlayers[m_NextPlayerID++] = pd; + //LOG_INFO("Spectator \"%s\" connected on IP: %s", pd.Name.c_str(), pd.Endpoint.address().to_string().c_str()); + + //// Send a message to the player that connected + //Packet connnectPacket(MessageType::Connect, pd.PacketID); + //m_UDPServer.Send(connnectPacket); + + //// Send notification that a player has connected + //Packet notificationPacket(MessageType::PlayerConnected); + //broadcast(notificationPacket); +} + +void Server::parseTCPConnect(Packet & packet) +{ + LOG_INFO("Parsing connections"); + // Check if player is already connected + PlayerID playerID = GetPlayerIDFromEndpoint(); + if (playerID = -1) { + return; + } + // Create a new player + m_ConnectedPlayers.at(playerID).EntityID = 0; // Overlook this + m_ConnectedPlayers.at(playerID).Name = packet.ReadString(); + m_ConnectedPlayers.at(playerID).PacketID = 0; + m_ConnectedPlayers.at(playerID).StopTime = std::clock(); + LOG_INFO("Spectator \"%s\" connected on IP: %s", m_ConnectedPlayers.at(playerID).Name.c_str(), m_ConnectedPlayers.at(playerID).Endpoint.address().to_string().c_str()); + + // Send a message to the player that connected + Packet connnectPacket(MessageType::Connect, m_ConnectedPlayers.at(playerID).PacketID); + m_TCPServer.Send(connnectPacket); + + // Send notification that a player has connected + Packet notificationPacket(MessageType::PlayerConnected); + //broadcast(notificationPacket); +} + void Server::parseDisconnect() { LOG_INFO("%i: Parsing disconnect", m_PacketID); @@ -232,7 +310,7 @@ void Server::kick(PlayerID player) { disconnect(player); Packet packet = Packet(MessageType::Kick); - send(packet); + m_TCPServer.Send(packet); } bool Server::OnInputCommand(const Events::InputCommand & e) @@ -261,7 +339,7 @@ bool Server::OnPlayerSpawned(const Events::PlayerSpawned & e) packet.WritePrimitive(e.Spawner.ID); // We don't send PlayerID here because it will always be set to -1 packet.WriteString(m_ConnectedPlayers[e.PlayerID].Name); - send(packet, m_ConnectedPlayers[e.PlayerID]); + m_TCPServer.Send(packet, m_ConnectedPlayers[e.PlayerID]); return false; } @@ -297,7 +375,7 @@ void Server::parseClientPing() // Return ping Packet packet(MessageType::Ping, m_ConnectedPlayers[player].PacketID); packet.WriteString("Ping received"); - send(packet); + m_TCPServer.Send(packet); } void Server::parsePing() diff --git a/src/Engine/Network/TCPClient.cpp b/src/Engine/Network/TCPClient.cpp index 42f724d0..69938c38 100644 --- a/src/Engine/Network/TCPClient.cpp +++ b/src/Engine/Network/TCPClient.cpp @@ -13,6 +13,12 @@ TCPClient::~TCPClient() void TCPClient::Connect(std::string playerName, std::string address, int port) { if (m_Socket) { + if (m_IsConnected) { + Packet packet(MessageType::Connect, m_SendPacketID); + packet.WriteString(playerName); + Send(packet); + LOG_INFO("Connect message sent again!"); + } return; } if (!m_IsConnected) { @@ -29,6 +35,7 @@ void TCPClient::Connect(std::string playerName, std::string address, int port) Packet packet(MessageType::Connect, m_SendPacketID); packet.WriteString(playerName); Send(packet); + LOG_INFO("Connect message sent!"); } } } diff --git a/src/Engine/Network/TCPServer.cpp b/src/Engine/Network/TCPServer.cpp index 09d2ce69..105aab9f 100644 --- a/src/Engine/Network/TCPServer.cpp +++ b/src/Engine/Network/TCPServer.cpp @@ -7,42 +7,38 @@ TCPServer::TCPServer() } TCPServer::~TCPServer() -{ } - -void TCPServer::readFromClients() { - acceptNewConnections(); - for (auto& kv : m_ConnectedPlayers) { - while (kv.second.TCPSocket->available()) { - try { - bytesRead = receive(readBuffer, *kv.second.TCPSocket); - lastReceivedSocket = kv.second.TCPSocket; - // Get logic for mother class - boost::asio::ip::tcp::endpoint remoteEndpoint = kv.second.TCPSocket->remote_endpoint(); - m_Address = remoteEndpoint.address(); - m_Port = remoteEndpoint.port(); - // Recreate packets - Packet packet(readBuffer, bytesRead); - parseMessageType(packet); - } catch (const std::exception& err) { - //LOG_ERROR("%i: Read from client crashed %s", m_PacketID, err.what()); - } - } - } } -void TCPServer::acceptNewConnections() +void TCPServer::AcceptNewConnections(int& nextPlayerID, std::map& connectedPlayers) { + //PlayerDefinition pd; + //connectedPlayers[nextPlayerID++] = pd; boost::shared_ptr newSocket = boost::shared_ptr(new tcp::socket(m_IOService)); m_IOService.poll(); acceptor->async_accept(*newSocket, - boost::bind(&TCPServer::handle_accept, this, newSocket, + boost::bind(&TCPServer::handle_accept, this, newSocket, boost::ref(nextPlayerID), boost::ref(connectedPlayers), boost::asio::placeholders::error)); } -void TCPServer::handle_accept(boost::shared_ptr socket, const boost::system::error_code& error) +PlayerID GetPlayerIDFromEndpoint(const std::map& connectedPlayers, + boost::asio::ip::address address, unsigned short port) { - if (!error && GetPlayerIDFromEndpoint() == -1) { + for (auto& kv : connectedPlayers) { + if (kv.second.Address == address && + kv.second.Port == port) { + return kv.first; + } + } + return -1; +} + +void TCPServer::handle_accept(boost::shared_ptr socket, + int& nextPlayerID, std::map& connectedPlayers, + const boost::system::error_code& error) +{ + if (!error && GetPlayerIDFromEndpoint(connectedPlayers, socket->remote_endpoint().address(), + socket->remote_endpoint().port()) == -1) { // Add tcp socket to connections boost::asio::ip::tcp::no_delay option(true); socket->set_option(option); @@ -51,55 +47,24 @@ void TCPServer::handle_accept(boost::shared_ptr socket, const boost pd.TCPSocket = socket; pd.Address = socket.get()->remote_endpoint().address(); pd.Port = socket.get()->remote_endpoint().port(); - m_ConnectedPlayers[m_NextPlayerID++] = pd; + connectedPlayers[nextPlayerID++] = pd; } } -void TCPServer::parseConnect(Packet & packet) -{ - LOG_INFO("Parsing connections"); - // Check if player is already connected - PlayerID playerID = GetPlayerIDFromEndpoint(); - if (playerID = -1) { - return; - } - - // Create a new player - m_ConnectedPlayers.at(playerID).EntityID = 0; // Overlook this - m_ConnectedPlayers.at(playerID).Name = packet.ReadString(); - m_ConnectedPlayers.at(playerID).PacketID = 0; - m_ConnectedPlayers.at(playerID).StopTime = std::clock(); - LOG_INFO("Spectator \"%s\" connected on IP: %s", m_ConnectedPlayers.at(playerID).Name.c_str(), m_ConnectedPlayers.at(playerID).Endpoint.address().to_string().c_str()); - - // Send a message to the player that connected - Packet connnectPacket(MessageType::Connect, m_ConnectedPlayers.at(playerID).PacketID); - send(connnectPacket); - - // Send notification that a player has connected - Packet notificationPacket(MessageType::PlayerConnected); - broadcast(notificationPacket); -} - -void TCPServer::send(Packet & packet, PlayerDefinition & playerDefinition) +void TCPServer::Send(Packet & packet, PlayerDefinition & playerDefinition) { try { packet.UpdateSize(); int bytesSent = playerDefinition.TCPSocket->send( boost::asio::buffer(packet.Data(), packet.Size()), 0); - // Network Debug data - if (isReadingData) { - m_NetworkData.TotalDataSent += packet.Size(); - m_NetworkData.DataSentThisInterval += packet.Size(); - m_NetworkData.AmountOfMessagesSent++; - } } catch (const boost::system::system_error& e) { // TODO: Clean up invalid endpoints out of m_ConnectedPlayers later playerDefinition.Endpoint = boost::asio::ip::udp::endpoint(); } } -void TCPServer::send(Packet & packet) +void TCPServer::Send(Packet & packet) { packet.UpdateSize(); lastReceivedSocket->send( @@ -107,33 +72,33 @@ void TCPServer::send(Packet & packet) packet.Data(), packet.Size()), 0); - if (isReadingData) { - // Network Debug data - m_NetworkData.TotalDataSent += packet.Size(); - m_NetworkData.DataSentThisInterval += packet.Size(); +} + +void TCPServer::Receive(Packet & packet, PlayerDefinition & playerDefinition) +{ + int bytesRead = readBuffer(m_ReadBuffer, playerDefinition); + if (bytesRead > 0) { + packet.ReconstructFromData(m_ReadBuffer, bytesRead); } } -int TCPServer::receive(char * data, boost::asio::ip::tcp::socket& socket) +int TCPServer::readBuffer(char* data, PlayerDefinition & playerDefinition) { + if (!playerDefinition.TCPSocket) { + return 0; + } boost::system::error_code error; // Read size of packet - int bytesReceived = socket.read_some(boost + int bytesReceived = playerDefinition.TCPSocket->read_some(boost ::asio::buffer((void*)data, sizeof(int)), error); int sizeOfPacket = 0; memcpy(&sizeOfPacket, data, sizeof(int)); // Read the rest of the message - bytesReceived += socket.read_some(boost + bytesReceived += playerDefinition.TCPSocket->read_some(boost ::asio::buffer((void*)(data + bytesReceived), sizeOfPacket - bytesReceived), error); - // Network Debug data - if (isReadingData) { - m_NetworkData.TotalDataReceived += bytesReceived; - m_NetworkData.DataReceivedThisInterval += bytesReceived; - m_NetworkData.AmountOfMessagesReceived++; - } if (error) { //LOG_ERROR("receive: %s", error.message().c_str()); } diff --git a/src/Engine/Network/UDPServer.cpp b/src/Engine/Network/UDPServer.cpp index 41cb436c..e0bdf3a2 100644 --- a/src/Engine/Network/UDPServer.cpp +++ b/src/Engine/Network/UDPServer.cpp @@ -6,71 +6,23 @@ UDPServer::UDPServer() } UDPServer::~UDPServer() -{ } - -void UDPServer::readFromClients() { - while (m_Socket->available()) { - try { - bytesRead = receive(readBuffer); - m_Address = m_ReceiverEndpoint.address(); - m_Port = m_ReceiverEndpoint.port(); - Packet packet(readBuffer, bytesRead); - parseMessageType(packet); - } catch (const std::exception& err) { - //LOG_ERROR("%i: Read from client crashed %s", m_PacketID, err.what()); - } - } } -void UDPServer::parseConnect(Packet& packet) -{ - LOG_INFO("Parsing connections"); - // Check if player is already connected - if (GetPlayerIDFromEndpoint() != -1) { - return; - } - // Create a new player - PlayerDefinition pd; - pd.EntityID = 0; // Overlook this - pd.Endpoint = m_ReceiverEndpoint; - pd.Address = m_ReceiverEndpoint.address(); - pd.Port = m_ReceiverEndpoint.port(); - pd.Name = packet.ReadString(); - pd.PacketID = 0; - pd.StopTime = std::clock(); - m_ConnectedPlayers[m_NextPlayerID++] = pd; - LOG_INFO("Spectator \"%s\" connected on IP: %s", pd.Name.c_str(), pd.Endpoint.address().to_string().c_str()); - - // Send a message to the player that connected - Packet connnectPacket(MessageType::Connect, pd.PacketID); - send(connnectPacket); - - // Send notification that a player has connected - Packet notificationPacket(MessageType::PlayerConnected); - broadcast(notificationPacket); -} - -void UDPServer::send(Packet& packet, PlayerDefinition & playerDefinition) +void UDPServer::Send(Packet& packet, PlayerDefinition & playerDefinition) { try { int bytesSent = m_Socket->send_to( boost::asio::buffer(packet.Data(), packet.Size()), playerDefinition.Endpoint, 0); - // Network Debug data - if (isReadingData) { - m_NetworkData.TotalDataSent += packet.Size(); - m_NetworkData.DataSentThisInterval += packet.Size(); - m_NetworkData.AmountOfMessagesSent++; - } } catch (const boost::system::system_error& e) { // TODO: Clean up invalid endpoints out of m_ConnectedPlayers later playerDefinition.Endpoint = boost::asio::ip::udp::endpoint(); } } // Send back to endpoint of received packet -void UDPServer::send(Packet & packet) +void UDPServer::Send(Packet & packet) { m_Socket->send_to( boost::asio::buffer( @@ -78,27 +30,32 @@ void UDPServer::send(Packet & packet) packet.Size()), m_ReceiverEndpoint, 0); - if (isReadingData) { - // Network Debug data - m_NetworkData.TotalDataSent += packet.Size(); - m_NetworkData.DataSentThisInterval += packet.Size(); - } } -int UDPServer::receive(char * data) +void UDPServer::Receive(Packet & packet, PlayerDefinition & playerDefinition) +{ + int bytesRead = readBuffer(m_ReadBuffer); + if (bytesRead > 0) { + packet.ReconstructFromData(m_ReadBuffer, bytesRead); + } + playerDefinition.Endpoint = m_ReceiverEndpoint; +} + +bool UDPServer::IsSocketAvailable() +{ + return m_Socket->available(); +} + +int UDPServer::readBuffer(char* data) { unsigned int length = m_Socket->receive_from( boost::asio::buffer((void*)data , BUFFERSIZE) , m_ReceiverEndpoint, 0); - // Network Debug data - if (isReadingData) { - m_NetworkData.TotalDataReceived += length; - m_NetworkData.DataReceivedThisInterval += length; - m_NetworkData.AmountOfMessagesReceived++; - } return length; } - +void UDPServer::AcceptNewConnections(int& nextPlayerID, std::map& connectedPlayers) +{ +} \ No newline at end of file diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index 931bb9dd..9e1bf708 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -156,7 +156,7 @@ void Game::Tick() // Update network if (m_IsClientOrServer) { if (m_IsServer) - m_ClientOrServer->Update(); + m_Server->Update(); else if (!m_IsServer) { m_Client->Update(); } @@ -197,9 +197,9 @@ void Game::networkFunction() if (m_IsServer) { m_IsClientOrServer = true; // m_ClientOrServer = new UDPServer(); - m_ClientOrServer = new TCPServer(); + m_Server = std::unique_ptr(new Server()); //m_ClientOrServer = new HybridServer(); - m_ClientOrServer->Start(m_World, m_EventBroker); + m_Server->Start(m_World, m_EventBroker); } From 2ec30fd2b20e35667954d1417d7748be9111a22a Mon Sep 17 00:00:00 2001 From: Jocke Date: Wed, 10 Feb 2016 11:28:03 +0100 Subject: [PATCH 07/18] Cleaned up code and fixed crash when closing client before server when using udp. --- include/Engine/Network/Client.h | 4 +- include/Engine/Network/NetworkServer.h | 11 -- include/Engine/Network/Server.h | 4 +- include/Engine/Network/TCPClient.h | 4 - include/Engine/Network/UDPClient.h | 4 - include/Engine/Network/UDPServer.h | 6 -- src/Engine/Network/Server.cpp | 133 +++++++++++++------------ src/Engine/Network/TCPClient.cpp | 1 - src/Engine/Network/TCPServer.cpp | 2 - src/Engine/Network/UDPServer.cpp | 12 ++- 10 files changed, 78 insertions(+), 103 deletions(-) diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index 0c9608ff..ffdf812f 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -103,9 +103,9 @@ protected: bool OnPlayerSpawned(const Events::PlayerSpawned& e); private: - //UDPClient m_UDPClient; + UDPClient m_UDPClient; //TCPClient m_TCPClient; - TCPClient m_UDPClient; + //TCPClient m_UDPClient; }; #endif diff --git a/include/Engine/Network/NetworkServer.h b/include/Engine/Network/NetworkServer.h index 36544292..d6406eab 100644 --- a/include/Engine/Network/NetworkServer.h +++ b/include/Engine/Network/NetworkServer.h @@ -16,17 +16,6 @@ public: virtual void Send(Packet & packet) = 0; protected: char m_ReadBuffer[BUFFERSIZE] = { 0 }; - //void handle_accept(boost::shared_ptr socket, const boost::system::error_code & error); - //void parseConnect(Packet & packet); - //void readFromClients(); - - //public: - // virtual void Connect(std::string playerName, std::string address, int port) = 0; - // virtual void Disconnect() = 0; - // virtual Packet Receive() = 0; - // virtual void Send(Packet & packet) = 0; - //protected: - // char m_ReadBuffer[BUFFERSIZE] = { 0 }; }; #endif \ No newline at end of file diff --git a/include/Engine/Network/Server.h b/include/Engine/Network/Server.h index 0a3c93c8..1b2e6956 100644 --- a/include/Engine/Network/Server.h +++ b/include/Engine/Network/Server.h @@ -92,8 +92,8 @@ protected: EventRelay m_EComponentDeleted; bool OnComponentDeleted(const Events::ComponentDeleted& e); private: - TCPServer m_TCPServer; - //UDPServer m_UDPServer; + //TCPServer m_TCPServer; + UDPServer m_UDPServer; }; #endif diff --git a/include/Engine/Network/TCPClient.h b/include/Engine/Network/TCPClient.h index ff10b63a..9f61cca5 100644 --- a/include/Engine/Network/TCPClient.h +++ b/include/Engine/Network/TCPClient.h @@ -16,10 +16,6 @@ public: void Send(Packet & packet); bool IsSocketAvailable(); private: - // Assio UDP logic - //boost::asio::io_service m_IOService; - //boost::asio::ip::udp::endpoint m_ReceiverEndpoint; - //boost::shared_ptr m_Socket; // Assio TCP logic boost::asio::ip::tcp::endpoint m_Endpoint; boost::asio::io_service m_IOService; diff --git a/include/Engine/Network/UDPClient.h b/include/Engine/Network/UDPClient.h index ca369f6b..3a458d3e 100644 --- a/include/Engine/Network/UDPClient.h +++ b/include/Engine/Network/UDPClient.h @@ -3,10 +3,6 @@ #include #include "Network/NetworkClient.h" -//virtual void Connect(std::string address, int port) = 0; -//virtual int Receive(char * data) = 0; -//virtual void Send(Packet & packet) = 0; -//virtual void Disconnect() = 0; class UDPClient : public NetworkClient { diff --git a/include/Engine/Network/UDPServer.h b/include/Engine/Network/UDPServer.h index 7c912a21..246fb333 100644 --- a/include/Engine/Network/UDPServer.h +++ b/include/Engine/Network/UDPServer.h @@ -3,11 +3,6 @@ #include "NetworkServer.h" #include -// -//virtual void AcceptNewConnections() = 0; -//virtual void Receive(Packet & packet, PlayerDefinition & playerDefinition) = 0; -//virtual void Send(Packet & packet, PlayerDefinition & playerDefinition) = 0; -//virtual void Send(Packet & packet) = 0; class UDPServer : public NetworkServer { @@ -16,7 +11,6 @@ public: ~UDPServer(); void AcceptNewConnections(int& nextPlayerID, std::map& connectedPlayers); void Receive(Packet & packet, PlayerDefinition & playerDefinition); - //void parseConnect(Packet & packet, PlayerDefinition & playerDefinition); void Send(Packet & packet, PlayerDefinition & playerDefinition); void Send(Packet & packet); bool IsSocketAvailable(); diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index de7b6e14..d3099e12 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -23,36 +23,37 @@ void Server::Start(World* world, EventBroker* eventBroker) void Server::Update() { - m_TCPServer.AcceptNewConnections(m_NextPlayerID, m_ConnectedPlayers); PlayerDefinition pd; - for (auto& kv : m_ConnectedPlayers) { - while (kv.second.TCPSocket->available()) { - // Packet will get real data in receive - Packet packet(MessageType::Invalid); - m_TCPServer.Receive(packet, kv.second); - m_Address = kv.second.TCPSocket->remote_endpoint().address(); - m_Port = kv.second.TCPSocket->remote_endpoint().port(); - if (packet.GetMessageType() == MessageType::Connect) { - parseTCPConnect(packet); - } else { - parseMessageType(packet); - } - } - } - - //while (m_UDPServer.IsSocketAvailable()) { - // // Packet will get real data in receive - // Packet packet(MessageType::Invalid); - // m_UDPServer.Receive(packet, pd); - // m_Address = pd.Endpoint.address(); - // m_Port = pd.Endpoint.port(); - // if (packet.GetMessageType() == MessageType::Connect) { - // parseConnect(packet, pd); - // } else { - // parseMessageType(packet); + + //m_TCPServer.AcceptNewConnections(m_NextPlayerID, m_ConnectedPlayers); + //for (auto& kv : m_ConnectedPlayers) { + // while (kv.second.TCPSocket->available()) { + // // Packet will get real data in receive + // Packet packet(MessageType::Invalid); + // m_TCPServer.Receive(packet, kv.second); + // m_Address = kv.second.TCPSocket->remote_endpoint().address(); + // m_Port = kv.second.TCPSocket->remote_endpoint().port(); + // if (packet.GetMessageType() == MessageType::Connect) { + // parseTCPConnect(packet); + // } else { + // parseMessageType(packet); + // } // } //} + while (m_UDPServer.IsSocketAvailable()) { + // Packet will get real data in receive + Packet packet(MessageType::Invalid); + m_UDPServer.Receive(packet, pd); + m_Address = pd.Endpoint.address(); + m_Port = pd.Endpoint.port(); + if (packet.GetMessageType() == MessageType::Connect) { + parseConnect(packet, pd); + } else { + parseMessageType(packet); + } + } + std::clock_t currentTime = std::clock(); // Send snapshot if (snapshotInterval < (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC)) { @@ -118,7 +119,7 @@ void Server::broadcast(Packet& packet) { for (auto& kv : m_ConnectedPlayers) { packet.ChangePacketID(kv.second.PacketID); - m_TCPServer.Send(packet, kv.second); + m_UDPServer.Send(packet, kv.second); } } @@ -213,54 +214,54 @@ void Server::checkForTimeOuts() } void Server::parseConnect(Packet & packet, PlayerDefinition & pd) -{ - //LOG_INFO("Parsing connections"); - //// Check if player is already connected - //if (GetPlayerIDFromEndpoint() != -1) { - // return; - //} - //// Create a new player - //pd.EntityID = 0; // Overlook this - //pd.Address = pd.Endpoint.address(); - //pd.Port = pd.Endpoint.port(); - //pd.Name = packet.ReadString(); - //pd.PacketID = 0; - //pd.StopTime = std::clock(); - //m_ConnectedPlayers[m_NextPlayerID++] = pd; - //LOG_INFO("Spectator \"%s\" connected on IP: %s", pd.Name.c_str(), pd.Endpoint.address().to_string().c_str()); - - //// Send a message to the player that connected - //Packet connnectPacket(MessageType::Connect, pd.PacketID); - //m_UDPServer.Send(connnectPacket); - - //// Send notification that a player has connected - //Packet notificationPacket(MessageType::PlayerConnected); - //broadcast(notificationPacket); -} - -void Server::parseTCPConnect(Packet & packet) { LOG_INFO("Parsing connections"); // Check if player is already connected - PlayerID playerID = GetPlayerIDFromEndpoint(); - if (playerID = -1) { + if (GetPlayerIDFromEndpoint() != -1) { return; } // Create a new player - m_ConnectedPlayers.at(playerID).EntityID = 0; // Overlook this - m_ConnectedPlayers.at(playerID).Name = packet.ReadString(); - m_ConnectedPlayers.at(playerID).PacketID = 0; - m_ConnectedPlayers.at(playerID).StopTime = std::clock(); - LOG_INFO("Spectator \"%s\" connected on IP: %s", m_ConnectedPlayers.at(playerID).Name.c_str(), m_ConnectedPlayers.at(playerID).Endpoint.address().to_string().c_str()); + pd.EntityID = 0; // Overlook this + pd.Address = pd.Endpoint.address(); + pd.Port = pd.Endpoint.port(); + pd.Name = packet.ReadString(); + pd.PacketID = 0; + pd.StopTime = std::clock(); + m_ConnectedPlayers[m_NextPlayerID++] = pd; + LOG_INFO("Spectator \"%s\" connected on IP: %s", pd.Name.c_str(), pd.Endpoint.address().to_string().c_str()); // Send a message to the player that connected - Packet connnectPacket(MessageType::Connect, m_ConnectedPlayers.at(playerID).PacketID); - m_TCPServer.Send(connnectPacket); + Packet connnectPacket(MessageType::Connect, pd.PacketID); + m_UDPServer.Send(connnectPacket); // Send notification that a player has connected Packet notificationPacket(MessageType::PlayerConnected); - //broadcast(notificationPacket); + broadcast(notificationPacket); } +// +//void Server::parseTCPConnect(Packet & packet) +//{ +// LOG_INFO("Parsing connections"); +// // Check if player is already connected +// PlayerID playerID = GetPlayerIDFromEndpoint(); +// if (playerID = -1) { +// return; +// } +// // Create a new player +// m_ConnectedPlayers.at(playerID).EntityID = 0; // Overlook this +// m_ConnectedPlayers.at(playerID).Name = packet.ReadString(); +// m_ConnectedPlayers.at(playerID).PacketID = 0; +// m_ConnectedPlayers.at(playerID).StopTime = std::clock(); +// LOG_INFO("Spectator \"%s\" connected on IP: %s", m_ConnectedPlayers.at(playerID).Name.c_str(), m_ConnectedPlayers.at(playerID).Endpoint.address().to_string().c_str()); +// +// // Send a message to the player that connected +// Packet connnectPacket(MessageType::Connect, m_ConnectedPlayers.at(playerID).PacketID); +// m_TCPServer.Send(connnectPacket); +// +// // Send notification that a player has connected +// Packet notificationPacket(MessageType::PlayerConnected); +// //broadcast(notificationPacket); +//} void Server::parseDisconnect() { @@ -310,7 +311,7 @@ void Server::kick(PlayerID player) { disconnect(player); Packet packet = Packet(MessageType::Kick); - m_TCPServer.Send(packet); + m_UDPServer.Send(packet); } bool Server::OnInputCommand(const Events::InputCommand & e) @@ -339,7 +340,7 @@ bool Server::OnPlayerSpawned(const Events::PlayerSpawned & e) packet.WritePrimitive(e.Spawner.ID); // We don't send PlayerID here because it will always be set to -1 packet.WriteString(m_ConnectedPlayers[e.PlayerID].Name); - m_TCPServer.Send(packet, m_ConnectedPlayers[e.PlayerID]); + m_UDPServer.Send(packet, m_ConnectedPlayers[e.PlayerID]); return false; } @@ -375,7 +376,7 @@ void Server::parseClientPing() // Return ping Packet packet(MessageType::Ping, m_ConnectedPlayers[player].PacketID); packet.WriteString("Ping received"); - m_TCPServer.Send(packet); + m_UDPServer.Send(packet); } void Server::parsePing() diff --git a/src/Engine/Network/TCPClient.cpp b/src/Engine/Network/TCPClient.cpp index 69938c38..21bb653f 100644 --- a/src/Engine/Network/TCPClient.cpp +++ b/src/Engine/Network/TCPClient.cpp @@ -83,7 +83,6 @@ void TCPClient::Send(Packet & packet) m_Socket->send(boost::asio::buffer( packet.Data(), packet.Size()), 0, error); - //Network::logSentData(packet.Size()); } bool TCPClient::IsSocketAvailable() diff --git a/src/Engine/Network/TCPServer.cpp b/src/Engine/Network/TCPServer.cpp index 105aab9f..f8da15e2 100644 --- a/src/Engine/Network/TCPServer.cpp +++ b/src/Engine/Network/TCPServer.cpp @@ -12,8 +12,6 @@ TCPServer::~TCPServer() void TCPServer::AcceptNewConnections(int& nextPlayerID, std::map& connectedPlayers) { - //PlayerDefinition pd; - //connectedPlayers[nextPlayerID++] = pd; boost::shared_ptr newSocket = boost::shared_ptr(new tcp::socket(m_IOService)); m_IOService.poll(); acceptor->async_accept(*newSocket, diff --git a/src/Engine/Network/UDPServer.cpp b/src/Engine/Network/UDPServer.cpp index e0bdf3a2..6bf4e466 100644 --- a/src/Engine/Network/UDPServer.cpp +++ b/src/Engine/Network/UDPServer.cpp @@ -6,8 +6,7 @@ UDPServer::UDPServer() } UDPServer::~UDPServer() -{ -} +{ } void UDPServer::Send(Packet& packet, PlayerDefinition & playerDefinition) { @@ -49,13 +48,16 @@ bool UDPServer::IsSocketAvailable() int UDPServer::readBuffer(char* data) { + boost::system::error_code error = boost::asio::error::host_not_found; unsigned int length = m_Socket->receive_from( boost::asio::buffer((void*)data , BUFFERSIZE) - , m_ReceiverEndpoint, 0); + , m_ReceiverEndpoint, 0, error); + if (error) { + LOG_WARNING(error.message().c_str()); + } return length; } void UDPServer::AcceptNewConnections(int& nextPlayerID, std::map& connectedPlayers) -{ -} \ No newline at end of file +{ } \ No newline at end of file From 4f2ad3ad00ab561cb241be49812f757d00416b2b Mon Sep 17 00:00:00 2001 From: Jocke Date: Wed, 10 Feb 2016 16:16:56 +0100 Subject: [PATCH 08/18] Reliable message should now be working, further testing is to be done. --- include/Engine/Network/Client.h | 8 +- include/Engine/Network/PlayerDefinition.h | 4 +- include/Engine/Network/Server.h | 13 +- src/Engine/Network/Client.cpp | 62 ++++++-- src/Engine/Network/Packet.cpp | 7 +- src/Engine/Network/Server.cpp | 165 ++++++++++++---------- src/Engine/Network/TCPServer.cpp | 9 +- src/Engine/Network/UDPClient.cpp | 4 - src/Engine/Network/UDPServer.cpp | 1 - 9 files changed, 160 insertions(+), 113 deletions(-) diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index ffdf812f..d1530b0e 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -70,7 +70,8 @@ protected: void disconnect(); void parseMessageType(Packet& packet); void updateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID, const std::string& componentType); - void parseConnect(Packet& packet); + void parseUDPConnect(Packet& packet); + void parseTCPConnect(Packet& packet); void parsePlayerConnected(Packet& packet); void parsePing(); void parseKick(); @@ -103,9 +104,8 @@ protected: bool OnPlayerSpawned(const Events::PlayerSpawned& e); private: - UDPClient m_UDPClient; - //TCPClient m_TCPClient; - //TCPClient m_UDPClient; + UDPClient m_Unreliable; + TCPClient m_Reliable; }; #endif diff --git a/include/Engine/Network/PlayerDefinition.h b/include/Engine/Network/PlayerDefinition.h index e4c3e5c5..afd5d889 100644 --- a/include/Engine/Network/PlayerDefinition.h +++ b/include/Engine/Network/PlayerDefinition.h @@ -10,8 +10,8 @@ struct PlayerDefinition { boost::asio::ip::udp::endpoint Endpoint; unsigned int PacketID; std::clock_t StopTime; - boost::asio::ip::address Address; - unsigned short Port; + boost::asio::ip::address TCPAddress; + unsigned short TCPPort; // use for tcp connections boost::shared_ptr TCPSocket; }; diff --git a/include/Engine/Network/Server.h b/include/Engine/Network/Server.h index 1b2e6956..7386e43d 100644 --- a/include/Engine/Network/Server.h +++ b/include/Engine/Network/Server.h @@ -59,7 +59,8 @@ protected: // Private member functions //int receive(char* data); - void broadcast(Packet& packet); + void reliableBroadcast(Packet& packet); + void unreliableBroadcast(Packet& packet); void sendSnapshot(); void addChildrenToPacket(Packet& packet, EntityID entityID); void sendPing(); @@ -74,13 +75,9 @@ protected: void parseOnInputCommand(Packet& packet); void parseClientPing(); void parsePing(); - void parseConnect(Packet & packet, PlayerDefinition & pd); + void parseUDPConnect(Packet & packet); void parseTCPConnect(Packet & packet); void parseDisconnect(); - //// Pure virtual functions - //virtual void readFromClients() = 0; - //virtual void send(Packet& packet, PlayerDefinition & playerDefinition) = 0; - //virtual void send(Packet& packet) = 0; // Debug event EventRelay m_EInputCommand; @@ -92,8 +89,8 @@ protected: EventRelay m_EComponentDeleted; bool OnComponentDeleted(const Events::ComponentDeleted& e); private: - //TCPServer m_TCPServer; - UDPServer m_UDPServer; + TCPServer m_Reliable; + UDPServer m_Unreliable; }; #endif diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index eaacac47..ba528f27 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -34,11 +34,27 @@ void Client::Start(World* world, EventBroker* eventBroker) void Client::Update() { m_EventBroker->Process(); - while (m_UDPClient.IsSocketAvailable()) { + while (m_Unreliable.IsSocketAvailable()) { // Packet will get real data in receive Packet packet(MessageType::Invalid); - m_UDPClient.Receive(packet); - parseMessageType(packet); + m_Unreliable.Receive(packet); + if (packet.GetMessageType() == MessageType::Connect) { + parseUDPConnect(packet); + } else { + parseMessageType(packet); + } + } + + while (m_Reliable.IsSocketAvailable()) { + // Packet will get real data in receive + Packet packet(MessageType::Invalid); + m_Reliable.Receive(packet); + if (packet.GetMessageType() == MessageType::Connect) { + parseTCPConnect(packet); + } else { + parseMessageType(packet); + } + } if (m_IsConnected) { @@ -67,9 +83,6 @@ void Client::parseMessageType(Packet& packet) //identifyPacketLoss(); switch (static_cast(messageType)) { - case MessageType::Connect: - parseConnect(packet); - break; case MessageType::Ping: parsePing(); break; @@ -100,12 +113,32 @@ void Client::parseMessageType(Packet& packet) } } -void Client::parseConnect(Packet& packet) +void Client::parseUDPConnect(Packet& packet) { // Map ServerEntityID and your PlayerID LOG_INFO("I be connected PogChamp"); } +void Client::parseTCPConnect(Packet& packet) +{ + LOG_INFO("Received TCP connect from server"); + // Pop size of message int + packet.ReadPrimitive(); + int messageType = packet.ReadPrimitive(); + // Read packet ID + m_PreviousPacketID = m_PacketID; // Set previous packet id + m_PacketID = packet.ReadPrimitive(); //Read new packet id + // parse player id and other stuff + m_PlayerID = packet.ReadPrimitive(); + m_PlayerID = packet.ReadPrimitive(); + LOG_INFO("A Player connected"); + Packet UnreliablePacket(MessageType::Connect, m_SendPacketID); + // Add player id and other stuff + packet.WritePrimitive(m_PlayerID); + m_Unreliable.Send(packet); + LOG_INFO("Sent UDP Connect Server"); +} + void Client::parsePlayerConnected(Packet & packet) { // Map ServerEntityID and other player's PlayerID @@ -123,7 +156,7 @@ void Client::parsePing() Packet packet(MessageType::Ping, m_SendPacketID); packet.WriteString("Ping recieved"); - m_UDPClient.Send(packet); + m_Reliable.Send(packet); } void Client::parseKick() @@ -255,14 +288,15 @@ void Client::disconnect() m_PreviousPacketID = 0; m_PacketID = 0; Packet packet(MessageType::Disconnect, m_SendPacketID); - m_UDPClient.Send(packet); + m_Reliable.Send(packet); } bool Client::OnInputCommand(const Events::InputCommand & e) { if (e.Command == "ConnectToServer") { // Connect for now if (e.Value > 0) { - m_UDPClient.Connect(m_PlayerName, address, port); + m_Reliable.Connect(m_PlayerName, address, port); + m_Unreliable.Connect(m_PlayerName, address, port); } //LOG_DEBUG("Client::OnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID); return true; @@ -299,7 +333,7 @@ bool Client::OnPlayerDamage(const Events::PlayerDamage & e) Packet packet(MessageType::OnPlayerDamage, m_SendPacketID); packet.WritePrimitive(e.Damage); packet.WritePrimitive(m_ClientIDToServerID.at(e.Player.ID)); - m_UDPClient.Send(packet); + m_Reliable.Send(packet); return false; } @@ -327,7 +361,7 @@ void Client::sendLocalPlayerTransform() packet.WritePrimitive(orientation.x); packet.WritePrimitive(orientation.y); packet.WritePrimitive(orientation.z); - m_UDPClient.Send(packet); + m_Unreliable.Send(packet); } void Client::identifyPacketLoss() @@ -370,7 +404,7 @@ void Client::sendInputCommands() packet.WriteString(m_InputCommandBuffer[i].Command); packet.WritePrimitive(m_InputCommandBuffer[i].Value); } - m_UDPClient.Send(packet); + m_Reliable.Send(packet); m_InputCommandBuffer.clear(); } } @@ -378,7 +412,7 @@ void Client::sendInputCommands() void Client::becomePlayer() { Packet packet = Packet(MessageType::BecomePlayer, m_SendPacketID); - m_UDPClient.Send(packet); + m_Reliable.Send(packet); } bool Client::clientServerMapsHasEntity(EntityID clientEntityID) diff --git a/src/Engine/Network/Packet.cpp b/src/Engine/Network/Packet.cpp index c9e8832a..c99390bb 100644 --- a/src/Engine/Network/Packet.cpp +++ b/src/Engine/Network/Packet.cpp @@ -35,11 +35,11 @@ void Packet::Init(MessageType type, unsigned int & packetID) m_Offset = 0; // Create message header // allocate memory for size of packet(only used in tcp) - Packet::WritePrimitive(0); + WritePrimitive(0); // Add message type int messageType = static_cast(type); - Packet::WritePrimitive(messageType); - Packet::WritePrimitive(packetID); + WritePrimitive(messageType); + WritePrimitive(packetID); packetID++; m_HeaderSize = m_Offset; } @@ -98,6 +98,7 @@ void Packet::ReconstructFromData(char * data, int sizeOfData) void Packet::UpdateSize() { + int whatisoffset = m_Offset; memcpy(m_Data, &m_Offset, sizeof(int)); } diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index d3099e12..406abfb7 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -24,31 +24,31 @@ void Server::Start(World* world, EventBroker* eventBroker) void Server::Update() { PlayerDefinition pd; - - //m_TCPServer.AcceptNewConnections(m_NextPlayerID, m_ConnectedPlayers); - //for (auto& kv : m_ConnectedPlayers) { - // while (kv.second.TCPSocket->available()) { - // // Packet will get real data in receive - // Packet packet(MessageType::Invalid); - // m_TCPServer.Receive(packet, kv.second); - // m_Address = kv.second.TCPSocket->remote_endpoint().address(); - // m_Port = kv.second.TCPSocket->remote_endpoint().port(); - // if (packet.GetMessageType() == MessageType::Connect) { - // parseTCPConnect(packet); - // } else { - // parseMessageType(packet); - // } - // } - //} - while (m_UDPServer.IsSocketAvailable()) { + m_Reliable.AcceptNewConnections(m_NextPlayerID, m_ConnectedPlayers); + for (auto& kv : m_ConnectedPlayers) { + while (kv.second.TCPSocket->available()) { + // Packet will get real data in receive + Packet packet(MessageType::Invalid); + m_Reliable.Receive(packet, kv.second); + m_Address = kv.second.TCPSocket->remote_endpoint().address(); + m_Port = kv.second.TCPSocket->remote_endpoint().port(); + if (packet.GetMessageType() == MessageType::Connect) { + parseTCPConnect(packet); + } else { + parseMessageType(packet); + } + } + } + + while (m_Unreliable.IsSocketAvailable()) { // Packet will get real data in receive Packet packet(MessageType::Invalid); - m_UDPServer.Receive(packet, pd); + m_Unreliable.Receive(packet, pd); m_Address = pd.Endpoint.address(); m_Port = pd.Endpoint.port(); if (packet.GetMessageType() == MessageType::Connect) { - parseConnect(packet, pd); + parseUDPConnect(packet); } else { parseMessageType(packet); } @@ -115,11 +115,19 @@ void Server::parseMessageType(Packet& packet) } } -void Server::broadcast(Packet& packet) +void Server::reliableBroadcast(Packet& packet) { for (auto& kv : m_ConnectedPlayers) { packet.ChangePacketID(kv.second.PacketID); - m_UDPServer.Send(packet, kv.second); + m_Reliable.Send(packet, kv.second); + } +} + +void Server::unreliableBroadcast(Packet& packet) +{ + for (auto& kv : m_ConnectedPlayers) { + packet.ChangePacketID(kv.second.PacketID); + m_Unreliable.Send(packet, kv.second); } } @@ -128,7 +136,7 @@ void Server::sendSnapshot() { Packet packet(MessageType::Snapshot); addChildrenToPacket(packet, EntityID_Invalid); - broadcast(packet); + unreliableBroadcast(packet); } void Server::addChildrenToPacket(Packet & packet, EntityID entityID) @@ -189,7 +197,7 @@ void Server::sendPing() // Time message m_StartPingTime = std::clock(); // Send message - broadcast(packet); + reliableBroadcast(packet); } void Server::checkForTimeOuts() @@ -199,7 +207,7 @@ void Server::checkForTimeOuts() std::vector playersToRemove; for (auto& kv : m_ConnectedPlayers) { - if (kv.second.Address != boost::asio::ip::address()) { + if (kv.second.TCPAddress != boost::asio::ip::address()) { int stopPing = 1000 * kv.second.StopTime / static_cast(CLOCKS_PER_SEC); if (startPing > stopPing + m_TimeoutMs) { @@ -213,63 +221,71 @@ void Server::checkForTimeOuts() } } -void Server::parseConnect(Packet & packet, PlayerDefinition & pd) +void Server::parseUDPConnect(Packet & packet) { + // Pop size of message int + packet.ReadPrimitive(); + int messageType = packet.ReadPrimitive(); + // Read packet ID + m_PreviousPacketID = m_PacketID; // Set previous packet id + m_PacketID = packet.ReadPrimitive(); //Read new packet id + // parse player id and other stuff + PlayerID playerID = packet.ReadPrimitive(); + // Do something here? + boost::asio::ip::udp::endpoint endpoint(m_Address, m_Port); + m_ConnectedPlayers.at(playerID).Endpoint = endpoint; + LOG_INFO("parseUDPConnect: Spectator \"%s\" connected on IP: %s", m_ConnectedPlayers.at(playerID).Name.c_str(), m_ConnectedPlayers.at(playerID).Endpoint.address().to_string().c_str()); + // Send a message to the player that connected + Packet connnectPacket(MessageType::Connect, m_ConnectedPlayers.at(playerID).PacketID); + m_Unreliable.Send(connnectPacket); + LOG_INFO("UDP Connect sent to client"); +} + +void Server::parseTCPConnect(Packet & packet) +{ + // Pop size of message int + packet.ReadPrimitive(); + int messageType = packet.ReadPrimitive(); + // Read packet ID + m_PreviousPacketID = m_PacketID; // Set previous packet id + m_PacketID = packet.ReadPrimitive(); //Read new packet id + LOG_INFO("Parsing connections"); // Check if player is already connected - if (GetPlayerIDFromEndpoint() != -1) { + // Ska vara till lagd i TCPServer receive + PlayerID playerID = GetPlayerIDFromEndpoint(); + if (playerID == -1) { return; } // Create a new player - pd.EntityID = 0; // Overlook this - pd.Address = pd.Endpoint.address(); - pd.Port = pd.Endpoint.port(); - pd.Name = packet.ReadString(); - pd.PacketID = 0; - pd.StopTime = std::clock(); - m_ConnectedPlayers[m_NextPlayerID++] = pd; - LOG_INFO("Spectator \"%s\" connected on IP: %s", pd.Name.c_str(), pd.Endpoint.address().to_string().c_str()); + m_ConnectedPlayers.at(playerID).EntityID = 0; // Overlook this + m_ConnectedPlayers.at(playerID).Name = packet.ReadString(); + m_ConnectedPlayers.at(playerID).PacketID = 0; + m_ConnectedPlayers.at(playerID).StopTime = std::clock(); + m_ConnectedPlayers.at(playerID).TCPAddress = m_Address; + m_ConnectedPlayers.at(playerID).TCPPort = m_Port; + + LOG_INFO("parseTCPConnect: Spectator \"%s\" connected on IP: %s", m_ConnectedPlayers.at(playerID).Name.c_str(), + m_ConnectedPlayers.at(playerID).TCPAddress); // Send a message to the player that connected - Packet connnectPacket(MessageType::Connect, pd.PacketID); - m_UDPServer.Send(connnectPacket); + Packet connnectPacket(MessageType::Connect, m_ConnectedPlayers.at(playerID).PacketID); + // Write playerID to packet + connnectPacket.WritePrimitive(playerID); + m_Reliable.Send(connnectPacket); // Send notification that a player has connected - Packet notificationPacket(MessageType::PlayerConnected); - broadcast(notificationPacket); + //Packet notificationPacket(MessageType::PlayerConnected); + //broadcast(notificationPacket); } -// -//void Server::parseTCPConnect(Packet & packet) -//{ -// LOG_INFO("Parsing connections"); -// // Check if player is already connected -// PlayerID playerID = GetPlayerIDFromEndpoint(); -// if (playerID = -1) { -// return; -// } -// // Create a new player -// m_ConnectedPlayers.at(playerID).EntityID = 0; // Overlook this -// m_ConnectedPlayers.at(playerID).Name = packet.ReadString(); -// m_ConnectedPlayers.at(playerID).PacketID = 0; -// m_ConnectedPlayers.at(playerID).StopTime = std::clock(); -// LOG_INFO("Spectator \"%s\" connected on IP: %s", m_ConnectedPlayers.at(playerID).Name.c_str(), m_ConnectedPlayers.at(playerID).Endpoint.address().to_string().c_str()); -// -// // Send a message to the player that connected -// Packet connnectPacket(MessageType::Connect, m_ConnectedPlayers.at(playerID).PacketID); -// m_TCPServer.Send(connnectPacket); -// -// // Send notification that a player has connected -// Packet notificationPacket(MessageType::PlayerConnected); -// //broadcast(notificationPacket); -//} void Server::parseDisconnect() { LOG_INFO("%i: Parsing disconnect", m_PacketID); for (auto& kv : m_ConnectedPlayers) { - if (kv.second.Address == m_Address && - kv.second.Port == m_Port) { + if (kv.second.TCPAddress == m_Address && + kv.second.TCPPort == m_Port) { disconnect(kv.first); break; } @@ -311,7 +327,7 @@ void Server::kick(PlayerID player) { disconnect(player); Packet packet = Packet(MessageType::Kick); - m_UDPServer.Send(packet); + m_Reliable.Send(packet); } bool Server::OnInputCommand(const Events::InputCommand & e) @@ -340,7 +356,7 @@ bool Server::OnPlayerSpawned(const Events::PlayerSpawned & e) packet.WritePrimitive(e.Spawner.ID); // We don't send PlayerID here because it will always be set to -1 packet.WriteString(m_ConnectedPlayers[e.PlayerID].Name); - m_UDPServer.Send(packet, m_ConnectedPlayers[e.PlayerID]); + m_Reliable.Send(packet, m_ConnectedPlayers[e.PlayerID]); return false; } @@ -349,7 +365,7 @@ bool Server::OnEntityDeleted(const Events::EntityDeleted & e) if (!e.Cascaded) { Packet packet = Packet(MessageType::EntityDeleted); packet.WritePrimitive(e.DeletedEntity); - broadcast(packet); + reliableBroadcast(packet); } return false; } @@ -360,7 +376,7 @@ bool Server::OnComponentDeleted(const Events::ComponentDeleted & e) Packet packet = Packet(MessageType::ComponentDeleted); packet.WritePrimitive(e.Entity); packet.WriteString(e.ComponentType); - broadcast(packet); + reliableBroadcast(packet); } return false; } @@ -376,14 +392,14 @@ void Server::parseClientPing() // Return ping Packet packet(MessageType::Ping, m_ConnectedPlayers[player].PacketID); packet.WriteString("Ping received"); - m_UDPServer.Send(packet); + m_Reliable.Send(packet); } void Server::parsePing() { for (auto& kv : m_ConnectedPlayers) { - if (kv.second.Address == m_Address && - kv.second.Port == m_Port) { + if (kv.second.TCPAddress == m_Address && + kv.second.TCPPort == m_Port) { kv.second.StopTime = std::clock(); break; } @@ -430,9 +446,12 @@ void Server::parsePlayerTransform(Packet& packet) PlayerID Server::GetPlayerIDFromEndpoint() { + // check both tcp and udp connection for (auto& kv : m_ConnectedPlayers) { - if (kv.second.Address == m_Address && - kv.second.Port == m_Port) { + if ((kv.second.TCPAddress == m_Address + && kv.second.TCPPort == m_Port) + || (kv.second.Endpoint.address() == m_Address + && kv.second.Endpoint.port() == m_Port)) { return kv.first; } } diff --git a/src/Engine/Network/TCPServer.cpp b/src/Engine/Network/TCPServer.cpp index f8da15e2..0b44013d 100644 --- a/src/Engine/Network/TCPServer.cpp +++ b/src/Engine/Network/TCPServer.cpp @@ -23,8 +23,8 @@ PlayerID GetPlayerIDFromEndpoint(const std::map& con boost::asio::ip::address address, unsigned short port) { for (auto& kv : connectedPlayers) { - if (kv.second.Address == address && - kv.second.Port == port) { + if (kv.second.TCPAddress == address && + kv.second.TCPPort == port) { return kv.first; } } @@ -43,8 +43,8 @@ void TCPServer::handle_accept(boost::shared_ptr socket, PlayerDefinition pd; pd.StopTime = std::clock(); pd.TCPSocket = socket; - pd.Address = socket.get()->remote_endpoint().address(); - pd.Port = socket.get()->remote_endpoint().port(); + pd.TCPAddress = socket.get()->remote_endpoint().address(); + pd.TCPPort = socket.get()->remote_endpoint().port(); connectedPlayers[nextPlayerID++] = pd; } } @@ -78,6 +78,7 @@ void TCPServer::Receive(Packet & packet, PlayerDefinition & playerDefinition) if (bytesRead > 0) { packet.ReconstructFromData(m_ReadBuffer, bytesRead); } + lastReceivedSocket = playerDefinition.TCPSocket; } int TCPServer::readBuffer(char* data, PlayerDefinition & playerDefinition) diff --git a/src/Engine/Network/UDPClient.cpp b/src/Engine/Network/UDPClient.cpp index e5eafc08..c76de084 100644 --- a/src/Engine/Network/UDPClient.cpp +++ b/src/Engine/Network/UDPClient.cpp @@ -18,10 +18,6 @@ void UDPClient::Connect(std::string playerName, std::string address, int port) m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string(address), port); m_Socket = boost::shared_ptr(new boost::asio::ip::udp::socket(m_IOService)); m_Socket->connect(m_ReceiverEndpoint); - - Packet packet(MessageType::Connect, m_SendPacketID); - packet.WriteString(playerName); - Send(packet); } void UDPClient::Disconnect() diff --git a/src/Engine/Network/UDPServer.cpp b/src/Engine/Network/UDPServer.cpp index 6bf4e466..4b0a08ba 100644 --- a/src/Engine/Network/UDPServer.cpp +++ b/src/Engine/Network/UDPServer.cpp @@ -31,7 +31,6 @@ void UDPServer::Send(Packet & packet) 0); } - void UDPServer::Receive(Packet & packet, PlayerDefinition & playerDefinition) { int bytesRead = readBuffer(m_ReadBuffer); From 7cbdc33f840fa53075af983a6e3157baaf3c10bd Mon Sep 17 00:00:00 2001 From: Jocke Date: Wed, 10 Feb 2016 17:39:23 +0100 Subject: [PATCH 09/18] Updated submodules --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 7531e441..1c510a53 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 7531e441fea639076d69c6cf05e3ae8ff7170cf9 +Subproject commit 1c510a53d38b0f443ef141ddb3265a76c394ef7c From 95fa1f4bbd4f1b757e05236d58aec9802a218973 Mon Sep 17 00:00:00 2001 From: Jocke Date: Wed, 10 Feb 2016 20:10:20 +0100 Subject: [PATCH 10/18] Connect Fix for TCP Client --- src/Engine/Network/TCPClient.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/Engine/Network/TCPClient.cpp b/src/Engine/Network/TCPClient.cpp index 21bb653f..703e4cbe 100644 --- a/src/Engine/Network/TCPClient.cpp +++ b/src/Engine/Network/TCPClient.cpp @@ -19,16 +19,25 @@ void TCPClient::Connect(std::string playerName, std::string address, int port) Send(packet); LOG_INFO("Connect message sent again!"); } - return; + else { + boost::system::error_code error = boost::asio::error::host_not_found; + m_Socket->connect(m_Endpoint, error); + if (!error) { + m_IsConnected = true; + Packet packet(MessageType::Connect, m_SendPacketID); + packet.WriteString(playerName); + Send(packet); + LOG_INFO("Connect message sent!"); + } + } } - if (!m_IsConnected) { + else if (!m_IsConnected) { boost::system::error_code error = boost::asio::error::host_not_found; m_Endpoint = tcp::endpoint(boost::asio::ip::address::from_string(address), port); - m_Socket = std::unique_ptr(new tcp::socket(m_IOService, m_Endpoint)); + m_Socket = std::unique_ptr(new tcp::socket(m_IOService)); + m_Socket->connect(m_Endpoint, error); tcp::no_delay option(true); m_Socket->set_option(option); - m_Socket->close(); - m_Socket->connect(m_Endpoint, error); LOG_INFO(error.message().c_str()); if (!error) { m_IsConnected = true; From ec54b1298d0b7d383ae837337ded5eb190705f44 Mon Sep 17 00:00:00 2001 From: Jocke Date: Wed, 10 Feb 2016 21:02:46 +0100 Subject: [PATCH 11/18] Reconnect is now possible. --- include/Engine/Network/TCPServer.h | 1 + src/Engine/Network/Client.cpp | 5 +++-- src/Engine/Network/Server.cpp | 2 ++ src/Engine/Network/TCPClient.cpp | 9 ++++++++- src/Engine/Network/TCPServer.cpp | 5 +++++ 5 files changed, 19 insertions(+), 3 deletions(-) diff --git a/include/Engine/Network/TCPServer.h b/include/Engine/Network/TCPServer.h index b1aa7ce0..9cc7646a 100644 --- a/include/Engine/Network/TCPServer.h +++ b/include/Engine/Network/TCPServer.h @@ -15,6 +15,7 @@ public: void Receive(Packet & packet, PlayerDefinition & playerDefinition); void Send(Packet & packet, PlayerDefinition & playerDefinition); void Send(Packet & packet); + void Disconnect(); private: // TCP logic boost::asio::io_service m_IOService; diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 4eaefde2..f7fc956c 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -58,13 +58,14 @@ void Client::Update() } if (m_IsConnected) { - hasServerTimedOut(); // Don't send 1 input in 1 packet, bunch em up. if (m_SendInputIntervalMs < (1000 * (std::clock() - m_TimeSinceSentInputs) / (double)CLOCKS_PER_SEC)) { sendInputCommands(); m_TimeSinceSentInputs = std::clock(); } sendLocalPlayerTransform(); + + m_IsConnected = !hasServerTimedOut(); } //Network::Update(); } @@ -380,7 +381,7 @@ bool Client::hasServerTimedOut() if (timeSincePing > m_TimeoutMs) { // Clear everything and go to menu. LOG_INFO("Server has timed out, returning to menu, Beep Boop."); - m_IsConnected = false; + m_Reliable.Disconnect(); return true; } return false; diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index bc2099bd..0c9af69c 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -302,6 +302,8 @@ void Server::disconnect(PlayerID playerID) e.PlayerID = playerID; m_EventBroker->Publish(e); + m_ConnectedPlayers[playerID].TCPSocket->shutdown(boost::asio::ip::tcp::socket::shutdown_both); + m_ConnectedPlayers[playerID].TCPSocket->close(); m_ConnectedPlayers.erase(playerID); } diff --git a/src/Engine/Network/TCPClient.cpp b/src/Engine/Network/TCPClient.cpp index 703e4cbe..5c8ccee7 100644 --- a/src/Engine/Network/TCPClient.cpp +++ b/src/Engine/Network/TCPClient.cpp @@ -51,7 +51,10 @@ void TCPClient::Connect(std::string playerName, std::string address, int port) void TCPClient::Disconnect() { - + m_Socket->shutdown(boost::asio::ip::tcp::socket::shutdown_both); + m_Socket->close(); + m_Socket = nullptr; + m_IsConnected = false; } void TCPClient::Receive(Packet& packet) @@ -87,6 +90,10 @@ int TCPClient::readBuffer(char* data) void TCPClient::Send(Packet & packet) { + if (!m_Socket) { + LOG_WARNING("TCPClient::Send: Socket is null"); + return; + } packet.UpdateSize(); boost::system::error_code error; m_Socket->send(boost::asio::buffer( diff --git a/src/Engine/Network/TCPServer.cpp b/src/Engine/Network/TCPServer.cpp index 0b44013d..2bfcde74 100644 --- a/src/Engine/Network/TCPServer.cpp +++ b/src/Engine/Network/TCPServer.cpp @@ -72,6 +72,11 @@ void TCPServer::Send(Packet & packet) 0); } +void TCPServer::Disconnect() +{ + +} + void TCPServer::Receive(Packet & packet, PlayerDefinition & playerDefinition) { int bytesRead = readBuffer(m_ReadBuffer, playerDefinition); From eb244f87c4e773fd2939d24e2141cbeae10b2705 Mon Sep 17 00:00:00 2001 From: Jocke Date: Wed, 10 Feb 2016 23:27:46 +0100 Subject: [PATCH 12/18] Added disconnect functionality and removed some warnings. --- include/Engine/Network/Client.h | 2 +- include/Engine/Network/Packet.h | 2 +- include/Engine/Network/Server.h | 9 +++++---- include/Engine/Network/TCPClient.h | 2 +- src/Engine/Network/Client.cpp | 11 +++++------ src/Engine/Network/Packet.cpp | 2 +- src/Engine/Network/Server.cpp | 13 ++++++++++--- src/Engine/Network/TCPClient.cpp | 9 ++++++--- src/Engine/Network/TCPServer.cpp | 2 +- 9 files changed, 31 insertions(+), 21 deletions(-) diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index 4ff2ecf8..76bb0470 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -82,7 +82,7 @@ protected: void InterpolateFields(Packet & packet, const ComponentInfo & componentInfo, const EntityID & entityID, const std::string & componentType); void parseSnapshot(Packet& packet); void identifyPacketLoss(); - bool hasServerTimedOut(); + void hasServerTimedOut(); EntityID createPlayer(); void sendInputCommands(); void sendLocalPlayerTransform(); diff --git a/include/Engine/Network/Packet.h b/include/Engine/Network/Packet.h index 694fd703..b688b8c6 100644 --- a/include/Engine/Network/Packet.h +++ b/include/Engine/Network/Packet.h @@ -50,7 +50,7 @@ public: // Pops the first element as if it was a string. std::string ReadString(); // Construct a packet - void ReconstructFromData(char* data, int SizeOfData); + void ReconstructFromData(char* data, size_t SizeOfData); // Update size of packet variable in header void UpdateSize(); char* ReadData(int SizeOfData); diff --git a/include/Engine/Network/Server.h b/include/Engine/Network/Server.h index 308a74ed..ee40b707 100644 --- a/include/Engine/Network/Server.h +++ b/include/Engine/Network/Server.h @@ -27,12 +27,16 @@ public: ~Server(); void Start(World* m_world, EventBroker *eventBroker) override; void Update() override; -protected: +private: + // Network channels + TCPServer m_Reliable; + UDPServer m_Unreliable; // dont forget to set these in the childrens receive logic boost::asio::ip::address m_Address; unsigned short m_Port; // Sending messages to client logic std::map m_ConnectedPlayers; + std::vector m_PlayersToDisconnect; // HACK: Fix INPUTSIZE char readBuffer[BUFFERSIZE] = { 0 }; size_t bytesRead = 0; @@ -88,9 +92,6 @@ protected: bool OnEntityDeleted(const Events::EntityDeleted& e); EventRelay m_EComponentDeleted; bool OnComponentDeleted(const Events::ComponentDeleted& e); -private: - TCPServer m_Reliable; - UDPServer m_Unreliable; }; #endif diff --git a/include/Engine/Network/TCPClient.h b/include/Engine/Network/TCPClient.h index 9f61cca5..a666cbbe 100644 --- a/include/Engine/Network/TCPClient.h +++ b/include/Engine/Network/TCPClient.h @@ -20,7 +20,7 @@ private: boost::asio::ip::tcp::endpoint m_Endpoint; boost::asio::io_service m_IOService; std::unique_ptr m_Socket; - int readBuffer(char* data); + size_t readBuffer(char* data); PacketID m_SendPacketID = 0; bool m_IsConnected = false; }; diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index f7fc956c..c5c7596e 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -64,8 +64,8 @@ void Client::Update() m_TimeSinceSentInputs = std::clock(); } sendLocalPlayerTransform(); - - m_IsConnected = !hasServerTimedOut(); + + hasServerTimedOut(); } //Network::Update(); } @@ -290,6 +290,7 @@ void Client::disconnect() m_PacketID = 0; Packet packet(MessageType::Disconnect, m_SendPacketID); m_Reliable.Send(packet); + m_Reliable.Disconnect(); } bool Client::OnInputCommand(const Events::InputCommand & e) @@ -374,17 +375,15 @@ void Client::identifyPacketLoss() } } -bool Client::hasServerTimedOut() +void Client::hasServerTimedOut() { // Time in ms double timeSincePing = 1000 * (std::clock() - m_StartPingTime) / static_cast(CLOCKS_PER_SEC); if (timeSincePing > m_TimeoutMs) { // Clear everything and go to menu. LOG_INFO("Server has timed out, returning to menu, Beep Boop."); - m_Reliable.Disconnect(); - return true; + disconnect(); } - return false; } EntityID Client::createPlayer() diff --git a/src/Engine/Network/Packet.cpp b/src/Engine/Network/Packet.cpp index af8f91c2..475ca673 100644 --- a/src/Engine/Network/Packet.cpp +++ b/src/Engine/Network/Packet.cpp @@ -81,7 +81,7 @@ std::string Packet::ReadString() return returnValue; } -void Packet::ReconstructFromData(char * data, int sizeOfData) +void Packet::ReconstructFromData(char * data, size_t sizeOfData) { if (sizeOfData > m_MaxPacketSize) { // Delete our data diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index 0c9af69c..8a0ecd36 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -53,6 +53,11 @@ void Server::Update() parseMessageType(packet); } } + // Check if players have disconnected + for (int i = 0; i < m_PlayersToDisconnect.size(); i++) { + disconnect(m_PlayersToDisconnect.at(i)); + } + m_PlayersToDisconnect.clear(); std::clock_t currentTime = std::clock(); // Send snapshot @@ -74,6 +79,7 @@ void Server::Update() if (isReadingData) { Network::Update(); } + } void Server::parseMessageType(Packet& packet) @@ -249,7 +255,7 @@ void Server::parseTCPConnect(Packet & packet) // Read packet ID m_PreviousPacketID = m_PacketID; // Set previous packet id m_PacketID = packet.ReadPrimitive(); //Read new packet id - + LOG_INFO("Parsing connections"); // Check if player is already connected // Ska vara till lagd i TCPServer receive @@ -286,7 +292,7 @@ void Server::parseDisconnect() for (auto& kv : m_ConnectedPlayers) { if (kv.second.TCPAddress == m_Address && kv.second.TCPPort == m_Port) { - disconnect(kv.first); + m_PlayersToDisconnect.push_back(kv.first); break; } } @@ -301,10 +307,11 @@ void Server::disconnect(PlayerID playerID) e.Entity = m_ConnectedPlayers.at(playerID).EntityID; e.PlayerID = playerID; m_EventBroker->Publish(e); - + //m_World->DeleteEntity(m_ConnectedPlayers[playerID].EntityID); m_ConnectedPlayers[playerID].TCPSocket->shutdown(boost::asio::ip::tcp::socket::shutdown_both); m_ConnectedPlayers[playerID].TCPSocket->close(); m_ConnectedPlayers.erase(playerID); + // Send disconnect to the other players. } void Server::parseOnPlayerDamage(Packet & packet) diff --git a/src/Engine/Network/TCPClient.cpp b/src/Engine/Network/TCPClient.cpp index 5c8ccee7..38bac621 100644 --- a/src/Engine/Network/TCPClient.cpp +++ b/src/Engine/Network/TCPClient.cpp @@ -51,6 +51,9 @@ void TCPClient::Connect(std::string playerName, std::string address, int port) void TCPClient::Disconnect() { + if (!m_IsConnected) { + return; + } m_Socket->shutdown(boost::asio::ip::tcp::socket::shutdown_both); m_Socket->close(); m_Socket = nullptr; @@ -59,20 +62,20 @@ void TCPClient::Disconnect() void TCPClient::Receive(Packet& packet) { - int bytesRead = readBuffer(m_ReadBuffer); + size_t bytesRead = readBuffer(m_ReadBuffer); if (bytesRead > 0) { packet.ReconstructFromData(m_ReadBuffer, bytesRead); } } -int TCPClient::readBuffer(char* data) +size_t TCPClient::readBuffer(char* data) { if (!m_Socket) { return 0; } boost::system::error_code error; // Read size of packet - int bytesReceived = m_Socket->read_some(boost + size_t bytesReceived = m_Socket->read_some(boost ::asio::buffer((void*)data, sizeof(int)), error); int sizeOfPacket = 0; diff --git a/src/Engine/Network/TCPServer.cpp b/src/Engine/Network/TCPServer.cpp index 2bfcde74..a449e684 100644 --- a/src/Engine/Network/TCPServer.cpp +++ b/src/Engine/Network/TCPServer.cpp @@ -93,7 +93,7 @@ int TCPServer::readBuffer(char* data, PlayerDefinition & playerDefinition) } boost::system::error_code error; // Read size of packet - int bytesReceived = playerDefinition.TCPSocket->read_some(boost + size_t bytesReceived = playerDefinition.TCPSocket->read_some(boost ::asio::buffer((void*)data, sizeof(int)), error); int sizeOfPacket = 0; From fa2e556ab2d2865ea29c7ef1a4735f845bdbc83c Mon Sep 17 00:00:00 2001 From: Jocke Date: Thu, 11 Feb 2016 14:07:51 +0100 Subject: [PATCH 13/18] fixed some error handling in TCPClient. --- src/Engine/Network/Server.cpp | 2 +- src/Engine/Network/TCPClient.cpp | 16 +++++----------- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index 8a0ecd36..cc774c2f 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -272,7 +272,7 @@ void Server::parseTCPConnect(Packet & packet) m_ConnectedPlayers.at(playerID).TCPPort = m_Port; LOG_INFO("parseTCPConnect: Spectator \"%s\" connected on IP: %s", m_ConnectedPlayers.at(playerID).Name.c_str(), - m_ConnectedPlayers.at(playerID).TCPAddress); + m_ConnectedPlayers.at(playerID).TCPAddress.to_string().c_str()); // Send a message to the player that connected Packet connnectPacket(MessageType::Connect, m_ConnectedPlayers.at(playerID).PacketID); diff --git a/src/Engine/Network/TCPClient.cpp b/src/Engine/Network/TCPClient.cpp index 38bac621..df4f3826 100644 --- a/src/Engine/Network/TCPClient.cpp +++ b/src/Engine/Network/TCPClient.cpp @@ -19,17 +19,6 @@ void TCPClient::Connect(std::string playerName, std::string address, int port) Send(packet); LOG_INFO("Connect message sent again!"); } - else { - boost::system::error_code error = boost::asio::error::host_not_found; - m_Socket->connect(m_Endpoint, error); - if (!error) { - m_IsConnected = true; - Packet packet(MessageType::Connect, m_SendPacketID); - packet.WriteString(playerName); - Send(packet); - LOG_INFO("Connect message sent!"); - } - } } else if (!m_IsConnected) { boost::system::error_code error = boost::asio::error::host_not_found; @@ -46,6 +35,11 @@ void TCPClient::Connect(std::string playerName, std::string address, int port) Send(packet); LOG_INFO("Connect message sent!"); } + // If error + else { + m_Socket->close(); + m_Socket = nullptr; + } } } From 49d4a45ef87f86b56b9896f1cdd3250e4ba92086 Mon Sep 17 00:00:00 2001 From: Jocke Date: Thu, 11 Feb 2016 16:27:33 +0100 Subject: [PATCH 14/18] Client crashed when connecting, this was a hot fix. --- src/Engine/Rendering/PickingPass.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Engine/Rendering/PickingPass.cpp b/src/Engine/Rendering/PickingPass.cpp index cc9837ff..07440749 100644 --- a/src/Engine/Rendering/PickingPass.cpp +++ b/src/Engine/Rendering/PickingPass.cpp @@ -104,8 +104,11 @@ void PickingPass::Draw(RenderScene& scene) std::vector frameBones; frameBones = modelJob->Skeleton->GetBones(); - glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); - + // temp check revise later crashed client when connectiong + // frameBones.size() was 0 // Jocke + if (frameBones.size() > 0) { + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + } } } else { m_PickingProgram->Bind(); From afd9e24df64d0c4d7541aee9c327180ee2427fa0 Mon Sep 17 00:00:00 2001 From: stiffly Date: Thu, 11 Feb 2016 21:23:53 +0100 Subject: [PATCH 15/18] Reverted last commit. Also testing to delay OnPlayerSpawn event for clients. No progress... --- include/Engine/Network/Client.h | 2 + src/Engine/Network/Client.cpp | 29 ++++++++++++-- src/Engine/Rendering/PickingPass.cpp | 59 +++++++++++++--------------- 3 files changed, 54 insertions(+), 36 deletions(-) diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index 7ea63ad8..f2b18eee 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -35,6 +35,8 @@ public: void Connect(std::string address, int port); void Update() override; + std::vector m_PlayerSpawnEvents; + void parseSpawnEvents(); // Save for children std::unique_ptr m_SnapshotFilter = nullptr; diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 7c19d852..d88becdb 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -54,7 +54,6 @@ void Client::Update() parseMessageType(packet); } } - while (m_Reliable.IsSocketAvailable()) { // Packet will get real data in receive Packet packet(MessageType::Invalid); @@ -177,14 +176,35 @@ void Client::parseKick() m_IsConnected = false; } +void Client::parseSpawnEvents() +{ + for (int i = 0; i < m_PlayerSpawnEvents.size(); i++) { + Events::PlayerSpawned e; + e.Player = EntityWrapper(m_World, m_ServerIDToClientID[m_PlayerSpawnEvents[i].Player.ID]); + e.Spawner = EntityWrapper(m_World, m_ServerIDToClientID[m_PlayerSpawnEvents[i].Spawner.ID]); + e.PlayerID = -1; + e.PlayerName = m_PlayerSpawnEvents[i].PlayerName; + m_EventBroker->Publish(e); + } + m_PlayerSpawnEvents.clear(); +} + void Client::parsePlayersSpawned(Packet& packet) { + //Events::PlayerSpawned e; + //e.Player = EntityWrapper(m_World, m_ServerIDToClientID[packet.ReadPrimitive()]); + //e.Spawner = EntityWrapper(m_World, m_ServerIDToClientID[packet.ReadPrimitive()]); + //e.PlayerID = -1; + //e.PlayerName = packet.ReadString(); + //m_EventBroker->Publish(e); + Events::PlayerSpawned e; - e.Player = EntityWrapper(m_World, m_ServerIDToClientID[packet.ReadPrimitive()]); - e.Spawner = EntityWrapper(m_World, m_ServerIDToClientID[packet.ReadPrimitive()]); + e.Player = EntityWrapper(m_World, packet.ReadPrimitive()); + e.Spawner = EntityWrapper(m_World, packet.ReadPrimitive()); e.PlayerID = -1; e.PlayerName = packet.ReadString(); - m_EventBroker->Publish(e); + m_PlayerSpawnEvents.push_back(e); + parseSpawnEvents(); } void Client::parseEntityDeletion(Packet & packet) @@ -322,6 +342,7 @@ void Client::parseSnapshot(Packet& packet) m_World->SetParent(localEntityID, m_ServerIDToClientID.at(serverParentID)); } } + // parseSpawnEvents(); } void Client::disconnect() diff --git a/src/Engine/Rendering/PickingPass.cpp b/src/Engine/Rendering/PickingPass.cpp index 07440749..2a0a8cf8 100644 --- a/src/Engine/Rendering/PickingPass.cpp +++ b/src/Engine/Rendering/PickingPass.cpp @@ -42,22 +42,22 @@ void PickingPass::InitializeShaderPrograms() m_PickingProgram->BindFragDataLocation(0, "TextureFragment"); m_PickingProgram->Link(); - m_PickingSkinnedProgram = ResourceManager::Load("#PickingSkinnedProgram"); + m_PickingSkinnedProgram = ResourceManager::Load("#PickingSkinnedProgram"); - m_PickingSkinnedProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/PickingSkinned.vert.glsl"))); - m_PickingSkinnedProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/Picking.frag.glsl"))); - m_PickingSkinnedProgram->Compile(); - m_PickingSkinnedProgram->BindFragDataLocation(0, "TextureFragment"); - m_PickingSkinnedProgram->Link(); + m_PickingSkinnedProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/PickingSkinned.vert.glsl"))); + m_PickingSkinnedProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/Picking.frag.glsl"))); + m_PickingSkinnedProgram->Compile(); + m_PickingSkinnedProgram->BindFragDataLocation(0, "TextureFragment"); + m_PickingSkinnedProgram->Link(); } void PickingPass::Draw(RenderScene& scene) { PickingPassState* state = new PickingPassState(m_PickingBuffer.GetHandle()); - + //TODO: Render: Add code for more jobs than modeljobs. GLuint shaderHandle = m_PickingProgram->GetHandle(); - GLuint shaderSkinnedHandle = m_PickingSkinnedProgram->GetHandle(); + GLuint shaderSkinnedHandle = m_PickingSkinnedProgram->GetHandle(); m_PickingProgram->Bind(); if (scene.ClearDepth) { @@ -92,31 +92,26 @@ void PickingPass::Draw(RenderScene& scene) m_PickingColorsToEntity[glm::ivec2(pickColor[0], pickColor[1])] = pickInfo; - if (modelJob->Model->IsSkinned()) - { - m_PickingSkinnedProgram->Bind(); - glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix)); - glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); - glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); - glUniform2fv(glGetUniformLocation(shaderSkinnedHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1]))); + if (modelJob->Model->IsSkinned()) { + m_PickingSkinnedProgram->Bind(); + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix)); + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + glUniform2fv(glGetUniformLocation(shaderSkinnedHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1]))); - if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) { + if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) { std::vector frameBones; frameBones = modelJob->Skeleton->GetBones(); - // temp check revise later crashed client when connectiong - // frameBones.size() was 0 // Jocke - if (frameBones.size() > 0) { - glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); - } - } - } else { + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + } + } else { m_PickingProgram->Bind(); - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix)); - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); - glUniform2fv(glGetUniformLocation(shaderHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1]))); - } + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix)); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + glUniform2fv(glGetUniformLocation(shaderHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1]))); + } glBindVertexArray(modelJob->Model->VAO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer); @@ -202,7 +197,7 @@ void PickingPass::Draw(RenderScene& scene) m_PickingColorsToEntity[glm::ivec2(pickColor[0], pickColor[1])] = pickInfo; - if(modelJob->Model->IsSkinned()) { + if (modelJob->Model->IsSkinned()) { m_PickingSkinnedProgram->Bind(); glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix)); glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); @@ -257,7 +252,7 @@ void PickingPass::Draw(RenderScene& scene) if (modelJob->Model->IsSkinned()) { m_PickingSkinnedProgram->Bind(); - + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix)); glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); @@ -280,7 +275,7 @@ void PickingPass::Draw(RenderScene& scene) glUniform2fv(glGetUniformLocation(shaderHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1]))); } - + glBindVertexArray(modelJob->Model->VAO); @@ -288,7 +283,7 @@ void PickingPass::Draw(RenderScene& scene) glDrawElements(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(modelJob->StartIndex * sizeof(unsigned int))); } } - + m_PickingBuffer.Unbind(); GLERROR("PickingPass Error"); From b66e3d36309da8b1dffe736ed37d22848d22525f Mon Sep 17 00:00:00 2001 From: stiffly Date: Thu, 11 Feb 2016 22:15:47 +0100 Subject: [PATCH 16/18] WIP trying to hot fix --- src/Engine/Network/Client.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index d88becdb..d6aece06 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -178,15 +178,22 @@ void Client::parseKick() void Client::parseSpawnEvents() { + std::vector tempSpawn; for (int i = 0; i < m_PlayerSpawnEvents.size(); i++) { Events::PlayerSpawned e; - e.Player = EntityWrapper(m_World, m_ServerIDToClientID[m_PlayerSpawnEvents[i].Player.ID]); - e.Spawner = EntityWrapper(m_World, m_ServerIDToClientID[m_PlayerSpawnEvents[i].Spawner.ID]); + if (!serverClientMapsHasEntity(m_PlayerSpawnEvents.at(i).Player.ID) || + !serverClientMapsHasEntity(m_PlayerSpawnEvents.at(i).Spawner.ID)) { + tempSpawn.push_back(m_PlayerSpawnEvents.at(i)); + continue; + } + e.Player = EntityWrapper(m_World, m_ServerIDToClientID.at(m_PlayerSpawnEvents.at(i).Player.ID)); + e.Spawner = EntityWrapper(m_World, m_ServerIDToClientID.at(m_PlayerSpawnEvents.at(i).Spawner.ID)); e.PlayerID = -1; - e.PlayerName = m_PlayerSpawnEvents[i].PlayerName; + e.PlayerName = m_PlayerSpawnEvents.at(i).PlayerName; m_EventBroker->Publish(e); } - m_PlayerSpawnEvents.clear(); + m_PlayerSpawnEvents = tempSpawn; + // m_PlayerSpawnEvents.clear(); } void Client::parsePlayersSpawned(Packet& packet) From e24a84c52d87591d58d848a9c229dfc0f73911f1 Mon Sep 17 00:00:00 2001 From: stiffly Date: Thu, 11 Feb 2016 23:52:55 +0100 Subject: [PATCH 17/18] Server now deletes the player on a new player spawn. --- src/Engine/Network/Client.cpp | 5 +++-- src/Game/Systems/PlayerSpawnSystem.cpp | 9 ++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index d6aece06..d75b8412 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -287,7 +287,8 @@ void Client::parseSnapshot(Packet& packet) for (std::size_t i = 0; i < numInputCommands; ++i) { Events::InputCommand e; e.PlayerID = packet.ReadPrimitive(); - e.Player = EntityWrapper(m_World, m_ServerIDToClientID.at(packet.ReadPrimitive())); + EntityID player = packet.ReadPrimitive(); + e.Player = EntityWrapper(m_World, m_ServerIDToClientID.at(player)); e.Command = packet.ReadString(); e.Value = packet.ReadPrimitive(); m_EventBroker->Publish(e); @@ -349,7 +350,7 @@ void Client::parseSnapshot(Packet& packet) m_World->SetParent(localEntityID, m_ServerIDToClientID.at(serverParentID)); } } - // parseSpawnEvents(); + parseSpawnEvents(); } void Client::disconnect() diff --git a/src/Game/Systems/PlayerSpawnSystem.cpp b/src/Game/Systems/PlayerSpawnSystem.cpp index 507ed0f5..e2775280 100644 --- a/src/Game/Systems/PlayerSpawnSystem.cpp +++ b/src/Game/Systems/PlayerSpawnSystem.cpp @@ -71,18 +71,17 @@ bool PlayerSpawnSystem::OnInputCommand(const Events::InputCommand& e) bool PlayerSpawnSystem::OnPlayerSpawned(Events::PlayerSpawned& e) { // When a player is actually spawned (since the actual spawning is handled on the server) - if (!IsClient) { - return false; - } - // Check if a player already exists + // Hack should be moved. if (m_PlayerEntities.count(e.PlayerID) != 0) { // TODO: Disallow infinite respawning here if (m_PlayerEntities[e.PlayerID].Valid()) { m_World->DeleteEntity(m_PlayerEntities[e.PlayerID].ID); } } - + if (!IsClient) { + return false; + } // Store the player for future reference m_PlayerEntities[e.PlayerID] = e.Player; From 3b42f5dbf412e972efbf7f52d27eccf5a49e530f Mon Sep 17 00:00:00 2001 From: Jocke Date: Fri, 12 Feb 2016 01:33:45 +0100 Subject: [PATCH 18/18] Fixed server so it now deletes. --- src/Game/Systems/PlayerSpawnSystem.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Game/Systems/PlayerSpawnSystem.cpp b/src/Game/Systems/PlayerSpawnSystem.cpp index e2775280..108fa502 100644 --- a/src/Game/Systems/PlayerSpawnSystem.cpp +++ b/src/Game/Systems/PlayerSpawnSystem.cpp @@ -79,11 +79,12 @@ bool PlayerSpawnSystem::OnPlayerSpawned(Events::PlayerSpawned& e) m_World->DeleteEntity(m_PlayerEntities[e.PlayerID].ID); } } + // Store the player for future reference + m_PlayerEntities[e.PlayerID] = e.Player; + if (!IsClient) { return false; } - // Store the player for future reference - m_PlayerEntities[e.PlayerID] = e.Player; // Set the camera to the correct entity EntityWrapper cameraEntity = e.Player.FirstChildByName("Camera");