1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-04-25 14:07:46 +00:00

Replace UtilNetwork with GamePacketParser

This commit is contained in:
Minho Kang 2017-08-26 15:06:27 +09:00
parent ef0a248444
commit 35c42c1f23
6 changed files with 289 additions and 70 deletions

View file

@ -0,0 +1,161 @@
#include "CommonNetwork.h"
#include "GamePacketParser.h"
using namespace Core::Network::Packets;
namespace Core
{
namespace Network
{
namespace Packets
{
PacketParseResult getHeader(
const std::vector< uint8_t > &buffer,
const uint32_t offset,
FFXIVARR_PACKET_HEADER &header)
{
const auto headerSize = sizeof( FFXIVARR_PACKET_HEADER );
// Check if we have enough bytes in the buffer.
auto remainingBytes = buffer.size() - offset;
if ( remainingBytes < headerSize )
{
return Incomplete;
}
// Copy packet header.
memcpy( &header, buffer.data() + offset, headerSize );
if ( !checkHeader(header) )
{
return Malformed;
}
return Success;
}
PacketParseResult getSegmentHeader(
const std::vector< uint8_t > &buffer,
const uint32_t offset,
FFXIVARR_PACKET_SEGMENT_HEADER &header)
{
const auto headerSize = sizeof( FFXIVARR_PACKET_SEGMENT_HEADER );
// Check if we have enough bytes in the buffer.
auto remainingBytes = buffer.size() - offset;
if (remainingBytes < headerSize)
{
return Incomplete;
}
// Copy segment header
memcpy(&header, buffer.data() + offset, headerSize);
return Success;
}
PacketParseResult getPackets(
const std::vector< uint8_t > &buffer,
const uint32_t offset,
const FFXIVARR_PACKET_HEADER &packetHeader,
std::vector< FFXIVARR_PACKET_RAW > &packets)
{
// sanity check: check there's enough bytes in the buffer
const auto bytesExpected = packetHeader.size - sizeof(struct FFXIVARR_PACKET_HEADER);
if ( buffer.size() - offset < bytesExpected )
{
return Incomplete;
}
// Loop each message
uint32_t count = 0;
uint32_t bytesProcessed = 0;
while ( count < packetHeader.count )
{
FFXIVARR_PACKET_RAW rawPacket;
// Copy ipc packet message
const auto packetResult = getPacket(buffer, offset + bytesProcessed, rawPacket);
if ( packetResult != Success )
{
return packetResult;
}
// NOTE: isn't rawPacket is allocated on stack?
// why is okay to do this?
packets.push_back( rawPacket );
// Add message size and count
bytesProcessed += rawPacket.segHdr.size;
count += 1;
}
// sanity check: check if we processed all bytes.
// this check can fail if size of messages don't add up to size reported from packet header.
if ( bytesExpected != bytesProcessed )
{
return Malformed;
}
return Success;
}
PacketParseResult getPacket(
const std::vector< uint8_t > &buffer,
const uint32_t offset,
FFXIVARR_PACKET_RAW &packet
)
{
// Copy segment header
const auto headerResult = getSegmentHeader(buffer, offset, packet.segHdr);
if ( headerResult != Success )
{
return headerResult;
}
// Check header sanity and it's size
if ( !checkSegmentHeader( packet.segHdr ) )
{
return Malformed;
}
const auto dataOffset = offset + sizeof(struct FFXIVARR_PACKET_SEGMENT_HEADER);
const auto dataSize = packet.segHdr.size;
// Allocate data buffer and copy
packet.data.resize( dataSize );
memcpy( packet.data.data(), buffer.data() + dataOffset, dataSize );
return Success;
}
bool checkHeader(const FFXIVARR_PACKET_HEADER &header)
{
// Max size of the packet is capped at 1MB for now.
if ( header.size > 1 * 1024 * 1024 )
{
return false;
}
// Max number of message is capped at 255 for now.
if ( header.count > 255 )
{
return false;
}
return true;
}
bool checkSegmentHeader(const FFXIVARR_PACKET_SEGMENT_HEADER &header)
{
// Max size of individual message is capped at 256KB for now.
if ( header.size > 256 * 1024 )
{
return false;
}
return true;
}
}
}
}

View file

@ -0,0 +1,64 @@
#ifndef _GAMEPACKETPARSER_H
#define _GAMEPACKETPARSER_H
#include "CommonNetwork.h"
namespace Core
{
namespace Network
{
namespace Packets
{
enum PacketParseResult
{
/// Dissected game packet successfully
Success,
/// Buffer is too short to dissect a message.
Incomplete,
/// Invalid data detected.
Malformed
};
/// Read packet header from buffer with given offset.
/// Buffer with given offset must be pointing to start of the new FFXIV packet.
PacketParseResult getHeader(
const std::vector< uint8_t > &buffer,
const uint32_t offset,
FFXIVARR_PACKET_HEADER &header
);
/// Read packet header from buffer with given offset.
/// Buffer with given offset must be pointing to start of FFXIVARR_PACKET_SEGMENT_HEADER data.
/// Keep in mind that this function does check for data validity. Call checkSegmentHeader() if that's needed.
PacketParseResult getSegmentHeader(
const std::vector< uint8_t > &buffer,
const uint32_t offset,
FFXIVARR_PACKET_SEGMENT_HEADER &header
);
/// Read packets from the buffer with given offset.
/// Buffer with given offset must be pointing to end of FFXIVARR_PACKET_HEADER data.
PacketParseResult getPackets(
const std::vector< uint8_t > &buffer,
const uint32_t offset,
const FFXIVARR_PACKET_HEADER &header,
std::vector< Packets::FFXIVARR_PACKET_RAW > &packets);
/// Read single packet from the buffer with given offset.
/// Buffer with an offset must be pointing to start of FFXIVARR_PACKET_SEGMENT_HEADER data.
PacketParseResult getPacket(
const std::vector< uint8_t > &buffer,
const uint32_t offset,
FFXIVARR_PACKET_RAW &packet
);
bool checkHeader(const FFXIVARR_PACKET_HEADER &header);
bool checkSegmentHeader(const FFXIVARR_PACKET_SEGMENT_HEADER &header);
}
}
}
#endif

View file

@ -1,35 +0,0 @@
#include "UtilNetwork.h"
#include <string.h>
bool Core::Network::Util::bufferToPacketList( const std::vector< uint8_t > &buffer,
Packets::FFXIVARR_PACKET_HEADER &ipcHeader,
std::vector< Packets::FFXIVARR_PACKET_RAW > &packetList )
{
memcpy( &ipcHeader, ( uint8_t* ) &buffer[0], sizeof( struct Packets::FFXIVARR_PACKET_HEADER ) );
uint16_t offset = 0;
for( std::size_t x = 0; x < ipcHeader.count; x++ )
{
Packets::FFXIVARR_PACKET_RAW packet;
uint32_t headerSize = sizeof( struct Packets::FFXIVARR_PACKET_HEADER );
uint32_t headerSegSize = sizeof( struct Packets::FFXIVARR_PACKET_SEGMENT_HEADER );
memcpy( &packet.segHdr, ( uint8_t* ) &buffer[headerSize + offset], headerSegSize );
std::vector<uint8_t> packetData;
uint16_t startOff = sizeof( struct Packets::FFXIVARR_PACKET_HEADER ) + offset;
for( std::size_t y = 0; y < packet.segHdr.size - sizeof( struct Packets::FFXIVARR_PACKET_SEGMENT_HEADER ); y++ )
{
packet.data.push_back( buffer.at( startOff + y + sizeof( struct Packets::FFXIVARR_PACKET_SEGMENT_HEADER ) ) );
}
offset += packet.segHdr.size;
packetList.push_back( packet );
}
return true;
}

View file

@ -1,18 +0,0 @@
#ifndef _UTILNETWORK_H
#define _UTILNETWORK_H
#include "src/servers/Server_Common/Network/CommonNetwork.h"
namespace Core {
namespace Network {
namespace Util {
bool bufferToPacketList( const std::vector< uint8_t > &buffer,
Packets::FFXIVARR_PACKET_HEADER &ipcHeader,
std::vector< Packets::FFXIVARR_PACKET_RAW > &packetList );
}
}
}
#endif

View file

@ -1,11 +1,11 @@
#include <src/servers/Server_Common/Common.h>
#include <src/servers/Server_Common/Network/CommonNetwork.h>
#include <src/servers/Server_Common/Util/Util.h>
#include <src/servers/Server_Common/Util/UtilNetwork.h>
#include <src/servers/Server_Common/Logging/Logger.h>
#include <src/servers/Server_Common/Network/GamePacket.h>
#include <src/servers/Server_Common/Network/GamePacketNew.h>
#include <src/servers/Server_Common/Network/PacketDef/Lobby/ServerLobbyDef.h>
#include "Server_Common/Network/GamePacketParser.h"
#include <src/servers/Server_Common/Crypt/md5.h>
#include <boost/format.hpp>
@ -25,7 +25,6 @@
extern Core::Logger g_log;
extern Core::ServerLobby g_serverLobby;
extern Core::Network::RestConnector g_restConnector;
@ -65,12 +64,45 @@ void Core::Network::GameConnection::OnDisconnect()
void Core::Network::GameConnection::OnRecv( std::vector< uint8_t > & buffer )
{
Packets::FFXIVARR_PACKET_HEADER ipcHeader;
Packets::FFXIVARR_PACKET_HEADER packetHeader;
const auto headerResult = Packets::getHeader(buffer, 0, packetHeader);
if (headerResult == Incomplete)
{
g_log.info("Dropping connection due to incomplete packet header.");
g_log.info("FIXME: Packet message bounary is not implemented.");
Disconnect();
return;
}
if (headerResult == Malformed)
{
g_log.info("Dropping connection due to malformed packet header.");
Disconnect();
return;
}
// Dissect packet list
std::vector< Packets::FFXIVARR_PACKET_RAW > packetList;
const auto packetResult = Packets::getPackets(buffer, sizeof(struct FFXIVARR_PACKET_HEADER), packetHeader, packetList);
Network::Util::bufferToPacketList( buffer, ipcHeader, packetList );
if (packetResult == Incomplete)
{
g_log.info("Dropping connection due to incomplete packets.");
g_log.info("FIXME: Packet message bounary is not implemented.");
Disconnect();
return;
}
handlePackets( ipcHeader, packetList );
if (packetResult == Malformed)
{
g_log.info("Dropping connection due to malformed packets.");
Disconnect();
return;
}
// Handle it
handlePackets(packetHeader, packetList);
}

View file

@ -2,9 +2,9 @@
#include <src/servers/Server_Common/Network/CommonNetwork.h>
#include <src/servers/Server_Common/Database/Database.h>
#include <src/servers/Server_Common/Util/Util.h>
#include <src/servers/Server_Common/Util/UtilNetwork.h>
#include <src/servers/Server_Common/Logging/Logger.h>
#include <src/servers/Server_Common/Network/PacketContainer.h>
#include <src/servers/Server_Common/Network/GamePacketParser.h>
#include <boost/format.hpp>
#include "GameConnection.h"
@ -112,30 +112,45 @@ void Core::Network::GameConnection::OnRecv( std::vector< uint8_t > & buffer )
{
// This is assumed packet always start with valid FFXIVARR_PACKET_HEADER for now.
// not enough bytes for packet header, drop connection for now.
// TODO: buffer it
Packets::FFXIVARR_PACKET_HEADER packetHeader;
const auto headerResult = Packets::getHeader(buffer, 0, packetHeader);
// Dissect packet header
Packets::FFXIVARR_PACKET_HEADER ipcHeader;
if ( !Network::Util::bufferToPacketHeader( buffer, ipcHeader ) )
if (headerResult == Incomplete)
{
g_log.info("FIXME: Dropping connection due to incomplete packet header.");
g_log.info("See https://github.com/SapphireMordred/Sapphire/issues/24 for more info.");
g_log.info("Dropping connection due to incomplete packet header.");
g_log.info("FIXME: Packet message bounary is not implemented.");
Disconnect();
return;
}
if (headerResult == Malformed)
{
g_log.info("Dropping connection due to malformed packet header.");
Disconnect();
return;
}
// Dissect packet list
std::vector< Packets::FFXIVARR_PACKET_RAW > packetList;
if ( !Network::Util::bufferToPacketList( buffer, ipcHeader, packetList ) )
const auto packetResult = Packets::getPackets(buffer, sizeof(struct FFXIVARR_PACKET_HEADER), packetHeader, packetList);
if (packetResult == Incomplete)
{
g_log.info("Dropping connection due to incomplete message.");
g_log.info("Dropping connection due to incomplete packets.");
g_log.info("FIXME: Packet message bounary is not implemented.");
Disconnect();
return;
}
if (packetResult == Malformed)
{
g_log.info("Dropping connection due to malformed packets.");
Disconnect();
return;
}
// Handle it
handlePackets( ipcHeader, packetList );
handlePackets( packetHeader, packetList );
}
void Core::Network::GameConnection::OnError( const boost::system::error_code & error )