/* 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 . */ #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 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 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_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 field = this->_network->_queue.get_msg(index); uint32_t current_received_number = field->get_id(); Ref msgin = field->get_msgin(); this->_data->_current_received_number = current_received_number; //Ref 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 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 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_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 field = this->_network->_queue.get_msg(index); uint32_t current_received_number = field->get_id(); this->_data->_current_received_number = current_received_number; Ref 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(); } /* * */