2018-03-02 07:22:25 -03:00
|
|
|
#include <boost/format.hpp>
|
|
|
|
|
2017-12-18 12:36:52 +01:00
|
|
|
#include <common/Common.h>
|
|
|
|
#include <common/Network/CommonNetwork.h>
|
|
|
|
#include <common/Util/Util.h>
|
|
|
|
#include <common/Logging/Logger.h>
|
|
|
|
#include <common/Network/PacketContainer.h>
|
|
|
|
#include <common/Network/GamePacketParser.h>
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2017-12-08 15:38:25 +01:00
|
|
|
#include "Zone/Zone.h"
|
2018-03-02 07:22:25 -03:00
|
|
|
|
2017-12-08 15:38:25 +01:00
|
|
|
#include "Network/PacketWrappers/InitUIPacket.h"
|
2018-03-02 07:22:25 -03:00
|
|
|
|
2018-01-28 11:16:34 +01:00
|
|
|
#include "DebugCommand/DebugCommandHandler.h"
|
2018-03-02 07:22:25 -03:00
|
|
|
|
2017-12-08 15:38:25 +01:00
|
|
|
#include "Actor/Player.h"
|
2018-03-02 07:22:25 -03:00
|
|
|
|
|
|
|
#include "GameConnection.h"
|
|
|
|
#include "ServerZone.h"
|
|
|
|
#include "Session.h"
|
|
|
|
#include "Framework.h"
|
2017-12-08 15:38:25 +01:00
|
|
|
#include "Forwards.h"
|
2017-08-18 17:16:15 +02:00
|
|
|
|
2018-03-02 07:22:25 -03:00
|
|
|
extern Core::Framework g_framework;
|
2017-08-08 13:53:47 +02:00
|
|
|
|
|
|
|
using namespace Core::Common;
|
|
|
|
using namespace Core::Network::Packets;
|
|
|
|
using namespace Core::Network::Packets::Server;
|
|
|
|
|
|
|
|
Core::Network::GameConnection::GameConnection( Core::Network::HivePtr pHive,
|
|
|
|
Core::Network::AcceptorPtr pAcceptor )
|
|
|
|
: Connection( pHive )
|
|
|
|
, m_pAcceptor( pAcceptor )
|
|
|
|
, m_conType( ConnectionType::None )
|
|
|
|
{
|
2017-08-20 22:31:23 +02:00
|
|
|
auto setZoneHandler = [=]( uint16_t opcode, std::string handlerName, GameConnection::Handler pHandler )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2017-08-20 22:31:23 +02:00
|
|
|
m_zoneHandlerMap[opcode] = pHandler;
|
2017-08-22 21:36:20 +02:00
|
|
|
m_zoneHandlerStrMap[opcode] = handlerName;
|
|
|
|
};
|
|
|
|
|
|
|
|
auto setChatHandler = [=]( uint16_t opcode, std::string handlerName, GameConnection::Handler pHandler )
|
|
|
|
{
|
|
|
|
m_chatHandlerMap[opcode] = pHandler;
|
|
|
|
m_chatHandlerStrMap[opcode] = handlerName;
|
2017-08-08 13:53:47 +02:00
|
|
|
};
|
|
|
|
|
2017-08-20 22:31:23 +02:00
|
|
|
setZoneHandler( ClientZoneIpcType::PingHandler, "PingHandler", &GameConnection::pingHandler );
|
|
|
|
setZoneHandler( ClientZoneIpcType::InitHandler, "InitHandler", &GameConnection::initHandler );
|
|
|
|
setZoneHandler( ClientZoneIpcType::ChatHandler, "ChatHandler", &GameConnection::chatHandler );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2017-08-20 22:31:23 +02:00
|
|
|
setZoneHandler( ClientZoneIpcType::FinishLoadingHandler, "FinishLoadingHandler", &GameConnection::finishLoadingHandler );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2017-08-20 22:31:23 +02:00
|
|
|
setZoneHandler( ClientZoneIpcType::PlayTimeHandler, "PlayTimeHandler", &GameConnection::playTimeHandler );
|
|
|
|
setZoneHandler( ClientZoneIpcType::LogoutHandler, "LogoutHandler", &GameConnection::logoutHandler );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2017-08-20 22:31:23 +02:00
|
|
|
setZoneHandler( ClientZoneIpcType::SocialListHandler, "SocialListHandler", &GameConnection::socialListHandler );
|
|
|
|
setZoneHandler( ClientZoneIpcType::SetSearchInfoHandler, "SetSearchInfoHandler", &GameConnection::setSearchInfoHandler );
|
|
|
|
setZoneHandler( ClientZoneIpcType::ReqSearchInfoHandler, "ReqSearchInfoHandler", &GameConnection::reqSearchInfoHandler );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2017-08-20 22:31:23 +02:00
|
|
|
setZoneHandler( ClientZoneIpcType::BlackListHandler, "BlackListHandler", &GameConnection::blackListHandler );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2017-08-20 22:31:23 +02:00
|
|
|
setZoneHandler( ClientZoneIpcType::LinkshellListHandler, "LinkshellListHandler", &GameConnection::linkshellListHandler );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2017-08-20 22:31:23 +02:00
|
|
|
setZoneHandler( ClientZoneIpcType::FcInfoReqHandler, "FcInfoReqHandler", &GameConnection::fcInfoReqHandler );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2017-08-20 22:31:23 +02:00
|
|
|
setZoneHandler( ClientZoneIpcType::ZoneLineHandler, "ZoneLineHandler", &GameConnection::zoneLineHandler );
|
|
|
|
setZoneHandler( ClientZoneIpcType::ActionHandler, "ActionHandler", &GameConnection::actionHandler );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2017-08-20 22:31:23 +02:00
|
|
|
setZoneHandler( ClientZoneIpcType::DiscoveryHandler, "DiscoveryHandler", &GameConnection::discoveryHandler );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2017-08-20 22:31:23 +02:00
|
|
|
setZoneHandler( ClientZoneIpcType::SkillHandler, "SkillHandler", &GameConnection::skillHandler );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2017-08-20 22:31:23 +02:00
|
|
|
setZoneHandler( ClientZoneIpcType::GMCommand1, "GMCommand1", &GameConnection::gm1Handler );
|
|
|
|
setZoneHandler( ClientZoneIpcType::GMCommand2, "GMCommand2", &GameConnection::gm2Handler );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2017-08-20 22:31:23 +02:00
|
|
|
setZoneHandler( ClientZoneIpcType::UpdatePositionHandler,"UpdatePositionHandler", &GameConnection::updatePositionHandler );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2017-08-20 22:31:23 +02:00
|
|
|
setZoneHandler( ClientZoneIpcType::InventoryModifyHandler,"InventoryModifyHandler", &GameConnection::inventoryModifyHandler );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-01-14 23:54:26 +01:00
|
|
|
setZoneHandler( ClientZoneIpcType::TalkEventHandler, "EventHandlerTalk", &GameConnection::eventHandlerTalk );
|
2018-01-16 02:16:48 +01:00
|
|
|
setZoneHandler( ClientZoneIpcType::EmoteEventHandler, "EventHandlerEmote", &GameConnection::eventHandlerEmote );
|
|
|
|
setZoneHandler( ClientZoneIpcType::WithinRangeEventHandler, "EventHandlerWithinRange", &GameConnection::eventHandlerWithinRange );
|
|
|
|
setZoneHandler( ClientZoneIpcType::OutOfRangeEventHandler, "EventHandlerOutsideRange", &GameConnection::eventHandlerOutsideRange );
|
2018-01-18 21:49:12 +01:00
|
|
|
setZoneHandler( ClientZoneIpcType::EnterTeriEventHandler, "EventHandlerEnterTeri", &GameConnection::eventHandlerEnterTerritory );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2018-01-18 21:49:12 +01:00
|
|
|
setZoneHandler( ClientZoneIpcType::ReturnEventHandler, "EventHandlerReturn", &GameConnection::eventHandlerReturn );
|
|
|
|
setZoneHandler( ClientZoneIpcType::TradeReturnEventHandler, "EventHandlerReturn", &GameConnection::eventHandlerReturn );
|
2017-08-23 23:58:14 +02:00
|
|
|
|
2018-01-18 21:49:12 +01:00
|
|
|
setZoneHandler( ClientZoneIpcType::LinkshellEventHandler, "LinkshellEventHandler", &GameConnection::eventHandlerLinkshell );
|
|
|
|
setZoneHandler( ClientZoneIpcType::LinkshellEventHandler1, "LinkshellEventHandler1", &GameConnection::eventHandlerLinkshell );
|
2017-08-12 23:20:26 +09:00
|
|
|
|
2017-08-20 22:31:23 +02:00
|
|
|
setZoneHandler( ClientZoneIpcType::CFDutyInfoHandler, "CFDutyInfoRequest", &GameConnection::cfDutyInfoRequest );
|
|
|
|
setZoneHandler( ClientZoneIpcType::CFRegisterDuty, "CFRegisterDuty", &GameConnection::cfRegisterDuty );
|
|
|
|
setZoneHandler( ClientZoneIpcType::CFRegisterRoulette, "CFRegisterRoulette", &GameConnection::cfRegisterRoulette );
|
|
|
|
setZoneHandler( ClientZoneIpcType::CFCommenceHandler, "CFDutyAccepted", &GameConnection::cfDutyAccepted);
|
2017-08-12 23:20:26 +09:00
|
|
|
|
2017-11-22 00:29:42 +09:00
|
|
|
setZoneHandler( ClientZoneIpcType::ReqEquipDisplayFlagsChange, "ReqEquipDisplayFlagsChange", &GameConnection::reqEquipDisplayFlagsHandler );
|
|
|
|
|
|
|
|
setZoneHandler( ClientZoneIpcType::PerformNoteHandler, "PerformNoteHandler", &GameConnection::performNoteHandler );
|
2017-08-22 21:36:20 +02:00
|
|
|
|
2017-10-05 20:24:58 +02:00
|
|
|
setChatHandler( ClientChatIpcType::TellReq, "TellReq", &GameConnection::tellHandler);
|
2017-08-22 21:36:20 +02:00
|
|
|
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
2017-11-28 17:29:06 +01:00
|
|
|
Core::Network::GameConnection::~GameConnection() = default;
|
2017-08-08 13:53:47 +02:00
|
|
|
|
|
|
|
|
|
|
|
// overwrite the parents onConnect for our game socket needs
|
|
|
|
void Core::Network::GameConnection::OnAccept( const std::string & host, uint16_t port )
|
|
|
|
{
|
|
|
|
GameConnectionPtr connection( new GameConnection( m_hive, m_pAcceptor ) );
|
|
|
|
m_pAcceptor->Accept( connection );
|
|
|
|
|
2018-03-02 07:22:25 -03:00
|
|
|
g_framework.getLogger().info( "Connect from " + m_socket.remote_endpoint().address().to_string() );
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Core::Network::GameConnection::OnDisconnect()
|
|
|
|
{
|
2018-03-02 07:22:25 -03:00
|
|
|
g_framework.getLogger().debug( "GameConnection DISCONNECT" );
|
2017-08-08 13:53:47 +02:00
|
|
|
m_pSession = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Core::Network::GameConnection::OnRecv( std::vector< uint8_t > & buffer )
|
|
|
|
{
|
2017-08-23 20:04:02 +09:00
|
|
|
// This is assumed packet always start with valid FFXIVARR_PACKET_HEADER for now.
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2017-11-28 00:09:36 +01:00
|
|
|
Packets::FFXIVARR_PACKET_HEADER packetHeader{};
|
2017-11-28 17:29:06 +01:00
|
|
|
const auto headerResult = Packets::getHeader( buffer, 0, packetHeader );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2017-11-28 17:29:06 +01:00
|
|
|
if( headerResult == Incomplete )
|
2017-08-23 20:04:02 +09:00
|
|
|
{
|
2018-03-02 07:22:25 -03:00
|
|
|
g_framework.getLogger().info( "Dropping connection due to incomplete packet header." );
|
|
|
|
g_framework.getLogger().info( "FIXME: Packet message bounary is not implemented." );
|
2017-08-23 20:04:02 +09:00
|
|
|
Disconnect();
|
|
|
|
return;
|
|
|
|
}
|
2017-12-08 11:46:47 +01:00
|
|
|
else if( headerResult == Malformed )
|
2017-08-26 15:06:27 +09:00
|
|
|
{
|
2018-03-02 07:22:25 -03:00
|
|
|
g_framework.getLogger().info( "Dropping connection due to malformed packet header." );
|
2017-08-26 15:06:27 +09:00
|
|
|
Disconnect();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-08-23 20:04:02 +09:00
|
|
|
// Dissect packet list
|
|
|
|
std::vector< Packets::FFXIVARR_PACKET_RAW > packetList;
|
2017-11-28 17:29:06 +01:00
|
|
|
const auto packetResult = Packets::getPackets( buffer, sizeof( struct FFXIVARR_PACKET_HEADER ),
|
|
|
|
packetHeader, packetList );
|
2017-08-26 15:06:27 +09:00
|
|
|
|
2017-11-28 17:29:06 +01:00
|
|
|
if( packetResult == Incomplete )
|
2017-08-23 20:04:02 +09:00
|
|
|
{
|
2018-03-02 07:22:25 -03:00
|
|
|
g_framework.getLogger().info( "Dropping connection due to incomplete packets." );
|
|
|
|
g_framework.getLogger().info( "FIXME: Packet message bounary is not implemented." );
|
2017-08-23 20:04:02 +09:00
|
|
|
Disconnect();
|
|
|
|
return;
|
|
|
|
}
|
2017-12-08 11:46:47 +01:00
|
|
|
else if( packetResult == Malformed )
|
2017-08-26 15:06:27 +09:00
|
|
|
{
|
2018-03-02 07:22:25 -03:00
|
|
|
g_framework.getLogger().info( "Dropping connection due to malformed packets." );
|
2017-08-26 15:06:27 +09:00
|
|
|
Disconnect();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-08-23 20:04:02 +09:00
|
|
|
// Handle it
|
2017-08-26 15:06:27 +09:00
|
|
|
handlePackets( packetHeader, packetList );
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Core::Network::GameConnection::OnError( const boost::system::error_code & error )
|
|
|
|
{
|
2018-03-02 07:22:25 -03:00
|
|
|
g_framework.getLogger().debug( "GameConnection ERROR: " + error.message() );
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Core::Network::GameConnection::queueInPacket( Core::Network::Packets::GamePacketPtr inPacket )
|
|
|
|
{
|
|
|
|
m_inQueue.push( inPacket );
|
|
|
|
}
|
|
|
|
|
|
|
|
void Core::Network::GameConnection::queueOutPacket( Core::Network::Packets::GamePacketPtr outPacket )
|
|
|
|
{
|
|
|
|
m_outQueue.push( outPacket );
|
|
|
|
}
|
|
|
|
|
2017-08-22 21:36:20 +02:00
|
|
|
void Core::Network::GameConnection::handleZonePacket( const Packets::GamePacket& pPacket )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2017-08-22 21:36:20 +02:00
|
|
|
auto it = m_zoneHandlerMap.find( pPacket.getSubType() );
|
|
|
|
|
|
|
|
std::string sessionStr = "[" + std::to_string( m_pSession->getId() ) + "]";
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2017-08-22 21:36:20 +02:00
|
|
|
if( it != m_zoneHandlerMap.end() )
|
2017-08-20 22:31:23 +02:00
|
|
|
{
|
2017-08-22 21:36:20 +02:00
|
|
|
auto itStr = m_zoneHandlerStrMap.find( pPacket.getSubType() );
|
|
|
|
std::string name = itStr != m_zoneHandlerStrMap.end() ? itStr->second : "unknown";
|
|
|
|
// dont display packet notification if it is a ping or pos update, don't want the spam
|
|
|
|
if( pPacket.getSubType() != PingHandler &&
|
|
|
|
pPacket.getSubType() != UpdatePositionHandler )
|
|
|
|
|
2018-03-02 07:22:25 -03:00
|
|
|
g_framework.getLogger().debug( sessionStr + " Handling Zone IPC : " + name + "( " +
|
2017-08-22 21:36:20 +02:00
|
|
|
boost::str( boost::format( "%|04X|" ) %
|
|
|
|
static_cast< uint32_t >( pPacket.getSubType() & 0xFFFF ) ) + " )" );
|
|
|
|
|
2017-12-08 11:46:47 +01:00
|
|
|
( this->*( it->second ) )( pPacket, *m_pSession->getPlayer() );
|
2017-08-20 22:31:23 +02:00
|
|
|
}
|
2017-08-22 21:36:20 +02:00
|
|
|
else
|
2017-08-20 22:31:23 +02:00
|
|
|
{
|
2018-03-02 07:22:25 -03:00
|
|
|
g_framework.getLogger().debug( sessionStr + " Undefined Zone IPC : Unknown ( " +
|
2017-08-22 21:36:20 +02:00
|
|
|
boost::str( boost::format( "%|04X|" ) %
|
|
|
|
static_cast< uint32_t >( pPacket.getSubType() & 0xFFFF ) ) + " )" );
|
2018-03-02 07:22:25 -03:00
|
|
|
g_framework.getLogger().debug( "\n" + pPacket.toString() );
|
2017-08-22 21:36:20 +02:00
|
|
|
}
|
|
|
|
}
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2017-08-20 22:31:23 +02:00
|
|
|
|
2017-08-22 21:36:20 +02:00
|
|
|
void Core::Network::GameConnection::handleChatPacket( const Packets::GamePacket& pPacket )
|
|
|
|
{
|
|
|
|
auto it = m_chatHandlerMap.find( pPacket.getSubType() );
|
|
|
|
|
|
|
|
std::string sessionStr = "[" + std::to_string( m_pSession->getId() ) + "]";
|
|
|
|
|
|
|
|
if( it != m_chatHandlerMap.end() )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2017-08-22 21:36:20 +02:00
|
|
|
auto itStr = m_chatHandlerStrMap.find( pPacket.getSubType() );
|
|
|
|
std::string name = itStr != m_chatHandlerStrMap.end() ? itStr->second : "unknown";
|
2017-08-08 13:53:47 +02:00
|
|
|
// dont display packet notification if it is a ping or pos update, don't want the spam
|
|
|
|
|
2018-03-02 07:22:25 -03:00
|
|
|
g_framework.getLogger().debug( sessionStr + " Handling Chat IPC : " + name + "( " +
|
2017-08-22 21:36:20 +02:00
|
|
|
boost::str( boost::format( "%|04X|" ) %
|
|
|
|
static_cast< uint32_t >( pPacket.getSubType() & 0xFFFF ) ) + " )" );
|
|
|
|
|
2017-12-08 11:46:47 +01:00
|
|
|
( this->*( it->second ) )( pPacket, *m_pSession->getPlayer() );
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-03-02 07:22:25 -03:00
|
|
|
g_framework.getLogger().debug( sessionStr + " Undefined Chat IPC : Unknown ( " +
|
2017-08-22 21:36:20 +02:00
|
|
|
boost::str( boost::format( "%|04X|" ) %
|
|
|
|
static_cast< uint32_t >( pPacket.getSubType() & 0xFFFF ) ) + " )" );
|
2018-03-02 07:22:25 -03:00
|
|
|
g_framework.getLogger().debug( pPacket.toString() );
|
2017-08-22 21:36:20 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Core::Network::GameConnection::handlePacket( Core::Network::Packets::GamePacketPtr pPacket )
|
|
|
|
{
|
|
|
|
if( !m_pSession )
|
|
|
|
return;
|
|
|
|
|
|
|
|
switch( m_conType )
|
|
|
|
{
|
|
|
|
case Network::ConnectionType::Zone:
|
|
|
|
handleZonePacket( *pPacket );
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Network::ConnectionType::Chat:
|
|
|
|
handleChatPacket( *pPacket );
|
|
|
|
break;
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2017-11-28 17:29:06 +01:00
|
|
|
void Core::Network::GameConnection::sendPackets( Packets::PacketContainer* pPacket )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
|
|
|
//g_log.Log(LoggingSeverity::info, pPacket->toString());
|
|
|
|
std::vector< uint8_t > sendBuffer;
|
|
|
|
|
|
|
|
pPacket->fillSendBuffer( sendBuffer );
|
|
|
|
Send( sendBuffer );
|
|
|
|
}
|
|
|
|
|
|
|
|
void Core::Network::GameConnection::processInQueue()
|
|
|
|
{
|
|
|
|
// handle the incoming game packets
|
|
|
|
while( auto pPacket = m_inQueue.pop() )
|
|
|
|
{
|
2017-11-28 00:09:36 +01:00
|
|
|
handlePacket( pPacket );
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Core::Network::GameConnection::processOutQueue()
|
|
|
|
{
|
|
|
|
|
|
|
|
if( m_outQueue.size() < 1 )
|
|
|
|
return;
|
|
|
|
|
|
|
|
int32_t totalSize = 0;
|
|
|
|
|
|
|
|
// create a new packet container
|
|
|
|
PacketContainer pRP = PacketContainer();
|
|
|
|
|
|
|
|
// get next packet off the queue
|
|
|
|
while( auto pPacket = m_outQueue.pop() )
|
|
|
|
{
|
|
|
|
if( pPacket->getSize() == 0 )
|
|
|
|
{
|
2018-03-02 07:22:25 -03:00
|
|
|
g_framework.getLogger().debug( "end of packet set" );
|
2017-08-08 13:53:47 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
pRP.addPacket( *pPacket );
|
|
|
|
totalSize += pPacket->getSize();
|
|
|
|
}
|
|
|
|
|
|
|
|
if( totalSize > 0 )
|
|
|
|
sendPackets( &pRP );
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2017-11-28 17:29:06 +01:00
|
|
|
void Core::Network::GameConnection::sendSinglePacket( Packets::GamePacket* pPacket )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
|
|
|
PacketContainer pRP = PacketContainer();
|
|
|
|
pRP.addPacket( *pPacket );
|
|
|
|
sendPackets( &pRP );
|
|
|
|
}
|
|
|
|
|
2018-01-08 21:42:44 +01:00
|
|
|
void Core::Network::GameConnection::injectPacket( const std::string& packetpath, Core::Entity::Player& player )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
|
|
|
|
|
|
|
char packet[0x11570];
|
|
|
|
memset( packet, 0, 0x11570 );
|
|
|
|
|
|
|
|
// get the packet name / path from the command arguments
|
|
|
|
FILE *fp = nullptr;
|
|
|
|
fp = fopen( packetpath.c_str(), "rb" );
|
|
|
|
if( fp == nullptr )
|
|
|
|
{
|
2018-01-08 21:42:44 +01:00
|
|
|
player.sendDebug( "Packet " + packetpath + " not found!" );
|
2017-08-08 13:53:47 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// read the packet into the buffer
|
|
|
|
fseek( fp, 0, SEEK_END );
|
|
|
|
int32_t size = ftell( fp );
|
|
|
|
rewind( fp );
|
2017-11-01 22:24:50 -07:00
|
|
|
if ( fread( packet, sizeof( char ), size, fp ) != size )
|
|
|
|
{
|
2018-01-08 21:42:44 +01:00
|
|
|
player.sendDebug( "Packet " + packetpath + " did not read full size: " + std::to_string( size ) );
|
2017-11-01 22:24:50 -07:00
|
|
|
return;
|
|
|
|
}
|
2017-08-08 13:53:47 +02:00
|
|
|
fclose( fp );
|
|
|
|
|
|
|
|
// cycle through the packet entries and queue each one
|
2017-11-28 00:09:36 +01:00
|
|
|
for( int32_t k = 0x18; k < size; )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2018-01-08 21:42:44 +01:00
|
|
|
uint32_t tmpId = player.getId();
|
2017-08-08 13:53:47 +02:00
|
|
|
// replace ids in the entryheader if needed
|
|
|
|
if( !memcmp( packet + k + 0x04, packet + k + 0x08, 4 ) )
|
|
|
|
{
|
|
|
|
memcpy( packet + k + 0x04, &tmpId, 4 );
|
|
|
|
memcpy( packet + k + 0x08, &tmpId, 4 );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
memcpy( packet + k + 0x08, &tmpId, 4 );
|
|
|
|
|
|
|
|
uint16_t pSize = *reinterpret_cast< uint16_t* >( packet + k );
|
|
|
|
// queue packet to the session
|
|
|
|
if( pSize == 0 )
|
|
|
|
return;
|
|
|
|
|
|
|
|
queueOutPacket( GamePacketPtr( new GamePacket( packet + k, pSize, false ) ) );
|
|
|
|
k += ( pSize );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Core::Network::GameConnection::handlePackets( const Core::Network::Packets::FFXIVARR_PACKET_HEADER& ipcHeader,
|
2017-11-28 00:09:36 +01:00
|
|
|
const std::vector< Core::Network::Packets::FFXIVARR_PACKET_RAW >& packetData )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
|
|
|
// if a session is set, update the last time it recieved a game packet
|
|
|
|
if( m_pSession )
|
|
|
|
m_pSession->updateLastDataTime();
|
|
|
|
|
|
|
|
for( auto inPacket : packetData )
|
|
|
|
{
|
|
|
|
switch( inPacket.segHdr.type )
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
{
|
|
|
|
char* id = ( char* ) &( inPacket.data[4] );
|
|
|
|
uint32_t playerId = boost::lexical_cast< uint32_t >( id );
|
|
|
|
auto pCon = boost::static_pointer_cast< GameConnection, Connection >( shared_from_this() );
|
|
|
|
|
|
|
|
// try to retrieve the session for this id
|
2018-03-02 07:22:25 -03:00
|
|
|
auto session = g_framework.getServerZone().getSession( playerId );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
|
|
|
if( !session )
|
|
|
|
{
|
2018-03-02 07:22:25 -03:00
|
|
|
g_framework.getLogger().info( "[" + std::string( id ) + "] Session not registered, creating" );
|
2017-08-08 13:53:47 +02:00
|
|
|
// return;
|
2018-03-02 07:22:25 -03:00
|
|
|
if( !g_framework.getServerZone().createSession( playerId ) )
|
2017-10-06 00:13:29 +02:00
|
|
|
{
|
|
|
|
Disconnect();
|
|
|
|
return;
|
|
|
|
}
|
2018-03-02 07:22:25 -03:00
|
|
|
session = g_framework.getServerZone().getSession( playerId );
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
2017-11-28 17:29:06 +01:00
|
|
|
//TODO: Catch more things in lobby and send real errors
|
|
|
|
else if( !session->isValid() || ( session->getPlayer() && session->getPlayer()->getLastPing() != 0 ) )
|
2017-10-06 12:54:03 +02:00
|
|
|
{
|
2018-03-02 07:22:25 -03:00
|
|
|
g_framework.getLogger().error( "[" + std::string(id) + "] Session INVALID, disconnecting" );
|
2017-10-06 12:54:03 +02:00
|
|
|
Disconnect();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-08-08 13:53:47 +02:00
|
|
|
// if not set, set the session for this connection
|
|
|
|
if( !m_pSession && session )
|
|
|
|
m_pSession = session;
|
|
|
|
|
2017-08-23 17:39:59 +02:00
|
|
|
GamePacket pPe( 0x00, 0x18, 0, 0, 0x07 );
|
|
|
|
//pPe.setValAt< uint32_t >( 0x10, 0xE0000005 );
|
|
|
|
pPe.setValAt< uint32_t >( 0x10, 0xE0037603 );
|
|
|
|
pPe.setValAt< uint32_t >( 0x14, static_cast< uint32_t >( time( nullptr ) ) );
|
|
|
|
sendSinglePacket( &pPe );
|
|
|
|
|
2017-08-08 13:53:47 +02:00
|
|
|
// main connection, assinging it to the session
|
2017-08-20 20:48:55 +02:00
|
|
|
if( ipcHeader.connectionType == ConnectionType::Zone )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2017-08-23 17:39:59 +02:00
|
|
|
pPe = GamePacket( 0x00, 0x38, 0, 0, 0x02 );
|
|
|
|
pPe.setValAt< uint32_t >( 0x10, playerId );
|
|
|
|
sendSinglePacket( &pPe );
|
2018-03-02 07:22:25 -03:00
|
|
|
g_framework.getLogger().info( "[" + std::string( id ) + "] Setting session for zone connection" );
|
2017-08-08 13:53:47 +02:00
|
|
|
session->setZoneConnection( pCon );
|
|
|
|
}
|
|
|
|
// chat connection, assinging it to the session
|
2017-08-20 20:48:55 +02:00
|
|
|
else if( ipcHeader.connectionType == ConnectionType::Chat )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2017-08-23 17:39:59 +02:00
|
|
|
pPe = GamePacket( 0x00, 0x38, 0, 0, 0x02 );
|
|
|
|
pPe.setValAt< uint32_t >( 0x10, playerId );
|
|
|
|
sendSinglePacket( &pPe );
|
|
|
|
|
2018-03-02 07:22:25 -03:00
|
|
|
g_framework.getLogger().info( "[" + std::string( id ) + "] Setting session for chat connection" );
|
2017-08-20 20:48:55 +02:00
|
|
|
session->setChatConnection( pCon );
|
2017-08-23 17:39:59 +02:00
|
|
|
pPe = GamePacket( 0x02, 0x28, playerId, playerId, 0x03 );
|
|
|
|
sendSinglePacket( &pPe );
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
case 3: // game packet
|
|
|
|
{
|
|
|
|
auto pPacket = new GamePacket( inPacket );
|
|
|
|
queueInPacket( Packets::GamePacketPtr( pPacket ) );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 7: // keep alive
|
|
|
|
{
|
|
|
|
uint32_t id = *( uint32_t* ) &inPacket.data[0];
|
|
|
|
uint32_t timeStamp = *( uint32_t* ) &inPacket.data[4];
|
|
|
|
|
|
|
|
GamePacket pPe( 0x00, 0x18, 0, 0, 0x08 );
|
|
|
|
pPe.setValAt< uint32_t >( 0x10, id );
|
|
|
|
pPe.setValAt< uint32_t >( 0x14, timeStamp );
|
|
|
|
sendSinglePacket( &pPe );
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 8:
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|