diff --git a/include/Engine/Network/NetworkClient.h b/include/Engine/Network/NetworkClient.h index d0339d84..4adc68f5 100644 --- a/include/Engine/Network/NetworkClient.h +++ b/include/Engine/Network/NetworkClient.h @@ -9,13 +9,16 @@ typedef unsigned int PacketID; class NetworkClient { public: + NetworkClient(); + virtual ~NetworkClient(); 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 }; + char* m_ReadBuffer; + unsigned int m_BufferSize = BUFFERSIZE; }; #endif \ No newline at end of file diff --git a/include/Engine/Network/NetworkServer.h b/include/Engine/Network/NetworkServer.h index ccec82cc..296c8762 100644 --- a/include/Engine/Network/NetworkServer.h +++ b/include/Engine/Network/NetworkServer.h @@ -10,12 +10,15 @@ typedef unsigned int PacketID; class NetworkServer { public: + NetworkServer(); + virtual ~NetworkServer(); 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 }; + char* m_ReadBuffer; + unsigned int m_BufferSize = BUFFERSIZE; }; #endif \ No newline at end of file diff --git a/include/Engine/Network/Server.h b/include/Engine/Network/Server.h index 982df3b1..542792b2 100644 --- a/include/Engine/Network/Server.h +++ b/include/Engine/Network/Server.h @@ -56,7 +56,7 @@ private: std::vector m_InputCommandsToBroadcast; //Timers std::clock_t m_StartPingTime; - + // Packet loss logic PacketID m_PacketID = 0; PacketID m_PreviousPacketID = 0; @@ -66,6 +66,7 @@ private: void reliableBroadcast(Packet& packet); void unreliableBroadcast(Packet& packet); void sendSnapshot(); + void addPlayersToPacket(Packet& packet, EntityID entityID); void addChildrenToPacket(Packet& packet, EntityID entityID); void addInputCommandsToPacket(Packet& packet); void sendPing(); @@ -79,7 +80,7 @@ private: void parsePlayerTransform(Packet& packet); void parseOnInputCommand(Packet& packet); void parseClientPing(); - void parsePing(); + void parsePing(); void parseUDPConnect(Packet & packet); void parseTCPConnect(Packet & packet); void parseDisconnect(); diff --git a/include/Engine/Network/TCPClient.h b/include/Engine/Network/TCPClient.h index a666cbbe..2108fa3d 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; - size_t readBuffer(char* data); + size_t readBuffer(); PacketID m_SendPacketID = 0; bool m_IsConnected = false; }; diff --git a/include/Engine/Network/TCPServer.h b/include/Engine/Network/TCPServer.h index 1140579a..66caef08 100644 --- a/include/Engine/Network/TCPServer.h +++ b/include/Engine/Network/TCPServer.h @@ -28,7 +28,7 @@ private: void handle_accept(boost::shared_ptr socket, int& nextPlayerID, std::map& connectedPlayers, const boost::system::error_code& error); - int readBuffer(char* data, PlayerDefinition& playerDefinition); + int readBuffer(PlayerDefinition& playerDefinition); int GetPort(); std::string GetAddress(); int m_Port = 0; diff --git a/include/Engine/Network/UDPClient.h b/include/Engine/Network/UDPClient.h index f986dd08..42c27783 100644 --- a/include/Engine/Network/UDPClient.h +++ b/include/Engine/Network/UDPClient.h @@ -21,7 +21,7 @@ private: boost::asio::io_service m_IOService; boost::asio::ip::udp::endpoint m_ReceiverEndpoint; boost::shared_ptr m_Socket; - int readBuffer(char* data); + int readBuffer(); PacketID m_SendPacketID = 0; }; diff --git a/include/Engine/Network/UDPServer.h b/include/Engine/Network/UDPServer.h index 15dd977c..54f4e327 100644 --- a/include/Engine/Network/UDPServer.h +++ b/include/Engine/Network/UDPServer.h @@ -22,7 +22,7 @@ private: boost::asio::io_service m_IOService; boost::asio::ip::udp::endpoint m_ReceiverEndpoint; std::unique_ptr m_Socket; - int readBuffer(char* data); + int readBuffer(); }; #endif \ No newline at end of file diff --git a/src/Engine/Network/NetworkClient.cpp b/src/Engine/Network/NetworkClient.cpp index e69de29b..7a61d5f3 100644 --- a/src/Engine/Network/NetworkClient.cpp +++ b/src/Engine/Network/NetworkClient.cpp @@ -0,0 +1,11 @@ +#include "Network/NetworkClient.h" + +NetworkClient::NetworkClient() +{ + m_ReadBuffer = new char[m_BufferSize]; +} + +NetworkClient::~NetworkClient() +{ + delete[] m_ReadBuffer; +} diff --git a/src/Engine/Network/NetworkServer.cpp b/src/Engine/Network/NetworkServer.cpp new file mode 100644 index 00000000..1412621d --- /dev/null +++ b/src/Engine/Network/NetworkServer.cpp @@ -0,0 +1,11 @@ +#include "Network/NetworkServer.h" + +NetworkServer::NetworkServer() +{ + m_ReadBuffer = new char[m_BufferSize]; +} + +NetworkServer::~NetworkServer() +{ + delete[] m_ReadBuffer; +} diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index e309acf3..4b83967e 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -164,7 +164,7 @@ void Server::sendSnapshot() { Packet packet(MessageType::Snapshot); addInputCommandsToPacket(packet); - addChildrenToPacket(packet, EntityID_Invalid); + addPlayersToPacket(packet, EntityID_Invalid); unreliableBroadcast(packet); } @@ -181,7 +181,7 @@ void Server::addInputCommandsToPacket(Packet& packet) m_InputCommandsToBroadcast.clear(); } -void Server::addChildrenToPacket(Packet & packet, EntityID entityID) +void Server::addPlayersToPacket(Packet & packet, EntityID entityID) { auto itPair = m_World->GetChildren(entityID); std::unordered_map worldComponentPools = m_World->GetComponentPools(); @@ -231,6 +231,49 @@ void Server::addChildrenToPacket(Packet & packet, EntityID entityID) } } +void Server::addChildrenToPacket(Packet & packet, EntityID entityID) +{ + auto itPair = m_World->GetChildren(entityID); + std::unordered_map worldComponentPools = m_World->GetComponentPools(); + // Loop through every child + for (auto it = itPair.first; it != itPair.second; it++) { + EntityID childEntityID = it->second; + // Write EntityID and parentsID and Entity name + packet.WritePrimitive(childEntityID); + packet.WritePrimitive(entityID); + packet.WriteString(m_World->GetName(childEntityID)); + // Write components to child + int numberOfComponents = 0; + for (auto& i : worldComponentPools) { + if (i.second->KnowsEntity(childEntityID)) { + numberOfComponents++; + } + } + // Write how many components should be read + packet.WritePrimitive(numberOfComponents); + for (auto& i : worldComponentPools) { + // If the entity exist in the pool + if (i.second->KnowsEntity(childEntityID)) { + ComponentWrapper componentWrapper = i.second->GetByEntity(childEntityID); + // ComponentType + packet.WriteString(componentWrapper.Info.Name); + // Loop through fields + for (auto& componentField : componentWrapper.Info.FieldsInOrder) { + ComponentInfo::Field_t fieldInfo = componentWrapper.Info.Fields.at(componentField); + if (fieldInfo.Type == "string") { + std::string& value = componentWrapper[componentField]; + packet.WriteString(value); + } else { + packet.WriteData(componentWrapper.Data + fieldInfo.Offset, fieldInfo.Stride); + } + } + } + } + // Go to to your children + addChildrenToPacket(packet, childEntityID); + } +} + void Server::sendPing() { // Prints connected players ping @@ -325,6 +368,11 @@ void Server::parseTCPConnect(Packet & packet) connnectPacket.WritePrimitive(playerID); m_Reliable.Send(connnectPacket); + Packet firstSnapshot(MessageType::Snapshot); + addInputCommandsToPacket(firstSnapshot); + addChildrenToPacket(firstSnapshot, EntityID_Invalid); + m_Reliable.Send(firstSnapshot); + // Send notification that a player has connected //Packet notificationPacket(MessageType::PlayerConnected); //broadcast(notificationPacket); @@ -482,7 +530,9 @@ void Server::parsePing() { for (auto& kv : m_ConnectedPlayers) { if (kv.second.TCPAddress == m_Address && - kv.second.TCPPort == m_Port) { + kv.second.TCPPort == m_Port + || (kv.second.Endpoint.address() == m_Address + && kv.second.Endpoint.port() == m_Port)) { kv.second.StopTime = std::clock(); break; } diff --git a/src/Engine/Network/TCPClient.cpp b/src/Engine/Network/TCPClient.cpp index df4f3826..f2920ae5 100644 --- a/src/Engine/Network/TCPClient.cpp +++ b/src/Engine/Network/TCPClient.cpp @@ -56,32 +56,62 @@ void TCPClient::Disconnect() void TCPClient::Receive(Packet& packet) { - size_t bytesRead = readBuffer(m_ReadBuffer); + size_t bytesRead = readBuffer(); if (bytesRead > 0) { packet.ReconstructFromData(m_ReadBuffer, bytesRead); } } -size_t TCPClient::readBuffer(char* data) +size_t TCPClient::readBuffer() { + //if (!m_Socket) { + // return 0; + //} + //boost::system::error_code error; + //// Read size of packet + //size_t 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); + //if (error) { + // //LOG_ERROR("receive: %s", error.message().c_str()); + //} + //return bytesReceived; + if (!m_Socket) { return 0; } boost::system::error_code error; // Read size of packet - size_t bytesReceived = m_Socket->read_some(boost - ::asio::buffer((void*)data, sizeof(int)), - error); - int sizeOfPacket = 0; - memcpy(&sizeOfPacket, data, sizeof(int)); + m_Socket->receive(boost + ::asio::buffer((void*)m_ReadBuffer, sizeof(int)), + boost::asio::ip::tcp::socket::message_peek, error); + unsigned int sizeOfPacket = 0; + memcpy(&sizeOfPacket, m_ReadBuffer, sizeof(int)); + // if the buffer is to small increase the size of it + // TODO if message is huge 1 time the buffer will not decrease. + if (sizeOfPacket > m_BufferSize) { + delete[] m_ReadBuffer; + m_ReadBuffer = new char[sizeOfPacket]; + m_BufferSize = sizeOfPacket; + } // Read the rest of the message - bytesReceived += m_Socket->read_some(boost - ::asio::buffer((void*)(data + bytesReceived), sizeOfPacket - bytesReceived), + size_t bytesReceived = m_Socket->read_some(boost + ::asio::buffer((void*)(m_ReadBuffer), sizeOfPacket), error); if (error) { //LOG_ERROR("receive: %s", error.message().c_str()); } + if (sizeOfPacket > 1000000) + LOG_WARNING("The packets received are bigger than 1MB"); + return bytesReceived; } diff --git a/src/Engine/Network/TCPServer.cpp b/src/Engine/Network/TCPServer.cpp index 452efa62..ac2ba655 100644 --- a/src/Engine/Network/TCPServer.cpp +++ b/src/Engine/Network/TCPServer.cpp @@ -9,8 +9,7 @@ TCPServer::TCPServer() } TCPServer::~TCPServer() -{ -} +{ } void TCPServer::AcceptNewConnections(int& nextPlayerID, std::map& connectedPlayers) { @@ -33,7 +32,7 @@ PlayerID GetPlayerIDFromEndpoint(const std::map& con return -1; } -void TCPServer::handle_accept(boost::shared_ptr socket, +void TCPServer::handle_accept(boost::shared_ptr socket, int& nextPlayerID, std::map& connectedPlayers, const boost::system::error_code& error) { @@ -53,8 +52,8 @@ void TCPServer::handle_accept(boost::shared_ptr socket, void TCPServer::Send(Packet & packet, PlayerDefinition & playerDefinition) { + packet.UpdateSize(); try { - packet.UpdateSize(); int bytesSent = playerDefinition.TCPSocket->send( boost::asio::buffer(packet.Data(), packet.Size()), 0); @@ -75,7 +74,7 @@ void TCPServer::Send(Packet & packet) } void TCPServer::Disconnect() -{ +{ } int TCPServer::GetPort() @@ -92,34 +91,75 @@ std::string TCPServer::GetAddress() return endpoint.address().to_string().c_str(); } +//void TCPServer::Receive(Packet & packet, PlayerDefinition & playerDefinition) +//{ +// int bytesRead = readBuffer(m_ReadBuffer, playerDefinition); +// if (bytesRead > 0) { +// packet.ReconstructFromData(m_ReadBuffer, bytesRead); +// } +// lastReceivedSocket = playerDefinition.TCPSocket; +//} +// +//int TCPServer::readBuffer(char* data, PlayerDefinition & playerDefinition) +//{ +// if (!playerDefinition.TCPSocket) { +// return 0; +// } +// boost::system::error_code error; +// // Read size of packet +// size_t 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 += playerDefinition.TCPSocket->read_some(boost +// ::asio::buffer((void*)(data + bytesReceived), sizeOfPacket - bytesReceived), +// error); +// if (error) { +// //LOG_ERROR("receive: %s", error.message().c_str()); +// } +// return bytesReceived; +//} + void TCPServer::Receive(Packet & packet, PlayerDefinition & playerDefinition) { - int bytesRead = readBuffer(m_ReadBuffer, playerDefinition); + int bytesRead = readBuffer(playerDefinition); if (bytesRead > 0) { packet.ReconstructFromData(m_ReadBuffer, bytesRead); } lastReceivedSocket = playerDefinition.TCPSocket; } -int TCPServer::readBuffer(char* data, PlayerDefinition & playerDefinition) +int TCPServer::readBuffer(PlayerDefinition & playerDefinition) { if (!playerDefinition.TCPSocket) { return 0; } boost::system::error_code error; // Read size of packet - size_t bytesReceived = playerDefinition.TCPSocket->read_some(boost - ::asio::buffer((void*)data, sizeof(int)), - error); - int sizeOfPacket = 0; - memcpy(&sizeOfPacket, data, sizeof(int)); + playerDefinition.TCPSocket->receive(boost + ::asio::buffer((void*)m_ReadBuffer, sizeof(int)), + boost::asio::ip::tcp::socket::message_peek, error); + unsigned int sizeOfPacket = 0; + memcpy(&sizeOfPacket, m_ReadBuffer, sizeof(int)); + // if the buffer is to small increase the size of it + if (sizeOfPacket > m_BufferSize) { + delete[] m_ReadBuffer; + m_ReadBuffer = new char[sizeOfPacket]; + m_BufferSize = sizeOfPacket; + } // Read the rest of the message - bytesReceived += playerDefinition.TCPSocket->read_some(boost - ::asio::buffer((void*)(data + bytesReceived), sizeOfPacket - bytesReceived), + size_t bytesReceived = playerDefinition.TCPSocket->read_some(boost + ::asio::buffer((void*)(m_ReadBuffer), sizeOfPacket), error); if (error) { //LOG_ERROR("receive: %s", error.message().c_str()); } + if (sizeOfPacket > 1000000) + LOG_WARNING("The packets received are bigger than 1MB"); + return bytesReceived; } \ No newline at end of file diff --git a/src/Engine/Network/UDPClient.cpp b/src/Engine/Network/UDPClient.cpp index 68aebb03..f31d5a17 100644 --- a/src/Engine/Network/UDPClient.cpp +++ b/src/Engine/Network/UDPClient.cpp @@ -27,30 +27,62 @@ void UDPClient::Disconnect() void UDPClient::Receive(Packet& packet) { - int bytesRead = readBuffer(m_ReadBuffer); + int bytesRead = readBuffer(); if (bytesRead > 0) { packet.ReconstructFromData(m_ReadBuffer, bytesRead); } } -int UDPClient::readBuffer(char* data) +int UDPClient::readBuffer() { + //if (!m_Socket) { + // return 0; + //} + //boost::system::error_code error; + //int bytesReceived = m_Socket->receive_from(boost + // ::asio::buffer((void*)data, BUFFERSIZE), + // m_ReceiverEndpoint, + // 0, error); + //if (error) { + // //LOG_ERROR("receive: %s", error.message().c_str()); + //} + //return bytesReceived; if (!m_Socket) { return 0; } boost::system::error_code error; - int bytesReceived = m_Socket->receive_from(boost - ::asio::buffer((void*)data, BUFFERSIZE), - m_ReceiverEndpoint, - 0, error); + // Read size of packet + m_Socket->receive(boost + ::asio::buffer((void*)m_ReadBuffer, sizeof(int)), + boost::asio::ip::udp::socket::message_peek, error); + int sizeOfPacket = 0; + memcpy(&sizeOfPacket, m_ReadBuffer, sizeof(int)); + + // if the buffer is to small increase the size of it + if (sizeOfPacket > m_BufferSize) { + delete[] m_ReadBuffer; + m_ReadBuffer = new char[sizeOfPacket]; + m_BufferSize = sizeOfPacket; + } + + size_t availableData = m_Socket->available(); + // Read the rest of the message + size_t bytesReceived = m_Socket->receive_from(boost + ::asio::buffer((void*)(m_ReadBuffer), + sizeOfPacket), + m_ReceiverEndpoint, 0, error); if (error) { //LOG_ERROR("receive: %s", error.message().c_str()); } + if (sizeOfPacket > 1000000) + LOG_WARNING("The packets received are bigger than 1MB"); + return bytesReceived; } void UDPClient::Send(Packet& packet) { + packet.UpdateSize(); m_Socket->send_to(boost::asio::buffer( packet.Data(), packet.Size()), diff --git a/src/Engine/Network/UDPServer.cpp b/src/Engine/Network/UDPServer.cpp index f751d369..fcf26aec 100644 --- a/src/Engine/Network/UDPServer.cpp +++ b/src/Engine/Network/UDPServer.cpp @@ -15,6 +15,7 @@ UDPServer::~UDPServer() void UDPServer::Send(Packet& packet, PlayerDefinition & playerDefinition) { + packet.UpdateSize(); try { int bytesSent = m_Socket->send_to( boost::asio::buffer(packet.Data(), packet.Size()), @@ -28,6 +29,7 @@ void UDPServer::Send(Packet& packet, PlayerDefinition & playerDefinition) // Send back to endpoint of received packet void UDPServer::Send(Packet & packet) { + packet.UpdateSize(); m_Socket->send_to( boost::asio::buffer( packet.Data(), @@ -62,7 +64,7 @@ void UDPServer::Broadcast(Packet & packet, int port) void UDPServer::Receive(Packet & packet, PlayerDefinition & playerDefinition) { - int bytesRead = readBuffer(m_ReadBuffer); + int bytesRead = readBuffer(); if (bytesRead > 0) { packet.ReconstructFromData(m_ReadBuffer, bytesRead); } @@ -74,17 +76,47 @@ bool UDPServer::IsSocketAvailable() return m_Socket->available(); } -int UDPServer::readBuffer(char* data) +int UDPServer::readBuffer() { - 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, error); - if (error) { - LOG_WARNING(error.message().c_str()); + //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, error); + //if (error) { + // LOG_WARNING(error.message().c_str()); + //} + //return length; + if (!m_Socket) { + return 0; } - return length; + boost::system::error_code error; + // Read size of packet + m_Socket->receive_from(boost + ::asio::buffer((void*)m_ReadBuffer, sizeof(int)), + m_ReceiverEndpoint, boost::asio::ip::udp::socket::message_peek, error); + unsigned int sizeOfPacket = 0; + memcpy(&sizeOfPacket, m_ReadBuffer, sizeof(int)); + + // if the buffer is to small increase the size of it + if (sizeOfPacket > m_BufferSize) { + delete[] m_ReadBuffer; + m_ReadBuffer = new char[sizeOfPacket]; + m_BufferSize = sizeOfPacket; + } + + // Read the rest of the message + size_t bytesReceived = m_Socket->receive_from(boost + ::asio::buffer((void*)(m_ReadBuffer), + sizeOfPacket), + m_ReceiverEndpoint, 0, error); + if (error) { + //LOG_ERROR("receive: %s", error.message().c_str()); + } + if (sizeOfPacket > 1000000) + LOG_WARNING("The packets received are bigger than 1MB"); + + return bytesReceived; } void UDPServer::AcceptNewConnections(int& nextPlayerID, std::map& connectedPlayers)