Core/NetworkIO: Fixed boost::asio::async_write usage - packets will now be sent properly

This commit is contained in:
Shauren
2014-07-24 17:08:53 +02:00
parent 03146835e5
commit f1a41eabae
3 changed files with 37 additions and 17 deletions

View File

@@ -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

View File

@@ -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);
bool needsWriteStart = _writeQueue.empty();
_authCrypt.EncryptSend(data.data(), header.getHeaderLength());
_writeQueue.push(std::move(data));
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(buffer.get(), header.getHeaderLength() + packet.size()), [this, self, buffer](boost::system::error_code error, std::size_t /*length*/)
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();
});
}

View File

@@ -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;