1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-04-28 07:07:45 +00:00

Oodle support for 6.15

Requires the oodle2base.h and oodle2net.h header files, and oo2net_9_win64.dll, to be placed in /deps/Oodle/ - they are not included here
This commit is contained in:
Moydow 2022-06-12 21:44:11 +01:00 committed by Maple
parent 6389597004
commit 7449d16c7e
8 changed files with 130 additions and 7 deletions

View file

@ -15,6 +15,7 @@ add_custom_target( copy_runtime_files ALL
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/web ${CMAKE_BINARY_DIR}/bin/web
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/sql_import.sh ${CMAKE_BINARY_DIR}/bin/sql_import.sh
COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_BINARY_DIR}/bin/data/actions
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/deps/oo2net_9_win64.dll ${CMAKE_BINARY_DIR}/bin/oo2net_9_win64.dll
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/deps/ffxiv-actions/actions ${CMAKE_BINARY_DIR}/bin/data/actions )
######################################
@ -43,6 +44,7 @@ find_package( MySQL )
##############################
add_subdirectory( "deps/zlib" )
add_subdirectory( "deps/MySQL" )
add_subdirectory( "deps/Oodle" )
add_subdirectory( "deps/datReader" )
add_subdirectory( "deps/mysqlConnector" )
add_subdirectory( "deps/recastnavigation" )

9
deps/Oodle/CMakeLists.txt vendored Normal file
View file

@ -0,0 +1,9 @@
add_library(OodleNet STATIC IMPORTED GLOBAL)
set_target_properties(
OodleNet
PROPERTIES
IMPORTED_IMPLIB "${CMAKE_SOURCE_DIR}/deps/Oodle/oo2net_9_win64.lib"
IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/deps/Oodle/oo2net_9_win64.lib"
LINKER_LANGUAGE C
)

View file

@ -20,7 +20,8 @@ target_link_libraries( common
PUBLIC
xivdat
mysqlConnector
mysql )
mysql
OodleNet )
if( UNIX )
target_link_libraries( common
PUBLIC
@ -32,6 +33,7 @@ target_include_directories( common
PUBLIC
"${CMAKE_CURRENT_SOURCE_DIR}/"
"${CMAKE_CURRENT_SOURCE_DIR}/../../deps/"
"${CMAKE_CURRENT_SOURCE_DIR}/../../deps/Oodle/"
"${CMAKE_CURRENT_SOURCE_DIR}/../../deps/asio/asio/include/"
"${CMAKE_CURRENT_SOURCE_DIR}/../../deps/spdlog/include/" )

View file

@ -44,7 +44,7 @@ namespace Sapphire::Network::Packets
* +-------------------------------+---------------+-------+-------+
* | timestamp | size | cType | count |
* +---+---+-------+---------------+---------------+-------+-------+
* | ? |CMP| ? | ? |
* | ? |CMP| ? | oodleDcmpSize |
* +---+---+-------+---------------+
* (followed by /count/ FFXIVARR_PACKET_SEGMENTs)
*/
@ -62,9 +62,13 @@ namespace Sapphire::Network::Packets
/** The number of packet segments that follow. */
uint16_t count;
uint8_t unknown_20;
/** Indicates if the data segments of this packet are compressed. */
uint8_t isCompressed;
uint32_t unknown_24;
/** Indicates compression method of the data segments of this packet.
* 0: none, 1: Zlib, 2: Oodle
*/
uint8_t compressionType;
uint16_t unknown_22;
/** The size of the packet payload when decompressed, only used if compressionType = Oodle */
uint32_t oodleDecompressedSize;
};
inline std::ostream& operator<<( std::ostream& os, const FFXIVARR_PACKET_HEADER& hdr )

View file

@ -1,7 +1,9 @@
#include "CommonNetwork.h"
#include "GamePacketParser.h"
#include "Oodle.h"
#include <string.h> // memcpy
#include <Logging/Logger.h>
using namespace Sapphire;
using namespace Sapphire::Network::Packets;
@ -49,10 +51,51 @@ PacketParseResult Network::Packets::getPackets( const std::vector< uint8_t >& bu
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 );
auto bytesExpected = packetHeader.size - sizeof( struct FFXIVARR_PACKET_HEADER );
if( buffer.size() - offset < bytesExpected )
return Incomplete;
std::vector< uint8_t > decompBuf;
// check compression, do decompress if Oodle/Zlib
if( packetHeader.compressionType == Oodle )
{
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 );
if( !oodleSuccess )
{
Logger::warn( "Oodle decompression failed." );
return Malformed;
}
bytesExpected = packetHeader.oodleDecompressedSize;
decompBuf.assign( buffer.begin(), buffer.begin() + sizeof( struct FFXIVARR_PACKET_HEADER ) );
decompBuf.insert( decompBuf.end(), outBuf.begin(), outBuf.end() );
}
else if( packetHeader.compressionType == Zlib )
{
// to do(?): Zlib decompression should go here,
// but I don't think the client ever sends Zlib packets? So it may not be needed
}
else if( packetHeader.compressionType == NoCompression )
decompBuf.assign( buffer.begin(), buffer.end() );
else
{
Logger::warn( "Unknown packet compression type: {}", packetHeader.compressionType );
return Malformed;
}
// Loop each message
uint32_t count = 0;
uint32_t bytesProcessed = 0;
@ -61,7 +104,7 @@ PacketParseResult Network::Packets::getPackets( const std::vector< uint8_t >& bu
FFXIVARR_PACKET_RAW rawPacket;
// Copy ipc packet message
const auto packetResult = getPacket( buffer, offset + bytesProcessed, rawPacket );
const auto packetResult = getPacket( decompBuf, offset + bytesProcessed, rawPacket );
if( packetResult != Success )
return packetResult;

View file

@ -18,6 +18,13 @@ namespace Sapphire::Network::Packets
Malformed
};
enum CompressionType
{
NoCompression,
Zlib,
Oodle,
};
/// 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,

View file

@ -0,0 +1,28 @@
#include "Oodle.h"
using namespace Sapphire;
Network::Oodle::Oodle() :
m_htbits(19)
{
auto stateSize = OodleNetwork1UDP_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 );
oodleInit();
}
void Network::Oodle::oodleInit()
{
OodleNetwork1_Shared_SetWindow( (OodleNetwork1_Shared*) &m_shared[0], m_htbits, &m_window[0], (int) m_window.size() );
OodleNetwork1UDP_Train( (OodleNetwork1UDP_State*) &m_state[0], (OodleNetwork1_Shared*) &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 )
{
OodleNetwork1_Shared_SetWindow( (OodleNetwork1_Shared*) &m_shared[0], m_htbits, &m_window[0], (int) m_window.size() );
return OodleNetwork1UDP_Decode( (OodleNetwork1UDP_State*) &m_state[0], (OodleNetwork1_Shared*) &m_shared[0], &enc[0], encSize, &dec[0], decSize );
}

View file

@ -0,0 +1,28 @@
#ifndef _OODLE_H
#define _OODLE_H
#include <vector>
#include <oodle2net.h>
namespace Sapphire::Network
{
class Oodle
{
private:
std::vector< uint8_t > m_state;
std::vector< uint8_t > m_shared;
std::vector< uint8_t > m_window;
int m_htbits;
public:
Oodle();
virtual ~Oodle() = default;
void oodleInit();
bool oodleDecode( const std::vector< uint8_t > &enc, uint32_t encSize, std::vector< uint8_t > &dec, uint32_t decSize );
};
}
#endif // _OODLE_H