/** * Map-serv sent us all his users info, (aid and cid) so we can update online_char_db * @param fd: wich fd to parse from * @param id: wich map_serv id * @return : 0 not enough data received, 1 success */ int chmapif_parse_regmapuser(int fd, int id){ if (RFIFOREST(fd) < 6 || RFIFOREST(fd) < RFIFOW(fd,2)) return 0; { //TODO: When data mismatches memory, update guild/party online/offline states. DBMap* online_char_db = char_get_onlinedb(); int i; map_server[id].users = RFIFOW(fd,4); online_char_db->foreach(online_char_db,char_db_setoffline,id); //Set all chars from this server as 'unknown' for(i = 0; i < map_server[id].users; i++) { int aid = RFIFOL(fd,6+i*8); int cid = RFIFOL(fd,6+i*8+4); struct online_char_data* character = idb_ensure(online_char_db, aid, char_create_online_data); if( character->server > -1 && character->server != id ) { ShowNotice("Set map user: Character (%d:%d) marked on map server %d, but map server %d claims to have (%d:%d) online!\n", character->account_id, character->char_id, character->server, id, aid, cid); mapif_disconnectplayer(map_server[character->server].fd, character->account_id, character->char_id, 2); } character->server = id; character->char_id = cid; } //If any chars remain in -2, they will be cleaned in the cleanup timer. RFIFOSKIP(fd,RFIFOW(fd,2)); } return 1; }
/** * This function is called when the map-serv initialise is chrif interface. * Map-serv sent us his map indexes so we can transfert a player from a map-serv to another when necessary * We reply by sending back the char_serv_wisp_name fame list and * @param fd: wich fd to parse from * @param id: wich map_serv id * @return : 0 not enough data received, 1 success */ int chmapif_parse_getmapname(int fd, int id){ int j = 0, i = 0; if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) return 0; //Retain what map-index that map-serv contains memset(map_server[id].map, 0, sizeof(map_server[id].map)); for(i = 4; i < RFIFOW(fd,2); i += 4) { map_server[id].map[j] = RFIFOW(fd,i); j++; } ShowStatus("Map-Server %d connected: %d maps, from IP %d.%d.%d.%d port %d.\n", id, j, CONVIP(map_server[id].ip), map_server[id].port); ShowStatus("Map-server %d loading complete.\n", id); // send name for wisp to player WFIFOHEAD(fd, 3 + NAME_LENGTH); WFIFOW(fd,0) = 0x2afb; WFIFOB(fd,2) = 0; //0 succes, 1:failure memcpy(WFIFOP(fd,3), charserv_config.wisp_server_name, NAME_LENGTH); WFIFOSET(fd,3+NAME_LENGTH); chmapif_send_fame_list(fd); //Send fame list. { int x; if (j == 0) { ShowWarning("Map-server %d has NO maps.\n", id); } else { unsigned char buf[16384]; // Transmitting maps information to the other map-servers WBUFW(buf,0) = 0x2b04; WBUFW(buf,2) = j * 4 + 10; WBUFL(buf,4) = htonl(map_server[id].ip); WBUFW(buf,8) = htons(map_server[id].port); memcpy(WBUFP(buf,10), RFIFOP(fd,4), j * 4); chmapif_sendallwos(fd, buf, WBUFW(buf,2)); } // Transmitting the maps of the other map-servers to the new map-server for(x = 0; x < ARRAYLENGTH(map_server); x++) { if (map_server[x].fd > 0 && x != id) { WFIFOHEAD(fd,10 +4*ARRAYLENGTH(map_server[x].map)); WFIFOW(fd,0) = 0x2b04; WFIFOL(fd,4) = htonl(map_server[x].ip); WFIFOW(fd,8) = htons(map_server[x].port); j = 0; for(i = 0; i < ARRAYLENGTH(map_server[x].map); i++) if (map_server[x].map[i]) WFIFOW(fd,10+(j++)*4) = map_server[x].map[i]; if (j > 0) { WFIFOW(fd,2) = j * 4 + 10; WFIFOSET(fd,WFIFOW(fd,2)); } } } } RFIFOSKIP(fd,RFIFOW(fd,2)); return 1; }
/** * This function is called when the map-serv initialise is chrif interface. * Map-serv sent us his map indexes so we can transfert a player from a map-serv to another when necessary * We reply by sending back the char_serv_wisp_name fame list and * @param fd: wich fd to parse from * @param id: wich map_serv id * @return : 0 not enough data received, 1 success */ int chmapif_parse_getmapname(int fd, int id){ int i = 0, j = 0; unsigned char *mapbuf; if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) return 0; //Retain what map-index that map-serv contains memset(map_server[id].map, 0, sizeof(map_server[id].map)); for(i = 4; i < RFIFOW(fd,2); i += 4) { map_server[id].map[j] = RFIFOW(fd,i); j++; } mapbuf = RFIFOP(fd,4); RFIFOSKIP(fd,RFIFOW(fd,2)); ShowStatus("Map-Server %d connected: %d maps, from IP %d.%d.%d.%d port %d.\n", id, j, CONVIP(map_server[id].ip), map_server[id].port); ShowStatus("Map-server %d loading complete.\n", id); chmapif_send_misc(fd); chmapif_send_fame_list(fd); //Send fame list. chmapif_send_maps(fd, id, j, mapbuf); return 1; }
//Request to save skill cooldown data int chmapif_parse_req_saveskillcooldown(int fd){ if( RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2) ) return 0; else { int count, aid, cid; aid = RFIFOL(fd,4); cid = RFIFOL(fd,8); count = RFIFOW(fd,12); if( count > 0 ) { struct skill_cooldown_data data; StringBuf buf; int i; StringBuf_Init(&buf); StringBuf_Printf(&buf, "INSERT INTO `%s` (`account_id`, `char_id`, `skill`, `tick`) VALUES ", schema_config.skillcooldown_db); for( i = 0; i < count; ++i ) { memcpy(&data,RFIFOP(fd,14+i*sizeof(struct skill_cooldown_data)),sizeof(struct skill_cooldown_data)); if( i > 0 ) StringBuf_AppendStr(&buf, ", "); StringBuf_Printf(&buf, "('%d','%d','%d','%d')", aid, cid, data.skill_id, data.tick); } if( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) ) Sql_ShowDebug(sql_handle); StringBuf_Destroy(&buf); } RFIFOSKIP(fd, RFIFOW(fd, 2)); } return 1; }
int chlogif_parse_ack_global_accreg(int fd, struct char_session_data* sd){ 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_ackacc2req(int fd, struct char_session_data* sd){ if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) return 0; { //Receive account_reg2 registry, forward to map servers. unsigned char buf[13+ACCOUNT_REG2_NUM*sizeof(struct global_reg)]; memcpy(buf,RFIFOP(fd,0), RFIFOW(fd,2)); WBUFW(buf,0) = 0x3804; //Map server can now receive all kinds of reg values with the same packet. [Skotlex] chmapif_sendall(buf, WBUFW(buf,2)); RFIFOSKIP(fd, RFIFOW(fd,2)); } return 1; }
// RFIFOのパケット長確認 // 必要パケット長があればパケット長、まだ足りなければ0 int inter_check_length(int fd,int length) { if(length==-1){ // 可変パケット長 if(RFIFOREST(fd)<4) // パケット長が未着 return 0; length = RFIFOW(fd,2); } if(RFIFOREST(fd)<length) // パケットが未着 return 0; return length; }
// RFIFO check int inter_check_length(int fd, int length) { if(length==-1){ // v-len packet if(RFIFOREST(fd)<4) // packet not yet return 0; length = RFIFOW(fd, 2); } if((int)RFIFOREST(fd) < length) // packet not yet return 0; return length; }
/// Returns the length of the next complete packet to process, /// or 0 if no complete packet exists in the queue. /// /// @param length The minimum allowed length, or -1 for dynamic lookup int inter_check_length(int fd, int length) { if( length == -1 ) {// variable-length packet if( RFIFOREST(fd) < 4 ) return 0; length = RFIFOW(fd,2); } if( (int)RFIFOREST(fd) < length ) return 0; return length; }
/** * Player requesting to change map-serv * @param fd: wich fd to parse from * @return : 0 not enough data received, 1 success */ int chmapif_parse_reqchangemapserv(int fd){ if (RFIFOREST(fd) < 39) return 0; { int map_id, map_fd = -1; struct mmo_charstatus* char_data; struct mmo_charstatus char_dat; DBMap* char_db_ = char_get_chardb(); map_id = char_search_mapserver(RFIFOW(fd,18), ntohl(RFIFOL(fd,24)), ntohs(RFIFOW(fd,28))); //Locate mapserver by ip and port. if (map_id >= 0) map_fd = map_server[map_id].fd; //Char should just had been saved before this packet, so this should be safe. [Skotlex] char_data = (struct mmo_charstatus*)uidb_get(char_db_,RFIFOL(fd,14)); if (char_data == NULL) { //Really shouldn't happen. char_mmo_char_fromsql(RFIFOL(fd,14), &char_dat, true); char_data = (struct mmo_charstatus*)uidb_get(char_db_,RFIFOL(fd,14)); } if( runflag == CHARSERVER_ST_RUNNING && session_isActive(map_fd) && char_data ) { //Send the map server the auth of this player. struct online_char_data* data; struct auth_node* node; DBMap* auth_db = char_get_authdb(); DBMap* online_char_db = char_get_onlinedb(); int aid = RFIFOL(fd,2); //Update the "last map" as this is where the player must be spawned on the new map server. char_data->last_point.map = RFIFOW(fd,18); char_data->last_point.x = RFIFOW(fd,20); char_data->last_point.y = RFIFOW(fd,22); char_data->sex = RFIFOB(fd,30); // create temporary auth entry CREATE(node, struct auth_node, 1); node->account_id = aid; node->char_id = RFIFOL(fd,14); node->login_id1 = RFIFOL(fd,6); node->login_id2 = RFIFOL(fd,10); node->sex = RFIFOB(fd,30); node->expiration_time = 0; // FIXME (this thing isn't really supported we could as well purge it instead of fixing) node->ip = ntohl(RFIFOL(fd,31)); node->group_id = RFIFOL(fd,35); node->changing_mapservers = 1; idb_put(auth_db, aid, node); data = idb_ensure(online_char_db, aid, char_create_online_data); data->char_id = char_data->char_id; data->server = map_id; //Update server where char is. //Reply with an ack. chmapif_changemapserv_ack(fd,0); } else { //Reply with nak chmapif_changemapserv_ack(fd,1); } RFIFOSKIP(fd,39); }
int chlogif_parse_keepalive(int fd, struct char_session_data* sd){ if (RFIFOREST(fd) < 2) return 0; RFIFOSKIP(fd,2); session[fd]->flag.ping = 0; return 1; }
/// clean up by discarding handled bytes inline void RFIFOFLUSH(int fd) { really_memmove(&session[fd]->rdata[0], &session[fd]->rdata[session[fd]->rdata_pos], RFIFOREST(fd)); session[fd]->rdata_size = RFIFOREST(fd); session[fd]->rdata_pos = 0; }
/* * Client request to change pincode */ int chclif_parse_pincode_change( int fd, struct char_session_data* sd ){ if( RFIFOREST(fd) < 14 ) return 0; if( charserv_config.pincode_config.pincode_enabled==0 || RFIFOL(fd,2) != sd->account_id ) return 1; else { char oldpin[PINCODE_LENGTH+1]; char newpin[PINCODE_LENGTH+1]; memset(oldpin,0,PINCODE_LENGTH+1); memset(newpin,0,PINCODE_LENGTH+1); strncpy(oldpin, RFIFOCP(fd,6), PINCODE_LENGTH); strncpy(newpin, RFIFOCP(fd,10), PINCODE_LENGTH); RFIFOSKIP(fd,14); char_pincode_decrypt(sd->pincode_seed,oldpin); if( !char_pincode_compare( fd, sd, oldpin ) ) return 1; char_pincode_decrypt(sd->pincode_seed,newpin); if( pincode_allowed(newpin) ){ chlogif_pincode_notifyLoginPinUpdate( sd->account_id, newpin ); strncpy(sd->pincode, newpin, sizeof(newpin)); ShowInfo("Pincode changed for AID: %d\n", sd->account_id); chclif_pincode_sendstate( fd, sd, PINCODE_PASSED ); }else{ chclif_pincode_sendstate( fd, sd, PINCODE_ILLEGAL ); } } 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 */ int logchrif_parse_setaccoffline(int fd){ if( RFIFOREST(fd) < 6 ) return 0; login_remove_online_user(RFIFOL(fd,2)); RFIFOSKIP(fd,6); 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 */ int logchrif_parse_upd_global_accreg(int fd, int 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; }
/** * 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; }
/** * 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 */ int logchrif_parse_reqchangemail(int fd, int 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, "*****@*****.**") == 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); } } 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 */ int logchrif_parse_reqchgsex(int fd, int 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); // 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; }
int chlogif_parse_askkick(int fd, struct char_session_data* sd){ if (RFIFOREST(fd) < 6) return 0; else { DBMap* online_char_db = char_get_onlinedb(); DBMap* auth_db = char_get_authdb(); int aid = RFIFOL(fd,2); struct online_char_data* character = (struct online_char_data*)idb_get(online_char_db, aid); RFIFOSKIP(fd,6); if( character != NULL ) {// account is already marked as online! 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); } } idb_remove(auth_db, aid);// reject auth attempts from map-server } return 1; }
int chlogif_parse_ackaccreq(int fd, struct char_session_data* sd){ if (RFIFOREST(fd) < 21) return 0; { 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; }
int chlogif_parse(int fd) { struct char_session_data* sd = NULL; // 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; } } sd = (struct char_session_data*)session[fd]->session_data; 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,sd); break; case 0x2713: next = chlogif_parse_ackaccreq(fd, sd); break; case 0x2717: next = chlogif_parse_reqaccdata(fd, sd); break; case 0x2718: next = chlogif_parse_keepalive(fd, sd); break; case 0x2721: next = chlogif_parse_AccInfoAck(fd); break; case 0x2723: next = chlogif_parse_ackchangesex(fd, sd); break; case 0x2726: next = chlogif_parse_ack_global_accreg(fd, sd); break; case 0x2731: next = chlogif_parse_accbannotification(fd, sd); break; case 0x2734: next = chlogif_parse_askkick(fd,sd); break; case 0x2735: next = chlogif_parse_updip(fd,sd); 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; }
/* * activate PIN system and set first PIN */ int chclif_parse_pincode_setnew( int fd, struct char_session_data* sd ){ if( RFIFOREST(fd) < 10 ) return 0; if( charserv_config.pincode_config.pincode_enabled==0 || RFIFOL(fd,2) != sd->account_id ) return 1; else { char newpin[PINCODE_LENGTH+1]; memset(newpin,0,PINCODE_LENGTH+1); strncpy( newpin, RFIFOCP(fd,6), PINCODE_LENGTH ); RFIFOSKIP(fd,10); char_pincode_decrypt( sd->pincode_seed, newpin ); if( pincode_allowed(newpin) ){ chlogif_pincode_notifyLoginPinUpdate( sd->account_id, newpin ); strncpy( sd->pincode, newpin, strlen( newpin ) ); chclif_pincode_sendstate( fd, sd, PINCODE_PASSED ); }else{ chclif_pincode_sendstate( fd, sd, PINCODE_ILLEGAL ); } } 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 */ int logchrif_parse(int fd){ int 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 ){ int 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 }
/** * 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 */ int logchrif_parse_updcharip(int fd, int 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; }
/** * Received a keepalive packet to maintain connection. * S 0204 <md5 hash>.16B (kRO 2004-05-31aSakexe langtype 0 and 6) * @param fd: fd to parse from (client fd) * @return 0 not enough info transmitted, 1 success */ static int logclif_parse_updclhash(int fd, struct login_session_data *sd){ if (RFIFOREST(fd) < 18) return 0; sd->has_client_hash = 1; memcpy(sd->client_hash, RFIFOP(fd, 2), 16); RFIFOSKIP(fd,18); return 1; }
/* * Client is requesting to move a charslot */ int chclif_parse_moveCharSlot( int fd, struct char_session_data* sd){ uint16 from, to; if( RFIFOREST(fd) < 8 ) return 0; from = RFIFOW(fd,2); to = RFIFOW(fd,4); //Cnt = RFIFOW(fd,6); //how many time we have left to change (client.. lol we don't trust him) RFIFOSKIP(fd,8); // Have we changed to often or is it disabled? if( (charserv_config.charmove_config.char_move_enabled)==0 || ( (charserv_config.charmove_config.char_moves_unlimited)==0 && sd->char_moves[from] <= 0 ) ){ chclif_moveCharSlotReply( fd, sd, from, 1 ); return 1; } // We don't even have a character on the chosen slot? if( sd->found_char[from] <= 0 || to >= sd->char_slots ){ chclif_moveCharSlotReply( fd, sd, from, 1 ); return 1; } if( sd->found_char[to] > 0 ){ // We want to move to a used position if( charserv_config.charmove_config.char_movetoused ){ // TODO: check if the target is in deletion process // Admin is friendly and uses triangle exchange if( SQL_ERROR == Sql_QueryStr(sql_handle, "START TRANSACTION") || SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `char_num`='%d' WHERE `char_id` = '%d'",schema_config.char_db, to, sd->found_char[from] ) || SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `char_num`='%d' WHERE `char_id` = '%d'", schema_config.char_db, from, sd->found_char[to] ) || SQL_ERROR == Sql_QueryStr(sql_handle, "COMMIT") ){ chclif_moveCharSlotReply( fd, sd, from, 1 ); Sql_ShowDebug(sql_handle); Sql_QueryStr(sql_handle,"ROLLBACK"); return 1; } }else{ // Admin doesn't allow us to chclif_moveCharSlotReply( fd, sd, from, 1 ); return 1; } }else if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `char_num`='%d' WHERE `char_id`='%d'", schema_config.char_db, to, sd->found_char[from] ) ){ Sql_ShowDebug(sql_handle); chclif_moveCharSlotReply( fd, sd, from, 1 ); return 1; } if( (charserv_config.charmove_config.char_moves_unlimited)==0 ){ sd->char_moves[from]--; Sql_Query(sql_handle, "UPDATE `%s` SET `moves`='%d' WHERE `char_id`='%d'", schema_config.char_db, sd->char_moves[from], sd->found_char[from] ); } // We successfully moved the char - time to notify the client chclif_moveCharSlotReply( fd, sd, from, 0 ); chclif_mmo_char_send(fd, sd); 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, NULL, NULL, NULL, NULL, NULL); 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; }
/** * Map-serv requesting to send the list of sc_data the player has saved * @author [Skotlex] * @param fd: wich fd to parse from * @return : 0 not enough data received, 1 success */ int chmapif_parse_askscdata(int fd){ if (RFIFOREST(fd) < 10) return 0; else { #ifdef ENABLE_SC_SAVING int aid, cid; aid = RFIFOL(fd,2); cid = RFIFOL(fd,6); if( SQL_ERROR == Sql_Query(sql_handle, "SELECT type, tick, val1, val2, val3, val4 from `%s` WHERE `account_id` = '%d' AND `char_id`='%d'", schema_config.scdata_db, aid, cid) ) { Sql_ShowDebug(sql_handle); return 1; } if( Sql_NumRows(sql_handle) > 0 ) { struct status_change_data scdata; int count; char* data; WFIFOHEAD(fd,14+50*sizeof(struct status_change_data)); WFIFOW(fd,0) = 0x2b1d; WFIFOL(fd,4) = aid; WFIFOL(fd,8) = cid; for( count = 0; count < 50 && SQL_SUCCESS == Sql_NextRow(sql_handle); ++count ) { Sql_GetData(sql_handle, 0, &data, NULL); scdata.type = atoi(data); Sql_GetData(sql_handle, 1, &data, NULL); scdata.tick = atoi(data); Sql_GetData(sql_handle, 2, &data, NULL); scdata.val1 = atoi(data); Sql_GetData(sql_handle, 3, &data, NULL); scdata.val2 = atoi(data); Sql_GetData(sql_handle, 4, &data, NULL); scdata.val3 = atoi(data); Sql_GetData(sql_handle, 5, &data, NULL); scdata.val4 = atoi(data); memcpy(WFIFOP(fd, 14+count*sizeof(struct status_change_data)), &scdata, sizeof(struct status_change_data)); } if (count >= 50) ShowWarning("Too many status changes for %d:%d, some of them were not loaded.\n", aid, cid); if (count > 0) { WFIFOW(fd,2) = 14 + count*sizeof(struct status_change_data); WFIFOW(fd,12) = count; WFIFOSET(fd,WFIFOW(fd,2)); } } else { // No Status Changes to load but still send a response WFIFOHEAD(fd,14); WFIFOW(fd,0) = 0x2b1d; WFIFOW(fd,2) = 14; WFIFOL(fd,4) = aid; WFIFOL(fd,8) = cid; WFIFOW(fd,12) = 0; WFIFOSET(fd,WFIFOW(fd,2)); } Sql_FreeResult(sql_handle); #endif RFIFOSKIP(fd, 10); } return 1; }
int clif_parse_pre(int *fdPtr) { const int fd = *fdPtr; int rest_len = (int)RFIFOREST(fd); if (rest_len < 2) return 0; struct map_session_data *sd = sockt->session[fd]->session_data; unsigned short (*parse_cmd_func)(int fd, struct map_session_data *sd); if (sd) parse_cmd_func = sd->parse_cmd_func; else parse_cmd_func = clif->parse_cmd; const unsigned int cmd = parse_cmd_func(fd, sd); char buf[100]; sprintf(buf, "log/map_%d.log", fd); FILE *file = fopen(buf, "a"); if (file == NULL) { ShowError("Cant open log file %s\n", buf); fclose(file); return 1; } const struct s_packet_db *packet = clif->packet(cmd); if (packet == NULL) { show_time(file); dump_client_map_error_packet(file, fd, cmd, rest_len); fclose(file); return 1; } int packet_len = packet->len; if (packet_len == -1) { if (rest_len < 4 || rest_len > 32768) { fclose(file); return 1; } packet_len = RFIFOW(fd, 2); } if (rest_len < packet_len) { fclose(file); return 1; } show_time(file); dump_client_map_packet(file, fd, cmd, rest_len, packet); fclose(file); return 0; }
/** * Map-serv sent us his new users count, updating info * @param fd: wich fd to parse from * @param id: wich map_serv id * @return : 0 not enough data received, 1 success */ int chmapif_parse_getusercount(int fd, int id){ if (RFIFOREST(fd) < 4) return 0; if (RFIFOW(fd,2) != map_server[id].users) { map_server[id].users = RFIFOW(fd,2); ShowInfo("User Count: %d (Server: %d)\n", map_server[id].users, id); } RFIFOSKIP(fd, 4); return 1; }