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:
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/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);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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 )
|
||||
|
|
Loading…
Add table
Reference in a new issue