aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/game/Server/Protocol/ServerPktHeader.h4
-rw-r--r--src/server/game/Server/WorldSocket.cpp38
-rw-r--r--src/server/game/Server/WorldSocket.h12
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;