2017-08-26 15:06:27 +09:00
|
|
|
#include "CommonNetwork.h"
|
|
|
|
#include "GamePacketParser.h"
|
|
|
|
|
2017-08-26 15:29:57 +09:00
|
|
|
#include <string> // memcpy
|
|
|
|
#include <stdlib.h> //realloc
|
|
|
|
|
2017-08-26 15:06:27 +09:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|