diff --git a/deps/Oodle/oodle2net.h b/deps/Oodle/oodle2net.h index 59c718c9..07e5505b 100644 --- a/deps/Oodle/oodle2net.h +++ b/deps/Oodle/oodle2net.h @@ -4,6 +4,7 @@ extern "C" intptr_t __stdcall OodleNetwork1_Shared_Size( int32_t htbits ); extern "C" intptr_t __stdcall OodleNetwork1UDP_State_Size(); +extern "C" intptr_t __stdcall OodleNetwork1TCP_State_Size(); extern "C" void __stdcall OodleNetwork1_Shared_SetWindow( void* shared, @@ -20,6 +21,14 @@ extern "C" void __stdcall OodleNetwork1UDP_Train( int32_t numTrainingPackets ); +extern "C" void __stdcall OodleNetwork1TCP_Train( + void* state, + const void* shared, + const void** trainingPacketPointers, + const int32_t* trainingPacketSizes, + int32_t numTrainingPackets +); + extern "C" bool __stdcall OodleNetwork1UDP_Decode( void* state, const void* shared, @@ -29,4 +38,29 @@ extern "C" bool __stdcall OodleNetwork1UDP_Decode( intptr_t decSize ); +extern "C" bool __stdcall OodleNetwork1TCP_Decode( + void* state, + const void* shared, + const void* enc, + intptr_t encSize, + void* dec, + intptr_t decSize +); + +extern "C" intptr_t __stdcall OodleNetwork1UDP_Encode( + void* state, + const void* shared, + const void* dec, + intptr_t decSize, + void* enc +); + +extern "C" intptr_t __stdcall OodleNetwork1TCP_Encode( + void* state, + const void* shared, + const void* dec, + intptr_t decSize, + void* enc +); + #endif \ No newline at end of file diff --git a/src/common/Forwards.h b/src/common/Forwards.h index 1fa810c9..7affe0e9 100644 --- a/src/common/Forwards.h +++ b/src/common/Forwards.h @@ -2,6 +2,7 @@ #define COMMON_FORWARDS_H #include +#include "Network/Oodle.h" namespace Sapphire { @@ -23,6 +24,7 @@ namespace Sapphire::Network using HivePtr = std::shared_ptr< Hive >; using AcceptorPtr = std::shared_ptr< Acceptor >; using ConnectionPtr = std::shared_ptr< Connection >; + using OodlePtr = std::unique_ptr< Network::Oodle >; } namespace Sapphire::Network::Packets diff --git a/src/common/Network/GamePacketParser.cpp b/src/common/Network/GamePacketParser.cpp index f16248f2..f784f102 100644 --- a/src/common/Network/GamePacketParser.cpp +++ b/src/common/Network/GamePacketParser.cpp @@ -48,7 +48,8 @@ PacketParseResult Network::Packets::getSegmentHeader( const std::vector< uint8_t PacketParseResult Network::Packets::getPackets( const std::vector< uint8_t >& buffer, const uint32_t offset, const FFXIVARR_PACKET_HEADER& packetHeader, - std::vector< FFXIVARR_PACKET_RAW >& packets ) + std::vector< FFXIVARR_PACKET_RAW >& packets, + Network::Oodle* oodle) { // sanity check: check there's enough bytes in the buffer auto bytesExpected = packetHeader.size - sizeof( struct FFXIVARR_PACKET_HEADER ); @@ -60,14 +61,19 @@ PacketParseResult Network::Packets::getPackets( const std::vector< uint8_t >& bu // check compression, do decompress if Oodle/Zlib if( packetHeader.compressionType == Oodle ) { + if( oodle == nullptr ) + { + Logger::warn( "Oodle compression type was specified, but no Oodle decompressor was supplied for this connection." ); + return Malformed; + } + std::vector< uint8_t > inBuf; inBuf.assign( buffer.begin() + sizeof( struct FFXIVARR_PACKET_HEADER ), buffer.end() ); std::vector< uint8_t > outBuf; outBuf.resize( packetHeader.oodleDecompressedSize ); - auto _oodle = Network::Oodle(); - bool oodleSuccess = _oodle.oodleDecode( inBuf, bytesExpected, outBuf, packetHeader.oodleDecompressedSize ); + bool oodleSuccess = oodle->oodleDecode( inBuf, bytesExpected, outBuf, packetHeader.oodleDecompressedSize ); if( !oodleSuccess ) { diff --git a/src/common/Network/GamePacketParser.h b/src/common/Network/GamePacketParser.h index a8083f8b..a5a31f14 100644 --- a/src/common/Network/GamePacketParser.h +++ b/src/common/Network/GamePacketParser.h @@ -2,6 +2,7 @@ #define _GAMEPACKETPARSER_H #include "CommonNetwork.h" +#include "Oodle.h" namespace Sapphire::Network::Packets { @@ -40,7 +41,8 @@ namespace Sapphire::Network::Packets /// 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 ); + std::vector< Packets::FFXIVARR_PACKET_RAW >& packets, + Network::Oodle* oodle); /// Read single packet from the buffer with given offset. /// Buffer with an offset must be pointing to start of FFXIVARR_PACKET_SEGMENT_HEADER data. diff --git a/src/common/Network/Oodle.cpp b/src/common/Network/Oodle.cpp index 58f65f73..efc8a146 100644 --- a/src/common/Network/Oodle.cpp +++ b/src/common/Network/Oodle.cpp @@ -3,14 +3,14 @@ using namespace Sapphire; Network::Oodle::Oodle() : - m_htbits(19) + m_htbits(17) { - auto stateSize = OodleNetwork1UDP_State_Size(); + auto stateSize = OodleNetwork1TCP_State_Size(); auto sharedSize = OodleNetwork1_Shared_Size( m_htbits ); m_state = std::vector< uint8_t >( stateSize, 0 ); m_shared = std::vector< uint8_t >( sharedSize, 0 ); - m_window = std::vector< uint8_t >( 0x8000, 0 ); + m_window = std::vector< uint8_t >( 0x100000, 0 ); oodleInit(); } @@ -18,10 +18,15 @@ Network::Oodle::Oodle() : void Network::Oodle::oodleInit() { OodleNetwork1_Shared_SetWindow( &m_shared[0], m_htbits, &m_window[0], (int) m_window.size() ); - OodleNetwork1UDP_Train( &m_state[0], &m_shared[0], nullptr, nullptr, 0 ); + OodleNetwork1TCP_Train( &m_state[0], &m_shared[0], nullptr, nullptr, 0 ); } bool Network::Oodle::oodleDecode( const std::vector< uint8_t > &enc, uint32_t encSize, std::vector< uint8_t > &dec, uint32_t decSize ) { - return OodleNetwork1UDP_Decode( &m_state[0], &m_shared[0], &enc[0], encSize, &dec[0], decSize ); + return OodleNetwork1TCP_Decode( &m_state[0], &m_shared[0], &enc[0], encSize, &dec[0], decSize ); +} + +intptr_t Network::Oodle::oodleEncode( const std::vector< uint8_t > &dec, uint32_t decSize, std::vector< uint8_t > &enc ) +{ + return OodleNetwork1TCP_Encode( &m_state[0], &m_shared[0], &dec[0], decSize, &enc[0] ); } \ No newline at end of file diff --git a/src/common/Network/Oodle.h b/src/common/Network/Oodle.h index b01dcf29..3a87483e 100644 --- a/src/common/Network/Oodle.h +++ b/src/common/Network/Oodle.h @@ -22,6 +22,7 @@ namespace Sapphire::Network void oodleInit(); bool oodleDecode( const std::vector< uint8_t > &enc, uint32_t encSize, std::vector< uint8_t > &dec, uint32_t decSize ); + intptr_t oodleEncode( const std::vector< uint8_t > &raw, uint32_t rawSize, std::vector< uint8_t > &enc ); }; } diff --git a/src/common/Network/PacketContainer.cpp b/src/common/Network/PacketContainer.cpp index 0b6fa1b1..f06f1c8f 100644 --- a/src/common/Network/PacketContainer.cpp +++ b/src/common/Network/PacketContainer.cpp @@ -2,6 +2,7 @@ #include "Util/Util.h" #include "Common.h" #include "Forwards.h" +#include "GamePacketParser.h" #include #include @@ -30,21 +31,11 @@ void Network::Packets::PacketContainer::addPacket( Network::Packets::FFXIVPacket m_ipcHdr.count++; } -void Network::Packets::PacketContainer::fillSendBuffer( std::vector< uint8_t >& sendBuffer ) +void Network::Packets::PacketContainer::fillSendBuffer( std::vector< uint8_t >& sendBuffer, Network::Oodle* oodle ) { std::vector< uint8_t > tempBuffer( m_ipcHdr.size ); memset( &tempBuffer[ 0 ], 0, m_ipcHdr.size ); - using namespace std::chrono; - auto ms = duration_cast< milliseconds >( system_clock::now().time_since_epoch() ); - uint64_t tick = ms.count(); - m_ipcHdr.unknown_0 = 0xE2465DFF41a05252; - m_ipcHdr.unknown_8 = 0x75C4997B4D642A7F; - m_ipcHdr.timestamp = tick; - m_ipcHdr.unknown_20 = 1; - - memcpy( &tempBuffer[ 0 ], &m_ipcHdr, sizeof( FFXIVARR_PACKET_HEADER ) ); - auto it = m_entryList.begin(); std::size_t offset = 0; @@ -65,15 +56,45 @@ void Network::Packets::PacketContainer::fillSendBuffer( std::vector< uint8_t >& offset += pPacket->getSize(); } - sendBuffer.assign( &tempBuffer[ 0 ], &tempBuffer[ 0 ] + m_ipcHdr.size ); + // oodle is always nullptr, but i guess this is here if we ever want to encode like retail + if ( oodle != nullptr ) + { + std::vector< uint8_t > inBuf; + inBuf.assign( tempBuffer.begin() + sizeof( struct FFXIVARR_PACKET_HEADER ), tempBuffer.end() ); + std::vector< uint8_t > outBuf; + outBuf.resize( m_ipcHdr.size ); + + auto compLen = oodle->oodleEncode(inBuf, inBuf.size(), outBuf); + + // Check if we compressed at all + if (compLen != m_ipcHdr.size) { + tempBuffer.resize(compLen); + memcpy(&inBuf[0], &outBuf[0], compLen); + m_ipcHdr.oodleDecompressedSize = m_ipcHdr.size; + m_ipcHdr.size = compLen; + m_ipcHdr.compressionType = static_cast< uint8_t >(Packets::CompressionType::Oodle); + } + } + + using namespace std::chrono; + auto ms = duration_cast< milliseconds >( system_clock::now().time_since_epoch() ); + uint64_t tick = ms.count(); + m_ipcHdr.unknown_0 = 0xE2465DFF41a05252; + m_ipcHdr.unknown_8 = 0x75C4997B4D642A7F; + m_ipcHdr.timestamp = tick; + m_ipcHdr.unknown_20 = 1; + + memcpy( &tempBuffer[ 0 ], &m_ipcHdr, sizeof( FFXIVARR_PACKET_HEADER ) ); + + sendBuffer.assign( &tempBuffer[ 0 ], &tempBuffer[ 0 ] + m_ipcHdr.size ); } std::string Network::Packets::PacketContainer::toString() { std::vector< uint8_t > tmpBuffer; - fillSendBuffer( tmpBuffer ); + fillSendBuffer( tmpBuffer, nullptr ); std::string str = "\n"; for( uint32_t i = 0; i < m_ipcHdr.size; i++ ) diff --git a/src/common/Network/PacketContainer.h b/src/common/Network/PacketContainer.h index 80a35cf1..8d891aeb 100644 --- a/src/common/Network/PacketContainer.h +++ b/src/common/Network/PacketContainer.h @@ -7,6 +7,7 @@ #include "CommonNetwork.h" #include "GamePacket.h" #include "Forwards.h" +#include "Oodle.h" namespace Sapphire::Network::Packets { @@ -27,7 +28,7 @@ namespace Sapphire::Network::Packets std::string toString(); - void fillSendBuffer( std::vector< uint8_t >& sendBuffer ); + void fillSendBuffer( std::vector< uint8_t >& sendBuffer, Network::Oodle* oodle ); private: uint32_t m_segmentTargetOverride; diff --git a/src/common/Network/PacketDef/Ipcs.h b/src/common/Network/PacketDef/Ipcs.h index 61936e63..8e8c79d7 100644 --- a/src/common/Network/PacketDef/Ipcs.h +++ b/src/common/Network/PacketDef/Ipcs.h @@ -338,7 +338,7 @@ namespace Sapphire::Network::Packets enum ClientZoneIpcType : uint16_t { PingHandler = 0x0273, // updated 6.31h - InitHandler = 0x03a8, // updated 6.31h + InitHandler = 0x0090, // updated 6.38 FinishLoadingHandler = 0x032d, // updated 6.31h @@ -356,7 +356,7 @@ namespace Sapphire::Network::Packets SocialResponseHandler = 0x023B, // updated 5.58h CreateCrossWorldLS = 0x035D, // updated 5.58h - ChatHandler = 0x00f1, // Updated 6.31h + ChatHandler = 0x01F2, // Updated 6.38 PartyChatHandler = 0x0065, PartySetLeaderHandler = 0x036C, // updated 5.58h LeavePartyHandler = 0x019D, // updated 5.58h @@ -364,7 +364,7 @@ namespace Sapphire::Network::Packets DisbandPartyHandler = 0x0276, // updated 5.58h SocialListHandler = 0x0200, // updated 6.31 - SetSearchInfoHandler = 0x0368, // updated 6.31h + SetSearchInfoHandler = 0x0165, // updated 6.38 ReqSearchInfoHandler = 0x03b0, // updated 6.31h ReqExamineSearchCommentHandler = 0x00E7, // updated 5.0 @@ -377,6 +377,7 @@ namespace Sapphire::Network::Packets MarketBoardRequestItemListingInfo = 0x00F4, // updated 5.58h MarketBoardRequestItemListings = 0x0122, // updated 5.58h MarketBoardSearch = 0x0082, // updated 5.58h + MarketBoardPurchaseHandler = 0x0397, // updated 6.38 ReqExamineFcInfo = 0x037B, // updated 5.58h @@ -392,19 +393,17 @@ namespace Sapphire::Network::Packets ReqCountdownCancel = 0x023a, // updated 6.31h ZoneLineHandler = 0x00ce, // updated 6.31h - ClientTrigger = 0x0244, // updated 6.31h + ClientTrigger = 0x01BE, // updated 6.38 DiscoveryHandler = 0x038B, // updated 5.58h - PlaceFieldMarkerPreset = 0x204, // updated 6.30h - PlaceFieldMarker = 0x38e, // updated 6.30h SkillHandler = 0x0133, // updated 6.31h GMCommand1 = 0x0278, // updated 6.31h GMCommand2 = 0x03d8, // updated 6.31h AoESkillHandler = 0x0152, // updated 5.58h - UpdatePositionHandler = 0x01f7, // updated 6.31h + UpdatePositionHandler = 0x025F, // updated 6.38 - InventoryModifyHandler = 0x01a2, // updated 6.31h + InventoryModifyHandler = 0x024D, // updated 6.38 InventoryEquipRecommendedItems = 0x01C9, // updated 5.58h @@ -436,7 +435,7 @@ namespace Sapphire::Network::Packets SetSharedEstateSettings = 0x00D2, // updated 5.58h - UpdatePositionInstance = 0x03bd, // Updated 6.31h + UpdatePositionInstance = 0x01A0, // Updated 6.38 PerformNoteHandler = 0x0243, // updated 5.58h diff --git a/src/lobby/GameConnection.cpp b/src/lobby/GameConnection.cpp index 8b804afe..158e3a5b 100644 --- a/src/lobby/GameConnection.cpp +++ b/src/lobby/GameConnection.cpp @@ -73,7 +73,7 @@ void Lobby::GameConnection::onRecv( std::vector< uint8_t >& buffer ) // Dissect packet list std::vector< FFXIVARR_PACKET_RAW > packetList; const auto packetResult = getPackets( m_packets, sizeof( struct FFXIVARR_PACKET_HEADER ), - packetHeader, packetList ); + packetHeader, packetList, nullptr ); if( packetResult == Incomplete ) return; @@ -433,7 +433,7 @@ void Lobby::GameConnection::sendPackets( Network::Packets::PacketContainer* pPac { std::vector< uint8_t > sendBuffer; - pPacket->fillSendBuffer( sendBuffer ); + pPacket->fillSendBuffer( sendBuffer, nullptr ); send( sendBuffer ); } diff --git a/src/world/Network/GameConnection.cpp b/src/world/Network/GameConnection.cpp index 25d65cf0..ef9be721 100644 --- a/src/world/Network/GameConnection.cpp +++ b/src/world/Network/GameConnection.cpp @@ -42,6 +42,8 @@ Sapphire::Network::GameConnection::GameConnection( Sapphire::Network::HivePtr pH m_chatHandlerStrMap[ opcode ] = handlerName; }; + m_pOodle = std::make_unique(); + setZoneHandler( ClientZoneIpcType::PingHandler, "PingHandler", &GameConnection::pingHandler ); setZoneHandler( ClientZoneIpcType::InitHandler, "InitHandler", &GameConnection::initHandler ); setZoneHandler( ClientZoneIpcType::ChatHandler, "ChatHandler", &GameConnection::chatHandler ); @@ -182,7 +184,7 @@ void Sapphire::Network::GameConnection::onRecv( std::vector< uint8_t >& buffer ) // Dissect packet list std::vector< Packets::FFXIVARR_PACKET_RAW > packetList; const auto packetResult = Packets::getPackets( m_packets, sizeof( struct FFXIVARR_PACKET_HEADER ), - packetHeader, packetList ); + packetHeader, packetList, m_pOodle.get()); if( packetResult == Incomplete ) return; @@ -284,7 +286,7 @@ void Sapphire::Network::GameConnection::sendPackets( Packets::PacketContainer* p { std::vector< uint8_t > sendBuffer; - pPacket->fillSendBuffer( sendBuffer ); + pPacket->fillSendBuffer( sendBuffer, nullptr); send( sendBuffer ); } diff --git a/src/world/Network/GameConnection.h b/src/world/Network/GameConnection.h index 576a7bb9..c8ff3e97 100644 --- a/src/world/Network/GameConnection.h +++ b/src/world/Network/GameConnection.h @@ -8,6 +8,7 @@ #include #include "ForwardsZone.h" +#include "Network/Oodle.h" #define DECLARE_HANDLER( x ) void x( const Sapphire::Network::Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player ) @@ -53,6 +54,7 @@ namespace Sapphire::Network Common::Util::LockedQueue< Network::Packets::FFXIVARR_PACKET_RAW > m_inQueue; Common::Util::LockedQueue< Packets::FFXIVPacketBasePtr > m_outQueue; std::vector< uint8_t > m_packets; + OodlePtr m_pOodle; public: ConnectionType m_conType;