/*========================================== * new auth system [Kevin] *------------------------------------------*/ void chrif_authreq(struct map_session_data *sd) { struct auth_node *node= chrif_search(sd->bl.id); if(!node) { //data from char server has not arrived yet. chrif_sd_to_auth(sd, ST_LOGIN); return; } if(node->state == ST_LOGIN && node->char_dat && node->account_id == sd->status.account_id && node->char_id == sd->status.char_id && node->login_id1 == sd->login_id1) { //auth ok if (!pc_authok(sd, node->login_id2, node->connect_until_time, node->char_dat)) { chrif_char_offline(sd); //Set client offline chrif_auth_delete(node->account_id, node->char_id, ST_LOGIN); } else { //char_dat no longer needed, but player auth is not completed yet. aFree(node->char_dat); node->char_dat = NULL; node->sd = sd; chrif_char_online(sd); //Set client online } } else { //auth failed pc_authfail(sd); chrif_char_offline(sd); //Set client offline chrif_auth_delete(sd->status.account_id, sd->status.char_id, ST_LOGIN); } return; }
/** * @see DBApply */ static int chrif_reconnect(DBKey key, DBData *data, va_list ap) { struct auth_node *node = DB->data2ptr(data); switch (node->state) { case ST_LOGIN: if ( node->sd && node->char_dat == NULL ) {//Since there is no way to request the char auth, make it fail. pc_authfail(node->sd); chrif_char_offline(node->sd); chrif_auth_delete(node->account_id, node->char_id, ST_LOGIN); } break; case ST_LOGOUT: //Re-send final save chrif_save(node->sd, 1); break; case ST_MAPCHANGE: { //Re-send map-change request. struct map_session_data *sd = node->sd; uint32 ip; uint16 port; if( map_mapname2ipport(sd->mapindex,&ip,&port) == 0 ) chrif_changemapserver(sd, ip, port); else //too much lag/timeout is the closest explanation for this error. clif->authfail_fd(sd->fd, 3); break; } } return 0; }
/*========================================== * new auth system [Kevin] *------------------------------------------*/ void chrif_authreq(struct map_session_data *sd) { struct auth_node *auth_data; auth_data=idb_get(auth_db, sd->bl.id); if(auth_data) { if(auth_data->char_dat && auth_data->account_id== sd->bl.id && auth_data->login_id1 == sd->login_id1) { //auth ok pc_authok(sd, auth_data->login_id2, auth_data->connect_until_time, auth_data->char_dat); } else { //auth failed pc_authfail(sd); chrif_char_offline(sd); //Set him offline, the char server likely has it set as online already. } if (auth_data->char_dat) aFree(auth_data->char_dat); idb_remove(auth_db, sd->bl.id); } else { //data from char server has not arrived yet. auth_data = aCalloc(1,sizeof(struct auth_node)); auth_data->sd = sd; auth_data->fd = sd->fd; auth_data->account_id = sd->bl.id; auth_data->login_id1 = sd->login_id1; auth_data->node_created = gettick(); uidb_put(auth_db, sd->bl.id, auth_data); } return; }
//character selected, insert into auth db void chrif_authok(int fd) { struct auth_node *auth_data; TBL_PC* sd; //Check if we don't already have player data in our server //(prevents data that is to be saved from being overwritten by //this received status data if this auth is later successful) [Skotlex] if ((sd = map_id2sd(RFIFOL(fd, 4))) != NULL) { struct mmo_charstatus *status = (struct mmo_charstatus *)RFIFOP(fd, 20); //Auth check is because this could be the very same sd that is waiting char-server authorization. if (sd->state.auth && sd->status.char_id == status->char_id) return; } if ((auth_data =uidb_get(auth_db, RFIFOL(fd, 4))) != NULL) { //Is the character already awaiting authorization? if (auth_data->sd) { //First, check to see if the session data still exists (avoid dangling pointers) if(session[auth_data->fd] && session[auth_data->fd]->session_data == auth_data->sd) { if (auth_data->char_dat == NULL && auth_data->account_id == RFIFOL(fd, 4) && auth_data->login_id1 == RFIFOL(fd, 8)) { //Auth Ok pc_authok(auth_data->sd, RFIFOL(fd, 16), RFIFOL(fd, 12), (struct mmo_charstatus*)RFIFOP(fd, 20)); } else { //Auth Failed pc_authfail(auth_data->sd); chrif_char_offline(auth_data->sd); //Set him offline, the char server likely has it set as online already. } } //else: Character no longer exists, just go through. } //Delete the data of this node... if (auth_data->char_dat) aFree (auth_data->char_dat); uidb_remove(auth_db, RFIFOL(fd, 4)); return; } // Awaiting for client to connect. auth_data = (struct auth_node *)aCalloc(1,sizeof(struct auth_node)); auth_data->char_dat = (struct mmo_charstatus *) aCalloc(1,sizeof(struct mmo_charstatus)); auth_data->account_id=RFIFOL(fd, 4); auth_data->login_id1=RFIFOL(fd, 8); auth_data->connect_until_time=RFIFOL(fd, 12); auth_data->login_id2=RFIFOL(fd, 16); memcpy(auth_data->char_dat,RFIFOP(fd, 20),sizeof(struct mmo_charstatus)); auth_data->node_created=gettick(); uidb_put(auth_db, RFIFOL(fd, 4), auth_data); }
//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); }
/*========================================== * 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); }