diff options
-rw-r--r-- | src/server/game/Server/Protocol/ServerPktHeader.h | 4 | ||||
-rw-r--r-- | src/server/game/Server/WorldSocket.cpp | 38 | ||||
-rw-r--r-- | src/server/game/Server/WorldSocket.h | 12 |
3 files changed, 37 insertions, 17 deletions
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<uint8> 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<char> buffer(data, [=](char* _b) - { - delete[] _b; // Ensure that the data is deleted as an array - }); + std::lock_guard<std::mutex> 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<uint8> 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<std::mutex> 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 <memory> -#include <chrono> -#include <boost/asio/ip/tcp.hpp> -#include <boost/asio/streambuf.hpp> #include "Common.h" #include "AuthCrypt.h" #include "Util.h" #include "WorldPacket.h" #include "WorldSession.h" +#include <memory> +#include <chrono> +#include <mutex> +#include <boost/asio/ip/tcp.hpp> +#include <boost/asio/streambuf.hpp> using boost::asio::ip::tcp; @@ -68,10 +69,13 @@ private: void AsyncReadHeader(); void AsyncReadData(size_t dataSize); + void AsyncWrite(std::vector<uint8> const& data); tcp::socket _socket; char _readBuffer[4096]; + std::mutex _writeLock; + std::queue<std::vector<uint8> > _writeQueue; uint32 _authSeed; AuthCrypt _authCrypt; |