123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880 |
- // Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
- // For more information, see LICENCE in the main folder
- #include "char_logif.hpp"
- #include <cstdlib>
- #include <cstring>
- #include <memory>
- #include <common/showmsg.hpp>
- #include <common/socket.hpp>
- #include <common/sql.hpp>
- #include <common/strlib.hpp>
- #include <common/timer.hpp>
- #include <common/utilities.hpp>
- #include <common/utils.hpp>
- #include "char.hpp"
- #include "char_clif.hpp"
- #include "char_mapif.hpp"
- #include "inter.hpp"
- #include "int_guild.hpp"
- using namespace rathena;
- //early declaration
- void chlogif_on_ready(void);
- void chlogif_on_disconnect(void);
- #if PACKETVER_SUPPORTS_PINCODE
- void chlogif_pincode_notifyLoginPinError( uint32 account_id ){
- if ( chlogif_isconnected() ){
- WFIFOHEAD(login_fd,6);
- WFIFOW(login_fd,0) = 0x2739;
- WFIFOL(login_fd,2) = account_id;
- WFIFOSET(login_fd,6);
- }
- }
- void chlogif_pincode_notifyLoginPinUpdate( uint32 account_id, char* pin ){
- if ( chlogif_isconnected() ){
- int size = 8 + PINCODE_LENGTH+1;
- WFIFOHEAD(login_fd,size);
- WFIFOW(login_fd,0) = 0x2738;
- WFIFOW(login_fd,2) = size;
- WFIFOL(login_fd,4) = account_id;
- strncpy( WFIFOCP(login_fd,8), pin, PINCODE_LENGTH+1 );
- WFIFOSET(login_fd,size);
- }
- }
- void chlogif_pincode_start(int fd, struct char_session_data* sd){
- if( charserv_config.pincode_config.pincode_enabled ){
- //ShowInfo("Asking to start pincode to AID: %d\n", sd->account_id);
- // PIN code system enabled
- if( sd->pincode[0] == '\0' ){
- // No PIN code has been set yet
- if( charserv_config.pincode_config.pincode_force ){
- chclif_pincode_sendstate( fd, sd, PINCODE_NEW );
- }else{
- chclif_pincode_sendstate( fd, sd, PINCODE_PASSED );
- }
- }else{
- if( !(charserv_config.pincode_config.pincode_changetime)
- || ( sd->pincode_change + charserv_config.pincode_config.pincode_changetime ) > time(nullptr) ){
- std::shared_ptr<struct online_char_data> node = util::umap_find( char_get_onlinedb(), sd->account_id );
- if( node != nullptr && node->pincode_success ){
- // User has already passed the check
- chclif_pincode_sendstate( fd, sd, PINCODE_PASSED );
- }else{
- // Ask user for his PIN code
- chclif_pincode_sendstate( fd, sd, PINCODE_ASK );
- }
- }else{
- // User hasnt changed his PIN code too long
- chclif_pincode_sendstate( fd, sd, PINCODE_EXPIRED );
- }
- }
- }else{
- // PIN code system disabled
- //ShowInfo("Pincode is disabled.\n");
- chclif_pincode_sendstate( fd, sd, PINCODE_OK );
- }
- }
- #endif
- /**
- * Timered function to send all account_id connected to login-serv
- * @param tid : Timer id
- * @param tick : Scheduled tick
- * @param id : GID linked to that timered call
- * @param data : data transmited for delayed function
- * @return
- */
- TIMER_FUNC(chlogif_send_acc_tologin){
- if ( chlogif_isconnected() ){
- // send account list to login server
- size_t users = char_get_onlinedb().size();
- int i = 0;
- WFIFOHEAD(login_fd,8+users*4);
- WFIFOW(login_fd,0) = 0x272d;
- for( const auto& pair : char_get_onlinedb() ){
- std::shared_ptr<struct online_char_data> character = pair.second;
- if( character->server > -1 ){
- WFIFOL( login_fd, 8 + i * 4 ) = character->account_id;
- i++;
- }
- }
- WFIFOW(login_fd,2) = 8+ i*4;
- WFIFOL(login_fd,4) = i;
- WFIFOSET(login_fd,WFIFOW(login_fd,2));
- return 1;
- }
- return 0;
- }
- void chlogif_send_usercount(int users){
- if (!chlogif_isconnected())
- return;
- // send number of user to login server
- WFIFOHEAD(login_fd,6);
- WFIFOW(login_fd,0) = 0x2714;
- WFIFOL(login_fd,2) = users;
- WFIFOSET(login_fd,6);
- }
- TIMER_FUNC(chlogif_broadcast_user_count){
- uint8 buf[6];
- int users = char_count_users();
- // only send an update when needed
- static int prev_users = 0;
- if( prev_users == users )
- return 0;
- prev_users = users;
- if( chlogif_isconnected() )
- {
- // send number of user to login server
- WFIFOHEAD(login_fd,6);
- WFIFOW(login_fd,0) = 0x2714;
- WFIFOL(login_fd,2) = users;
- WFIFOSET(login_fd,6);
- }
- // send number of players to all map-servers
- WBUFW(buf,0) = 0x2b00;
- WBUFL(buf,2) = users;
- chmapif_sendall(buf,6);
- return 0;
- }
- void chlogif_upd_global_accreg(uint32 account_id, uint32 char_id) {
- if ( chlogif_isconnected() ){
- WFIFOHEAD(login_fd, 60000 + 300);
- WFIFOW(login_fd, 0) = 0x2728;
- WFIFOW(login_fd, 2) = 14;
- WFIFOL(login_fd, 4) = account_id;
- WFIFOL(login_fd, 8) = char_id;
- WFIFOW(login_fd, 12) = 0; // count
- }
- }
- void chlogif_prepsend_global_accreg(void) {
- if ( chlogif_isconnected() ){
- WFIFOSET(login_fd, WFIFOW(login_fd,2));
- }
- }
- void chlogif_send_global_accreg(const char *key, unsigned int index, int64 int_value, const char* string_value, bool is_string) {
- if (!chlogif_isconnected())
- return;
- int16 nlen = WFIFOW( login_fd, 2 );
- size_t len;
- len = strlen(key)+1;
- WFIFOB(login_fd, nlen) = (unsigned char)len; // won't be higher; the column size is 32
- nlen += 1;
- safestrncpy(WFIFOCP(login_fd,nlen), key, len);
- nlen += static_cast<decltype(nlen)>( len );
- WFIFOL(login_fd, nlen) = index;
- nlen += 4;
- if( is_string ) {
- WFIFOB(login_fd, nlen) = string_value ? 2 : 3;
- nlen += 1;
- if( string_value ) {
- len = strlen(string_value)+1;
- WFIFOB(login_fd, nlen) = (unsigned char)len; // won't be higher; the column size is 254
- nlen += 1;
- safestrncpy(WFIFOCP(login_fd,nlen), string_value, len);
- nlen += static_cast<decltype(nlen)>( len );
- }
- } else {
- WFIFOB(login_fd, nlen) = int_value ? 0 : 1;
- nlen += 1;
- if( int_value ) {
- WFIFOQ(login_fd, nlen) = int_value;
- nlen += 8;
- }
- }
- WFIFOW(login_fd,12) += 1;
- WFIFOW(login_fd, 2) = nlen;
- if( WFIFOW(login_fd, 2) > 60000 ) {
- int account_id = WFIFOL(login_fd,4), char_id = WFIFOL(login_fd,8);
- chlogif_prepsend_global_accreg();
- chlogif_upd_global_accreg(account_id, char_id); // prepare next
- }
- }
- void chlogif_request_accreg2(uint32 account_id, uint32 char_id){
- if (!chlogif_isconnected())
- return;
- WFIFOHEAD(login_fd,10);
- WFIFOW(login_fd,0) = 0x272e;
- WFIFOL(login_fd,2) = account_id;
- WFIFOL(login_fd,6) = char_id;
- WFIFOSET(login_fd,10);
- }
- void chlogif_send_reqaccdata(int fd, struct char_session_data *sd){
- if (!chlogif_isconnected())
- return;
- WFIFOHEAD(fd,6);
- WFIFOW(fd,0) = 0x2716;
- WFIFOL(fd,2) = sd->account_id;
- WFIFOSET(fd,6);
- }
- void chlogif_send_setacconline(int aid){
- if (!chlogif_isconnected())
- return;
- WFIFOHEAD(login_fd,6);
- WFIFOW(login_fd,0) = 0x272b;
- WFIFOL(login_fd,2) = aid;
- WFIFOSET(login_fd,6);
- }
- void chlogif_send_setallaccoffline(int fd){
- if (!chlogif_isconnected())
- return;
- WFIFOHEAD(fd,2);
- WFIFOW(fd,0) = 0x2737;
- WFIFOSET(fd,2);
- }
- void chlogif_send_setaccoffline(int fd, int aid){
- if (!chlogif_isconnected())
- return;
- WFIFOHEAD(fd,6);
- WFIFOW(fd,0) = 0x272c;
- WFIFOL(fd,2) = aid;
- WFIFOSET(fd,6);
- }
- int chlogif_parse_ackconnect(int fd){
- if (RFIFOREST(fd) < 3)
- return 0;
- if (RFIFOB(fd,2)) {
- //printf("connect login server error : %d\n", RFIFOB(fd,2));
- ShowError("Can not connect to login-server.\n");
- ShowError("The server communication passwords (default s1/p1) are probably invalid.\n");
- ShowError("Also, please make sure your login db has the correct communication username/passwords and the gender of the account is S.\n");
- ShowError("The communication passwords are set in map_athena.conf and char_athena.conf\n");
- set_eof(fd);
- return 0;
- } else {
- ShowStatus("Connected to login-server (connection #%d).\n", fd);
- chlogif_on_ready();
- }
- RFIFOSKIP(fd,3);
- return 1;
- }
- int chlogif_parse_ackaccreq(int fd){
- if (RFIFOREST(fd) < 21)
- return 0;
- {
- struct char_session_data* sd;
- uint32 account_id = RFIFOL(fd,2);
- uint32 login_id1 = RFIFOL(fd,6);
- uint32 login_id2 = RFIFOL(fd,10);
- uint8 sex = RFIFOB(fd,14);
- uint8 result = RFIFOB(fd,15);
- int request_id = RFIFOL(fd,16);
- uint8 clienttype = RFIFOB(fd,20);
- RFIFOSKIP(fd,21);
- if( session_isActive(request_id) && (sd=(struct char_session_data*)session[request_id]->session_data) &&
- !sd->auth && sd->account_id == account_id && sd->login_id1 == login_id1 && sd->login_id2 == login_id2 && sd->sex == sex )
- {
- int client_fd = request_id;
- sd->clienttype = clienttype;
- switch( result )
- {
- case 0:// ok
- char_auth_ok(client_fd, sd);
- break;
- case 1:// auth failed
- chclif_reject(client_fd,0); // rejected from server
- break;
- }
- }
- }
- return 1;
- }
- /**
- * Receive account data from login-server
- * AH 0x2717 <aid>.L <email>.40B <expiration_time>.L <group_id>.B <birthdate>.11B <pincode>.5B <pincode_change>.L <isvip>.B <char_vip>.B <char_billing>.B
- **/
- int chlogif_parse_reqaccdata(int fd){
- if (RFIFOREST(fd) < 75)
- return 0;
- int u_fd; //user fd
- struct char_session_data* sd;
- // find the authenticated session with this account id
- ARR_FIND( 0, fd_max, u_fd, session[u_fd] && (sd = (struct char_session_data*)session[u_fd]->session_data) && sd->auth && sd->account_id == RFIFOL(fd,2) );
- if( u_fd < fd_max )
- {
- memcpy(sd->email, RFIFOP(fd,6), 40);
- sd->expiration_time = (time_t)RFIFOL(fd,46);
- sd->group_id = RFIFOB(fd,50);
- sd->char_slots = RFIFOB(fd,51);
- if( sd->char_slots > MAX_CHARS ) {
- ShowError("Account '%d' `character_slots` column is higher than supported MAX_CHARS (%d), update MAX_CHARS in mmo.hpp! capping to MAX_CHARS...\n",sd->account_id,sd->char_slots);
- sd->char_slots = MAX_CHARS;/* cap to maximum */
- } else if ( !sd->char_slots )/* no value aka 0 in sql */
- sd->char_slots = MIN_CHARS;/* cap to minimum */
- safestrncpy(sd->birthdate, RFIFOCP(fd,52), sizeof(sd->birthdate));
- safestrncpy(sd->pincode, RFIFOCP(fd,63), sizeof(sd->pincode));
- sd->pincode_change = (time_t)RFIFOL(fd,68);
- sd->isvip = RFIFOB(fd,72);
- sd->chars_vip = RFIFOB(fd,73);
- sd->chars_billing = RFIFOB(fd,74);
- // continued from char_auth_ok...
- if(((charserv_config.max_connect_user == 0 || charserv_config.char_maintenance == 1) ||
- (charserv_config.max_connect_user > 0 && char_count_users() >= charserv_config.max_connect_user)) &&
- sd->group_id < charserv_config.gm_allow_group) {
- // refuse connection (over populated)
- chclif_reject(u_fd,0);
- } else {
- // send characters to player
- chclif_mmo_char_send(u_fd, sd);
- #if PACKETVER_SUPPORTS_PINCODE
- chlogif_pincode_start(u_fd,sd);
- #endif
- }
- }
- RFIFOSKIP(fd,75);
- return 1;
- }
- int chlogif_parse_keepalive(int fd){
- if (RFIFOREST(fd) < 2)
- return 0;
- RFIFOSKIP(fd,2);
- session[fd]->flag.ping = 0;
- return 1;
- }
- /**
- * Performs the necessary operations when changing a character's sex, such as
- * correcting the job class and unequipping items, and propagating the
- * information to the guild data.
- *
- * @param sex The new sex (SEX_MALE or SEX_FEMALE).
- * @param acc The character's account ID.
- * @param char_id The character ID.
- * @param class_ The character's current job class.
- * @param guild_id The character's guild ID.
- */
- void chlogif_parse_change_sex_sub(int sex, int acc, int char_id, int class_, int guild_id)
- {
- // job modification
- switch (class_)
- {
- case JOB_BARD:
- class_ = JOB_DANCER;
- break;
- case JOB_DANCER:
- class_ = JOB_BARD;
- break;
- case JOB_CLOWN:
- class_ = JOB_GYPSY;
- break;
- case JOB_GYPSY:
- class_ = JOB_CLOWN;
- break;
- case JOB_BABY_BARD:
- class_ = JOB_BABY_DANCER;
- break;
- case JOB_BABY_DANCER:
- class_ = JOB_BABY_BARD;
- break;
- case JOB_MINSTREL:
- class_ = JOB_WANDERER;
- break;
- case JOB_WANDERER:
- class_ = JOB_MINSTREL;
- break;
- case JOB_MINSTREL_T:
- class_ = JOB_WANDERER_T;
- break;
- case JOB_WANDERER_T:
- class_ = JOB_MINSTREL_T;
- break;
- case JOB_BABY_MINSTREL:
- class_ = JOB_BABY_WANDERER;
- break;
- case JOB_BABY_WANDERER:
- class_ = JOB_BABY_MINSTREL;
- break;
- case JOB_KAGEROU:
- class_ = JOB_OBORO;
- break;
- case JOB_OBORO:
- class_ = JOB_KAGEROU;
- break;
- case JOB_BABY_KAGEROU:
- class_ = JOB_BABY_OBORO;
- break;
- case JOB_BABY_OBORO:
- class_ = JOB_BABY_KAGEROU;
- break;
- case JOB_TROUBADOUR:
- class_ = JOB_TROUVERE;
- break;
- case JOB_TROUVERE:
- class_ = JOB_TROUBADOUR;
- break;
- case JOB_SHINKIRO:
- class_ = JOB_SHIRANUI;
- break;
- case JOB_SHIRANUI:
- class_ = JOB_SHINKIRO;
- break;
- }
- if (SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `equip` = '0' WHERE `char_id` = '%d'", schema_config.inventory_db, char_id))
- Sql_ShowDebug(sql_handle);
- if (SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `class` = '%d', `weapon` = '0', `shield` = '0', `head_top` = '0', `head_mid` = '0', `head_bottom` = '0', `sex` = '%c' WHERE `char_id` = '%d'", schema_config.char_db, class_, sex == SEX_MALE ? 'M' : 'F', char_id))
- Sql_ShowDebug(sql_handle);
- if (guild_id) // If there is a guild, update the guild_member data [Skotlex]
- inter_guild_sex_changed(guild_id, acc, char_id, sex);
- }
- int chlogif_parse_ackchangesex(int fd)
- {
- if (RFIFOREST(fd) < 7)
- return 0;
- else {
- unsigned char buf[7];
- uint32 acc = RFIFOL(fd,2);
- int sex = RFIFOB(fd,6);
- RFIFOSKIP(fd,7);
- if (acc > 0) { // TODO: Is this even possible?
- unsigned char i;
- int char_id = 0, class_ = 0, guild_id = 0;
- std::shared_ptr<struct auth_node> node = util::umap_find( char_get_authdb(), acc );
- SqlStmt *stmt;
- if (node != nullptr)
- node->sex = sex;
- // get characters
- stmt = SqlStmt_Malloc(sql_handle);
- if (SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT `char_id`, `class`, `guild_id` FROM `%s` WHERE `account_id` = '%d'", schema_config.char_db, acc) || SqlStmt_Execute(stmt)) {
- SqlStmt_ShowDebug(stmt);
- SqlStmt_Free(stmt);
- }
- SqlStmt_BindColumn(stmt, 0, SQLDT_INT, &char_id, 0, nullptr, nullptr);
- SqlStmt_BindColumn(stmt, 1, SQLDT_SHORT, &class_, 0, nullptr, nullptr);
- SqlStmt_BindColumn(stmt, 2, SQLDT_INT, &guild_id, 0, nullptr, nullptr);
- for (i = 0; i < MAX_CHARS && SQL_SUCCESS == SqlStmt_NextRow(stmt); ++i) {
- chlogif_parse_change_sex_sub(sex, acc, char_id, class_, guild_id);
- }
- SqlStmt_Free(stmt);
- }
- // notify all mapservers about this change
- WBUFW(buf,0) = 0x2b0d;
- WBUFL(buf,2) = acc;
- WBUFB(buf,6) = sex;
- chmapif_sendall(buf, 7);
- }
- return 1;
- }
- /**
- * Changes a character's sex.
- * The information is updated on database, and the character is kicked if it
- * currently is online.
- *
- * @param char_id The character's ID.
- * @param sex The new sex.
- * @retval 0 in case of success.
- * @retval 1 in case of failure.
- */
- int chlogif_parse_ackchangecharsex(int char_id, int sex)
- {
- int class_ = 0, guild_id = 0, account_id = 0;
- unsigned char buf[7];
- char *data;
- // get character data
- if (SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`class`,`guild_id` FROM `%s` WHERE `char_id` = '%d'", schema_config.char_db, char_id)) {
- Sql_ShowDebug(sql_handle);
- return 1;
- }
- if (Sql_NumRows(sql_handle) != 1 || SQL_ERROR == Sql_NextRow(sql_handle)) {
- Sql_FreeResult(sql_handle);
- return 1;
- }
- Sql_GetData(sql_handle, 0, &data, nullptr); account_id = atoi(data);
- Sql_GetData(sql_handle, 1, &data, nullptr); class_ = atoi(data);
- Sql_GetData(sql_handle, 2, &data, nullptr); guild_id = atoi(data);
- Sql_FreeResult(sql_handle);
- chlogif_parse_change_sex_sub(sex, account_id, char_id, class_, guild_id);
- // disconnect player if online on char-server
- char_disconnect_player(account_id);
- // notify all mapservers about this change
- WBUFW(buf,0) = 0x2b0d;
- WBUFL(buf,2) = account_id;
- WBUFB(buf,6) = sex;
- chmapif_sendall(buf, 7);
- return 0;
- }
- int chlogif_parse_ack_global_accreg(int fd){
- if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
- return 0;
- else { //Receive account_reg2 registry, forward to map servers.
- RFIFOW(fd,0) = 0x3804;
- chmapif_sendall(RFIFOP(fd,0), RFIFOW(fd,2));
- RFIFOSKIP(fd, RFIFOW(fd,2));
- }
- return 1;
- }
- int chlogif_parse_accbannotification(int fd){
- if (RFIFOREST(fd) < 11)
- return 0;
- else { // send to all map-servers to disconnect the player
- unsigned char buf[11];
- WBUFW(buf,0) = 0x2b14;
- WBUFL(buf,2) = RFIFOL(fd,2);
- WBUFB(buf,6) = RFIFOB(fd,6); // 0: change of statut, 1: ban
- WBUFL(buf,7) = RFIFOL(fd,7); // status or final date of a banishment
- chmapif_sendall(buf, 11);
- }
- // disconnect player if online on char-server
- char_disconnect_player(RFIFOL(fd,2));
- RFIFOSKIP(fd,11);
- return 1;
- }
- int chlogif_parse_askkick(int fd){
- if (RFIFOREST(fd) < 6)
- return 0;
- else {
- uint32 aid = RFIFOL(fd,2);
- RFIFOSKIP(fd,6);
- std::shared_ptr<struct online_char_data> character = util::umap_find( char_get_onlinedb(), aid );
- // account is already marked as online!
- if( character != nullptr ){
- if( character->server > -1 )
- { //Kick it from the map server it is on.
- mapif_disconnectplayer(map_server[character->server].fd, character->account_id, character->char_id, 2);
- if (character->waiting_disconnect == INVALID_TIMER)
- character->waiting_disconnect = add_timer(gettick()+AUTH_TIMEOUT, char_chardb_waiting_disconnect, character->account_id, 0);
- }
- else
- {// Manual kick from char server.
- struct char_session_data *tsd;
- int i;
- ARR_FIND( 0, fd_max, i, session[i] && (tsd = (struct char_session_data*)session[i]->session_data) && tsd->account_id == aid );
- if( i < fd_max )
- {
- chclif_send_auth_result(i,2); //Send "Someone has already logged in with this id"
- set_eof(i);
- }
- else // still moving to the map-server
- char_set_char_offline(-1, aid);
- }
- }
- // reject auth attempts from map-server
- char_get_authdb().erase( aid );
- }
- return 1;
- }
- int chlogif_parse_updip(int fd){
- unsigned char buf[2];
- uint32 new_ip = 0;
- /**
- * !CHECKME: This is intended? Just tell if there's IP sync request
- * without sending current char IP (if changed) to map-server?
- **/
- WBUFW(buf,0) = 0x2b1e;
- chmapif_sendall(buf, 2);
- new_ip = host2ip(charserv_config.login_ip_str);
- if (new_ip && new_ip != charserv_config.login_ip)
- charserv_config.login_ip = new_ip; //Update login ip, too.
- new_ip = host2ip(charserv_config.char_ip_str);
- if (new_ip && new_ip != charserv_config.char_ip) { // Char-server IP is updated.
- charserv_config.char_ip = new_ip;
- ShowInfo("Updating IP for [%s].\n", charserv_config.char_ip_str);
- // notify login server about the change
- WFIFOHEAD(fd,6);
- WFIFOW(fd,0) = 0x2736;
- WFIFOL(fd,2) = htonl(charserv_config.char_ip);
- WFIFOSET(fd,6);
- }
- RFIFOSKIP(fd,2);
- return 1;
- }
- /*
- * AH 0x2743
- * We received the info from login-serv, transmit it to map
- */
- int chlogif_parse_vipack(int fd) {
- #ifdef VIP_ENABLE
- if (RFIFOREST(fd) < 19)
- return 0;
- else {
- uint32 aid = RFIFOL(fd,2); //aid
- uint32 vip_time = RFIFOL(fd,6); //vip_time
- uint8 flag = RFIFOB(fd,10);
- uint32 groupid = RFIFOL(fd,11); //new group id
- int mapfd = RFIFOL(fd,15); //link to mapserv for ack
- RFIFOSKIP(fd,19);
- chmapif_vipack(mapfd,aid,vip_time,groupid,flag);
- }
- #endif
- return 1;
- }
- /**
- * HA 0x2742
- * Request vip data to loginserv
- * @param aid : account_id to request the vip data
- * @param flag : 0x1 Select info and update old_groupid, 0x2 VIP duration is changed by atcommand or script, 0x8 First request on player login
- * @param add_vip_time : tick to add to vip timestamp
- * @param mapfd: link to mapserv for ack
- * @return 0 if success
- */
- int chlogif_reqvipdata(uint32 aid, uint8 flag, int32 timediff, int mapfd) {
- loginif_check(-1);
- #ifdef VIP_ENABLE
- WFIFOHEAD(login_fd,15);
- WFIFOW(login_fd,0) = 0x2742;
- WFIFOL(login_fd,2) = aid; //aid
- WFIFOB(login_fd,6) = flag; //flag
- WFIFOL(login_fd,7) = timediff; //req_inc_duration
- WFIFOL(login_fd,11) = mapfd; //req_inc_duration
- WFIFOSET(login_fd,15);
- #endif
- return 0;
- }
- /**
- * HA 0x2720
- * Request account info to login-server
- */
- int chlogif_req_accinfo(int fd, int u_fd, int u_aid, int account_id, int8 type) {
- loginif_check(-1);
- //ShowInfo("%d request account info for %d (type %d)\n", u_aid, account_id, type);
- WFIFOHEAD(login_fd,19);
- WFIFOW(login_fd,0) = 0x2720;
- WFIFOL(login_fd,2) = fd;
- WFIFOL(login_fd,6) = u_fd;
- WFIFOL(login_fd,10) = u_aid;
- WFIFOL(login_fd,14) = account_id;
- WFIFOB(login_fd,18) = type;
- WFIFOSET(login_fd,19);
- return 1;
- }
- /**
- * AH 0x2721
- * Retrieve account info from login-server, ask inter-server to tell player
- */
- int chlogif_parse_AccInfoAck(int fd) {
- if (RFIFOREST(fd) < 19)
- return 0;
- else {
- int8 type = RFIFOB(fd, 18);
- if (type == 0 || RFIFOREST(fd) < 122+NAME_LENGTH) {
- mapif_accinfo_ack(false, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOL(fd,14), 0, -1, 0, 0, nullptr, nullptr, nullptr, nullptr, nullptr);
- RFIFOSKIP(fd,19);
- return 1;
- }
- type>>=1;
- mapif_accinfo_ack(true, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOL(fd,14), type, RFIFOL(fd,19), RFIFOL(fd,23), RFIFOL(fd,27),
- RFIFOCP(fd,31), RFIFOCP(fd,71), RFIFOCP(fd,87), RFIFOCP(fd,111),
- RFIFOCP(fd,122));
- RFIFOSKIP(fd,122+NAME_LENGTH);
- }
- return 1;
- }
- int chlogif_parse(int fd) {
- // only process data from the login-server
- if( fd != login_fd ) {
- ShowDebug("parse_fromlogin: Disconnecting invalid session #%d (is not the login-server)\n", fd);
- do_close(fd);
- return 0;
- }
- if( session[fd]->flag.eof ) {
- do_close(fd);
- login_fd = -1;
- chlogif_on_disconnect();
- return 0;
- } else if ( session[fd]->flag.ping ) {/* we've reached stall time */
- if( DIFF_TICK(last_tick, session[fd]->rdata_tick) > (stall_time * 2) ) {/* we can't wait any longer */
- set_eof(fd);
- return 0;
- } else if( session[fd]->flag.ping != 2 ) { /* we haven't sent ping out yet */
- WFIFOHEAD(fd,2);// sends a ping packet to login server (will receive pong 0x2718)
- WFIFOW(fd,0) = 0x2719;
- WFIFOSET(fd,2);
- session[fd]->flag.ping = 2;
- }
- }
- while(RFIFOREST(fd) >= 2) {
- // -1: Login server is not connected
- // 0: Avoid processing followup packets (prev was probably incomplete) packet
- // 1: Continue parsing
- int next = 1;
- uint16 command = RFIFOW(fd,0);
- switch( command ) {
- case 0x2711: next = chlogif_parse_ackconnect(fd); break;
- case 0x2713: next = chlogif_parse_ackaccreq(fd); break;
- case 0x2717: next = chlogif_parse_reqaccdata(fd); break;
- case 0x2718: next = chlogif_parse_keepalive(fd); break;
- case 0x2721: next = chlogif_parse_AccInfoAck(fd); break;
- case 0x2723: next = chlogif_parse_ackchangesex(fd); break;
- case 0x2726: next = chlogif_parse_ack_global_accreg(fd); break;
- case 0x2731: next = chlogif_parse_accbannotification(fd); break;
- case 0x2734: next = chlogif_parse_askkick(fd); break;
- case 0x2735: next = chlogif_parse_updip(fd); break;
- case 0x2743: next = chlogif_parse_vipack(fd); break;
- default:
- ShowError("Unknown packet 0x%04x received from login-server, disconnecting.\n", command);
- set_eof(fd);
- return 0;
- }
- if (next == 0)
- return 0; //do not parse next data
- }
- RFIFOFLUSH(fd);
- return 0;
- }
- TIMER_FUNC(chlogif_check_connect_logserver){
- if (chlogif_isconnected())
- return 0;
- ShowInfo("Attempt to connect to login-server...\n");
- login_fd = make_connection(charserv_config.login_ip, charserv_config.login_port, false,10);
- if (login_fd == -1)
- { //Try again later. [Skotlex]
- login_fd = 0;
- return 0;
- }
- session[login_fd]->func_parse = chlogif_parse;
- session[login_fd]->flag.server = 1;
- realloc_fifo(login_fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
- WFIFOHEAD(login_fd,86);
- WFIFOW(login_fd,0) = 0x2710;
- memcpy(WFIFOP(login_fd,2), charserv_config.userid, 24);
- memcpy(WFIFOP(login_fd,26), charserv_config.passwd, 24);
- WFIFOL(login_fd,50) = 0;
- WFIFOL(login_fd,54) = htonl(charserv_config.char_ip);
- WFIFOW(login_fd,58) = htons(charserv_config.char_port);
- memcpy(WFIFOP(login_fd,60), charserv_config.server_name, 20);
- WFIFOW(login_fd,80) = 0;
- WFIFOW(login_fd,82) = charserv_config.char_maintenance;
- WFIFOW(login_fd,84) = charserv_config.char_new_display; //only display (New) if they want to [Kevin]
- WFIFOSET(login_fd,86);
- return 1;
- }
- int chlogif_isconnected(){
- return session_isActive(login_fd);
- }
- void do_init_chlogif(void) {
- // establish char-login connection if not present
- add_timer_func_list(chlogif_check_connect_logserver, "check_connect_login_server");
- add_timer_interval(gettick() + 1000, chlogif_check_connect_logserver, 0, 0, 10 * 1000);
- // send a list of all online account IDs to login server
- add_timer_func_list(chlogif_send_acc_tologin, "send_accounts_tologin");
- add_timer_interval(gettick() + 1000, chlogif_send_acc_tologin, 0, 0, 3600 * 1000); //Sync online accounts every hour
- }
- /// Resets all the data.
- void chlogif_reset(void){
- int id;
- // TODO kick everyone out and reset everything or wait for connect and try to reaquire locks [FlavioJS]
- for( id = 0; id < ARRAYLENGTH(map_server); ++id )
- chmapif_server_reset(id);
- flush_fifos();
- exit(EXIT_FAILURE);
- }
- /// Called when the connection to Login Server is disconnected.
- void chlogif_on_disconnect(void){
- ShowWarning("Connection to Login Server lost.\n\n");
- }
- /// Called when all the connection steps are completed.
- void chlogif_on_ready(void)
- {
- int i;
- //Send online accounts to login server.
- chlogif_send_acc_tologin(INVALID_TIMER, gettick(), 0, 0);
- // if no map-server already connected, display a message...
- ARR_FIND( 0, ARRAYLENGTH(map_server), i, session_isValid(map_server[i].fd) && !map_server[i].maps.empty() );
- if( i == ARRAYLENGTH(map_server) )
- ShowStatus("Awaiting maps from map-server.\n");
- }
- void do_final_chlogif(void)
- {
- if( login_fd != -1 )
- {
- do_close(login_fd);
- login_fd = -1;
- }
- }
|