int netserver_drop(NETSERVER *s, int client_id, const char *reason) { /* TODO: insert lots of checks here */ NETADDR addr; netserver_client_addr(s, client_id, &addr); dbg_msg("net_server", "client dropped. cid=%d ip=%d.%d.%d.%d reason=\"%s\"", client_id, addr.ip[0], addr.ip[1], addr.ip[2], addr.ip[3], reason ); conn_disconnect(&s->slots[client_id].conn, reason); if(s->del_client) s->del_client(client_id, s->user_ptr); return 0; }
int netserver_drop(NETSERVER *s, int client_id, const char *reason) { /* TODO: insert lots of checks here */ NETADDR addr; netserver_client_addr(s, client_id, &addr); dbg_msg("Client", "Player: %s Disconnected.",server_clientname(client_id)); dbg_msg("Client", "Cid: %d Disconnected. IP: %d.%d.%d.%d reason: \"%s\"", client_id, addr.ip[0], addr.ip[1], addr.ip[2], addr.ip[3], reason ); if(s->del_client) s->del_client(client_id, s->user_ptr); conn_disconnect(&s->slots[client_id].conn, reason); return 0; }
static void server_process_client_packet(NETCHUNK *packet) { int cid = packet->client_id; NETADDR addr; int sys; int msg = msg_unpack_start(packet->data, packet->data_size, &sys); if(clients[cid].state == SRVCLIENT_STATE_AUTH) { if(sys && msg == NETMSG_INFO) { char version[64]; const char *password; str_copy(version, msg_unpack_string(), 64); if(strcmp(version, mods_net_version()) != 0) { /* OH F**K! wrong version, drop him */ char reason[256]; str_format(reason, sizeof(reason), "wrong version. server is running '%s' and client '%s'.", mods_net_version(), version); netserver_drop(net, cid, reason); return; } str_copy(clients[cid].name, msg_unpack_string(), MAX_NAME_LENGTH); str_copy(clients[cid].clan, msg_unpack_string(), MAX_CLANNAME_LENGTH); password = msg_unpack_string(); if(config.password[0] != 0 && strcmp(config.password, password) != 0) { /* wrong password */ netserver_drop(net, cid, "wrong password"); return; } clients[cid].state = SRVCLIENT_STATE_CONNECTING; server_send_map(cid); } } else { if(sys) { /* system message */ if(msg == NETMSG_REQUEST_MAP_DATA) { int chunk = msg_unpack_int(); int chunk_size = 1024-128; int offset = chunk * chunk_size; int last = 0; /* drop faulty map data requests */ if(chunk < 0 || offset > current_map_size) return; if(offset+chunk_size >= current_map_size) { chunk_size = current_map_size-offset; if(chunk_size < 0) chunk_size = 0; last = 1; } msg_pack_start_system(NETMSG_MAP_DATA, MSGFLAG_VITAL|MSGFLAG_FLUSH); msg_pack_int(last); msg_pack_int(current_map_size); msg_pack_int(chunk_size); msg_pack_raw(¤t_map_data[offset], chunk_size); msg_pack_end(); server_send_msg(cid); if(config.debug) dbg_msg("server", "sending chunk %d with size %d", chunk, chunk_size); } else if(msg == NETMSG_READY) { if(clients[cid].state == SRVCLIENT_STATE_CONNECTING) { netserver_client_addr(net, cid, &addr); dbg_msg("server", "player is ready. cid=%x ip=%d.%d.%d.%d", cid, addr.ip[0], addr.ip[1], addr.ip[2], addr.ip[3] ); clients[cid].state = SRVCLIENT_STATE_READY; mods_connected(cid); } } else if(msg == NETMSG_ENTERGAME) { if(clients[cid].state == SRVCLIENT_STATE_READY) { netserver_client_addr(net, cid, &addr); dbg_msg("server", "player has entered the game. cid=%x ip=%d.%d.%d.%d", cid, addr.ip[0], addr.ip[1], addr.ip[2], addr.ip[3] ); clients[cid].state = SRVCLIENT_STATE_INGAME; mods_client_enter(cid); } } else if(msg == NETMSG_INPUT) { int tick, size, i; CLIENT_INPUT *input; int64 tagtime; clients[cid].last_acked_snapshot = msg_unpack_int(); tick = msg_unpack_int(); size = msg_unpack_int(); /* check for errors */ if(msg_unpack_error() || size/4 > MAX_INPUT_SIZE) return; if(clients[cid].last_acked_snapshot > 0) clients[cid].snap_rate = SRVCLIENT_SNAPRATE_FULL; if(snapstorage_get(&clients[cid].snapshots, clients[cid].last_acked_snapshot, &tagtime, 0, 0) >= 0) clients[cid].latency = (int)(((time_get()-tagtime)*1000)/time_freq()); /* add message to report the input timing */ /* skip packets that are old */ if(tick > clients[cid].last_input_tick) { int time_left = ((server_tick_start_time(tick)-time_get())*1000) / time_freq(); msg_pack_start_system(NETMSG_INPUTTIMING, 0); msg_pack_int(tick); msg_pack_int(time_left); msg_pack_end(); server_send_msg(cid); } clients[cid].last_input_tick = tick; input = &clients[cid].inputs[clients[cid].current_input]; if(tick <= server_tick()) tick = server_tick()+1; input->game_tick = tick; for(i = 0; i < size/4; i++) input->data[i] = msg_unpack_int(); mem_copy(clients[cid].latestinput.data, input->data, MAX_INPUT_SIZE*sizeof(int)); clients[cid].current_input++; clients[cid].current_input %= 200; /* call the mod with the fresh input data */ if(clients[cid].state == SRVCLIENT_STATE_INGAME) mods_client_direct_input(cid, clients[cid].latestinput.data); } else if(msg == NETMSG_RCON_CMD) { const char *cmd = msg_unpack_string(); if(msg_unpack_error() == 0 && clients[cid].authed) { dbg_msg("server", "cid=%d rcon='%s'", cid, cmd); console_execute_line(cmd); } } else if(msg == NETMSG_RCON_AUTH) { const char *pw; msg_unpack_string(); /* login name, not used */ pw = msg_unpack_string(); if(msg_unpack_error() == 0) { if(config.sv_rcon_password[0] == 0) { server_send_rcon_line(cid, "No rcon password set on server. Set sv_rcon_password to enable the remote console."); } else if(strcmp(pw, config.sv_rcon_password) == 0) { msg_pack_start_system(NETMSG_RCON_AUTH_STATUS, MSGFLAG_VITAL); msg_pack_int(1); msg_pack_end(); server_send_msg(cid); clients[cid].authed = 1; server_send_rcon_line(cid, "Authentication successful. Remote console access granted."); dbg_msg("server", "cid=%d authed", cid); } else { server_send_rcon_line(cid, "Wrong password."); } } } else if(msg == NETMSG_PING) { msg_pack_start_system(NETMSG_PING_REPLY, 0); msg_pack_end(); server_send_msg(cid); } else { char hex[] = "0123456789ABCDEF"; char buf[512]; int b; for(b = 0; b < packet->data_size && b < 32; b++) { buf[b*3] = hex[((const unsigned char *)packet->data)[b]>>4]; buf[b*3+1] = hex[((const unsigned char *)packet->data)[b]&0xf]; buf[b*3+2] = ' '; buf[b*3+3] = 0; } dbg_msg("server", "strange message cid=%d msg=%d data_size=%d", cid, msg, packet->data_size); dbg_msg("server", "%s", buf); } } else { /* game message */ if(clients[cid].state >= SRVCLIENT_STATE_READY) mods_message(msg, cid); } }