2017-08-08 13:53:47 +02:00
|
|
|
#ifndef _GAMEPACKETNEW_H
|
|
|
|
#define _GAMEPACKETNEW_H
|
|
|
|
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
#include "GamePacket.h"
|
|
|
|
|
|
|
|
#include <sstream>
|
|
|
|
#include <time.h>
|
|
|
|
|
|
|
|
namespace Core {
|
|
|
|
namespace Network {
|
|
|
|
namespace Packets {
|
|
|
|
|
|
|
|
// Must forward define these in order to enable the compiler to produce the
|
|
|
|
// correct template functions.
|
|
|
|
|
2018-06-03 19:31:03 +02:00
|
|
|
template < typename T, typename T1 >
|
2017-08-08 13:53:47 +02:00
|
|
|
class GamePacketNew;
|
|
|
|
|
2018-06-03 19:31:03 +02:00
|
|
|
template < typename T, typename T1 >
|
2018-06-07 20:33:06 +02:00
|
|
|
std::ostream& operator << ( std::ostream& os, const GamePacketNew< T, T1 >& packet );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2017-11-21 18:43:09 +01:00
|
|
|
template< class T >
|
|
|
|
using ZoneChannelPacket = GamePacketNew< T, ServerZoneIpcType >;
|
|
|
|
|
|
|
|
template< class T >
|
|
|
|
using ChatChannelPacket = GamePacketNew< T, ServerChatIpcType >;
|
|
|
|
|
2017-08-08 13:53:47 +02:00
|
|
|
/**
|
|
|
|
* The base implementation of a game packet. Needed for parsing packets.
|
|
|
|
*/
|
2018-06-03 19:31:03 +02:00
|
|
|
template < typename T1 >
|
2018-06-07 20:33:06 +02:00
|
|
|
class FFXIVIpcPacketBase
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
|
|
|
public:
|
2018-06-07 20:33:06 +02:00
|
|
|
virtual ~FFXIVIpcPacketBase() = default;
|
2017-08-08 13:53:47 +02:00
|
|
|
/**
|
|
|
|
* @brief Gets the IPC type of this packet. (Useful for determining the
|
|
|
|
* type of a parsed packet.)
|
|
|
|
*/
|
2018-06-07 20:33:06 +02:00
|
|
|
virtual T1 ipcType() = 0;
|
2017-08-08 13:53:47 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A game packet, or IPC packet, object is a template class for constructing
|
|
|
|
* the data to be sent or parsed. The template works by accepting a structure
|
|
|
|
* type that represents just the IPC data portion (the bytes after the initial
|
|
|
|
* 32 byte header information.)
|
|
|
|
*/
|
2018-06-03 19:31:03 +02:00
|
|
|
template < typename T, typename T1 >
|
2018-06-07 20:33:06 +02:00
|
|
|
class GamePacketNew : public FFXIVIpcPacketBase< T1 >
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
/**
|
|
|
|
* @brief Constructs a new game packet with the specified actors.
|
|
|
|
* @param sourceActorId The source actor id.
|
|
|
|
* @param targetActorId The target actor id.
|
|
|
|
*/
|
2018-06-03 19:31:03 +02:00
|
|
|
GamePacketNew< T, T1 >( uint32_t sourceActorId, uint32_t targetActorId )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
|
|
|
initialize();
|
|
|
|
m_segHdr.source_actor = sourceActorId;
|
|
|
|
m_segHdr.target_actor = targetActorId;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Constructs a new game packet with the specified actors.
|
|
|
|
* @param sourceActorId The source and target actor id.
|
|
|
|
*/
|
2018-06-03 19:31:03 +02:00
|
|
|
GamePacketNew< T, T1 >( uint32_t bothActorId )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
|
|
|
initialize();
|
|
|
|
m_segHdr.source_actor = bothActorId;
|
|
|
|
m_segHdr.target_actor = bothActorId;
|
|
|
|
};
|
|
|
|
|
|
|
|
protected:
|
|
|
|
/** Initializes the fields of the header structures */
|
|
|
|
virtual void initialize( void )
|
|
|
|
{
|
|
|
|
// Zero out the structures.
|
|
|
|
memset( &m_segHdr, 0, sizeof( FFXIVARR_PACKET_SEGMENT_HEADER ) );
|
|
|
|
memset( &m_ipcHdr, 0, sizeof( FFXIVARR_IPC_HEADER ) );
|
|
|
|
memset( &m_data, 0, sizeof( T ) );
|
|
|
|
|
|
|
|
// Set the values of static fields.
|
|
|
|
// The size must be the sum of the segment header, the ipc header, and
|
|
|
|
// the IPC data itself.
|
|
|
|
m_segHdr.size = sizeof( FFXIVARR_PACKET_SEGMENT_HEADER ) + sizeof( FFXIVARR_IPC_HEADER ) + sizeof( T );
|
|
|
|
// Game packets (IPC) are type 3.
|
|
|
|
m_segHdr.type = 3;
|
|
|
|
// The IPC type itself.
|
2017-08-20 22:31:23 +02:00
|
|
|
m_ipcHdr.type = static_cast< ServerZoneIpcType >( m_data._ServerIpcType );
|
2017-08-08 13:53:47 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
public:
|
2018-06-07 20:33:06 +02:00
|
|
|
virtual T1 ipcType()
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2017-08-20 22:31:23 +02:00
|
|
|
return static_cast< T1 >( m_data._ServerIpcType );
|
2017-08-08 13:53:47 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
/** Gets a reference to the underlying IPC data structure. */
|
|
|
|
T& data( void ) { return m_data; };
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Sets the source actor id for this IPC packet.
|
|
|
|
* @param actorId The source actor id.
|
|
|
|
* @return This IPC packet object (can be used for chaining).
|
|
|
|
*/
|
2018-06-03 19:31:03 +02:00
|
|
|
GamePacketNew< T, T1 > sourceActor( uint32_t actorId )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
|
|
|
m_segHdr.source_actor = actorId;
|
|
|
|
return this;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Gets the source actor id for this IPC packet.
|
|
|
|
* @return The source actor id.
|
|
|
|
*/
|
|
|
|
uint32_t sourceActor( void ) const
|
|
|
|
{
|
|
|
|
return m_segHdr.source_actor;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Sets the target actor id for this IPC packet.
|
|
|
|
* @param actorId The target actor id.
|
|
|
|
* @return This IPC packet object (can be used for chaining).
|
|
|
|
*/
|
2018-06-03 19:31:03 +02:00
|
|
|
GamePacketNew< T, T1 > targetActor( uint32_t actorId )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
|
|
|
m_segHdr.target_actor = actorId;
|
|
|
|
return this;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Gets the target actor id for this IPC packet.
|
|
|
|
* @return The target actor id.
|
|
|
|
*/
|
|
|
|
uint32_t targetActor( void ) const
|
|
|
|
{
|
|
|
|
return m_segHdr.target_actor;
|
|
|
|
};
|
|
|
|
|
2018-06-03 19:31:03 +02:00
|
|
|
friend std::ostream& operator<< <> ( std::ostream& os, const GamePacketNew< T, T1 >& packet );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
|
|
|
friend class GamePacketFactory;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Adapts the new-style packet into the old style.
|
|
|
|
*/
|
|
|
|
operator GamePacket* ( ) const
|
|
|
|
{
|
|
|
|
std::ostringstream buf;
|
|
|
|
serialize( buf );
|
|
|
|
// NOTE: This should be ok because CGamePacket's constructor will
|
|
|
|
// copy the contents of the buffer.
|
|
|
|
GamePacket* pOldStyle = new GamePacket( const_cast< char* >( buf.str().c_str() ), m_segHdr.size, false );
|
|
|
|
return pOldStyle;
|
|
|
|
};
|
|
|
|
|
|
|
|
operator GamePacketPtr () const
|
|
|
|
{
|
|
|
|
std::ostringstream buf;
|
|
|
|
serialize( buf );
|
|
|
|
// NOTE: This should be ok because CGamePacket's constructor will
|
|
|
|
// copy the contents of the buffer.
|
|
|
|
GamePacketPtr pOldStyle( new GamePacket( const_cast< char* >( buf.str().c_str() ), m_segHdr.size, true ) );
|
|
|
|
return pOldStyle;
|
|
|
|
};
|
|
|
|
|
|
|
|
protected:
|
|
|
|
// TODO: Is this a waste of storage memory?
|
|
|
|
/** The segment header */
|
|
|
|
FFXIVARR_PACKET_SEGMENT_HEADER m_segHdr;
|
|
|
|
/** The IPC packet header */
|
|
|
|
FFXIVARR_IPC_HEADER m_ipcHdr;
|
|
|
|
/** The underlying data portion of the packet as a structure */
|
|
|
|
T m_data;
|
|
|
|
|
|
|
|
private:
|
|
|
|
std::ostream& serialize( std::ostream& os ) const
|
|
|
|
{
|
|
|
|
// Since the packet itself is constant, we need to make a copy of the IPC
|
|
|
|
// header in order to set the timestamp.
|
|
|
|
FFXIVARR_IPC_HEADER ipcHdr;
|
|
|
|
memcpy( &ipcHdr, &m_ipcHdr, sizeof( ipcHdr ) );
|
|
|
|
|
|
|
|
// TODO: Fixed timestamp? Can we use a manipulator on the stream to assign
|
|
|
|
// a fixed timestamp value. This might be useful if several packets must
|
|
|
|
// be sent having the exact same timestamp. (Maybe this doesn't really
|
|
|
|
// need to happen though...)
|
|
|
|
ipcHdr.timestamp = static_cast< uint32_t >( time( nullptr ) );
|
|
|
|
|
|
|
|
// TODO: What about encryption? compression?
|
|
|
|
// Ideally, these could come directly from the stream using manipulators.
|
|
|
|
// We could check the stream's flags, and perform the appropriate
|
|
|
|
// operations here. The snag is encryption, which does not occur for
|
|
|
|
// segment headers, but may occur for IPC headers, and their data.
|
|
|
|
// Compression occurs for the entire segment header down.
|
|
|
|
os << m_segHdr << ipcHdr;
|
|
|
|
return os.write( reinterpret_cast< const char* >( &m_data ), sizeof( T ) );
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2018-06-03 19:31:03 +02:00
|
|
|
template < typename T, typename T1 >
|
2017-08-20 22:31:23 +02:00
|
|
|
std::ostream& operator<<( std::ostream& os, const GamePacketNew<T, T1>& packet )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
|
|
|
#if 0
|
|
|
|
// Since the packet itself is constant, we need to make a copy of the IPC
|
|
|
|
// header in order to set the timestamp.
|
|
|
|
FFXIVARR_IPC_HEADER ipcHdr;
|
|
|
|
memcpy( &ipcHdr, &packet.m_ipcHdr, sizeof( ipcHdr ) );
|
|
|
|
|
|
|
|
// TODO: Fixed timestamp? Can we use a manipulator on the stream to assign
|
|
|
|
// a fixed timestamp value. This might be useful if several packets must
|
|
|
|
// be sent having the exact same timestamp. (Maybe this doesn't really
|
|
|
|
// need to happen though...)
|
|
|
|
ipcHdr.timestamp = time( NULL );
|
|
|
|
|
|
|
|
// TODO: What about encryption? compression?
|
|
|
|
// Ideally, these could come directly from the stream using manipulators.
|
|
|
|
// We could check the stream's flags, and perform the appropriate
|
|
|
|
// operations here. The snag is encryption, which does not occur for
|
|
|
|
// segment headers, but may occur for IPC headers, and their data.
|
|
|
|
// Compression occurs for the entire segment header down.
|
|
|
|
os << packet.m_segHdr << ipcHdr;
|
|
|
|
return os.write(
|
|
|
|
reinterpret_cast< const char* >( &packet.m_data ), sizeof( T ) );
|
|
|
|
#else
|
|
|
|
return packet.serialize( os );
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
} /* Packets */
|
|
|
|
} /* Network */
|
|
|
|
} /* Core */
|
|
|
|
|
|
|
|
#endif /*_CORE_NETWORK_PACKETS_CGAMEPACKETNEW_H*/
|