void handle_accept(tcp_connection::pointer new_connection, const boost::system::error_code& error) { if (!error) { new_connection->set_parser(default_parser_); new_connection->start(); } start_accept(); }
/*! * \brief Parse from Client * * \author Fimbulwinter Development Team * \author GreenBox * \date 08/12/11 * **/ int CharServer::parse_from_client(tcp_connection::pointer cl) { CharSessionData *csd = ((CharSessionData *)cl->get_data()); if (cl->flags.eof) { if (csd && csd->auth && auth_conn_ok) { WFIFOHEAD(auth_conn,6); WFIFOW(auth_conn,0) = INTER_CA_SET_ACC_OFF; WFIFOL(auth_conn,2) = csd->account_id; auth_conn->send_buffer(6); } set_char_offline(csd->account_id, -1); if (csd) delete csd; ShowInfo("Closed connection from '"CL_WHITE"%s"CL_RESET"'.\n", cl->socket().remote_endpoint().address().to_string().c_str()); cl->do_close(); return 0; } while(RFIFOREST(cl) >= 2) { unsigned short cmd = RFIFOW(cl, 0); #define FIFOSD_CHECK(rest) { if(RFIFOREST(cl) < rest) return 0; if (csd==NULL || !csd->auth) { cl->skip(rest); return 0; } } switch (cmd) { case HEADER_CH_SELECT_CHAR: FIFOSD_CHECK(3); { int slot = RFIFOB(cl,2); int char_id; CharData cd; cl->skip(3); { statement s = (database->prepare << "SELECT `char_id` FROM `char` WHERE `account_id`=:a AND `char_num`=:s", use(csd->account_id), use(slot), into(char_id)); s.execute(true); if (s.get_affected_rows() <= 0) { WFIFOPACKET(cl, spacket, HC_REFUSE_ENTER); spacket->error_code = 0; cl->send_buffer(sizeof(struct PACKET_HC_REFUSE_ENTER)); } } chars->load_char(char_id, cd, true); int server = -1; if (map_to_zone.count(cd.last_point.map)) server = map_to_zone[cd.last_point.map]; if (server < 0) { // TODO: Find for major city WFIFOPACKET(cl, spacket, SC_NOTIFY_BAN); spacket->error_code = 1; cl->send_buffer(sizeof(struct PACKET_SC_NOTIFY_BAN)); break; } auth_nodes[csd->account_id].sex = csd->sex; auth_nodes[csd->account_id].char_id = char_id; auth_nodes[csd->account_id].gmlevel = csd->gmlevel; auth_nodes[csd->account_id].login_id1 = csd->login_id1; auth_nodes[csd->account_id].login_id2 = csd->login_id2; auth_nodes[csd->account_id].expiration_time = csd->expiration_time; WFIFOPACKET(cl, spacket, HC_NOTIFY_ZONESVR); spacket->char_id = char_id; maps.copy_map_name_ext((char*)spacket->map_name, cd.last_point.map); spacket->addr.ip = htonl(servers[server].addr.to_ulong()); spacket->addr.port = servers[server].port; cl->send_buffer(sizeof(struct PACKET_HC_NOTIFY_ZONESVR)); } break; case HEADER_CH_REQUEST_DEL_TIMER: FIFOSD_CHECK(6); delete2_req(cl, csd); cl->skip(6); break; case HEADER_CH_ACCEPT_DEL_REQ: FIFOSD_CHECK(12); delete2_accept(cl, csd); cl->skip(6); break; case HEADER_CH_CANCEL_DEL_REQ: FIFOSD_CHECK(6); delete2_cancel(cl, csd); cl->skip(6); break; case HEADER_CH_DELETE_CHAR: case HEADER_CH_DELETE_CHAR2: if (cmd == HEADER_CH_DELETE_CHAR) FIFOSD_CHECK(sizeof(struct PACKET_CH_DELETE_CHAR)); if (cmd == HEADER_CH_DELETE_CHAR2) FIFOSD_CHECK(sizeof(struct PACKET_CH_DELETE_CHAR2)); { int cid = RFIFOL(cl,2); char email[40]; memcpy(email, RFIFOP(cl,6), 40); cl->skip((cmd == HEADER_CH_DELETE_CHAR) ? sizeof(struct PACKET_CH_DELETE_CHAR) : sizeof(struct PACKET_CH_DELETE_CHAR2)); if (_strcmpi(email, csd->email) != 0 && (strcmp("*****@*****.**", csd->email) || (strcmp("*****@*****.**", email) && strcmp("", email)))) { WFIFOPACKET(cl, spacket, HC_REFUSE_DELETECHAR); spacket->error_code = 0; cl->send_buffer(sizeof(struct PACKET_HC_REFUSE_DELETECHAR)); break; } bool found = false; int i, ch; for (i = 0; i < MAX_CHARS; i++) { if (csd->found_char[i] == cid) { found = true; break; } } if (!found) { WFIFOPACKET(cl, spacket, HC_REFUSE_DELETECHAR); spacket->error_code = 0; cl->send_buffer(sizeof(struct PACKET_HC_REFUSE_DELETECHAR)); break; } else { for(ch = i; ch < MAX_CHARS - 1; ch++) csd->found_char[ch] = csd->found_char[ch+1]; csd->found_char[MAX_CHARS - 1] = -1; if (!chars->delete_char(cid)) { WFIFOPACKET(cl, spacket, HC_REFUSE_DELETECHAR); spacket->error_code = 0; cl->send_buffer(sizeof(struct PACKET_HC_REFUSE_DELETECHAR)); break; } WFIFOPACKET(cl, spacket, HC_ACCEPT_DELETECHAR); cl->send_buffer(sizeof(struct PACKET_HC_ACCEPT_DELETECHAR)); } } break; case HEADER_CH_MAKE_CHAR: FIFOSD_CHECK(sizeof(struct PACKET_CH_MAKE_CHAR)); { TYPECAST_PACKET(RFIFOP(cl,0),rpacket,CH_MAKE_CHAR); // TODO: Check create char disabled int i = create_char(csd, (char*)rpacket->name,rpacket->str,rpacket->agi,rpacket->vit,rpacket->int_,rpacket->dex,rpacket->luk,rpacket->char_slot,rpacket->head_color,rpacket->head_style); //'Charname already exists' (-1), 'Char creation denied' (-2) and 'You are underaged' (-3) if (i < 0) { WFIFOPACKET(cl, spacket, HC_REFUSE_MAKECHAR); switch (i) { case -1: spacket->error_code = 0x00; break; case -2: spacket->error_code = 0xFF; break; case -3: spacket->error_code = 0x01; break; } cl->send_buffer(sizeof(struct PACKET_HC_REFUSE_MAKECHAR)); } else { // retrieve data CharData char_dat; memset(&char_dat, 0, sizeof(CharData)); chars->load_char(i, char_dat, false); //Only the short data is needed. // send to player WFIFOPACKET(cl, spacket, HC_ACCEPT_MAKECHAR); char_to_buf(&spacket->charinfo, &char_dat); cl->send_buffer(sizeof(struct PACKET_HC_ACCEPT_MAKECHAR)); // add new entry to the chars list for (int n = 0; n < MAX_CHARS; n++) { if(csd->found_char[n] == -1) csd->found_char[n] = i; // the char_id of the new char } } cl->skip(sizeof(struct PACKET_CH_MAKE_CHAR)); } break; case HEADER_CH_ENTER_CHECKBOT: FIFOSD_CHECK(sizeof(struct PACKET_CH_ENTER_CHECKBOT)); { WFIFOPACKET(cl, spacket, HC_CHECKBOT_RESULT); spacket->packet_len = sizeof(struct PACKET_HC_CHECKBOT_RESULT); spacket->result = 1; cl->send_buffer(spacket->packet_len); cl->skip(TYPECAST_PACKET_ONCE(RFIFOP(cl,0), CH_ENTER_CHECKBOT)->packet_len); } break; case HEADER_CH_CHECKBOT: FIFOSD_CHECK(sizeof(struct PACKET_CH_CHECKBOT)); { WFIFOPACKET(cl, spacket, HC_CHECKBOT_RESULT); spacket->packet_len = sizeof(struct PACKET_HC_CHECKBOT_RESULT); spacket->result = 1; cl->send_buffer(spacket->packet_len); cl->skip(TYPECAST_PACKET_ONCE(RFIFOP(cl,0), CH_CHECKBOT)->packet_len); } break; case HEADER_CH_ENTER: if(RFIFOREST(cl) < sizeof(struct PACKET_CH_ENTER)) return 0; { int account_id = RFIFOL(cl,2); unsigned int login_id1 = RFIFOL(cl,6); unsigned int login_id2 = RFIFOL(cl,10); char sex = RFIFOB(cl,16); cl->skip(sizeof(struct PACKET_CH_ENTER)); if (csd) { break; } csd = new CharSessionData(); csd->account_id = account_id; csd->login_id1 = login_id1; csd->login_id2 = login_id2; csd->sex = sex; csd->auth = false; csd->cl = cl; cl->set_data((char*)csd); WFIFOHEAD(cl, 4); WFIFOL(cl,0) = account_id; cl->send_buffer(4); if (auth_nodes.count(account_id) && auth_nodes[account_id].login_id1 == login_id1 && auth_nodes[account_id].login_id2 == login_id2) { auth_nodes.erase(account_id); auth_ok(cl, csd); } else { if (auth_conn_ok) { WFIFOHEAD(auth_conn,19); WFIFOW(auth_conn,0) = INTER_CA_AUTH; WFIFOL(auth_conn,2) = csd->account_id; WFIFOL(auth_conn,6) = csd->login_id1; WFIFOL(auth_conn,10) = csd->login_id2; WFIFOB(auth_conn,14) = csd->sex; WFIFOL(auth_conn,15) = cl->tag(); auth_conn->send_buffer(19); } else { WFIFOPACKET(cl, spacket, HC_REFUSE_ENTER); spacket->error_code = 0; cl->send_buffer(sizeof(struct PACKET_HC_REFUSE_ENTER)); } } } break; case HEADER_PING: if (RFIFOREST(cl) < sizeof(PACKET_PING)) return 0; cl->skip(sizeof(PACKET_PING)); break; case INTER_ZC_LOGIN: if (RFIFOREST(cl) < 60) return 0; { char *user = (char*)RFIFOP(cl, 2); char *pass = (char*)RFIFOP(cl, 26); if (strcmp(user, config.inter_login_user.c_str()) || strcmp(pass, config.inter_login_pass.c_str())) { WFIFOHEAD(cl, 3); WFIFOW(cl, 0) = INTER_CZ_LOGIN_REPLY; WFIFOB(cl, 2) = 1; cl->send_buffer(3); } else { int id = cl->tag(); servers[id].cl = cl; servers[id].addr = address_v4(ntohl(RFIFOL(cl, 54))); servers[id].port = ntohs(RFIFOW(cl, 58)); servers[id].users = 0; cl->set_parser(&CharServer::parse_from_zone); cl->flags.server = 1; cl->realloc_fifo(FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK); WFIFOHEAD(cl, 3); WFIFOW(cl, 0) = INTER_CZ_LOGIN_REPLY; WFIFOB(cl, 2) = 0; cl->send_buffer(3); } cl->skip(60); } break; default: ShowWarning("Unknown packet 0x%04x sent from %s, closing connection.\n", cmd, cl->socket().remote_endpoint().address().to_string().c_str()); cl->set_eof(); return 0; } } return 0; }