/*========================================== * Request auth confirmation *------------------------------------------*/ void chrif_authreq(struct map_session_data *sd) { struct auth_node *node= chrif_search(sd->bl.id); if( node != NULL || !chrif_isconnected() ) { set_eof(sd->fd); return; } WFIFOHEAD(char_fd,19); WFIFOW(char_fd,0) = 0x2b26; WFIFOL(char_fd,2) = sd->status.account_id; WFIFOL(char_fd,6) = sd->status.char_id; WFIFOL(char_fd,10) = sd->login_id1; WFIFOB(char_fd,14) = sd->status.sex; WFIFOL(char_fd,15) = htonl(session[sd->fd]->client_addr); WFIFOSET(char_fd,19); chrif_sd_to_auth(sd, ST_LOGIN); }
//Moves the sd character to the auth_db structure. static bool chrif_sd_to_auth(TBL_PC* sd, enum sd_state state) { struct auth_node *node; if (chrif_search(sd->status.account_id)) return false; //Already exists? node = ers_alloc(auth_db_ers, struct auth_node); memset(node, 0, sizeof(struct auth_node)); node->account_id = sd->status.account_id; node->char_id = sd->status.char_id; node->login_id1 = sd->login_id1; node->login_id2 = sd->login_id2; node->sex = sd->status.sex; node->fd = sd->fd; node->sd = sd; //Data from logged on char. node->node_created = gettick(); //timestamp for node timeouts node->state = state; sd->state.active = 0; idb_put(auth_db, node->account_id, node); return true; }
// client authentication failed void chrif_authfail(int fd) {/* HELLO WORLD. ip in RFIFOL 15 is not being used (but is available) */ int account_id, char_id; uint32 login_id1; char sex; struct auth_node* node; account_id = RFIFOL(fd,2); char_id = RFIFOL(fd,6); login_id1 = RFIFOL(fd,10); sex = RFIFOB(fd,14); node = chrif_search(account_id); if( node != NULL && node->account_id == account_id && node->char_id == char_id && node->login_id1 == login_id1 && node->sex == sex && node->state == ST_LOGIN ) {// found a match clif->authfail_fd(node->fd, 0); chrif_auth_delete(account_id, char_id, ST_LOGIN); } }
//character selected, insert into auth db void chrif_authok(int fd) { struct auth_node *node; int account_id = RFIFOL(fd, 4); struct mmo_charstatus *status = (struct mmo_charstatus *)RFIFOP(fd, 20); int char_id = status->char_id; TBL_PC* sd; //Check if both servers agree on the struct's size if( RFIFOW(fd,2) - 20 != sizeof(struct mmo_charstatus) ) { ShowError("chrif_authok: Data size mismatch! %d != %d\n", RFIFOW(fd,2) - 20, sizeof(struct mmo_charstatus)); return; } //Check if we don't already have player data in our server //Causes problems if the currently connected player tries to quit or this data belongs to an already connected player which is trying to re-auth. if ((sd = map_id2sd(account_id)) != NULL) return; if ((node = chrif_search(account_id))) { //Is the character already awaiting authorization? if (node->state != ST_LOGIN) return; //character in logout phase, do not touch that data. if (node->sd) { sd = node->sd; if(node->char_dat == NULL && node->account_id == account_id && node->char_id == char_id && node->login_id1 == RFIFOL(fd, 8)) { //Auth Ok if (pc_authok(sd, RFIFOL(fd, 16), RFIFOL(fd, 12), status)) { chrif_char_online(sd); return; } } else { //Auth Failed pc_authfail(sd); } chrif_char_offline(sd); //Set client offline chrif_auth_delete(account_id, char_id, ST_LOGIN); return; } //When we receive double login info and the client has not connected yet, //discard the older one and keep the new one. chrif_auth_delete(node->account_id, node->char_id, ST_LOGIN); } // Awaiting for client to connect. node = ers_alloc(auth_db_ers, struct auth_node); memset(node, 0, sizeof(struct auth_node)); node->char_dat = (struct mmo_charstatus *) aMalloc(sizeof(struct mmo_charstatus)); node->account_id=account_id; node->char_id=char_id; node->login_id1=RFIFOL(fd, 8); node->connect_until_time=RFIFOL(fd, 12); node->login_id2=RFIFOL(fd, 16); memcpy(node->char_dat,status,sizeof(struct mmo_charstatus)); node->node_created=gettick(); idb_put(auth_db, account_id, node); }
struct auth_node* chrif_auth_check(int account_id, int char_id, enum sd_state state) { struct auth_node *node = chrif_search(account_id); return (node && node->char_id == char_id && node->state == state)?node:NULL; }
/*========================================== * Auth confirmation ack *------------------------------------------*/ void chrif_authok(int fd) { int account_id, group_id, char_id; uint32 login_id1,login_id2; time_t expiration_time; struct mmo_charstatus* status; struct auth_node *node; bool changing_mapservers; TBL_PC* sd; //Check if both servers agree on the struct's size if( RFIFOW(fd,2) - 25 != sizeof(struct mmo_charstatus) ) { ShowError("chrif_authok: Data size mismatch! %d != %d\n", RFIFOW(fd,2) - 25, sizeof(struct mmo_charstatus)); return; } account_id = RFIFOL(fd,4); login_id1 = RFIFOL(fd,8); login_id2 = RFIFOL(fd,12); expiration_time = (time_t)(int32)RFIFOL(fd,16); group_id = RFIFOL(fd,20); changing_mapservers = (RFIFOB(fd,24)); status = (struct mmo_charstatus*)RFIFOP(fd,25); char_id = status->char_id; //Check if we don't already have player data in our server //Causes problems if the currently connected player tries to quit or this data belongs to an already connected player which is trying to re-auth. if ( ( sd = map_id2sd(account_id) ) != NULL ) return; if ( ( node = chrif_search(account_id) ) == NULL ) return; // should not happen if ( node->state != ST_LOGIN ) return; //character in logout phase, do not touch that data. if ( node->sd == NULL ) { /* //When we receive double login info and the client has not connected yet, //discard the older one and keep the new one. chrif_auth_delete(node->account_id, node->char_id, ST_LOGIN); */ return; // should not happen } sd = node->sd; if( runflag == MAPSERVER_ST_RUNNING && node->char_dat == NULL && node->account_id == account_id && node->char_id == char_id && node->login_id1 == login_id1 ) { //Auth Ok if (pc_authok(sd, login_id2, expiration_time, group_id, status, changing_mapservers)) return; } else { //Auth Failed pc_authfail(sd); } chrif_char_offline(sd); //Set him offline, the char server likely has it set as online already. chrif_auth_delete(account_id, char_id, ST_LOGIN); }