/* * Copyright (C) Volition, Inc. 1999. All rights reserved. * * All source code herein is the property of Volition, Inc. You may not sell * or otherwise commercially exploit the source or things you created based on the * source. * */ /* * $Logfile: /Freespace2/code/Network/multi_kick.cpp $ * $Revision: 2.8 $ * $Date: 2005-10-10 17:21:07 $ * $Author: taylor $ * * $Log: not supported by cvs2svn $ * Revision 2.7 2005/07/13 03:25:59 Goober5000 * remove PreProcDefine #includes in FS2 * --Goober5000 * * Revision 2.6 2005/03/02 21:18:19 taylor * better support for Inferno builds (in PreProcDefines.h now, no networking support) * make sure NO_NETWORK builds are as friendly on Windows as it is on Linux/OSX * revert a timeout in Client.h back to the original value before Linux merge * * Revision 2.5 2005/02/04 10:12:31 taylor * merge with Linux/OSX tree - p0204 * * Revision 2.4 2004/07/26 20:47:42 Kazan * remove MCD complete * * Revision 2.3 2004/07/12 16:32:57 Kazan * MCD - define _MCD_CHECK to use memory tracking * * Revision 2.2 2004/03/05 09:02:02 Goober5000 * Uber pass at reducing #includes * --Goober5000 * * Revision 2.1 2002/08/01 01:41:07 penguin * The big include file move * * Revision 2.0 2002/06/03 04:02:26 penguin * Warpcore CVS sync * * Revision 1.1 2002/05/02 18:03:11 mharris * Initial checkin - converted filenames and includes to lower case * * * 8 10/13/99 3:51p Jefff * fixed unnumbered XSTRs * * 7 3/10/99 6:50p Dave * Changed the way we buffer packets for all clients. Optimized turret * fired packets. Did some weapon firing optimizations. * * 6 3/09/99 6:24p Dave * More work on object update revamping. Identified several sources of * unnecessary bandwidth. * * 5 11/19/98 8:03a Dave * Full support for D3-style reliable sockets. Revamped packet lag/loss * system, made it receiver side and at the lowest possible level. * * 4 11/17/98 11:12a Dave * Removed player identification by address. Now assign explicit id #'s. * * 3 11/05/98 5:55p Dave * Big pass at reducing #includes * * 2 10/07/98 10:53a Dave * Initial checkin. * * 1 10/07/98 10:50a Dave * * 16 9/15/98 7:24p Dave * Minor UI changes. Localized bunch of new text. * * 15 9/11/98 5:53p Dave * Final revisions to kick system changes. * * 14 9/11/98 5:08p Dave * More tweaks to kick notification system. * * 13 9/11/98 4:14p Dave * Fixed file checksumming of < file_size. Put in more verbose kicking and * PXO stats store reporting. * * 12 6/13/98 9:32p Mike * Kill last character in file which caused "Find in Files" to report the * file as "not a text file." * * 11 6/13/98 6:01p Hoffoss * Externalized all new (or forgot to be added) strings to all the code. * * 10 4/23/98 6:18p Dave * Store ETS values between respawns. Put kick feature in the text * messaging system. Fixed text messaging system so that it doesn't * process or trigger ship controls. Other UI fixes. * * 9 4/04/98 4:22p Dave * First rev of UDP reliable sockets is done. Seems to work well if not * overly burdened. * * 8 4/03/98 1:03a Dave * First pass at unreliable guaranteed delivery packets. * * 7 4/01/98 11:19p Dave * Put in auto-loading of xferred pilot pic files. Grey out background * behind pinfo popup. Put a chatbox message in when players are kicked. * Moved mission title down in briefing. Other ui fixes. * * 6 3/30/98 6:27p Dave * Put in a more official set of multiplayer options, including a system * for distributing netplayer and netgame settings. * * 5 3/24/98 5:00p Dave * Fixed several ui bugs. Put in pre and post voice stream playback sound * fx. Put in error specific popups for clients getting dropped from games * through actions other than their own. * * 4 3/18/98 5:52p Dave * Put in netgame password popup. Numerous ui changes. Laid groundwork for * streamed multi_voice data. * * 3 3/17/98 5:29p Dave * Minor bug fixes in player select menu. Solidified mp joining process. * Made furball mode support ingame joiners and dropped players correctly. * * 2 3/15/98 4:17p Dave * Fixed oberver hud problems. Put in handy netplayer macros. Reduced size * of network orientation matrices. * * 1 2/12/98 4:38p Dave * Multiplayer kick functionality * * $NoKeywords: $ */ #include "globalincs/pstypes.h" #include "network/multi.h" #include "network/multi_kick.h" #include "network/multimsgs.h" #include "network/multiutil.h" #include "freespace2/freespace.h" #include "playerman/player.h" #include "io/timer.h" // ---------------------------------------------------------------------------------- // KICK DEFINES/VARS // #define MULTI_KICK_RESPONSE_TIME 4000 // if someone who has been kicked has not responded in this time, disconnect him hard #define MAX_BAN_SLOTS 30 net_addr Multi_kick_ban_slots[MAX_BAN_SLOTS]; // banned addresses int Multi_kick_num_ban_slots; // the # of banned addresses // ---------------------------------------------------------------------------------- // KICK FORWARD DECLARATIONS // // send a player kick packet void send_player_kick_packet(int player_index, int ban = 1, int reason = KICK_REASON_NORM); // process a player kick packet void process_player_kick_packet(ubyte *data, header *hinfo); // add a net address to the banned list void multi_kick_add_ban(net_addr *addr); // can the given player perform a kick int multi_kick_can_kick(net_player *player); // ---------------------------------------------------------------------------------- // KICK FUNCTIONS // // initialize all kicking details (ban lists, etc). it is safe to call this function at any time void multi_kick_init() { // blast all the ban slots memset(Multi_kick_ban_slots,0,sizeof(net_addr)*MAX_BAN_SLOTS); Multi_kick_num_ban_slots = 0; } // process all kick details (disconnecting players who have been kicked but haven't closed their socket) void multi_kick_process() { int idx; // if i'm not the server, don't do anything if(!(Net_player->flags & NETINFO_FLAG_AM_MASTER)){ return; } // disconnect any kicked players who have timed out on leaving for(idx=0;idxflags & NETINFO_FLAG_AM_MASTER){ // if we're supposed to ban him, add his address to the banned list if(ban){ multi_kick_add_ban(&Net_players[player_index].p_info.addr); } // mark him as having been kicked Net_players[player_index].flags |= NETINFO_FLAG_KICKED; // set his kick timestamp and send him a leave game packet Net_players[player_index].s_info.kick_timestamp = timestamp(MULTI_KICK_RESPONSE_TIME); Net_players[player_index].s_info.kick_reason = reason; send_leave_game_packet(Net_players[player_index].player_id, reason, &Net_players[player_index]); // tell everyone else that he was kicked send_leave_game_packet(Net_players[player_index].player_id, reason); // wait until he either shuts his connection down or he times out) // add the string to the chatbox and the hud (always safe - if it is not inited, nothing bad will happen) char str[512]; memset(str, 0, 512); sprintf(str, XSTR("", 1501), Net_players[player_index].m_player->callsign); multi_display_chat_msg(str, player_index, 0); } // otherwise, we should send the packet indicating that this guy should be kicked else { send_player_kick_packet(player_index, ban, reason); } } } // is this net address currently kicked and banded int multi_kick_is_banned(net_addr *addr) { int idx; // traverse the banned list for(idx=0;idxcallsign,Dc_arg)==0)){ player_num = idx; break; } } // if we didn't find the player, notify of the results if(player_num == -1){ dc_printf("Could not find player %s to kick!",Dc_arg); } // if we found the guy, then try and kick him else { multi_kick_player(player_num); } } // fill in the passed string with the appropriate "kicked" string void multi_kick_get_text(net_player *pl, int reason, char *str) { // safety net if((pl == NULL) || (pl->m_player == NULL)){ strcpy(str, NOX("")); } switch(reason){ case KICK_REASON_BAD_XFER: sprintf(str, XSTR("<%s was kicked because of mission file xfer failure>", 1003), pl->m_player->callsign); break; case KICK_REASON_CANT_XFER: sprintf(str, XSTR("<%s was kicked for not having builtin mission %s>", 1004), pl->m_player->callsign, Game_current_mission_filename); break; case KICK_REASON_INGAME_ENDED: sprintf(str, XSTR("<%s was kicked for ingame joining an ended game>",1005), pl->m_player->callsign); break; default: sprintf(str, XSTR("<%s was kicked>",687), pl->m_player->callsign); break; } } // ---------------------------------------------------------------------------------- // KICK FORWARD DEFINITIONS // // add a net address to the banned list void multi_kick_add_ban(net_addr *addr) { // if we still have any slots left if(Multi_kick_num_ban_slots < (MAX_BAN_SLOTS - 1)){ memcpy(&Multi_kick_ban_slots[Multi_kick_num_ban_slots++],addr,sizeof(net_addr)); } } // ---------------------------------------------------------------------------------- // KICK PACKET HANDLERS // // send a player kick packet void send_player_kick_packet(int player_index, int ban, int reason) { ubyte data[MAX_PACKET_SIZE]; int packet_size = 0; BUILD_HEADER(KICK_PLAYER); // add the address of the player to be kicked ADD_SHORT(Net_players[player_index].player_id); // indicate if he should be banned ADD_INT(ban); ADD_INT(reason); // send the request to the server multi_io_send_reliable(Net_player, data, packet_size); } // process a player kick packet void process_player_kick_packet(ubyte *data, header *hinfo) { int player_num,from_player,ban,reason; short player_id; int offset = HEADER_LENGTH; // get the address of the guy who is to be kicked GET_SHORT(player_id); GET_INT(ban); GET_INT(reason); player_num = find_player_id(player_id); PACKET_SET_SIZE(); // only the server should ever receive a request to kick a guy Assert(Net_player->flags & NETINFO_FLAG_AM_MASTER); // determine who sent the packet from_player = find_player_id(hinfo->id); // check to see if this guy is allowed to make such a request if((from_player == -1) || !multi_kick_can_kick(&Net_players[from_player]) ){ nprintf(("Network","Received a kick request from an invalid player!!\n")); } // otherwise, process the request fully else { // make sure we have a valid player to kick if(player_num == -1){ nprintf(("Network","Received request to kick an unknown player!\n")); } else { // will handle all the rest of the details multi_kick_player(player_num,ban,reason); } } } // can the given player perform a kick int multi_kick_can_kick(net_player *player) { // only host or server can kick if((player->flags & NETINFO_FLAG_AM_MASTER) || (player->flags & NETINFO_FLAG_GAME_HOST)){ return 1; } // this guy cannot kick return 0; }