From b1cb11e9225aea3d44e618f78662dba14d604cfd Mon Sep 17 00:00:00 2001 From: danij Date: Tue, 19 Sep 2006 23:02:34 +0000 Subject: [PATCH] Finalized high level implementation for improved security on execution of console commands sent over the net. We now know where the command came from before executing (i.e. local or remote) and also the invocation method used (e.g. remote client console input, DED file etc). However, due to the fact that the remote invocation method MUST be sent over the net - any truly dangerous ccmds should be marked as CMDF_CLIENT. In order to implement this a new PKT_COMMAND2 type has been added which obsoletes the old type. Due to these measures any commands sent using the old PKT_COMMAND type will NEVER be executed. --- doomsday/engine/api/dd_share.h | 16 +- doomsday/engine/portable/include/con_decl.h | 4 +- doomsday/engine/portable/include/con_main.h | 23 +- doomsday/engine/portable/include/net_main.h | 257 ++++++++++---------- doomsday/engine/portable/src/cl_main.c | 10 +- doomsday/engine/portable/src/con_bind.c | 4 +- doomsday/engine/portable/src/con_config.c | 4 +- doomsday/engine/portable/src/con_main.c | 197 +++++++++++---- doomsday/engine/portable/src/dd_main.c | 6 +- doomsday/engine/portable/src/gl_main.c | 4 +- doomsday/engine/portable/src/net_buf.c | 4 +- doomsday/engine/portable/src/net_main.c | 4 +- doomsday/engine/portable/src/p_mobj.c | 4 +- doomsday/engine/portable/src/r_sky.c | 4 +- doomsday/engine/portable/src/r_world.c | 10 +- doomsday/engine/portable/src/sv_main.c | 76 +++--- doomsday/engine/portable/src/sys_network.c | 25 +- doomsday/engine/portable/src/sys_system.c | 13 +- doomsday/engine/portable/src/ui_mpi.c | 6 +- doomsday/engine/portable/src/ui_panel.c | 6 +- 20 files changed, 401 insertions(+), 276 deletions(-) diff --git a/doomsday/engine/api/dd_share.h b/doomsday/engine/api/dd_share.h index 4ab598648f..0af6b313e9 100644 --- a/doomsday/engine/api/dd_share.h +++ b/doomsday/engine/api/dd_share.h @@ -18,7 +18,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, + * Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301 USA */ @@ -506,7 +506,7 @@ extern "C" { // The mouse wheel is considered two extra mouse buttons. #define DDMB_MWHEELUP 0x1000 #define DDMB_MWHEELDOWN 0x2000 - + #define DD_MICKEY_ACCURACY 1000 //------------------------------------------------------------------------ @@ -1129,13 +1129,14 @@ typedef enum blendmode_e { // Console command. typedef struct ccmd_s { char *name; - int (*func) (int src, int argc, char **argv); + int (*func) (byte src, int argc, char **argv); int flags; } ccmd_t; // Command sources (where the console command originated from) // These are sent with every (sub)ccmd so we can decide whether or not to execute. enum { + CMDS_UNKNOWN, CMDS_DDAY, // Sent by the engine CMDS_GAME, // Sent by the game dll CMDS_CONSOLE, // Sent via direct console input @@ -1143,13 +1144,11 @@ typedef enum blendmode_e { CMDS_CONFIG, // Sent via config file CMDS_PROFILE, // Sent via player profile CMDS_CMDLINE, // Sent via the command line - CMDS_DED, // Sent based on a def in a DED file eg (state->execute) - CMDS_PKT, // Sent from a client (in a packet) - CMDS_SPKT // Sent from the server (in a packet) + CMDS_DED // Sent based on a def in a DED file eg (state->execute) }; // Helper macro for defining console command functions. -#define DEFCC(name) int name(int src, int argc, char **argv) +#define DEFCC(name) int name(byte src, int argc, char **argv) // Console command usage flags. // (what method(s) CAN NOT be used to invoke a ccmd (used with the CMDS codes above)). @@ -1161,8 +1160,7 @@ typedef enum blendmode_e { #define CMDF_PROFILE 0x20 #define CMDF_CMDLINE 0x40 #define CMDF_DED 0x80 -#define CMDF_PKT 0x100 // Not implemented yet -#define CMDF_SPKT 0x200 // Not implemented yet +#define CMDF_CLIENT 0x100 // sent over the net from a client // Console variable flags. #define CVF_NO_ARCHIVE 0x1 // Not written in/read from the defaults file. diff --git a/doomsday/engine/portable/include/con_decl.h b/doomsday/engine/portable/include/con_decl.h index 31ab4a33c4..3d485f10cc 100644 --- a/doomsday/engine/portable/include/con_decl.h +++ b/doomsday/engine/portable/include/con_decl.h @@ -18,7 +18,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, + * Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301 USA */ @@ -41,7 +41,7 @@ { ccmd_t _c = { name, CCmd##fn, flags }; Con_AddCommand(&_c); } // A handy helper for declaring console commands. -#define D_CMD(x) int CCmd##x(int src, int argc, char **argv) +#define D_CMD(x) int CCmd##x(byte src, int argc, char **argv) /* * Macros for creating new console variables. diff --git a/doomsday/engine/portable/include/con_main.h b/doomsday/engine/portable/include/con_main.h index 39cf513acc..92376187a6 100644 --- a/doomsday/engine/portable/include/con_main.h +++ b/doomsday/engine/portable/include/con_main.h @@ -18,7 +18,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, + * Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301 USA */ @@ -32,19 +32,19 @@ #include #include "dd_share.h" -#define MAX_ARGS 256 +#define MAX_ARGS 256 typedef struct { - char cmdLine[2048]; - int argc; - char *argv[MAX_ARGS]; + char cmdLine[2048]; + int argc; + char *argv[MAX_ARGS]; } cmdargs_t; // A console buffer line. typedef struct { - int len; // This is the length of the line (no term). - char *text; // This is the text. - int flags; + int len; // This is the length of the line (no term). + char *text; // This is the text. + int flags; } cbline_t; // Console commands can set this when they need to return a custom value @@ -72,11 +72,12 @@ boolean Con_Responder(event_t *event); void Con_Drawer(void); void Con_DrawRuler(int y, int lineHeight, float alpha); void Con_Printf(const char *format, ...); -void Con_FPrintf(int flags, const char *format, ...); // Flagged printf. +void Con_FPrintf(int flags, const char *format, ...); // Flagged printf. void Con_SetFont(ddfont_t *cfont); cbline_t *Con_GetBufferLine(int num); -int Con_Execute(int src, const char *command, int silent); -int Con_Executef(int src, int silent, const char *command, ...); +int Con_Execute(byte src, const char *command, int silent, + boolean netCmd); +int Con_Executef(byte src, int silent, const char *command, ...); void Con_Message(const char *message, ...); void Con_Error(const char *error, ...); diff --git a/doomsday/engine/portable/include/net_main.h b/doomsday/engine/portable/include/net_main.h index 536db590cd..31cca39870 100644 --- a/doomsday/engine/portable/include/net_main.h +++ b/doomsday/engine/portable/include/net_main.h @@ -36,214 +36,215 @@ #include "p_mapdata.h" #include "con_decl.h" -#define BIT(x) (1 << (x)) +#define BIT(x) (1 << (x)) -#define NSP_BROADCAST -1 // For Net_SendBuffer. +#define NSP_BROADCAST -1 // For Net_SendBuffer. // Flags for console text from the server. // Change with server version? -#define SV_CONSOLE_FLAGS (CBLF_WHITE|CBLF_LIGHT|CBLF_GREEN) +#define SV_CONSOLE_FLAGS (CBLF_WHITE|CBLF_LIGHT|CBLF_GREEN) -#define PING_TIMEOUT 1000 // Ping timeout (ms). -#define MAX_PINGS 10 +#define PING_TIMEOUT 1000 // Ping timeout (ms). +#define MAX_PINGS 10 // The default bandwidth rating for new clients. -#define BWR_DEFAULT 40 +#define BWR_DEFAULT 40 // A modest acktime used by default for new clients (1 sec ping). -#define ACK_DEFAULT 1000 +#define ACK_DEFAULT 1000 -#define MONITORTICS 7 +#define MONITORTICS 7 -#define LOCALTICS 10 // Built ticcmds are stored here. -#define BACKUPTICS 70 // Two seconds worth of tics. +#define LOCALTICS 10 // Built ticcmds are stored here. +#define BACKUPTICS 70 // Two seconds worth of tics. // The number of mobjs that can be stored in the input/visible buffer. // The server won't send more mobjs than this. -#define MAX_CLMOBJS 80 +#define MAX_CLMOBJS 80 -// Packet types. +// Packet types. // PKT = sent by anybody // PSV = sent by server // PCL = sent by client enum { - // Messages and responses. - PCL_HELLO = 0, - PKT_OK = 1, - PKT_CANCEL = 2, // unused? - PKT_PLAYER_INFO = 3, - PKT_CHAT = 4, - PKT_TICCMD = 5, // unused? - PKT_PING = 6, - PSV_HANDSHAKE = 7, - PSV_SERVER_CLOSE = 8, - PSV_FRAME = 9, // obsolete - PSV_PLAYER_EXIT = 10, - PSV_CONSOLE_TEXT = 11, - PCL_ACK_SHAKE = 12, - PSV_SYNC = 13, - PSV_FILTER = 14, // unused? - PKT_COMMAND = 15, - PKT_LOGIN = 16, - PCL_ACK_SETS = 17, - PKT_COORDS = 18, - PKT_DEMOCAM = 19, - PKT_DEMOCAM_RESUME = 20, - PCL_HELLO2 = 21, // Includes game ID - PSV_FRAME2 = 22, // Frame packet v2 - PSV_FIRST_FRAME2 = 23, // First PSV_FRAME2 after map change - PSV_SOUND2 = 24, // unused? - PSV_STOP_SOUND = 25, - PCL_ACKS = 26, + // Messages and responses. + PCL_HELLO = 0, + PKT_OK = 1, + PKT_CANCEL = 2, // unused? + PKT_PLAYER_INFO = 3, + PKT_CHAT = 4, + PKT_TICCMD = 5, // unused? + PKT_PING = 6, + PSV_HANDSHAKE = 7, + PSV_SERVER_CLOSE = 8, + PSV_FRAME = 9, // obsolete + PSV_PLAYER_EXIT = 10, + PSV_CONSOLE_TEXT = 11, + PCL_ACK_SHAKE = 12, + PSV_SYNC = 13, + PSV_FILTER = 14, // unused? + PKT_COMMAND = 15, // obsolete + PKT_LOGIN = 16, + PCL_ACK_SETS = 17, + PKT_COORDS = 18, + PKT_DEMOCAM = 19, + PKT_DEMOCAM_RESUME = 20, + PCL_HELLO2 = 21, // Includes game ID + PSV_FRAME2 = 22, // Frame packet v2 + PSV_FIRST_FRAME2 = 23, // First PSV_FRAME2 after map change + PSV_SOUND2 = 24, // unused? + PSV_STOP_SOUND = 25, + PCL_ACKS = 26, PSV_PLAYER_FIX = 27, // Fix angles/pos/mom. PCL_ACK_PLAYER_FIX = 28, // Acknowledge player fix. /* 28 */ + PKT_COMMAND2 = 29, - PCL_COMMANDS = DDPT_COMMANDS, // 32; ticcmds (handled by game) + PCL_COMMANDS = DDPT_COMMANDS, // 32; ticcmds (handled by game) - // Game specific events. - PKT_GAME_MARKER = DDPT_FIRST_GAME_EVENT // 64 + // Game specific events. + PKT_GAME_MARKER = DDPT_FIRST_GAME_EVENT // 64 }; -// Use the number defined in dd_share.h for sound packets. +// Use the number defined in dd_share.h for sound packets. // This is for backwards compatibility. -#define PSV_SOUND 71 /* DDPT_SOUND */ +#define PSV_SOUND 71 /* DDPT_SOUND */ -#define RESENDCOUNT 10 -#define HANDSHAKECOUNT 17 -#define UPDATECOUNT 20 +#define RESENDCOUNT 10 +#define HANDSHAKECOUNT 17 +#define UPDATECOUNT 20 // These dd-flags are packed (i.e. included in mobj deltas). -#define DDMF_PACK_MASK 0x3cfff1ff +#define DDMF_PACK_MASK 0x3cfff1ff // A client's acknowledgement threshold depends on the average of his // acknowledgement times. -#define NUM_ACK_TIMES 8 +#define NUM_ACK_TIMES 8 // The consoleplayer's camera position is written to the demo file // every 3rd tic. -#define LOCALCAM_WRITE_TICS 3 +#define LOCALCAM_WRITE_TICS 3 //--------------------------------------------------------------------------- // Types //--------------------------------------------------------------------------- typedef struct { - // High tics when ping was sent (0 if pinger not used). - int sent; + // High tics when ping was sent (0 if pinger not used). + int sent; - // A record of the pings (negative time: no response). - float times[MAX_PINGS]; + // A record of the pings (negative time: no response). + float times[MAX_PINGS]; - // Total number of pings and the current one. - int total; - int current; + // Total number of pings and the current one. + int total; + int current; } pinger_t; // Network information for a player. Corresponds the players array. typedef struct { - // ID number. Each client has a unique ID number. - ident_t id; + // ID number. Each client has a unique ID number. + ident_t id; - // Ticcmd buffer. The server uses this when clients send it ticcmds. - byte *ticCmds; + // Ticcmd buffer. The server uses this when clients send it ticcmds. + byte *ticCmds; - // Number of tics in the buffer. - int numTics; + // Number of tics in the buffer. + int numTics; - // Index of the first tic in the buffer. - int firstTic; + // Index of the first tic in the buffer. + int firstTic; - // Last command executed, reused if a new one isn't found. - ticcmd_t *lastCmd; + // Last command executed, reused if a new one isn't found. + ticcmd_t *lastCmd; - // Clients merge several ticcmds into this one, which is them sent - // periodically to the server. - ticcmd_t *aggregateCmd; + // Clients merge several ticcmds into this one, which is them sent + // periodically to the server. + ticcmd_t *aggregateCmd; - int lastTransmit; + int lastTransmit; - // If >0, the server will send the next world frame to the client. - // This is set when input is received from the client. - int updateCount; + // If >0, the server will send the next world frame to the client. + // This is set when input is received from the client. + int updateCount; - // Gametic when the client entered the game. - int enterTime; + // Gametic when the client entered the game. + int enterTime; - // Client-reported time of the last processed ticcmd. - // Older or as old tics than this are discarded. - byte runTime; + // Client-reported time of the last processed ticcmd. + // Older or as old tics than this are discarded. + byte runTime; - // Bandwidth rating for connection. Determines how much information - // can be sent to the client. Determined dynamically. - int bandwidthRating; + // Bandwidth rating for connection. Determines how much information + // can be sent to the client. Determined dynamically. + int bandwidthRating; - // During the adjust period, raising the BWR is allowed (hitting max - // frame size). - int bwrAdjustTime; + // During the adjust period, raising the BWR is allowed (hitting max + // frame size). + int bwrAdjustTime; - // A record of the past few acknowledgement times. - uint ackTimes[NUM_ACK_TIMES]; - int ackIdx; + // A record of the past few acknowledgement times. + uint ackTimes[NUM_ACK_TIMES]; + int ackIdx; - // Clients use this to determine how long ago they received the - // last update of this client. - int age; + // Clients use this to determine how long ago they received the + // last update of this client. + int age; - // Is this client connected? (Might not be in the game yet.) Only - // used by the server. - int connected; + // Is this client connected? (Might not be in the game yet.) Only + // used by the server. + int connected; - // Clients are pinged by the server when they join the game. - // This is the ping in milliseconds for this client. For the server. - unsigned int shakePing; + // Clients are pinged by the server when they join the game. + // This is the ping in milliseconds for this client. For the server. + unsigned int shakePing; - // If true, the server will send the player a handshake. The client must - // acknowledge it before this flag is turned off. - int handshake; + // If true, the server will send the player a handshake. The client must + // acknowledge it before this flag is turned off. + int handshake; - // Server uses this to determine whether it's OK to send game packets - // to the client. - int ready; + // Server uses this to determine whether it's OK to send game packets + // to the client. + int ready; - // The name of the player. - char name[PLAYERNAMELEN]; + // The name of the player. + char name[PLAYERNAMELEN]; - // Field of view. Used in determining visible mobjs (default: 90). - float fov; + // Field of view. Used in determining visible mobjs (default: 90). + float fov; - // The DirectPlay player that represents this client. - unsigned int nodeID; // DP player ID. + // The DirectPlay player that represents this client. + unsigned int nodeID; // DP player ID. - // Ping tracker for this client. - pinger_t ping; + // Ping tracker for this client. + pinger_t ping; - // Demo recording file (being recorded if not NULL). - LZFILE *demo; - boolean recording; - boolean recordPaused; + // Demo recording file (being recorded if not NULL). + LZFILE *demo; + boolean recording; + boolean recordPaused; - // View console. Which player this client is viewing? - int viewConsole; + // View console. Which player this client is viewing? + int viewConsole; } client_t; // Packets. typedef struct { - byte version; - unsigned short playerMask; // 16 players. - byte yourConsole; // Which one's you? - int gameTime; + byte version; + unsigned short playerMask; // 16 players. + byte yourConsole; // Which one's you? + int gameTime; } handshake_packet_t; typedef struct { - byte console; - char name[PLAYERNAMELEN]; + byte console; + char name[PLAYERNAMELEN]; } playerinfo_packet_t; //--------------------------------------------------------------------------- // Variables //--------------------------------------------------------------------------- extern boolean firstNetUpdate; -extern int resend_start; // set when server needs our tics +extern int resend_start; // set when server needs our tics extern int resend_count; extern int gametime, oldentertics; extern int num_clmobjs; @@ -267,14 +268,14 @@ void Net_Shutdown(void); void Net_AllocArrays(void); void Net_DestroyArrays(void); void Net_SendPacket(int to_player, int type, void *data, - int length); + int length); boolean Net_GetPacket(void); void Net_SendBuffer(int to_player, int sp_flags); void Net_InitGame(void); void Net_StartGame(void); void Net_StopGame(void); -void Net_BuildLocalCommands(timespan_t time); -void Net_SendCommands(void); +void Net_BuildLocalCommands(timespan_t time); +void Net_SendCommands(void); void Net_SendPing(int player, int count); void Net_PingResponse(void); void Net_ShowPingSummary(int player); diff --git a/doomsday/engine/portable/src/cl_main.c b/doomsday/engine/portable/src/cl_main.c index f6d109c33f..e8d9ce131f 100644 --- a/doomsday/engine/portable/src/cl_main.c +++ b/doomsday/engine/portable/src/cl_main.c @@ -18,7 +18,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, + * Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301 USA */ @@ -160,7 +160,7 @@ void Cl_AnswerHandshake(handshake_packet_t * pShake) Con_Message ("Cl_AnswerHandshake: Version conflict! (you:%i, server:%i)\n", SV_VERSION, shake.version); - Con_Execute(CMDS_DDAY, "net disconnect", false); + Con_Execute(CMDS_DDAY, "net disconnect", false, false); Demo_StopPlayback(); Con_Open(true); return; @@ -287,8 +287,8 @@ void Cl_GetPackets(void) { case PSV_PLAYER_FIX: Cl_HandlePlayerFix(); - break; - + break; + case PKT_DEMOCAM: case PKT_DEMOCAM_RESUME: Demo_ReadLocalCamera(); @@ -326,7 +326,7 @@ void Cl_GetPackets(void) case PSV_SERVER_CLOSE: // We should quit? netLoggedIn = false; - Con_Execute(CMDS_SPKT, "net disconnect", true); + Con_Execute(CMDS_DDAY, "net disconnect", true, false); break; case PSV_CONSOLE_TEXT: diff --git a/doomsday/engine/portable/src/con_bind.c b/doomsday/engine/portable/src/con_bind.c index fa91e8515a..007beb5df6 100644 --- a/doomsday/engine/portable/src/con_bind.c +++ b/doomsday/engine/portable/src/con_bind.c @@ -18,7 +18,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, + * Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301 USA */ @@ -350,7 +350,7 @@ boolean B_Responder(event_t *ev) if(cmd != NULL) { // Found one, execute! - Con_Execute(CMDS_BIND, cmd, true); + Con_Execute(CMDS_BIND, cmd, true, false); return true; } diff --git a/doomsday/engine/portable/src/con_config.c b/doomsday/engine/portable/src/con_config.c index e4453e3127..7001c91e1e 100644 --- a/doomsday/engine/portable/src/con_config.c +++ b/doomsday/engine/portable/src/con_config.c @@ -18,7 +18,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, + * Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301 USA */ @@ -84,7 +84,7 @@ int Con_ParseCommands(char *fileName, int setdefault) if(!M_IsComment(buff)) { // Execute the commands silently. - if(!Con_Execute(CMDS_CONFIG, buff, setdefault ? true : false)) + if(!Con_Execute(CMDS_CONFIG, buff, (setdefault ? true : false), false)) Con_Message("%s(%d): error executing command\n" " \"%s\"\n", fileName, line, buff); } diff --git a/doomsday/engine/portable/src/con_main.c b/doomsday/engine/portable/src/con_main.c index 0289586567..aabc67ec5c 100644 --- a/doomsday/engine/portable/src/con_main.c +++ b/doomsday/engine/portable/src/con_main.c @@ -18,7 +18,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, + * Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301 USA */ @@ -106,7 +106,9 @@ typedef struct calias_s { typedef struct execbuff_s { boolean used; // Is this in use? timespan_t when; // System time when to execute the command. - int source; // Where the command came from (console input, a cfg file etc..) + byte source; // Where the command came from + // (console input, a cfg file etc..) + boolean isNetCmd; // Command was sent over the net to us. char subCmd[1024]; // A single command w/args. } execbuff_t; @@ -131,8 +133,10 @@ typedef struct knownword_S { static void registerCommands(void); static void registerVariables(void); -static int executeSubCmd(const char *subCmd, int src); -void Con_SplitIntoSubCommands(const char *command, timespan_t markerOffset, int src); +static int executeSubCmd(const char *subCmd, byte src, boolean isNetCmd); +static void Con_SplitIntoSubCommands(const char *command, + timespan_t markerOffset, byte src, + boolean isNetCmd); calias_t *Con_GetAlias(const char *name); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- @@ -822,17 +826,19 @@ void Con_ClearBuffer() bLineOff = 0; } -/* +/** * Send a console command to the server. * This shouldn't be called unless we're logged in with the right password. */ -void Con_Send(const char *command, int silent) +void Con_Send(const char *command, byte src, int silent) { unsigned short len = strlen(command) + 1; - Msg_Begin(PKT_COMMAND); + Msg_Begin(PKT_COMMAND2); // Mark high bit for silent commands. Msg_WriteShort(len | (silent ? 0x8000 : 0)); + Msg_WriteShort(0); // flags. Unused at present. + Msg_WriteByte(src); Msg_Write(command, len); // Send it reliably. Net_SendBuffer(0, SPF_ORDERED); @@ -845,7 +851,8 @@ void Con_ClearExecBuffer() exBuffSize = 0; } -void Con_QueueCmd(const char *singleCmd, timespan_t atSecond, int source) +static void Con_QueueCmd(const char *singleCmd, timespan_t atSecond, + byte source, boolean isNetCmd) { execbuff_t *ptr = NULL; int i; @@ -868,6 +875,7 @@ void Con_QueueCmd(const char *singleCmd, timespan_t atSecond, int source) strcpy(ptr->subCmd, singleCmd); ptr->when = atSecond; ptr->source = source; + ptr->isNetCmd = isNetCmd; } void Con_Shutdown() @@ -954,7 +962,7 @@ boolean Con_CheckExecBuffer(void) curExec = ptr; ptr->used = false; strcpy(storage, ptr->subCmd); - if(!executeSubCmd(storage, ptr->source)) + if(!executeSubCmd(storage, ptr->source, ptr->isNetCmd)) ret = false; allDone = false; } @@ -1181,7 +1189,7 @@ static void expandWithArguments(char **expCommand, cmdargs_t * args) * executeSubCmd * The command is executed forthwith!! */ -static int executeSubCmd(const char *subCmd, int src) +static int executeSubCmd(const char *subCmd, byte src, boolean isNetCmd) { int i; char prefix; @@ -1204,10 +1212,10 @@ static int executeSubCmd(const char *subCmd, int src) } // If logged in, send command to server at this point. - if(netLoggedIn) + if(!isServer && netLoggedIn) { // We have logged in on the server. Send the command there. - Con_Send(subCmd, ConsoleSilent); + Con_Send(subCmd, src, ConsoleSilent); return true; } @@ -1216,15 +1224,106 @@ static int executeSubCmd(const char *subCmd, int src) if(!stricmp(ccmds[i].name, args.argv[0])) { // Found a match. Are we allowed to execute? - if((src == CMDS_DDAY && !(ccmds[i].flags & CMDF_DDAY)) || - (src == CMDS_GAME && !(ccmds[i].flags & CMDF_GAME)) || - (src == CMDS_CONSOLE && !(ccmds[i].flags & CMDF_CONSOLE)) || - (src == CMDS_BIND && !(ccmds[i].flags & CMDF_BIND)) || - (src == CMDS_CONFIG && !(ccmds[i].flags & CMDF_CONFIG)) || - (src == CMDS_PROFILE && !(ccmds[i].flags & CMDF_PROFILE)) || - (src == CMDS_CMDLINE && !(ccmds[i].flags & CMDF_CMDLINE)) || - (src == CMDS_DED && !(ccmds[i].flags & CMDF_DED))) + boolean canExecute = true; + + // Net commands sent to servers have extra protection. + if(isServer && isNetCmd) + { + // Is the command permitted for use by clients? + if(ccmds[i].flags & CMDF_CLIENT) + { + Con_Printf("executeSubCmd: Blocked command. A client" + " attempted to use '%s'.\n" + "This command is not permitted for use by clients\n", + ccmds[i].name); + // TODO: Tell the client! + return true; + } + + // Are ANY commands from this (remote) src permitted for use + // by our clients? + + // NOTE: + // This is an interim measure to protect against abuse of the + // most vulnerable invocation methods. + // Once all console commands are updated with the correct usage + // flags we can then remove these restrictions or make them + // optional for servers. + // + // The next step will then be allowing select console commands + // to be executed by non-logged in clients. + switch(src) + { + case CMDS_UNKNOWN: + case CMDS_CONFIG: + case CMDS_PROFILE: + case CMDS_CMDLINE: + case CMDS_DED: + Con_Printf("executeSubCmd: Blocked command. A client" + " attempted to use '%s' via %s.\n" + "This invocation method is not permitted " + "by clients\n", ccmds[i].name, CMDTYPESTR(src)); + // TODO: Tell the client! + return true; + + default: + break; + } + } + + // Is the src permitted for this command? + switch(src) { + case CMDS_UNKNOWN: + canExecute = false; + break; + + case CMDS_DDAY: + if(ccmds[i].flags & CMDF_DDAY) + canExecute = false; + break; + + case CMDS_GAME: + if(ccmds[i].flags & CMDF_GAME) + canExecute = false; + break; + + case CMDS_CONSOLE: + if(ccmds[i].flags & CMDF_CONSOLE) + canExecute = false; + break; + + case CMDS_BIND: + if(ccmds[i].flags & CMDF_BIND) + canExecute = false; + break; + + case CMDS_CONFIG: + if(ccmds[i].flags & CMDF_CONFIG) + canExecute = false; + break; + + case CMDS_PROFILE: + if(ccmds[i].flags & CMDF_PROFILE) + canExecute = false; + break; + + case CMDS_CMDLINE: + if(ccmds[i].flags & CMDF_CMDLINE) + canExecute = false; + break; + + case CMDS_DED: + if(ccmds[i].flags & CMDF_DED) + canExecute = false; + break; + + default: + return true; + } + + if(canExecute) + { // Execute the command! int cret = ccmds[i].func(src, args.argc, args.argv); if(cret == false) @@ -1264,7 +1363,8 @@ static int executeSubCmd(const char *subCmd, int src) } else if(var->flags & CVF_READ_ONLY) { - Con_Printf("%s is read-only. It can't be changed (not even with force)\n", var->name); + Con_Printf("%s is read-only. It can't be changed (not even " + "with force)\n", var->name); } else if(var->type == CVT_BYTE) { @@ -1344,7 +1444,7 @@ static int executeSubCmd(const char *subCmd, int src) strcpy(expCommand, cal->command); expandWithArguments(&expCommand, &args); // Do it, man! - Con_SplitIntoSubCommands(expCommand, 0, src); + Con_SplitIntoSubCommands(expCommand, 0, src, isNetCmd); free(expCommand); return true; } @@ -1358,7 +1458,9 @@ static int executeSubCmd(const char *subCmd, int src) * Splits the command into subcommands and queues them into the * execution buffer. */ -void Con_SplitIntoSubCommands(const char *command, timespan_t markerOffset, int src) +static void Con_SplitIntoSubCommands(const char *command, + timespan_t markerOffset, byte src, + boolean isNetCmd) { int gPos = 0, scPos = 0; char subCmd[2048]; @@ -1401,32 +1503,39 @@ void Con_SplitIntoSubCommands(const char *command, timespan_t markerOffset, int continue; // Queue it. - Con_QueueCmd(subCmd, sysTime + markerOffset, src); + Con_QueueCmd(subCmd, sysTime + markerOffset, src, isNetCmd); scPos = 0; } } -/* - * Wrapper for Con_Execute - * Allows plugin dlls to execute a console command +/** + * Wrapper for Con_Execute + * Allows plugin dlls to execute a console command */ int DD_Execute(const char *command, int silent) { - return Con_Execute(CMDS_GAME, command, silent); + return Con_Execute(CMDS_GAME, command, silent, false); } -/* +/** * Returns false if a command fails. + * + * @param src The source of the command (e.g. DDay internal, DED etc). + * @param command The command to be executed. + * @param silent Non-zero indicates not to log execution of the command. + * @param netCmd If true command was sent over the net. + * + * @return Non-zero if command was executed successfully. */ -int Con_Execute(int src, const char *command, int silent) +int Con_Execute(byte src, const char *command, int silent, boolean netCmd) { int ret; if(silent) ConsoleSilent = true; - Con_SplitIntoSubCommands(command, 0, src); + Con_SplitIntoSubCommands(command, 0, src, netCmd); ret = Con_CheckExecBuffer(); if(silent) @@ -1435,8 +1544,8 @@ int Con_Execute(int src, const char *command, int silent) return ret; } -/* - * exported version of Con_Executef +/** + * Exported version of Con_Executef */ int DD_Executef(int silent, const char *command, ...) { @@ -1446,10 +1555,10 @@ int DD_Executef(int silent, const char *command, ...) va_start(argptr, command); vsprintf(buffer, command, argptr); va_end(argptr); - return Con_Execute(CMDS_GAME, buffer, silent); + return Con_Execute(CMDS_GAME, buffer, silent, false); } -int Con_Executef(int src, int silent, const char *command, ...) +int Con_Executef(byte src, int silent, const char *command, ...) { va_list argptr; char buffer[4096]; @@ -1457,10 +1566,10 @@ int Con_Executef(int src, int silent, const char *command, ...) va_start(argptr, command); vsnprintf(buffer, sizeof(buffer), command, argptr); va_end(argptr); - return Con_Execute(src, buffer, silent); + return Con_Execute(src, buffer, silent, false); } -static void processCmd(int src) +static void processCmd(byte src) { DD_ClearKeyRepeaters(); @@ -1468,7 +1577,7 @@ static void processCmd(int src) addOldCmd(cmdLine); ocPos = numOldCmds; - Con_Execute(src, cmdLine, false); + Con_Execute(src, cmdLine, false, false); } static void updateCmdLine() @@ -1624,7 +1733,7 @@ boolean Con_Responder(event_t *event) if(!conInputLock && shiftDown && event->state == EVS_DOWN && event->data1 == DDKEY_ESCAPE) { - Con_Execute(CMDS_DDAY, "panel", true); + Con_Execute(CMDS_DDAY, "panel", true, false); return true; } @@ -1884,7 +1993,7 @@ boolean Con_Responder(event_t *event) if(conInputLock) break; - Con_Execute(CMDS_DDAY, "clear", true); + Con_Execute(CMDS_DDAY, "clear", true, false); break; default: // Check for a character. @@ -2852,7 +2961,7 @@ D_CMD(Wait) offset = strtod(argv[1], NULL) / 35; // Offset in seconds. if(offset < 0) offset = 0; - Con_SplitIntoSubCommands(argv[2], offset, CMDS_CONSOLE); + Con_SplitIntoSubCommands(argv[2], offset, CMDS_CONSOLE, false); return true; } @@ -2873,7 +2982,7 @@ D_CMD(Repeat) while(count-- > 0) { offset += interval; - Con_SplitIntoSubCommands(argv[3], offset, CMDS_CONSOLE); + Con_SplitIntoSubCommands(argv[3], offset, CMDS_CONSOLE, false); } return true; } @@ -3044,11 +3153,11 @@ D_CMD(If) // Should the command be executed? if(isTrue) { - Con_Execute(src, argv[4], ConsoleSilent); + Con_Execute(src, argv[4], ConsoleSilent, false); } else if(argc == 6) { - Con_Execute(src, argv[5], ConsoleSilent); + Con_Execute(src, argv[5], ConsoleSilent, false); } CmdReturnValue = isTrue; return true; diff --git a/doomsday/engine/portable/src/dd_main.c b/doomsday/engine/portable/src/dd_main.c index 0483f5bfaa..0c00efd29c 100644 --- a/doomsday/engine/portable/src/dd_main.c +++ b/doomsday/engine/portable/src/dd_main.c @@ -19,7 +19,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, + * Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301 USA */ @@ -601,7 +601,7 @@ void DD_Main(void) p--; break; } - Con_Execute(CMDS_CMDLINE, arg, false); + Con_Execute(CMDS_CMDLINE, arg, false, false); } } @@ -675,7 +675,7 @@ void DD_CheckTimeDemo(void) char buf[200]; sprintf(buf, "playdemo %s", ArgNext()); - Con_Execute(CMDS_CMDLINE, buf, false); + Con_Execute(CMDS_CMDLINE, buf, false, false); } } } diff --git a/doomsday/engine/portable/src/gl_main.c b/doomsday/engine/portable/src/gl_main.c index deb476f1d5..d03c92f8fb 100644 --- a/doomsday/engine/portable/src/gl_main.c +++ b/doomsday/engine/portable/src/gl_main.c @@ -19,7 +19,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, + * Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301 USA */ @@ -774,7 +774,7 @@ void GL_TotalReset(boolean doShutdown, boolean loadLightMaps, else { // Restore the old font. - //Con_Executef(CMDS_DDAY, true, "font name %s", oldFontName); + //Con_Executef(CMDS_DDAY, true, "font name %s", oldFontName, false); GL_Init2DState(); } GL_InitRefresh(loadLightMaps, loadFlares); diff --git a/doomsday/engine/portable/src/net_buf.c b/doomsday/engine/portable/src/net_buf.c index 17e210e903..956b877b5d 100644 --- a/doomsday/engine/portable/src/net_buf.c +++ b/doomsday/engine/portable/src/net_buf.c @@ -17,7 +17,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, + * Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301 USA */ @@ -115,7 +115,7 @@ void N_Shutdown(void) if(ArgExists("-huffavg")) { - Con_Execute(CMDS_DDAY, "huffman", false); + Con_Execute(CMDS_DDAY, "huffman", false, false); } } diff --git a/doomsday/engine/portable/src/net_main.c b/doomsday/engine/portable/src/net_main.c index ead96c844a..d911691328 100644 --- a/doomsday/engine/portable/src/net_main.c +++ b/doomsday/engine/portable/src/net_main.c @@ -18,7 +18,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, + * Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301 USA */ @@ -1271,7 +1271,7 @@ D_CMD(Connect) // Found something! Net_PrintServerInfo(0, NULL); Net_PrintServerInfo(0, &info); - Con_Execute(CMDS_CONSOLE, "net connect 0", false); + Con_Execute(CMDS_CONSOLE, "net connect 0", false, false); returnValue = true; goto endConnect; diff --git a/doomsday/engine/portable/src/p_mobj.c b/doomsday/engine/portable/src/p_mobj.c index e56f144f53..a47ea0a1ee 100644 --- a/doomsday/engine/portable/src/p_mobj.c +++ b/doomsday/engine/portable/src/p_mobj.c @@ -19,7 +19,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, + * Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301 USA */ @@ -135,7 +135,7 @@ void P_SetState(mobj_t *mobj, int statenum) } if(defs.states[statenum].execute) - Con_Execute(CMDS_DED, defs.states[statenum].execute, true); + Con_Execute(CMDS_DED, defs.states[statenum].execute, true, false); } /* diff --git a/doomsday/engine/portable/src/r_sky.c b/doomsday/engine/portable/src/r_sky.c index b8bbfaf4ac..d44bccb4ea 100644 --- a/doomsday/engine/portable/src/r_sky.c +++ b/doomsday/engine/portable/src/r_sky.c @@ -17,7 +17,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, + * Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301 USA */ @@ -136,7 +136,7 @@ void R_SkyTicker(void) // Execute a console command? if(sky->def->execute) - Con_Execute(CMDS_DED, sky->def->execute, true); + Con_Execute(CMDS_DED, sky->def->execute, true, false); } } } diff --git a/doomsday/engine/portable/src/r_world.c b/doomsday/engine/portable/src/r_world.c index 2cfdba5180..e9325affda 100644 --- a/doomsday/engine/portable/src/r_world.c +++ b/doomsday/engine/portable/src/r_world.c @@ -18,7 +18,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, + * Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301 USA */ @@ -1208,7 +1208,7 @@ void R_SetupFog(void) if(!mapinfo) { // Go with the defaults. - Con_Execute(CMDS_DDAY,"fog off", true); + Con_Execute(CMDS_DDAY,"fog off", true, false); return; } @@ -1217,7 +1217,7 @@ void R_SetupFog(void) if(flags & MIF_FOG) { // Setup fog. - Con_Execute(CMDS_DDAY, "fog on", true); + Con_Execute(CMDS_DDAY, "fog on", true, false); Con_Executef(CMDS_DDAY, true, "fog start %f", mapinfo->fog_start); Con_Executef(CMDS_DDAY, true, "fog end %f", mapinfo->fog_end); Con_Executef(CMDS_DDAY, true, "fog density %f", mapinfo->fog_density); @@ -1227,7 +1227,7 @@ void R_SetupFog(void) } else { - Con_Execute(CMDS_DDAY, "fog off", true); + Con_Execute(CMDS_DDAY, "fog off", true, false); } } @@ -2039,7 +2039,7 @@ void R_SetupLevel(char *level_id, int flags) // Run any commands specified in Map Info. if(mapinfo && mapinfo->execute) - Con_Execute(CMDS_DED, mapinfo->execute, true); + Con_Execute(CMDS_DED, mapinfo->execute, true, false); // The level setup has been completed. Run the special level // setup command, which the user may alias to do something diff --git a/doomsday/engine/portable/src/sv_main.c b/doomsday/engine/portable/src/sv_main.c index b82bf08d22..471dbec31e 100644 --- a/doomsday/engine/portable/src/sv_main.c +++ b/doomsday/engine/portable/src/sv_main.c @@ -18,7 +18,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, + * Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301 USA */ @@ -504,6 +504,8 @@ void Sv_Login(void) */ void Sv_ExecuteCommand(void) { + int flags; + byte cmdSource; unsigned short len; boolean silent; @@ -517,13 +519,30 @@ void Sv_ExecuteCommand(void) len = Msg_ReadShort(); silent = (len & 0x8000) != 0; len &= 0x7fff; + switch(netBuffer.msg.type) + { + case PKT_COMMAND: + cmdSource = CMDS_UNKNOWN; // unknown command source. + break; + + case PKT_COMMAND2: + // New format includes flags and command source. + // Flags are currently unused but added for future expansion. + flags = Msg_ReadShort(); + cmdSource = Msg_ReadByte(); + break; + + default: + Con_Error("Sv_ExecuteCommand: Not a command packet!\n"); + } + // Verify using string length. if(strlen(netBuffer.cursor) != (unsigned) len - 1) { Con_Printf("Sv_ExecuteCommand: Damaged packet?\n"); return; } - Con_Execute(CMDS_PKT, netBuffer.cursor, silent); + Con_Execute(cmdSource, netBuffer.cursor, silent, true); } /* @@ -639,17 +658,17 @@ void Sv_GetPackets(void) acked->mom = Msg_ReadLong(); #ifdef _DEBUG Con_Message("PCL_ACK_PLAYER_FIX: (%i) Angles %i (%i), pos %i (%i), mom %i (%i).\n", - netBuffer.player, - acked->angles, + netBuffer.player, + acked->angles, players[netBuffer.player].fixcounter.angles, - acked->pos, + acked->pos, players[netBuffer.player].fixcounter.pos, - acked->mom, + acked->mom, players[netBuffer.player].fixcounter.mom); #endif break; } - + case PKT_PING: Net_PingResponse(); break; @@ -667,6 +686,7 @@ void Sv_GetPackets(void) break; case PKT_COMMAND: + case PKT_COMMAND2: Sv_ExecuteCommand(); break; @@ -702,11 +722,11 @@ boolean Sv_PlayerArrives(unsigned int nodeID, char *name) clients[i].viewConsole = i; clients[i].lastTransmit = -1; strncpy(clients[i].name, name, PLAYERNAMELEN); - - players[i].fixacked.angles = - players[i].fixacked.pos = + + players[i].fixacked.angles = + players[i].fixacked.pos = players[i].fixacked.mom = -1; - + Sv_InitPoolForClient(i); VERBOSE(Con_Printf @@ -917,13 +937,13 @@ void Sv_Kick(int who) void Sv_SendPlayerFixes(ddplayer_t* player) { int fixes = 0; - + if(!(player->flags & (DDPF_FIXANGLES | DDPF_FIXPOS | DDPF_FIXMOM))) { // Nothing to fix. return; } - + // Start writing a player fix message. Msg_Begin(PSV_PLAYER_FIX); @@ -934,39 +954,39 @@ void Sv_SendPlayerFixes(ddplayer_t* player) fixes |= 2; if(player->flags & DDPF_FIXMOM) fixes |= 4; - + Msg_WriteLong(fixes); - + // Increment counters. if(player->flags & DDPF_FIXANGLES) { Msg_WriteLong(++player->fixcounter.angles); Msg_WriteLong(player->mo->angle); Msg_WriteLong(FLT2FIX(player->lookdir)); - + #ifdef _DEBUG Con_Message("Sv_SendPlayerFixes: Sent angles (%i): angle=%f lookdir=%f\n", player->fixcounter.angles, FIX2FLT(player->mo->angle), player->lookdir); #endif } - + if(player->flags & DDPF_FIXPOS) { Msg_WriteLong(++player->fixcounter.pos); Msg_WriteLong(player->mo->pos[VX]); - Msg_WriteLong(player->mo->pos[VY]); - Msg_WriteLong(player->mo->pos[VZ]); - + Msg_WriteLong(player->mo->pos[VY]); + Msg_WriteLong(player->mo->pos[VZ]); + #ifdef _DEBUG Con_Message("Sv_SendPlayerFixes: Sent position (%i): %f, %f, %f\n", - player->fixcounter.pos, + player->fixcounter.pos, FIX2FLT(player->mo->pos[VX]), FIX2FLT(player->mo->pos[VY]), FIX2FLT(player->mo->pos[VZ])); #endif } - + if(player->flags & DDPF_FIXMOM) { Msg_WriteLong(++player->fixcounter.mom); @@ -976,7 +996,7 @@ void Sv_SendPlayerFixes(ddplayer_t* player) #ifdef _DEBUG Con_Message("Sv_SendPlayerFixes: Sent momentum (%i): %f, %f, %f\n", - player->fixcounter.mom, + player->fixcounter.mom, FIX2FLT(player->mo->momx), FIX2FLT(player->mo->momy), FIX2FLT(player->mo->momz)); @@ -1002,7 +1022,7 @@ void Sv_Ticker(void) { if(!plr->ingame || !plr->mo) continue; - + plr->lastangle = plr->mo->angle; if(clients[i].bwrAdjustTime > 0) @@ -1010,9 +1030,9 @@ void Sv_Ticker(void) // BWR adjust time tics away. clients[i].bwrAdjustTime--; } - + // Increment counter, send new data. - Sv_SendPlayerFixes(plr); + Sv_SendPlayerFixes(plr); } } @@ -1110,7 +1130,7 @@ void Sv_PlaceThing(mobj_t* mo, fixed_t x, fixed_t y, fixed_t z, boolean onFloor) if(onFloor) { mo->pos[VZ] = mo->floorz; - } + } } /* @@ -1142,7 +1162,7 @@ void Sv_ClientCoords(int playerNum) // If we aren't about to forcibly change the client's position, update // with new pos if it's valid. - if(players[playerNum].fixcounter.pos == players[playerNum].fixacked.pos && + if(players[playerNum].fixcounter.pos == players[playerNum].fixacked.pos && P_CheckPosXYZ(mo, clx, cly, clz)) // But it must be a valid pos. { Sv_PlaceThing(mo, clx, cly, clz, onFloor); diff --git a/doomsday/engine/portable/src/sys_network.c b/doomsday/engine/portable/src/sys_network.c index 7a00b9f880..ce66c2707f 100644 --- a/doomsday/engine/portable/src/sys_network.c +++ b/doomsday/engine/portable/src/sys_network.c @@ -18,7 +18,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, + * Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301 USA */ @@ -447,13 +447,13 @@ boolean N_ReceiveReliably(nodeid_t from) if(received == -1) { SDLNet_FreePacket(packet); - Con_Message("N_ReceiveReliably: Error during TCP recv.\n %s (%s)", + Con_Message("N_ReceiveReliably: Error during TCP recv.\n %s (%s)", SDLNet_GetError(), strerror(errno)); - return false; + return false; } bytes += received; } - + // Post the received message. { netmessage_t *msg = calloc(sizeof(netmessage_t), 1); @@ -481,7 +481,7 @@ void N_SendDataBufferReliably(void *data, int size, nodeid_t destination) if(size <= 0 || !node->sock || !node->hasJoined) return; - + if(size > SHORT(packetSize)) { Con_Error("N_SendDataBufferReliably: Trying to send a too large data " @@ -494,16 +494,16 @@ void N_SendDataBufferReliably(void *data, int size, nodeid_t destination) transmissionBufferSize = size + 2; transmissionBuffer = realloc(transmissionBuffer, size + 2); } - + memcpy(transmissionBuffer, &packetSize, 2); memcpy(transmissionBuffer + 2, data, size); - + result = SDLNet_TCP_Send(node->sock, transmissionBuffer, size + 2); #ifdef _DEBUG - VERBOSE2( Con_Message("N_SendDataBufferReliably: Sent %i bytes, result=%i\n", + VERBOSE2( Con_Message("N_SendDataBufferReliably: Sent %i bytes, result=%i\n", size + 2, result) ); #endif - if(result != size + 2) + if(result != size + 2) perror("Socket error"); /* result = SDLNet_TCP_Send(node->sock, data, SHORT(packetSize)); @@ -782,7 +782,7 @@ void N_SystemInit(void) { Con_Message("N_SystemInit: %s\n", SDLNet_GetError()); } - + // Allocate the transmission buffer. transmissionBufferSize = DEFAULT_TRANSMISSION_SIZE; transmissionBuffer = malloc(transmissionBufferSize); @@ -797,7 +797,7 @@ void N_SystemShutdown(void) free(transmissionBuffer); transmissionBuffer = NULL; transmissionBufferSize = 0; - + N_ShutdownService(); SDLNet_Quit(); } @@ -929,7 +929,8 @@ void N_ShutdownService(void) if(netgame) { // We seem to be shutting down while a netgame is running. - Con_Execute(CMDS_DDAY, isServer ? "net server close" : "net disconnect", true); + Con_Execute(CMDS_DDAY, isServer ? "net server close" : "net disconnect", + true, false); } // Any queued messages will be destroyed. diff --git a/doomsday/engine/portable/src/sys_system.c b/doomsday/engine/portable/src/sys_system.c index d9a0a2078f..6c7f91db5f 100644 --- a/doomsday/engine/portable/src/sys_system.c +++ b/doomsday/engine/portable/src/sys_system.c @@ -17,16 +17,10 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, + * Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301 USA */ -//************************************************************************** -//** -//** SYS_SYSTEM.C -//** -//************************************************************************** - // HEADER FILES ------------------------------------------------------------ #ifdef WIN32 @@ -120,7 +114,7 @@ void Sys_Init(void) signal(SIGILL, handler); signal(SIGABRT, handler); #endif - + #ifndef WIN32 // We are not worried about broken pipes. When a TCP connection closes, // we prefer to receive an error code instead of a signal. @@ -233,7 +227,8 @@ void Sys_Quit(void) // Quit netgame if one is in progress. if(netgame) { - Con_Execute(CMDS_DDAY, isServer ? "net server close" : "net disconnect", true); + Con_Execute(CMDS_DDAY, isServer ? "net server close" : "net disconnect", + true, false); } Demo_StopPlayback(); diff --git a/doomsday/engine/portable/src/ui_mpi.c b/doomsday/engine/portable/src/ui_mpi.c index 5257b460b1..5e26393b0b 100644 --- a/doomsday/engine/portable/src/ui_mpi.c +++ b/doomsday/engine/portable/src/ui_mpi.c @@ -18,7 +18,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, + * Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301 USA */ @@ -391,7 +391,7 @@ void MPIStartServer(ui_object_t *ob) Con_SetString("net-master-address", str_masterip, true); // Start the server. - Con_Execute(CMDS_DDAY,"net server start", false); + Con_Execute(CMDS_DDAY,"net server start", false, false); UI_End(); } @@ -571,7 +571,7 @@ void MPIConnect(ui_object_t *ob) sprintf(buf, "net %sconnect %i", searchMode == SEARCH_MASTER ? "m" : "", lstit_found[lst_found.selection].data2); - if(Con_Execute(CMDS_DDAY,buf, false)) + if(Con_Execute(CMDS_DDAY,buf, false, false)) { // Success. UI_End(); diff --git a/doomsday/engine/portable/src/ui_panel.c b/doomsday/engine/portable/src/ui_panel.c index fd6085f767..ebf9c9ac58 100644 --- a/doomsday/engine/portable/src/ui_panel.c +++ b/doomsday/engine/portable/src/ui_panel.c @@ -18,7 +18,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, + * Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301 USA */ @@ -836,7 +836,7 @@ void CP_SetRes(ui_object_t *ob) UI_End(); GL_ChangeResolution(x, y, 0); // Reactivate the panel. - Con_Execute(CMDS_DDAY, "panel", true); + Con_Execute(CMDS_DDAY, "panel", true, false); } void CP_ResChanged(ui_object_t *ob) @@ -1035,7 +1035,7 @@ D_CMD(OpenPanel) if(isDedicated) return false; - Con_Execute(CMDS_DDAY, "conclose", true); + Con_Execute(CMDS_DDAY, "conclose", true, false); // The help window is hidden. panel_help_active = false;