417 lines
16 KiB
C++
417 lines
16 KiB
C++
|
/*
|
||
|
Library to manage state connexion
|
||
|
|
||
|
Copyright (C) 2019 AleaJactaEst
|
||
|
|
||
|
This program is free software: you can redistribute it and/or modify
|
||
|
it under the terms of the GNU General Public License as published by
|
||
|
the Free Software Foundation, either version 3 of the License, or
|
||
|
(at your option) any later version.
|
||
|
|
||
|
This program is distributed in the hope that it will be useful,
|
||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
GNU General Public License for more details.
|
||
|
|
||
|
You should have received a copy of the GNU General Public License
|
||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
||
|
*/
|
||
|
|
||
|
#include "check_memory.h"
|
||
|
#include "state_connexion.h"
|
||
|
#include "network_connection_core.h"
|
||
|
|
||
|
/*
|
||
|
* StateConnectionBase
|
||
|
*/
|
||
|
|
||
|
StateConnectionBase::StateConnectionBase(NetworkConnectionCore * network)
|
||
|
{
|
||
|
this->_network = network;
|
||
|
this->_data = & (network->_network_data);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* StateConnectionNotInitialized
|
||
|
*/
|
||
|
|
||
|
void StateConnectionNotInitialized::connect_to_server()
|
||
|
{
|
||
|
this->_network->_queue.clear();
|
||
|
this->_network->open_network();
|
||
|
this->_network->_state_connexion = & this->_network->_state_login;
|
||
|
OS::get_singleton()->print("[%s:%d] connect_to_server\n", __FILE__, __LINE__);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* StateConnectionLogin
|
||
|
*/
|
||
|
void StateConnectionLogin::send_system_quit()
|
||
|
{
|
||
|
OS::get_singleton()->print("[%s:%d] send quit to server\n", __FILE__, __LINE__);
|
||
|
BitStream msgout;
|
||
|
msgout.put_uint32(this->_data->_current_received_number);
|
||
|
msgout.put_bool(true);
|
||
|
msgout.put_uint8(CLFECOMMON::SYSTEM_QUIT_CODE);
|
||
|
msgout.put_sint32(this->_data->_quit_id);
|
||
|
|
||
|
if ( this->_network->_socketUDP->put_packet_buffer(msgout.get_data()) != Error::OK )
|
||
|
{
|
||
|
ERR_PRINT("Error to send disconnect");
|
||
|
}
|
||
|
this->_network->_state_connexion = & this->_network->_state_quit;
|
||
|
}
|
||
|
|
||
|
void StateConnectionLogin::send_message()
|
||
|
{
|
||
|
BitStream msgout;
|
||
|
msgout.put_uint32(this->_data->_current_received_number);
|
||
|
msgout.put_bool(true);
|
||
|
msgout.put_uint8(CLFECOMMON::SYSTEM_LOGIN_CODE);
|
||
|
msgout.put_string_hexa32(this->_data->_user_addr);
|
||
|
msgout.put_string_hexa32(this->_data->_user_key);
|
||
|
msgout.put_string_hexa32(this->_data->_user_id);
|
||
|
msgout.put_string(this->_data->_lang);
|
||
|
Error ret;
|
||
|
ret = this->_network->_socketUDP->put_packet_buffer(msgout.get_data()); // , msgout.get_data().size()
|
||
|
if ( ret != Error::OK)
|
||
|
{
|
||
|
this->_network->close_network();
|
||
|
switch(ret)
|
||
|
{
|
||
|
case Error::ERR_CANT_CONNECT:
|
||
|
ERR_PRINT("network connexion - Can't connect");
|
||
|
default:
|
||
|
ERR_PRINT("network connexion - Unknown error");
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
OS::get_singleton()->print("[%s:%d] Connected to khganat\n", __FILE__, __LINE__);
|
||
|
this->_network->_state_connexion = & this->_network->_state_synchronize;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* StateConnectionSynchronize
|
||
|
*/
|
||
|
|
||
|
void StateConnectionSynchronize::send_system_quit()
|
||
|
{
|
||
|
OS::get_singleton()->print("[%s:%d] send quit to server\n", __FILE__, __LINE__);
|
||
|
BitStream msgout;
|
||
|
msgout.put_uint32(this->_data->_current_received_number);
|
||
|
msgout.put_bool(true);
|
||
|
msgout.put_uint8(CLFECOMMON::SYSTEM_QUIT_CODE);
|
||
|
msgout.put_sint32(this->_data->_quit_id);
|
||
|
|
||
|
if ( this->_network->_socketUDP->put_packet_buffer(msgout.get_data()) != Error::OK )
|
||
|
{
|
||
|
ERR_PRINT("Error to send quit");
|
||
|
}
|
||
|
this->_network->_state_connexion = & this->_network->_state_quit;
|
||
|
}
|
||
|
|
||
|
void StateConnectionSynchronize::send_system_ack_sync()
|
||
|
{
|
||
|
OS::get_singleton()->print("[%s:%d] send system ACK Sync to server\n", __FILE__, __LINE__);
|
||
|
Ref<BitStream> msgout;
|
||
|
msgout.instance();
|
||
|
msgout->put_uint32(this->_data->_current_received_number);
|
||
|
msgout->put_bool(true);
|
||
|
msgout->put_uint8(CLFECOMMON::SYSTEM_ACK_SYNC_CODE);
|
||
|
msgout->put_sint32(this->_data->_last_received_number);
|
||
|
msgout->put_sint32(this->_data->_last_ack_in_long_ack);
|
||
|
this->_data->_long_ack_bit_field.write_serial(msgout);
|
||
|
msgout->put_sint32(this->_data->_server_sync);
|
||
|
if (this->_network->_socketUDP->put_packet_buffer(msgout->get_data()) != Error::OK)
|
||
|
{
|
||
|
ERR_PRINT("Error to send ack sync");
|
||
|
return;
|
||
|
}
|
||
|
msgout.unref();
|
||
|
this->_data->_client_sync = this->_data->_server_sync;
|
||
|
this->_network->_state_connexion = & this->_network->_state_connected;
|
||
|
}
|
||
|
|
||
|
void StateConnectionSynchronize::receive_system_sync(Ref<BitStream> msgin)
|
||
|
{
|
||
|
bool valide = true;
|
||
|
int i;
|
||
|
OS::get_singleton()->print("[%s:%d] SYSTEM_SYNC_CODE\n", __FILE__, __LINE__);
|
||
|
|
||
|
uint32_t synchronize = msgin->get_uint32();
|
||
|
int64_t stime = msgin->get_sint64();
|
||
|
uint32_t latestsync = msgin->get_uint32();
|
||
|
PoolByteArray msg_xml = msgin->get_array_uint8(16);
|
||
|
PoolByteArray database_xml = msgin->get_array_uint8(16);
|
||
|
|
||
|
OS::get_singleton()->print("[%s:%d] SYSTEM_SYNC_CODE synchronize:%u, stime:%ld, latestsync:%u\n", __FILE__, __LINE__, synchronize, stime, latestsync);
|
||
|
|
||
|
if ( msg_xml.size() != this->_data->_checksum_msg_xml.size() )
|
||
|
{
|
||
|
valide = false;
|
||
|
ERR_PRINTS("MSG XML is incorrect (server:" + itos(msg_xml.size()) +", client:" + itos(this->_data->_checksum_msg_xml.size()) + ")");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for(i=0; i<msg_xml.size(); ++i)
|
||
|
{
|
||
|
if ( (int) msg_xml[i] != (int) this->_data->_checksum_msg_xml[i] )
|
||
|
{
|
||
|
valide = false;
|
||
|
ERR_PRINTS("MSG XML is incorrect (pos:" + itos(i) +")");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( valide == true )
|
||
|
{
|
||
|
OS::get_singleton()->print("[%s:%d] MSG XML is correct\n", __FILE__, __LINE__);
|
||
|
this->_data->_server_sync = latestsync;
|
||
|
this->_data->_synchronize = synchronize;
|
||
|
this->_data->_current_server_tick = this->_data->_synchronize + this->_data->_current_received_number + 2;
|
||
|
this->_data->_current_client_tick = this->_data->_current_server_tick + (LCT + this->_data->_ms_per_tick) / this->_data->_ms_per_tick;
|
||
|
this->_data->_current_client_time = this->_data->_update_time - (LCT + this->_data->_ms_per_tick);
|
||
|
//this->_state = STATE::Synchronize;
|
||
|
}
|
||
|
else
|
||
|
ERR_PRINTS("MSG.XML is wrong");
|
||
|
}
|
||
|
|
||
|
void StateConnectionSynchronize::receive_message(int index)
|
||
|
{
|
||
|
bool system_mode;
|
||
|
|
||
|
OS::get_singleton()->print("[%s:%d] receive_message ...\n", __FILE__, __LINE__);
|
||
|
|
||
|
//this->_data->_current_received_number = current_received_number;
|
||
|
Ref<BitStreamField> field = this->_network->_queue.get_msg(index);
|
||
|
uint32_t current_received_number = field->get_id();
|
||
|
Ref<BitStream> msgin = field->get_msgin();
|
||
|
|
||
|
this->_data->_current_received_number = current_received_number;
|
||
|
|
||
|
//Ref<BitStreamField> msgin = this->_network->_queue.get_msg(index)->get_msgin();
|
||
|
system_mode = msgin->get_bool();
|
||
|
if ( system_mode == true )
|
||
|
{
|
||
|
int message = msgin->get_uint8();
|
||
|
switch (message)
|
||
|
{
|
||
|
case CLFECOMMON::SYSTEM_LOGIN_CODE:
|
||
|
OS::get_singleton()->print("[%s:%d] SYSTEM_LOGIN_CODE\n", __FILE__, __LINE__);
|
||
|
break;
|
||
|
case CLFECOMMON::SYSTEM_SYNC_CODE:
|
||
|
this->receive_system_sync(msgin);
|
||
|
break;
|
||
|
case CLFECOMMON::SYSTEM_STALLED_CODE:
|
||
|
OS::get_singleton()->print("[%s:%d] SYSTEM_STALLED_CODE\n", __FILE__, __LINE__);
|
||
|
break;
|
||
|
case CLFECOMMON::SYSTEM_SERVER_DOWN_CODE:
|
||
|
OS::get_singleton()->print("[%s:%d] SYSTEM_SERVER_DOWN_CODE\n", __FILE__, __LINE__);
|
||
|
break;
|
||
|
case CLFECOMMON::SYSTEM_PROBE_CODE:
|
||
|
OS::get_singleton()->print("[%s:%d] SYSTEM_PROBE_CODE\n", __FILE__, __LINE__);
|
||
|
break;
|
||
|
default:
|
||
|
ERR_PRINTS("Received unknown message [" + itos(message) + "]");
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
// this->_last_received_number = current_received_number;
|
||
|
this->_network->_queue.erase_index(index);
|
||
|
}
|
||
|
|
||
|
void StateConnectionSynchronize::send_message()
|
||
|
{
|
||
|
//OS::get_singleton()->print("[%s:%d] send_system %d / %d \n", __FILE__, __LINE__, this->_data->_server_sync, this->_data->_client_sync);
|
||
|
if ( this->_data->_server_sync != this->_data->_client_sync )
|
||
|
this->send_system_ack_sync();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* StateConnectionConnected
|
||
|
*/
|
||
|
|
||
|
void StateConnectionConnected::send_system_quit()
|
||
|
{
|
||
|
OS::get_singleton()->print("[%s:%d] send quit to server\n", __FILE__, __LINE__);
|
||
|
BitStream msgout;
|
||
|
msgout.put_uint32(this->_data->_current_received_number);
|
||
|
msgout.put_bool(true);
|
||
|
msgout.put_uint8(CLFECOMMON::SYSTEM_QUIT_CODE);
|
||
|
msgout.put_sint32(this->_data->_quit_id);
|
||
|
|
||
|
if ( this->_network->_socketUDP->put_packet_buffer(msgout.get_data()) != Error::OK )
|
||
|
{
|
||
|
ERR_PRINT("Error to send disconnect");
|
||
|
}
|
||
|
this->_network->_state_connexion = & this->_network->_state_quit;
|
||
|
}
|
||
|
|
||
|
void StateConnectionConnected::send_system_disconnect()
|
||
|
{
|
||
|
//if ( this->_state != STATE::Connected && this->_state != STATE::ForceSynchronize ) return;
|
||
|
OS::get_singleton()->print("[%s:%d] send disconnect to server\n", __FILE__, __LINE__);
|
||
|
BitStream msgout;
|
||
|
msgout.put_uint32(this->_data->_current_received_number);
|
||
|
msgout.put_bool(true);
|
||
|
msgout.put_uint8(CLFECOMMON::SYSTEM_DISCONNECTION_CODE);
|
||
|
|
||
|
if ( this->_network->_socketUDP->put_packet_buffer(msgout.get_data()) != Error::OK )
|
||
|
{
|
||
|
ERR_PRINT("Error to send disconnect");
|
||
|
}
|
||
|
this->_network->_socketUDP->close();
|
||
|
// this->_state = STATE::Disconnect;
|
||
|
this->_network->_state_connexion = & this->_network->_state_not_initialized;
|
||
|
}
|
||
|
|
||
|
void StateConnectionConnected::send_system_ack_sync()
|
||
|
{
|
||
|
OS::get_singleton()->print("[%s:%d] send system ACK Sync to server\n", __FILE__, __LINE__);
|
||
|
|
||
|
Ref<BitStream> msgout;
|
||
|
msgout.instance();
|
||
|
msgout->put_uint32(this->_data->_current_received_number);
|
||
|
msgout->put_bool(true);
|
||
|
msgout->put_uint8(CLFECOMMON::SYSTEM_ACK_SYNC_CODE);
|
||
|
msgout->put_sint32(this->_data->_last_received_number);
|
||
|
msgout->put_sint32(this->_data->_last_ack_in_long_ack);
|
||
|
this->_data->_long_ack_bit_field.write_serial(msgout);
|
||
|
msgout->put_sint32(this->_data->_server_sync);
|
||
|
if (this->_network->_socketUDP->put_packet_buffer(msgout->get_data()) != Error::OK)
|
||
|
{
|
||
|
ERR_PRINT("Error to send ack sync");
|
||
|
return;
|
||
|
}
|
||
|
msgout.unref();
|
||
|
this->_data->_client_sync = this->_data->_server_sync;
|
||
|
}
|
||
|
|
||
|
void StateConnectionConnected::send_system_ack_probe()
|
||
|
{
|
||
|
// khanat-opennel-code/code/ryzom/server/src/frontend_service/fe_receive_sub.cpp:1121 void CFeReceiveSub::handleReceivedMsg( CClientHost *clienthost )
|
||
|
OS::get_singleton()->print("[%s:%d] send system ACK PROBE to server\n", __FILE__, __LINE__);
|
||
|
int max = this->_data->_latest_probes.size() ;
|
||
|
|
||
|
BitStream msgout;
|
||
|
msgout.put_uint32(this->_data->_current_received_number);
|
||
|
msgout.put_bool(true);
|
||
|
msgout.put_uint8(CLFECOMMON::SYSTEM_ACK_PROBE_CODE);
|
||
|
msgout.put_sint32(max);
|
||
|
for(int i=0; i < max ; ++i )
|
||
|
{
|
||
|
int data = this->_data->_latest_probes[i];
|
||
|
msgout.put_sint32(data);
|
||
|
}
|
||
|
if (this->_network->_socketUDP->put_packet_buffer(msgout.get_data()) != Error::OK)
|
||
|
{
|
||
|
ERR_PRINT("Error to send disconnect");
|
||
|
return;
|
||
|
}
|
||
|
this->_data->_latest_probes.clear();
|
||
|
}
|
||
|
|
||
|
void StateConnectionConnected::receive_system_sync(Ref<BitStream> msgin)
|
||
|
{
|
||
|
bool valide = true;
|
||
|
int i;
|
||
|
OS::get_singleton()->print("[%s:%d] SYSTEM_SYNC_CODE\n", __FILE__, __LINE__);
|
||
|
|
||
|
uint32_t synchronize = msgin->get_uint32();
|
||
|
int64_t stime = msgin->get_sint64();
|
||
|
uint32_t latestsync = msgin->get_uint32();
|
||
|
PoolByteArray msg_xml = msgin->get_array_uint8(16);
|
||
|
PoolByteArray database_xml = msgin->get_array_uint8(16);
|
||
|
|
||
|
OS::get_singleton()->print("[%s:%d] SYSTEM_SYNC_CODE synchronize:%u, stime:%ld, latestsync:%u\n", __FILE__, __LINE__, synchronize, stime, latestsync);
|
||
|
|
||
|
if ( msg_xml.size() != this->_data->_checksum_msg_xml.size() )
|
||
|
{
|
||
|
valide = false;
|
||
|
ERR_PRINTS("MSG XML is incorrect (server:" + itos(msg_xml.size()) +", client:" + itos(this->_data->_checksum_msg_xml.size()) + ")");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for(i=0; i<msg_xml.size(); ++i)
|
||
|
{
|
||
|
if ( (int) msg_xml[i] != (int) this->_data->_checksum_msg_xml[i] )
|
||
|
{
|
||
|
valide = false;
|
||
|
ERR_PRINTS("MSG XML is incorrect (pos:" + itos(i) +")");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( valide == true )
|
||
|
{
|
||
|
OS::get_singleton()->print("[%s:%d] MSG XML is correct\n", __FILE__, __LINE__);
|
||
|
this->_data->_server_sync = latestsync;
|
||
|
this->_data->_synchronize = synchronize;
|
||
|
this->_data->_current_server_tick = this->_data->_synchronize + this->_data->_current_received_number + 2;
|
||
|
this->_data->_current_client_tick = this->_data->_current_server_tick + (LCT + this->_data->_ms_per_tick) / this->_data->_ms_per_tick;
|
||
|
this->_data->_current_client_time = this->_data->_update_time - (LCT + this->_data->_ms_per_tick);
|
||
|
//this->_state = STATE::Synchronize;
|
||
|
}
|
||
|
else
|
||
|
ERR_PRINTS("MSG.XML is wrong");
|
||
|
}
|
||
|
|
||
|
void StateConnectionConnected::receive_message(int index)
|
||
|
{
|
||
|
// SHOW_USAGE_MEMORY
|
||
|
bool system_mode;
|
||
|
|
||
|
Ref<BitStreamField> field = this->_network->_queue.get_msg(index);
|
||
|
uint32_t current_received_number = field->get_id();
|
||
|
this->_data->_current_received_number = current_received_number;
|
||
|
Ref<BitStream> msgin = field->get_msgin();
|
||
|
|
||
|
system_mode = msgin->get_bool();
|
||
|
if ( system_mode == true )
|
||
|
{
|
||
|
//OS::get_singleton()->print("[%s:%d] system message (%d) [%d]\n", __FILE__, __LINE__, (int)current_received_number, this->_network->_queue.length());
|
||
|
int message = msgin->get_uint8();
|
||
|
switch (message)
|
||
|
{
|
||
|
case CLFECOMMON::SYSTEM_LOGIN_CODE:
|
||
|
OS::get_singleton()->print("[%s:%d] Receive SYSTEM_LOGIN_CODE (%d) [%d]\n", __FILE__, __LINE__, (int)current_received_number, this->_network->_queue.length());
|
||
|
break;
|
||
|
case CLFECOMMON::SYSTEM_SYNC_CODE:
|
||
|
OS::get_singleton()->print("[%s:%d] Receive SYSTEM_SYNC_CODE (%d) [%d]\n", __FILE__, __LINE__, (int)current_received_number, this->_network->_queue.length());
|
||
|
this->receive_system_sync(msgin);
|
||
|
break;
|
||
|
case CLFECOMMON::SYSTEM_STALLED_CODE:
|
||
|
OS::get_singleton()->print("[%s:%d] Receive SYSTEM_STALLED_CODE (%d) [%d]\n", __FILE__, __LINE__, (int)current_received_number, this->_network->_queue.length());
|
||
|
break;
|
||
|
case CLFECOMMON::SYSTEM_SERVER_DOWN_CODE:
|
||
|
OS::get_singleton()->print("[%s:%d] Receive SYSTEM_SERVER_DOWN_CODE (%d) [%d]\n", __FILE__, __LINE__, (int)current_received_number, this->_network->_queue.length());
|
||
|
break;
|
||
|
case CLFECOMMON::SYSTEM_PROBE_CODE:
|
||
|
OS::get_singleton()->print("[%s:%d] Receive SYSTEM_PROBE_CODE (%d) [%d]\n", __FILE__, __LINE__, (int)current_received_number, this->_network->_queue.length());
|
||
|
this->_data->_latest_probes.append(msgin->get_sint32());
|
||
|
break;
|
||
|
default:
|
||
|
OS::get_singleton()->print("[%s:%d] Receive UNKNOWN SYSTEM MESSAGE [id:%d] (%d) [%d]\n", __FILE__, __LINE__, message, (int)current_received_number, this->_network->_queue.length());
|
||
|
//ERR_PRINTS("Received unknown message [" + itos(message) + "]");
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
OS::get_singleton()->print("[%s:%d] application message (%d) [%d]\n", __FILE__, __LINE__, (int)current_received_number, this->_network->_queue.length());
|
||
|
}
|
||
|
this->_network->_queue.erase_index(index);
|
||
|
}
|
||
|
|
||
|
void StateConnectionConnected::send_message()
|
||
|
{
|
||
|
if ( this->_data->_server_sync != this->_data->_client_sync )
|
||
|
this->send_system_ack_sync();
|
||
|
if (this->_data->_latest_probes.size() != 0 )
|
||
|
this->send_system_ack_probe();
|
||
|
}
|
||
|
/*
|
||
|
*
|
||
|
*/
|