diff --git a/src/common/Network/GamePacket.cpp b/src/common/Network/GamePacket.cpp index c4d61f81..bc142ab5 100644 --- a/src/common/Network/GamePacket.cpp +++ b/src/common/Network/GamePacket.cpp @@ -7,16 +7,17 @@ #include #include "Util/Util.h" -Core::Network::Packets::GamePacket::GamePacket( uint16_t subType, uint16_t size, uint32_t id1, uint32_t id2, uint16_t type ) +Core::Network::Packets::GamePacket::GamePacket( uint16_t subType, uint16_t size, + uint32_t id1, uint32_t id2, uint16_t type ) { - m_dataBuf = std::vector( size ); + m_dataBuf = std::vector< uint8_t >( size ); memset( &m_segHdr, 0, sizeof( m_segHdr ) ); setHeader( size, type, id1, id2, subType, 0x00 ); - } -void Core::Network::Packets::GamePacket::setHeader( uint16_t size, uint16_t type, uint32_t id1, uint32_t id2, uint16_t subType, uint32_t unknown ) +void Core::Network::Packets::GamePacket::setHeader( uint16_t size, uint16_t type, uint32_t id1, + uint32_t id2, uint16_t subType, uint32_t unknown ) { m_segHdr.size = size; @@ -40,7 +41,7 @@ void Core::Network::Packets::GamePacket::setHeader( uint16_t size, uint16_t type Core::Network::Packets::GamePacket::GamePacket( char * pData, uint16_t size, bool bWriteStamp ) { - m_dataBuf = std::vector( size ); + m_dataBuf = std::vector< uint8_t >( size ); memcpy( &m_dataBuf[0], pData, size ); m_unknown2 = 0; @@ -65,9 +66,12 @@ Core::Network::Packets::GamePacket::GamePacket( const Packets::FFXIVARR_PACKET_R { m_segHdr = packetData.segHdr; - m_dataBuf = std::vector( m_segHdr.size ); + m_dataBuf = std::vector< uint8_t >( m_segHdr.size ); + + memcpy( &m_dataBuf[0] + sizeof( Packets::FFXIVARR_PACKET_SEGMENT_HEADER ), + &packetData.data[0], + m_segHdr.size - sizeof( Packets::FFXIVARR_PACKET_SEGMENT_HEADER ) ); - memcpy( &m_dataBuf[0] + sizeof( Packets::FFXIVARR_PACKET_SEGMENT_HEADER ), &packetData.data[0], m_segHdr.size - sizeof( Packets::FFXIVARR_PACKET_SEGMENT_HEADER ) ); memcpy( &m_dataBuf[0], &m_segHdr, sizeof( Packets::FFXIVARR_PACKET_SEGMENT_HEADER ) ); m_subType = *reinterpret_cast< uint16_t* >( &m_dataBuf[0] + 0x12 ); @@ -98,5 +102,5 @@ void Core::Network::Packets::GamePacket::savePacket() std::string Core::Network::Packets::GamePacket::toString() const { - return Core::Util::binaryToHexDump( const_cast( &m_dataBuf[0] ), getSize() ); + return Core::Util::binaryToHexDump( const_cast< uint8_t* >( &m_dataBuf[0] ), getSize() ); } diff --git a/src/common/Network/GamePacketNew.h b/src/common/Network/GamePacketNew.h index 451c4eee..595b8222 100644 --- a/src/common/Network/GamePacketNew.h +++ b/src/common/Network/GamePacketNew.h @@ -20,7 +20,7 @@ template < typename T, typename T1 > class GamePacketNew; template < typename T, typename T1 > -std::ostream& operator<< ( std::ostream& os, const GamePacketNew< T, T1 >& packet ); +std::ostream& operator << ( std::ostream& os, const GamePacketNew< T, T1 >& packet ); template< class T > using ZoneChannelPacket = GamePacketNew< T, ServerZoneIpcType >; @@ -32,15 +32,15 @@ using ChatChannelPacket = GamePacketNew< T, ServerChatIpcType >; * The base implementation of a game packet. Needed for parsing packets. */ template < typename T1 > -class FFXIVPacketBase +class FFXIVIpcPacketBase { public: - virtual ~FFXIVPacketBase() = default; + virtual ~FFXIVIpcPacketBase() = default; /** * @brief Gets the IPC type of this packet. (Useful for determining the * type of a parsed packet.) */ - virtual T1 ipcType( void ) = 0; + virtual T1 ipcType() = 0; }; /** @@ -50,7 +50,7 @@ public: * 32 byte header information.) */ template < typename T, typename T1 > -class GamePacketNew : public FFXIVPacketBase< T1 > +class GamePacketNew : public FFXIVIpcPacketBase< T1 > { public: /** @@ -96,7 +96,7 @@ protected: }; public: - virtual T1 ipcType( void ) + virtual T1 ipcType() { return static_cast< T1 >( m_data._ServerIpcType ); }; diff --git a/src/common/Network/GamePacketParser.cpp b/src/common/Network/GamePacketParser.cpp index 4a9fd067..52cfe1a3 100644 --- a/src/common/Network/GamePacketParser.cpp +++ b/src/common/Network/GamePacketParser.cpp @@ -5,131 +5,122 @@ using namespace Core::Network::Packets; -namespace Core +PacketParseResult Core::Network::Packets::getHeader( const std::vector< uint8_t > &buffer, + const uint32_t offset, + FFXIVARR_PACKET_HEADER &header ) { - 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 ); + 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; + // 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 ); + // Copy packet header. + memcpy( &header, buffer.data() + offset, headerSize ); - if( !checkHeader(header) ) - return Malformed; + 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; - } - } - } + return Success; +} + +PacketParseResult Core::Network::Packets::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 Core::Network::Packets::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 Core::Network::Packets::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 Core::Network::Packets::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 Core::Network::Packets::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; } diff --git a/src/common/Network/GamePacketParser.h b/src/common/Network/GamePacketParser.h index 1ffda893..6f870bd2 100644 --- a/src/common/Network/GamePacketParser.h +++ b/src/common/Network/GamePacketParser.h @@ -2,62 +2,49 @@ #define _GAMEPACKETPARSER_H #include "CommonNetwork.h" -namespace Core -{ - namespace Network +namespace Core { +namespace Network { +namespace Packets { + + enum PacketParseResult { - namespace Packets - { - enum PacketParseResult - { - /// Dissected game packet successfully - Success, + /// Dissected game packet successfully + Success, - /// Buffer is too short to dissect a message. - Incomplete, - - /// Invalid data detected. - Malformed - }; + /// Buffer is too short to dissect a message. + Incomplete, - /// 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 - ); + /// Invalid data detected. + Malformed + }; - /// 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 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 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 - ); + /// 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 ); - bool checkHeader(const FFXIVARR_PACKET_HEADER &header); - bool checkSegmentHeader(const 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); + +} +} }