mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-04-25 22:17:45 +00:00
Replace UtilNetwork with GamePacketParser
This commit is contained in:
parent
ef0a248444
commit
35c42c1f23
6 changed files with 289 additions and 70 deletions
161
src/servers/Server_Common/Network/GamePacketParser.cpp
Normal file
161
src/servers/Server_Common/Network/GamePacketParser.cpp
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
64
src/servers/Server_Common/Network/GamePacketParser.h
Normal file
64
src/servers/Server_Common/Network/GamePacketParser.h
Normal 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
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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
|
|
|
@ -1,11 +1,11 @@
|
||||||
#include <src/servers/Server_Common/Common.h>
|
#include <src/servers/Server_Common/Common.h>
|
||||||
#include <src/servers/Server_Common/Network/CommonNetwork.h>
|
#include <src/servers/Server_Common/Network/CommonNetwork.h>
|
||||||
#include <src/servers/Server_Common/Util/Util.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/Logging/Logger.h>
|
||||||
#include <src/servers/Server_Common/Network/GamePacket.h>
|
#include <src/servers/Server_Common/Network/GamePacket.h>
|
||||||
#include <src/servers/Server_Common/Network/GamePacketNew.h>
|
#include <src/servers/Server_Common/Network/GamePacketNew.h>
|
||||||
#include <src/servers/Server_Common/Network/PacketDef/Lobby/ServerLobbyDef.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 <src/servers/Server_Common/Crypt/md5.h>
|
||||||
|
|
||||||
#include <boost/format.hpp>
|
#include <boost/format.hpp>
|
||||||
|
@ -25,7 +25,6 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
extern Core::Logger g_log;
|
extern Core::Logger g_log;
|
||||||
extern Core::ServerLobby g_serverLobby;
|
extern Core::ServerLobby g_serverLobby;
|
||||||
extern Core::Network::RestConnector g_restConnector;
|
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 )
|
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;
|
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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
#include <src/servers/Server_Common/Network/CommonNetwork.h>
|
#include <src/servers/Server_Common/Network/CommonNetwork.h>
|
||||||
#include <src/servers/Server_Common/Database/Database.h>
|
#include <src/servers/Server_Common/Database/Database.h>
|
||||||
#include <src/servers/Server_Common/Util/Util.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/Logging/Logger.h>
|
||||||
#include <src/servers/Server_Common/Network/PacketContainer.h>
|
#include <src/servers/Server_Common/Network/PacketContainer.h>
|
||||||
|
#include <src/servers/Server_Common/Network/GamePacketParser.h>
|
||||||
#include <boost/format.hpp>
|
#include <boost/format.hpp>
|
||||||
|
|
||||||
#include "GameConnection.h"
|
#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.
|
// This is assumed packet always start with valid FFXIVARR_PACKET_HEADER for now.
|
||||||
|
|
||||||
// not enough bytes for packet header, drop connection for now.
|
Packets::FFXIVARR_PACKET_HEADER packetHeader;
|
||||||
// TODO: buffer it
|
const auto headerResult = Packets::getHeader(buffer, 0, packetHeader);
|
||||||
|
|
||||||
// Dissect packet header
|
if (headerResult == Incomplete)
|
||||||
Packets::FFXIVARR_PACKET_HEADER ipcHeader;
|
|
||||||
if ( !Network::Util::bufferToPacketHeader( buffer, ipcHeader ) )
|
|
||||||
{
|
{
|
||||||
g_log.info("FIXME: Dropping connection due to incomplete packet header.");
|
g_log.info("Dropping connection due to incomplete packet header.");
|
||||||
g_log.info("See https://github.com/SapphireMordred/Sapphire/issues/24 for more info.");
|
g_log.info("FIXME: Packet message bounary is not implemented.");
|
||||||
Disconnect();
|
Disconnect();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (headerResult == Malformed)
|
||||||
|
{
|
||||||
|
g_log.info("Dropping connection due to malformed packet header.");
|
||||||
|
Disconnect();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Dissect packet list
|
// Dissect packet list
|
||||||
std::vector< Packets::FFXIVARR_PACKET_RAW > packetList;
|
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();
|
Disconnect();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (packetResult == Malformed)
|
||||||
|
{
|
||||||
|
g_log.info("Dropping connection due to malformed packets.");
|
||||||
|
Disconnect();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Handle it
|
// Handle it
|
||||||
handlePackets( ipcHeader, packetList );
|
handlePackets( packetHeader, packetList );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Core::Network::GameConnection::OnError( const boost::system::error_code & error )
|
void Core::Network::GameConnection::OnError( const boost::system::error_code & error )
|
||||||
|
|
Loading…
Add table
Reference in a new issue