/*========================================== * *------------------------------------------*/ int chrif_parse(int fd) { int packet_len, cmd; // only process data from the char-server if (fd != char_fd) { ShowDebug("chrif_parse: Disconnecting invalid session #%d (is not the char-server)\n", fd); do_close(fd); return 0; } if (session[fd]->flag.eof) { if (chrif_connected == 1) chrif_disconnect(fd); do_close(fd); return 0; } while (RFIFOREST(fd) >= 2) { cmd = RFIFOW(fd,0); if (cmd < 0x2af8 || cmd >= 0x2af8 + ARRAYLENGTH(packet_len_table) || packet_len_table[cmd-0x2af8] == 0) { int r = intif_parse(fd); // intifに渡す if (r == 1) continue; // intifで処理した if (r == 2) return 0; // intifで処理したが、データが足りない ShowWarning("chrif_parse: session #%d, intif_parse failed (unrecognized command 0x%.4x).\n", fd, cmd); set_eof(fd); return 0; } packet_len = packet_len_table[cmd-0x2af8]; if (packet_len == -1) { // dynamic-length packet, second WORD holds the length if (RFIFOREST(fd) < 4) return 0; packet_len = RFIFOW(fd,2); } if ((int)RFIFOREST(fd) < packet_len) return 0; //ShowDebug("Received packet 0x%4x (%d bytes) from char-server (connection %d)\n", RFIFOW(fd,0), packet_len, fd); switch(cmd) { case 0x2af9: chrif_connectack(fd); break; case 0x2afb: chrif_sendmapack(fd); break; case 0x2afd: chrif_authok(fd); break; case 0x2b00: map_setusers(RFIFOL(fd,2)); chrif_keepalive(fd); break; case 0x2b03: clif_charselectok(RFIFOL(fd,2)); break; case 0x2b04: chrif_recvmap(fd); break; case 0x2b06: chrif_changemapserverack(RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOL(fd,14), RFIFOW(fd,18), RFIFOW(fd,20), RFIFOW(fd,22), RFIFOL(fd,24), RFIFOW(fd,28)); break; case 0x2b07: clif_updatemaxid(RFIFOL(fd,2), RFIFOL(fd,6)); break; case 0x2b09: map_addnickdb(RFIFOL(fd,2), (char*)RFIFOP(fd,6)); break; case 0x2b0b: chrif_changedgm(fd); break; case 0x2b0d: chrif_changedsex(fd); break; case 0x2b0f: chrif_char_ask_name_answer(RFIFOL(fd,2), (char*)RFIFOP(fd,6), RFIFOW(fd,30), RFIFOW(fd,32)); break; case 0x2b12: chrif_divorce(RFIFOL(fd,2), RFIFOL(fd,6)); break; case 0x2b13: chrif_accountdeletion(fd); break; case 0x2b14: chrif_accountban(fd); break; case 0x2b15: chrif_recvgmaccounts(fd); break; case 0x2b1b: chrif_recvfamelist(fd); break; case 0x2b1d: chrif_load_scdata(fd); break; case 0x2b1e: chrif_update_ip(fd); break; case 0x2b1f: chrif_disconnectplayer(fd); break; case 0x2b20: chrif_removemap(fd); break; case 0x2b21: chrif_save_ack(fd); break; case 0x2b22: chrif_updatefamelist_ack(fd); break; case 0x2b24: chrif_keepalive_ack(fd); break; default: ShowError("chrif_parse : unknown packet (session #%d): 0x%x. Disconnecting.\n", fd, cmd); set_eof(fd); return 0; } if (fd == char_fd) //There's the slight chance we lost the connection during parse, in which case this would segfault if not checked [Skotlex] RFIFOSKIP(fd, packet_len); } return 0; }
/*========================================== * *------------------------------------------ */ static void chrif_parse(Session *s) { assert (s == char_session); RecvResult rv = RecvResult::Complete; uint16_t packet_id; while (rv == RecvResult::Complete && packet_peek_id(s, &packet_id)) { switch (packet_id) { case 0x2af9: { Packet_Fixed<0x2af9> fixed; rv = recv_fpacket<0x2af9, 3>(s, fixed); if (rv != RecvResult::Complete) break; chrif_connectack(s, fixed); break; } case 0x2afa: { Packet_Fixed<0x2afa> fixed; rv = recv_fpacket<0x2afa, 10>(s, fixed); if (rv != RecvResult::Complete) break; ladmin_itemfrob(s, fixed); break; } case 0x2afb: { Packet_Fixed<0x2afb> fixed; rv = recv_fpacket<0x2afb, 27>(s, fixed); if (rv != RecvResult::Complete) break; chrif_sendmapack(s, fixed); break; } case 0x2afd: { Packet_Payload<0x2afd> payload; rv = recv_ppacket<0x2afd>(s, payload); if (rv != RecvResult::Complete) break; AccountId id = payload.account_id; int login_id2 = payload.login_id2; TimeT connect_until_time = payload.connect_until; short tmw_version = payload.packet_tmw_version; CharKey st_key = payload.char_key; CharData st_data = payload.char_data; pc_authok(id, login_id2, connect_until_time, tmw_version, &st_key, &st_data); break; } case 0x2afe: { Packet_Fixed<0x2afe> fixed; rv = recv_fpacket<0x2afe, 6>(s, fixed); if (rv != RecvResult::Complete) break; pc_authfail(fixed.account_id); break; } case 0x2b00: { Packet_Fixed<0x2b00> fixed; rv = recv_fpacket<0x2b00, 6>(s, fixed); if (rv != RecvResult::Complete) break; map_setusers(fixed.users); break; } case 0x2b03: { Packet_Fixed<0x2b03> fixed; rv = recv_fpacket<0x2b03, 7>(s, fixed); if (rv != RecvResult::Complete) break; clif_charselectok(account_to_block(fixed.account_id)); break; } case 0x2b04: { Packet_Head<0x2b04> head; std::vector<Packet_Repeat<0x2b04>> repeat; rv = recv_vpacket<0x2b04, 10, 16>(s, head, repeat); if (rv != RecvResult::Complete) break; chrif_recvmap(s, head, repeat); break; } case 0x2b06: { Packet_Fixed<0x2b06> fixed; rv = recv_fpacket<0x2b06, 44>(s, fixed); if (rv != RecvResult::Complete) break; chrif_changemapserverack(s, fixed); break; } case 0x2b0b: { Packet_Fixed<0x2b0b> fixed; rv = recv_fpacket<0x2b0b, 10>(s, fixed); if (rv != RecvResult::Complete) break; chrif_changedgm(s, fixed); break; } case 0x2b0d: { Packet_Fixed<0x2b0d> fixed; rv = recv_fpacket<0x2b0d, 7>(s, fixed); if (rv != RecvResult::Complete) break; chrif_changedsex(s, fixed); break; } case 0x2b0f: { Packet_Fixed<0x2b0f> fixed; rv = recv_fpacket<0x2b0f, 34>(s, fixed); if (rv != RecvResult::Complete) break; chrif_char_ask_name_answer(s, fixed); break; } case 0x2b11: { Packet_Head<0x2b11> head; std::vector<Packet_Repeat<0x2b11>> repeat; rv = recv_vpacket<0x2b11, 8, 36>(s, head, repeat); if (rv != RecvResult::Complete) break; chrif_accountreg2(s, head, repeat); break; } case 0x2b12: { Packet_Fixed<0x2b12> fixed; rv = recv_fpacket<0x2b12, 10>(s, fixed); if (rv != RecvResult::Complete) break; chrif_divorce(fixed.char_id, fixed.partner_id); break; } case 0x2b13: { Packet_Fixed<0x2b13> fixed; rv = recv_fpacket<0x2b13, 6>(s, fixed); if (rv != RecvResult::Complete) break; chrif_accountdeletion(s, fixed); break; } case 0x2b14: { Packet_Fixed<0x2b14> fixed; rv = recv_fpacket<0x2b14, 11>(s, fixed); if (rv != RecvResult::Complete) break; chrif_accountban(s, fixed); break; } case 0x2b15: { std::vector<Packet_Repeat<0x2b15>> repeat; rv = recv_packet_repeatonly<0x2b15, 4, 5>(s, repeat); if (rv != RecvResult::Complete) break; chrif_recvgmaccounts(s, repeat); break; } default: { RecvResult r = intif_parse(s, packet_id); if (r == RecvResult::Complete) break; if (r == RecvResult::Incomplete) return; if (battle_config.error_log) PRINTF("chrif_parse : unknown packet %d %d\n"_fmt, s, packet_id); s->set_eof(); return; } } } if (rv == RecvResult::Error) s->set_eof(); }