123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911 |
- // Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
- // For more information, see LICENCE in the main folder
- #include "loginchrif.hpp"
- #include <cstdlib>
- #include <cstring>
- #include <common/showmsg.hpp> //show notice
- #include <common/socket.hpp> //wfifo session
- #include <common/strlib.hpp> //safeprint32
- #include <common/timer.hpp> //difftick
- #include "account.hpp"
- #include "login.hpp"
- #include "loginlog.hpp"
- //early declaration
- void logchrif_on_disconnect(int32 id);
- /**
- * Packet send to all char-servers, except one. (wos: without our self)
- * @param sfd: fd to discard sending to
- * @param buf: packet to send in form of an array buffer
- * @param len: size of packet
- * @return : the number of char-serv the packet was sent to
- */
- int32 logchrif_sendallwos(int32 sfd, uint8* buf, size_t len) {
- int32 i, c;
- for( i = 0, c = 0; i < ARRAYLENGTH(ch_server); ++i ) {
- int32 fd = ch_server[i].fd;
- if( session_isValid(fd) && fd != sfd ){
- WFIFOHEAD(fd,len);
- memcpy(WFIFOP(fd,0), buf, len);
- WFIFOSET(fd,len);
- ++c;
- }
- }
- return c;
- }
- /**
- * Timered function to synchronize ip addresses.
- * Requesting all char to update their registered ip and transmit their new ip.
- * Performed each ip_sync_interval.
- * @param tid: timer id
- * @param tick: tick of execution
- * @param id: unused
- * @param data: unused
- * @return 0
- */
- TIMER_FUNC(logchrif_sync_ip_addresses){
- uint8 buf[2];
- ShowInfo("IP Sync in progress...\n");
- WBUFW(buf,0) = 0x2735;
- logchrif_sendallwos(-1, buf, 2);
- return 0;
- }
- /// Parsing handlers
- /**
- * Request from char-server to authenticate an account.
- * @param fd: fd to parse from (char-serv)
- * @param id: id of char-serv
- * @param ip: char-serv ip (used for info)
- * @return 0 not enough info transmitted, 1 success
- */
- int32 logchrif_parse_reqauth(int32 fd, int32 id,char* ip){
- if( RFIFOREST(fd) < 23 )
- return 0;
- else{
- uint32 account_id = RFIFOL(fd,2);
- uint32 login_id1 = RFIFOL(fd,6);
- uint32 login_id2 = RFIFOL(fd,10);
- uint8 sex = RFIFOB(fd,14);
- //uint32 ip_ = ntohl(RFIFOL(fd,15));
- int32 request_id = RFIFOL(fd,19);
- RFIFOSKIP(fd,23);
- struct auth_node* node = login_get_auth_node( account_id );
- if( global_core->is_running() &&
- node != nullptr &&
- node->account_id == account_id &&
- node->login_id1 == login_id1 &&
- node->login_id2 == login_id2 &&
- node->sex == sex_num2str(sex) /*&&
- node->ip == ip_*/ ){// found
- //ShowStatus("Char-server '%s': authentication of the account %d accepted (ip: %s).\n", server[id].name, account_id, ip);
- // send ack
- WFIFOHEAD(fd,21);
- WFIFOW(fd,0) = 0x2713;
- WFIFOL(fd,2) = account_id;
- WFIFOL(fd,6) = login_id1;
- WFIFOL(fd,10) = login_id2;
- WFIFOB(fd,14) = sex;
- WFIFOB(fd,15) = 0;// ok
- WFIFOL(fd,16) = request_id;
- WFIFOB(fd,20) = node->clienttype;
- WFIFOSET(fd,21);
- // each auth entry can only be used once
- login_remove_auth_node( account_id );
- }else{// authentication not found
- ShowStatus("Char-server '%s': authentication of the account %d REFUSED (ip: %s).\n", ch_server[id].name, account_id, ip);
- WFIFOHEAD(fd,21);
- WFIFOW(fd,0) = 0x2713;
- WFIFOL(fd,2) = account_id;
- WFIFOL(fd,6) = login_id1;
- WFIFOL(fd,10) = login_id2;
- WFIFOB(fd,14) = sex;
- WFIFOB(fd,15) = 1;// auth failed
- WFIFOL(fd,16) = request_id;
- WFIFOB(fd,20) = 0;
- WFIFOSET(fd,21);
- }
- }
- return 1;
- }
- /**
- * Receive a request to update user count for char-server identified by id.
- * @param fd: fd to parse from (char-serv)
- * @param id: id of char-serv
- * @return 0 not enough info transmitted, 1 success
- */
- int32 logchrif_parse_ackusercount(int32 fd, int32 id){
- if( RFIFOREST(fd) < 6 )
- return 0;
- else{
- int32 users = RFIFOL(fd,2);
- RFIFOSKIP(fd,6);
- // how many users on world? (update)
- if( ch_server[id].users != users ){
- ShowStatus("set users %s : %d\n", ch_server[id].name, users);
- ch_server[id].users = users;
- }
- }
- return 1;
- }
- /**
- * Transmit account data to char_server
- * S 2717 aid.W email.40B exp_time.L group_id.B char_slot.B birthdate.11B pincode.5B pincode_change.L
- * isvip.1B char_vip.1B max_billing.1B (tot 75)
- * @return -1 : account not found, 1:sucess
- */
- int32 logchrif_send_accdata(int32 fd, uint32 aid) {
- struct mmo_account acc;
- time_t expiration_time = 0;
- char email[40] = "";
- int32 group_id = 0;
- char birthdate[10+1] = "";
- char pincode[PINCODE_LENGTH+1];
- char isvip = false;
- uint8 char_slots = MIN_CHARS, char_vip = 0, char_billing = MAX_CHAR_BILLING;
- AccountDB* accounts = login_get_accounts_db();
- memset(pincode,0,PINCODE_LENGTH+1);
- if( !accounts->load_num(accounts, &acc, aid) )
- return -1;
- else {
- safestrncpy(email, acc.email, sizeof(email));
- expiration_time = acc.expiration_time;
- group_id = acc.group_id;
- safestrncpy(birthdate, acc.birthdate, sizeof(birthdate));
- safestrncpy(pincode, acc.pincode, sizeof(pincode));
- char_slots = login_config.char_per_account;
- // Respect account information from login-server
- if( acc.char_slots > 0 ){
- char_slots = acc.char_slots;
- }
- #ifdef VIP_ENABLE
- char_vip = login_config.vip_sys.char_increase;
- if( acc.vip_time > time(nullptr) ) {
- isvip = true;
- char_slots += char_vip;
- }
- #endif
- }
- WFIFOHEAD(fd,75);
- WFIFOW(fd,0) = 0x2717;
- WFIFOL(fd,2) = aid;
- safestrncpy(WFIFOCP(fd,6), email, 40);
- WFIFOL(fd,46) = (uint32)expiration_time;
- WFIFOB(fd,50) = (unsigned char)group_id;
- WFIFOB(fd,51) = char_slots;
- safestrncpy(WFIFOCP(fd,52), birthdate, 10+1);
- safestrncpy(WFIFOCP(fd,63), pincode, 4+1 );
- WFIFOL(fd,68) = (uint32)acc.pincode_change;
- WFIFOB(fd,72) = isvip;
- WFIFOB(fd,73) = char_vip;
- WFIFOB(fd,74) = char_billing;
- WFIFOSET(fd,75);
- return 1;
- }
- /**
- * Transmit vip specific data to char-serv (will be transfered to mapserv)
- * @param fd
- * @param acc
- * @param flag 0x1: VIP, 0x2: GM, 0x4: Show rates on player
- * @param mapfd
- */
- int32 logchrif_sendvipdata(int32 fd, struct mmo_account* acc, unsigned char flag, int32 mapfd) {
- #ifdef VIP_ENABLE
- WFIFOHEAD(fd,19);
- WFIFOW(fd,0) = 0x2743;
- WFIFOL(fd,2) = acc->account_id;
- WFIFOL(fd,6) = (int)acc->vip_time;
- WFIFOB(fd,10) = flag;
- WFIFOL(fd,11) = acc->group_id; //new group id
- WFIFOL(fd,15) = mapfd; //link to mapserv
- WFIFOSET(fd,19);
- logchrif_send_accdata(fd,acc->account_id); //refresh char with new setting
- #endif
- return 1;
- }
- /**
- * Receive a request for account data reply by sending all mmo_account information.
- * @param fd: fd to parse from (char-serv)
- * @param id: id of char-serv
- * @param ip: char-serv ip (used for info)
- * @return 0 not enough info transmitted, 1 success
- */
- int32 logchrif_parse_reqaccdata(int32 fd, int32 id, char *ip){
- if( RFIFOREST(fd) < 6 )
- return 0;
- else {
- uint32 aid = RFIFOL(fd,2);
- RFIFOSKIP(fd,6);
- if( logchrif_send_accdata(fd,aid) < 0 )
- ShowNotice("Char-server '%s': account %d NOT found (ip: %s).\n", ch_server[id].name, aid, ip);
- }
- return 1;
- }
- /**
- * Ping request from char-server to send a reply.
- * @param fd: fd to parse from (char-serv)
- * @return 1 success
- */
- int32 logchrif_parse_keepalive(int32 fd){
- RFIFOSKIP(fd,2);
- WFIFOHEAD(fd,2);
- WFIFOW(fd,0) = 0x2718;
- WFIFOSET(fd,2);
- return 1;
- }
- /**
- * Map server send information to change an email of an account via char-server.
- * 0x2722 <account_id>.L <actual_e-mail>.40B <new_e-mail>.40B
- * @param fd: fd to parse from (char-serv)
- * @param id: id of char-serv
- * @param ip: char-serv ip (used for info)
- * @return 0 not enough info transmitted, 1 success
- */
- int32 logchrif_parse_reqchangemail(int32 fd, int32 id, char* ip){
- if (RFIFOREST(fd) < 86)
- return 0;
- else{
- struct mmo_account acc;
- AccountDB* accounts = login_get_accounts_db();
- char actual_email[40];
- char new_email[40];
- uint32 account_id = RFIFOL(fd,2);
- safestrncpy(actual_email, RFIFOCP(fd,6), 40);
- safestrncpy(new_email, RFIFOCP(fd,46), 40);
- RFIFOSKIP(fd, 86);
- if( e_mail_check(actual_email) == 0 )
- ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but actual email is invalid (account: %d, ip: %s)\n", ch_server[id].name, account_id, ip);
- else if( e_mail_check(new_email) == 0 )
- ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command) with a invalid new e-mail (account: %d, ip: %s)\n", ch_server[id].name, account_id, ip);
- else if( strcmpi(new_email, "a@a.com") == 0 )
- ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command) with a default e-mail (account: %d, ip: %s)\n", ch_server[id].name, account_id, ip);
- else if( !accounts->load_num(accounts, &acc, account_id) )
- ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but account doesn't exist (account: %d, ip: %s).\n", ch_server[id].name, account_id, ip);
- else if( strcmpi(acc.email, actual_email) != 0 )
- ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but actual e-mail is incorrect (account: %d (%s), actual e-mail: %s, proposed e-mail: %s, ip: %s).\n", ch_server[id].name, account_id, acc.userid, acc.email, actual_email, ip);
- else{
- safestrncpy(acc.email, new_email, 40);
- ShowNotice("Char-server '%s': Modify an e-mail on an account (@email GM command) (account: %d (%s), new e-mail: %s, ip: %s).\n", ch_server[id].name, account_id, acc.userid, new_email, ip);
- // Save
- accounts->save(accounts, &acc, false);
- }
- }
- return 1;
- }
- /**
- * Receiving an account state update request from a map-server (relayed via char-server).
- * @param fd: fd to parse from (char-serv)
- * @param id: id of char-serv
- * @param ip: char-serv ip (used for info)
- * @return 0 not enough info transmitted, 1 success
- * TODO seems pretty damn close to logchrif_parse_reqbanacc
- */
- int32 logchrif_parse_requpdaccstate(int32 fd, int32 id, char* ip){
- if (RFIFOREST(fd) < 10)
- return 0;
- else{
- struct mmo_account acc;
- uint32 account_id = RFIFOL(fd,2);
- uint32 state = RFIFOL(fd,6);
- AccountDB* accounts = login_get_accounts_db();
- RFIFOSKIP(fd,10);
- if( !accounts->load_num(accounts, &acc, account_id) )
- ShowNotice("Char-server '%s': Error of Status change (account: %d not found, suggested status %d, ip: %s).\n", ch_server[id].name, account_id, state, ip);
- else if( acc.state == state )
- ShowNotice("Char-server '%s': Error of Status change - actual status is already the good status (account: %d, status %d, ip: %s).\n", ch_server[id].name, account_id, state, ip);
- else{
- ShowNotice("Char-server '%s': Status change (account: %d, new status %d, ip: %s).\n", ch_server[id].name, account_id, state, ip);
- acc.state = state;
- // Save
- accounts->save(accounts, &acc, false);
- // notify other servers
- if (state != 0){
- uint8 buf[11];
- WBUFW(buf,0) = 0x2731;
- WBUFL(buf,2) = account_id;
- WBUFB(buf,6) = 0; // 0: change of state, 1: ban
- WBUFL(buf,7) = state; // status or final date of a banishment
- logchrif_sendallwos(-1, buf, 11);
- }
- }
- }
- return 1;
- }
- /**
- * Receiving a ban request from map-server via char-server.
- * @param fd: fd to parse from (char-serv)
- * @param id: id of char-serv
- * @param ip: char-serv ip (used for info)
- * @return 0 not enough info transmitted, 1 success
- * TODO check logchrif_parse_requpdaccstate for possible merge
- */
- int32 logchrif_parse_reqbanacc(int32 fd, int32 id, char* ip){
- if (RFIFOREST(fd) < 10)
- return 0;
- else{
- struct mmo_account acc;
- AccountDB* accounts = login_get_accounts_db();
- uint32 account_id = RFIFOL(fd,2);
- int32 timediff = RFIFOL(fd,6);
- RFIFOSKIP(fd,10);
- if( !accounts->load_num(accounts, &acc, account_id) )
- ShowNotice("Char-server '%s': Error of ban request (account: %d not found, ip: %s).\n", ch_server[id].name, account_id, ip);
- else{
- time_t timestamp;
- if (acc.unban_time == 0 || acc.unban_time < time(nullptr))
- timestamp = time(nullptr); // new ban
- else
- timestamp = acc.unban_time; // add to existing ban
- timestamp += timediff;
- if (timestamp == -1)
- ShowNotice("Char-server '%s': Error of ban request (account: %d, invalid date, ip: %s).\n", ch_server[id].name, account_id, ip);
- else if( timestamp <= time(nullptr) || timestamp == 0 )
- ShowNotice("Char-server '%s': Error of ban request (account: %d, new date unbans the account, ip: %s).\n", ch_server[id].name, account_id, ip);
- else{
- uint8 buf[11];
- char tmpstr[24];
- timestamp2string(tmpstr, sizeof(tmpstr), timestamp, login_config.date_format);
- ShowNotice("Char-server '%s': Ban request (account: %d, new final date of banishment: %s, ip: %s).\n", ch_server[id].name, account_id, tmpstr, ip);
- acc.unban_time = timestamp;
- // Save
- accounts->save(accounts, &acc, false);
- WBUFW(buf,0) = 0x2731;
- WBUFL(buf,2) = account_id;
- WBUFB(buf,6) = 1; // 0: change of status, 1: ban
- WBUFL(buf,7) = (uint32)timestamp; // status or final date of a banishment
- logchrif_sendallwos(-1, buf, 11);
- }
- }
- }
- return 1;
- }
- /**
- * Receiving a sex change request (sex is reversed).
- * @param fd: fd to parse from (char-serv)
- * @param id: id of char-serv
- * @param ip: char-serv ip (used for info)
- * @return 0 not enough info transmitted, 1 success
- */
- int32 logchrif_parse_reqchgsex(int32 fd, int32 id, char* ip){
- if( RFIFOREST(fd) < 6 )
- return 0;
- else{
- struct mmo_account acc;
- AccountDB* accounts = login_get_accounts_db();
- uint32 account_id = RFIFOL(fd,2);
- RFIFOSKIP(fd,6);
- if( !accounts->load_num(accounts, &acc, account_id) )
- ShowNotice("Char-server '%s': Error of sex change (account: %d not found, ip: %s).\n", ch_server[id].name, account_id, ip);
- else if( acc.sex == 'S' )
- ShowNotice("Char-server '%s': Error of sex change - account to change is a Server account (account: %d, ip: %s).\n", ch_server[id].name, account_id, ip);
- else{
- unsigned char buf[7];
- char sex = ( acc.sex == 'M' ) ? 'F' : 'M'; //Change gender
- ShowNotice("Char-server '%s': Sex change (account: %d, new sex %c, ip: %s).\n", ch_server[id].name, account_id, sex, ip);
- acc.sex = sex;
- // Save
- accounts->save(accounts, &acc, false);
- // announce to other servers
- WBUFW(buf,0) = 0x2723;
- WBUFL(buf,2) = account_id;
- WBUFB(buf,6) = sex_str2num(sex);
- logchrif_sendallwos(-1, buf, 7);
- }
- }
- return 1;
- }
- /**
- * We receive account_reg2 from a char-server, and we send them to other char-servers.
- * @param fd: fd to parse from (char-serv)
- * @param id: id of char-serv
- * @param ip: char-serv ip (used for info)
- * @return 0 not enough info transmitted, 1 success
- */
- int32 logchrif_parse_upd_global_accreg(int32 fd, int32 id, char* ip){
- if( RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2) )
- return 0;
- else{
- struct mmo_account acc;
- AccountDB* accounts = login_get_accounts_db();
- uint32 account_id = RFIFOL(fd,4);
- if( !accounts->load_num(accounts, &acc, account_id) )
- ShowStatus("Char-server '%s': receiving (from the char-server) of account_reg2 (account: %d not found, ip: %s).\n", ch_server[id].name, account_id, ip);
- else
- mmo_save_global_accreg(accounts,fd,account_id,RFIFOL(fd, 8));
- RFIFOSKIP(fd,RFIFOW(fd,2));
- }
- return 1;
- }
- /**
- * Receiving an unban request from map-server via char-server.
- * @param fd: fd to parse from (char-serv)
- * @param id: id of char-serv
- * @param ip: char-serv ip (used for info)
- * @return 0 not enough info transmitted, 1 success
- */
- int32 logchrif_parse_requnbanacc(int32 fd, int32 id, char* ip){
- if( RFIFOREST(fd) < 6 )
- return 0;
- else{
- struct mmo_account acc;
- AccountDB* accounts = login_get_accounts_db();
- uint32 account_id = RFIFOL(fd,2);
- RFIFOSKIP(fd,6);
- if( !accounts->load_num(accounts, &acc, account_id) )
- ShowNotice("Char-server '%s': Error of UnBan request (account: %d not found, ip: %s).\n", ch_server[id].name, account_id, ip);
- else if( acc.unban_time == 0 )
- ShowNotice("Char-server '%s': Error of UnBan request (account: %d, no change for unban date, ip: %s).\n", ch_server[id].name, account_id, ip);
- else{
- ShowNotice("Char-server '%s': UnBan request (account: %d, ip: %s).\n", ch_server[id].name, account_id, ip);
- acc.unban_time = 0;
- accounts->save(accounts, &acc, false);
- }
- }
- return 1;
- }
- /**
- * Set account_id to online.
- * @author [Wizputer]
- * @param fd: fd to parse from (char-serv)
- * @param id: id of char-serv
- * @return 0 not enough info transmitted, 1 success
- */
- int32 logchrif_parse_setacconline(int32 fd, int32 id){
- if( RFIFOREST(fd) < 6 )
- return 0;
- login_add_online_user(id, RFIFOL(fd,2));
- RFIFOSKIP(fd,6);
- return 1;
- }
- /**
- * Set account_id to offline.
- * @author [Wizputer]
- * @param fd: fd to parse from (char-serv)
- * @return 0 not enough info transmitted, 1 success
- */
- int32 logchrif_parse_setaccoffline(int32 fd){
- if( RFIFOREST(fd) < 6 )
- return 0;
- login_remove_online_user(RFIFOL(fd,2));
- RFIFOSKIP(fd,6);
- return 1;
- }
- /**
- * Receive list of all online accounts.
- * @author [Skotlex]
- * @param fd: fd to parse from (char-serv)
- * @param id: id of char-serv
- * @return 0 not enough info transmitted, 1 success
- */
- int32 logchrif_parse_updonlinedb(int32 fd, int32 id){
- if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
- return 0;
- else{
- //Set all chars from this char-server offline first
- login_online_db_setoffline( id );
- for( uint32 i = 0, users = RFIFOW(fd, 4); i < users; i++) {
- uint32 aid = RFIFOL(fd,6+i*4);
- login_add_online_user( id, aid );
- }
- RFIFOSKIP(fd,RFIFOW(fd,2));
- }
- return 1;
- }
- /**
- * Request account_reg2 for a character.
- * @param fd: fd to parse from (char-serv)
- * @return 0 not enough info transmitted, 1 success
- */
- int32 logchrif_parse_req_global_accreg(int32 fd){
- if (RFIFOREST(fd) < 10)
- return 0;
- else{
- AccountDB* accounts = login_get_accounts_db();
- uint32 account_id = RFIFOL(fd,2);
- uint32 char_id = RFIFOL(fd,6);
- RFIFOSKIP(fd,10);
- mmo_send_global_accreg(accounts,fd,account_id,char_id);
- }
- return 1;
- }
- /**
- * Received new charip from char-serv, update information.
- * @param fd: char-serv file descriptor
- * @param id: char-serv id
- * @return 0 not enough info transmitted, 1 success
- */
- int32 logchrif_parse_updcharip(int32 fd, int32 id){
- if( RFIFOREST(fd) < 6 )
- return 0;
- ch_server[id].ip = ntohl(RFIFOL(fd,2));
- ShowInfo("Updated IP of Server #%d to %d.%d.%d.%d.\n",id, CONVIP(ch_server[id].ip));
- RFIFOSKIP(fd,6);
- return 1;
- }
- /**
- * Request to set all accounts offline.
- * @param fd: fd to parse from (char-serv)
- * @param id: id of char-serv (char-serv)
- * @return 1 success
- */
- int32 logchrif_parse_setalloffline(int32 fd, int32 id){
- ShowInfo("Setting accounts from char-server %d offline.\n", id);
- login_online_db_setoffline( id );
- RFIFOSKIP(fd,2);
- return 1;
- }
- #if PACKETVER_SUPPORTS_PINCODE
- /**
- * Request to change PIN Code for an account.
- * @param fd: fd to parse from (char-serv)
- * @return 0 fail (packet does not have enough data), 1 success
- */
- int32 logchrif_parse_updpincode(int32 fd){
- if( RFIFOREST(fd) < 8 + PINCODE_LENGTH+1 )
- return 0;
- else{
- struct mmo_account acc;
- AccountDB* accounts = login_get_accounts_db();
- if( accounts->load_num(accounts, &acc, RFIFOL(fd,4) ) ){
- strncpy( acc.pincode, RFIFOCP(fd,8), PINCODE_LENGTH+1 );
- acc.pincode_change = time( nullptr );
- accounts->save(accounts, &acc, false);
- }
- RFIFOSKIP(fd,8 + PINCODE_LENGTH+1);
- }
- return 1;
- }
- /**
- * PIN Code was incorrectly entered too many times.
- * @param fd: fd to parse from (char-serv)
- * @return 0 fail (packet does not have enough data), 1 success (continue parsing)
- */
- int32 logchrif_parse_pincode_authfail(int32 fd){
- if( RFIFOREST(fd) < 6 )
- return 0;
- else{
- struct mmo_account acc;
- AccountDB* accounts = login_get_accounts_db();
- if( accounts->load_num(accounts, &acc, RFIFOL(fd,2) ) ){
- struct online_login_data* ld = login_get_online_user( acc.account_id );
- if( ld == nullptr ){
- return 0;
- }
- login_log( host2ip(acc.last_ip), acc.userid, 100, "PIN Code check failed" );
- }
- login_remove_online_user(acc.account_id);
- RFIFOSKIP(fd,6);
- }
- return 1;
- }
- #endif
- /**
- * Received a vip data reqest from char
- * type is the query to perform
- * 0x1 : Select info and update old_groupid
- * 0x2 : VIP duration is changed by atcommand or script
- * 0x8 : First request on player login
- * @param fd link to charserv
- * @return 0 missing data, 1 succeeded
- */
- int32 logchrif_parse_reqvipdata(int32 fd) {
- #ifdef VIP_ENABLE
- if( RFIFOREST(fd) < 15 )
- return 0;
- else { //request vip info
- struct mmo_account acc;
- AccountDB* accounts = login_get_accounts_db();
- int32 aid = RFIFOL(fd,2);
- int8 flag = RFIFOB(fd,6);
- int32 timediff = RFIFOL(fd,7);
- int32 mapfd = RFIFOL(fd,11);
- RFIFOSKIP(fd,15);
-
- if( accounts->load_num(accounts, &acc, aid ) ) {
- time_t now = time(nullptr);
- time_t vip_time = acc.vip_time;
- bool isvip = false;
- if( acc.group_id > login_config.vip_sys.group ) { //Don't change group if it's higher.
- logchrif_sendvipdata(fd,&acc,0x2|((flag&0x8)?0x4:0),mapfd);
- return 1;
- }
- if( flag&2 ) {
- if(!vip_time)
- vip_time = now; //new entry
- vip_time += timediff; // set new duration
- }
- if( now < vip_time ) { //isvip
- if(acc.group_id != login_config.vip_sys.group){ //only upd this if we're not vip already
- acc.old_group = acc.group_id;
- if( acc.char_slots == 0 ){
- acc.char_slots = MIN_CHARS;
- }
- acc.char_slots += login_config.vip_sys.char_increase;
- }
- acc.group_id = login_config.vip_sys.group;
- isvip = true;
- } else { //expired or @vip -xx
- vip_time = 0;
- if(acc.group_id == login_config.vip_sys.group){ //prevent alteration in case account wasn't registered as vip yet
- acc.group_id = acc.old_group;
- if( acc.char_slots == 0 ){
- acc.char_slots = MIN_CHARS;
- }else{
- acc.char_slots -= login_config.vip_sys.char_increase;
- }
- }
- acc.old_group = 0;
- }
- acc.vip_time = vip_time;
- accounts->save(accounts,&acc, false);
- if( flag&1 )
- logchrif_sendvipdata(fd,&acc,((isvip)?0x1:0)|((flag&0x8)?0x4:0),mapfd);
- }
- }
- #endif
- return 1;
- }
- /**
- * IA 0x2720
- * Get account info that asked by inter/char-server
- */
- int32 logchrif_parse_accinfo(int32 fd) {
- if( RFIFOREST(fd) < 19 )
- return 0;
- else {
- int32 map_fd = RFIFOL(fd, 2), u_fd = RFIFOL(fd, 6), u_aid = RFIFOL(fd, 10), account_id = RFIFOL(fd, 14);
- int8 type = RFIFOB(fd, 18);
- AccountDB* accounts = login_get_accounts_db();
- struct mmo_account acc;
- RFIFOSKIP(fd,19);
- // Send back the result to char-server
- if (accounts->load_num(accounts, &acc, account_id)) {
- int32 len = 122 + NAME_LENGTH;
- //ShowInfo("Found account info for %d, requested by %d\n", account_id, u_aid);
- WFIFOHEAD(fd, len);
- WFIFOW(fd, 0) = 0x2721;
- WFIFOL(fd, 2) = map_fd;
- WFIFOL(fd, 6) = u_fd;
- WFIFOL(fd, 10) = u_aid;
- WFIFOL(fd, 14) = account_id;
- WFIFOB(fd, 18) = (1<<type); // success
- WFIFOL(fd, 19) = acc.group_id;
- WFIFOL(fd, 23) = acc.logincount;
- WFIFOL(fd, 27) = acc.state;
- safestrncpy(WFIFOCP(fd, 31), acc.email, 40);
- safestrncpy(WFIFOCP(fd, 71), acc.last_ip, 16);
- safestrncpy(WFIFOCP(fd, 87), acc.lastlogin, 24);
- safestrncpy(WFIFOCP(fd, 111), acc.birthdate, 11);
- safestrncpy(WFIFOCP(fd, 122), acc.userid, NAME_LENGTH);
- WFIFOSET(fd, len);
- }
- else {
- //ShowInfo("Cannot found account info for %d, requested by %d\n", account_id, u_aid);
- WFIFOHEAD(fd, 19);
- WFIFOW(fd, 0) = 0x2721;
- WFIFOL(fd, 2) = map_fd;
- WFIFOL(fd, 6) = u_fd;
- WFIFOL(fd, 10) = u_aid;
- WFIFOL(fd, 14) = account_id;
- WFIFOB(fd, 18) = 0; // failed
- WFIFOSET(fd, 19);
- }
- }
- return 1;
- }
- /**
- * Entry point from char-server to log-server.
- * Function that checks incoming command, then splits it to the correct handler.
- * @param fd: file descriptor to parse, (link to char-serv)
- * @return 0=invalid server,marked for disconnection,unknow packet; 1=success
- */
- int32 logchrif_parse(int32 fd){
- int32 cid; //char-serv id
- uint32 ipl;
- char ip[16];
- ARR_FIND( 0, ARRAYLENGTH(ch_server), cid, ch_server[cid].fd == fd );
- if( cid == ARRAYLENGTH(ch_server) ){// not a char server
- ShowDebug("logchrif_parse: Disconnecting invalid session #%d (is not a char-server)\n", fd);
- set_eof(fd);
- do_close(fd);
- return 0;
- }
- if( session[fd]->flag.eof ){
- do_close(fd);
- ch_server[cid].fd = -1;
- logchrif_on_disconnect(cid);
- return 0;
- }
- ipl = ch_server[cid].ip;
- ip2str(ipl, ip);
- while( RFIFOREST(fd) >= 2 ){
- int32 next = 1; // 0: avoid processing followup packets (prev was probably incomplete) packet, 1: Continue parsing
- uint16 command = RFIFOW(fd,0);
- switch( command ){
- case 0x2712: next = logchrif_parse_reqauth(fd, cid, ip); break;
- case 0x2714: next = logchrif_parse_ackusercount(fd, cid); break;
- case 0x2716: next = logchrif_parse_reqaccdata(fd, cid, ip); break;
- case 0x2719: next = logchrif_parse_keepalive(fd); break;
- case 0x2720: next = logchrif_parse_accinfo(fd); break; //@accinfo from inter-server
- case 0x2722: next = logchrif_parse_reqchangemail(fd,cid,ip); break;
- case 0x2724: next = logchrif_parse_requpdaccstate(fd,cid,ip); break;
- case 0x2725: next = logchrif_parse_reqbanacc(fd,cid,ip); break;
- case 0x2727: next = logchrif_parse_reqchgsex(fd,cid,ip); break;
- case 0x2728: next = logchrif_parse_upd_global_accreg(fd,cid,ip); break;
- case 0x272a: next = logchrif_parse_requnbanacc(fd,cid,ip); break;
- case 0x272b: next = logchrif_parse_setacconline(fd,cid); break;
- case 0x272c: next = logchrif_parse_setaccoffline(fd); break;
- case 0x272d: next = logchrif_parse_updonlinedb(fd,cid); break;
- case 0x272e: next = logchrif_parse_req_global_accreg(fd); break;
- case 0x2736: next = logchrif_parse_updcharip(fd,cid); break;
- case 0x2737: next = logchrif_parse_setalloffline(fd,cid); break;
- #if PACKETVER_SUPPORTS_PINCODE
- case 0x2738: next = logchrif_parse_updpincode(fd); break;
- case 0x2739: next = logchrif_parse_pincode_authfail(fd); break;
- #endif
- case 0x2742: next = logchrif_parse_reqvipdata(fd); break; //Vip sys
- default:
- ShowError("logchrif_parse: Unknown packet 0x%x from a char-server! Disconnecting!\n", command);
- set_eof(fd);
- return 0;
- } // switch
- if (next == 0)
- return 0;
- } // while
- return 1; //or 0
- }
- /// Constructor destructor and signal handlers
- /**
- * Initializes a server structure.
- * @param id: id of char-serv (should be >0, FIXME)
- */
- void logchrif_server_init(int32 id) {
- memset(&ch_server[id], 0, sizeof(ch_server[id]));
- ch_server[id].fd = -1;
- }
- /**
- * Destroys a server structure.
- * @param id: id of char-serv (should be >0, FIXME)
- */
- void logchrif_server_destroy(int32 id){
- if( ch_server[id].fd != -1 ) {
- do_close(ch_server[id].fd);
- ch_server[id].fd = -1;
- }
- }
- /**
- * Resets all the data related to a server.
- * Actually destroys then recreates the struct.
- * @param id: id of char-serv (should be >0, FIXME)
- */
- void logchrif_server_reset(int32 id) {
- login_online_db_setoffline(id); //Set all chars from this char server to offline.
- logchrif_server_destroy(id);
- logchrif_server_init(id);
- }
- /**
- * Called when the connection to Char Server is disconnected.
- * @param id: id of char-serv (should be >0, FIXME)
- */
- void logchrif_on_disconnect(int32 id) {
- ShowStatus("Char-server '%s' has disconnected.\n", ch_server[id].name);
- logchrif_server_reset(id);
- }
- /**
- * loginchrif constructor
- * Initialisation, function called at start of the login-serv.
- */
- void do_init_loginchrif(void){
- int32 i;
- for( i = 0; i < ARRAYLENGTH(ch_server); ++i )
- logchrif_server_init(i);
- // add timer to detect ip address change and perform update
- if (login_config.ip_sync_interval) {
- add_timer_func_list(logchrif_sync_ip_addresses, "sync_ip_addresses");
- add_timer_interval(gettick() + login_config.ip_sync_interval, logchrif_sync_ip_addresses, 0, 0, login_config.ip_sync_interval);
- }
- }
- /**
- * Signal handler
- * This function attempts to properly close the server when an interrupt signal is received.
- * current signal catch : SIGTERM, SIGINT
- */
- void do_shutdown_loginchrif(void){
- int32 id;
- for( id = 0; id < ARRAYLENGTH(ch_server); ++id )
- logchrif_server_reset(id);
- }
- /**
- * loginchrif destructor
- * dealloc..., function called at exit of the login-serv
- */
- void do_final_loginchrif(void){
- int32 i;
- for( i = 0; i < ARRAYLENGTH(ch_server); ++i )
- logchrif_server_destroy(i);
- }
|