/** * 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 */ int logchrif_parse_setacconline(int fd, int id){ if( RFIFOREST(fd) < 6 ) return 0; login_add_online_user(id, RFIFOL(fd,2)); RFIFOSKIP(fd,6); return 1; }
/** * Auth successful, inform client and create a temp auth_node. * @param sd: player session */ static void logclif_auth_ok(struct login_session_data* sd) { int fd = sd->fd; uint32 ip = session[fd]->client_addr; uint8 server_num, n; uint32 subnet_char_ip; struct auth_node* node; int i; #if PACKETVER < 20170315 int cmd = 0x69; // AC_ACCEPT_LOGIN int header = 47; int size = 32; #else int cmd = 0xac4; // AC_ACCEPT_LOGIN3 int header = 64; int size = 160; #endif if( runflag != LOGINSERVER_ST_RUNNING ){ // players can only login while running logclif_sent_auth_result(fd,1); // server closed return; } if( login_config.group_id_to_connect >= 0 && sd->group_id != login_config.group_id_to_connect ) { ShowStatus("Connection refused: the required group id for connection is %d (account: %s, group: %d).\n", login_config.group_id_to_connect, sd->userid, sd->group_id); logclif_sent_auth_result(fd,1); // server closed return; } else if( login_config.min_group_id_to_connect >= 0 && login_config.group_id_to_connect == -1 && sd->group_id < login_config.min_group_id_to_connect ) { ShowStatus("Connection refused: the minimum group id required for connection is %d (account: %s, group: %d).\n", login_config.min_group_id_to_connect, sd->userid, sd->group_id); logclif_sent_auth_result(fd,1); // server closed return; } server_num = 0; for( i = 0; i < ARRAYLENGTH(ch_server); ++i ) if( session_isActive(ch_server[i].fd) ) server_num++; if( server_num == 0 ) {// if no char-server, don't send void list of servers, just disconnect the player with proper message ShowStatus("Connection refused: there is no char-server online (account: %s).\n", sd->userid); logclif_sent_auth_result(fd,1); // server closed return; } { struct online_login_data* data = (struct online_login_data*)idb_get(online_db, sd->account_id); if( data ) {// account is already marked as online! if( data->char_server > -1 ) {// Request char servers to kick this account out. [Skotlex] uint8 buf[6]; ShowNotice("User '%s' is already online - Rejected.\n", sd->userid); WBUFW(buf,0) = 0x2734; WBUFL(buf,2) = sd->account_id; logchrif_sendallwos(-1, buf, 6); if( data->waiting_disconnect == INVALID_TIMER ) data->waiting_disconnect = add_timer(gettick()+AUTH_TIMEOUT, login_waiting_disconnect_timer, sd->account_id, 0); logclif_sent_auth_result(fd,8); // 08 = Server still recognizes your last login return; } else if( data->char_server == -1 ) {// client has authed but did not access char-server yet // wipe previous session idb_remove(auth_db, sd->account_id); login_remove_online_user(sd->account_id); data = NULL; } } } login_log(ip, sd->userid, 100, "login ok"); ShowStatus("Connection of the account '%s' accepted.\n", sd->userid); WFIFOHEAD(fd,header+size*server_num); WFIFOW(fd,0) = cmd; WFIFOW(fd,2) = header+size*server_num; WFIFOL(fd,4) = sd->login_id1; WFIFOL(fd,8) = sd->account_id; WFIFOL(fd,12) = sd->login_id2; WFIFOL(fd,16) = 0; // in old version, that was for ip (not more used) //memcpy(WFIFOP(fd,20), sd->lastlogin, 24); // in old version, that was for name (not more used) memset(WFIFOP(fd,20), 0, 24); WFIFOW(fd,44) = 0; // unknown WFIFOB(fd,46) = sex_str2num(sd->sex); #if PACKETVER >= 20170315 memset(WFIFOP(fd,47),0,17); // Unknown #endif for( i = 0, n = 0; i < ARRAYLENGTH(ch_server); ++i ) { if( !session_isValid(ch_server[i].fd) ) continue; subnet_char_ip = lan_subnetcheck(ip); // Advanced subnet check [LuzZza] WFIFOL(fd,header+n*size) = htonl((subnet_char_ip) ? subnet_char_ip : ch_server[i].ip); WFIFOW(fd,header+n*size+4) = ntows(htons(ch_server[i].port)); // [!] LE byte order here [!] memcpy(WFIFOP(fd,header+n*size+6), ch_server[i].name, 20); WFIFOW(fd,header+n*size+26) = ch_server[i].users; WFIFOW(fd,header+n*size+28) = ch_server[i].type; WFIFOW(fd,header+n*size+30) = ch_server[i].new_; #if PACKETVER >= 20170315 memset(WFIFOP(fd, header+n*size+32), 0, 128); // Unknown #endif n++; } WFIFOSET(fd,header+size*server_num); // create temporary auth entry CREATE(node, struct auth_node, 1); node->account_id = sd->account_id; node->login_id1 = sd->login_id1; node->login_id2 = sd->login_id2; node->sex = sd->sex; node->ip = ip; node->clienttype = sd->clienttype; idb_put(auth_db, sd->account_id, node); { struct online_login_data* data; // mark client as 'online' data = login_add_online_user(-1, sd->account_id); // schedule deletion of this node data->waiting_disconnect = add_timer(gettick()+AUTH_TIMEOUT, login_waiting_disconnect_timer, sd->account_id, 0); } }