From f1a41eabaeef5468f1d510fcac253a8d7fabdf73 Mon Sep 17 00:00:00 2001 From: Shauren Date: Thu, 24 Jul 2014 17:08:53 +0200 Subject: Core/NetworkIO: Fixed boost::asio::async_write usage - packets will now be sent properly --- src/server/game/Server/Protocol/ServerPktHeader.h | 4 +++ src/server/game/Server/WorldSocket.cpp | 38 +++++++++++++++-------- src/server/game/Server/WorldSocket.h | 12 ++++--- 3 files changed, 37 insertions(+), 17 deletions(-) (limited to 'src/server') diff --git a/src/server/game/Server/Protocol/ServerPktHeader.h b/src/server/game/Server/Protocol/ServerPktHeader.h index 4b0dae9f0f3..fcb24cfa80d 100644 --- a/src/server/game/Server/Protocol/ServerPktHeader.h +++ b/src/server/game/Server/Protocol/ServerPktHeader.h @@ -21,6 +21,8 @@ #include "Log.h" +#pragma pack(push, 1) + struct ServerPktHeader { /** @@ -56,4 +58,6 @@ struct ServerPktHeader uint8 header[5]; }; +#pragma pack(pop) + #endif diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp index 8b4dd9b7f51..fa884090bfa 100644 --- a/src/server/game/Server/WorldSocket.cpp +++ b/src/server/game/Server/WorldSocket.cpp @@ -169,28 +169,40 @@ void WorldSocket::AsyncWrite(WorldPacket const& packet) TC_LOG_TRACE("network.opcode", "S->C: %s %s", (_worldSession ? _worldSession->GetPlayerInfo() : GetRemoteIpAddress()).c_str(), GetOpcodeNameForLogging(packet.GetOpcode()).c_str()); ServerPktHeader header(packet.size() + 2, packet.GetOpcode()); - _authCrypt.EncryptSend((uint8*)header.header, header.getHeaderLength()); - auto data = new char[header.getHeaderLength() + packet.size()]; - std::memcpy(data, (char*)header.header, header.getHeaderLength()); + std::vector data(header.getHeaderLength() + packet.size()); + std::memcpy(data.data(), header.header, header.getHeaderLength()); if (!packet.empty()) - std::memcpy(data + header.getHeaderLength(), (char const*)packet.contents(), packet.size()); + std::memcpy(&data[header.getHeaderLength()], packet.contents(), packet.size()); - // Use a shared_ptr here to prevent leaking memory after the async operation has completed - std::shared_ptr buffer(data, [=](char* _b) - { - delete[] _b; // Ensure that the data is deleted as an array - }); + std::lock_guard guard(_writeLock); - auto self(shared_from_this()); + bool needsWriteStart = _writeQueue.empty(); + _authCrypt.EncryptSend(data.data(), header.getHeaderLength()); + + _writeQueue.push(std::move(data)); - boost::asio::async_write(_socket, boost::asio::buffer(buffer.get(), header.getHeaderLength() + packet.size()), [this, self, buffer](boost::system::error_code error, std::size_t /*length*/) + if (needsWriteStart) + AsyncWrite(_writeQueue.front()); +} + +void WorldSocket::AsyncWrite(std::vector const& data) +{ + auto self(shared_from_this()); + boost::asio::async_write(_socket, boost::asio::buffer(data), [this, self](boost::system::error_code error, std::size_t /*length*/) { - if (error) + if (!error) { - _socket.close(); + std::lock_guard deleteGuard(_writeLock); + + _writeQueue.pop(); + + if (!_writeQueue.empty()) + AsyncWrite(_writeQueue.front()); } + else + _socket.close(); }); } diff --git a/src/server/game/Server/WorldSocket.h b/src/server/game/Server/WorldSocket.h index 039859b5579..07aae10513f 100644 --- a/src/server/game/Server/WorldSocket.h +++ b/src/server/game/Server/WorldSocket.h @@ -19,15 +19,16 @@ #ifndef __WORLDSOCKET_H__ #define __WORLDSOCKET_H__ -#include -#include -#include -#include #include "Common.h" #include "AuthCrypt.h" #include "Util.h" #include "WorldPacket.h" #include "WorldSession.h" +#include +#include +#include +#include +#include using boost::asio::ip::tcp; @@ -68,10 +69,13 @@ private: void AsyncReadHeader(); void AsyncReadData(size_t dataSize); + void AsyncWrite(std::vector const& data); tcp::socket _socket; char _readBuffer[4096]; + std::mutex _writeLock; + std::queue > _writeQueue; uint32 _authSeed; AuthCrypt _authCrypt; -- cgit v1.2.3