diff --git a/.gitignore b/.gitignore index 742e720c..e7db90d1 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,9 @@ git-status.sh build_official* bin/sys_error.txt bin/logs/* + +bin/main/* +bin/zone/* +bin/serverstatus.xml +bin/main_shared/* +bin/cod4x18_dedrun diff --git a/bin/main/xbase_00.iwd b/bin/main/xbase_00.iwd deleted file mode 100644 index 305ca01d..00000000 Binary files a/bin/main/xbase_00.iwd and /dev/null differ diff --git a/build_updateable_elf.sh b/build_updateable_elf.sh index babbc753..39c90f04 100644 --- a/build_updateable_elf.sh +++ b/build_updateable_elf.sh @@ -2,6 +2,7 @@ echo Compiling C-code... cd bin +rm cod4x18_dedrun gcc -m32 -Wall -O0 -g -fno-omit-frame-pointer -mtune=nocona -I../lib_tomcrypt/headers -I../lib_tomcrypt/math/tommath -D _GNU_SOURCE -c ../src/unix/sys_unix.c gcc -m32 -Wall -O0 -g -fno-omit-frame-pointer -mtune=nocona -I../lib_tomcrypt/headers -I../lib_tomcrypt/math/tommath -D _GNU_SOURCE -c ../src/unix/sys_linux.c diff --git a/dis/plugin_handler.c b/dis/plugin_handler.c index 3ab0d78e..fab9beac 100644 --- a/dis/plugin_handler.c +++ b/dis/plugin_handler.c @@ -6,7 +6,6 @@ #define P_P_F __attribute__((__noinline__)) __attribute__((__cdecl__)) pluginWrapper_t pluginFunctions; -mainFunctions_t mainFunctions; #include "plugin_com.c" @@ -17,76 +16,6 @@ void Plugin_Init() pluginFunctions.loadedPlugins=0; pluginFunctions.enabled=qfalse; - ptr=(void*)&mainFunctions.Com_Printf; - - // Copy the function pointers to mainFunctions struct - mainFunctions.Com_Printf = Com_Printf; - mainFunctions.Com_DPrintf = Com_DPrintf; - mainFunctions.Com_PrintWarning = Com_PrintWarning; - mainFunctions.Com_PrintError = Com_PrintError; - mainFunctions.Cmd_Argv = Cmd_Argv; - mainFunctions.Cmd_Argc = Cmd_Argc; - mainFunctions.FS_SV_FOpenFileRead = FS_SV_FOpenFileRead; - mainFunctions.FS_SV_FOpenFileWrite = FS_SV_FOpenFileWrite; - mainFunctions.FS_Read = FS_Read; - mainFunctions.FS_ReadLine = FS_ReadLine; - mainFunctions.FS_Write = FS_Write; - mainFunctions.FS_FCloseFile = FS_FCloseFile; - mainFunctions.Com_ParseGetToken = Com_ParseGetToken; - mainFunctions.Com_ParseTokenLength = Com_ParseTokenLength; - mainFunctions.Cvar_VariableValue = Cvar_VariableValue; - mainFunctions.Cvar_VariableIntegerValue = Cvar_VariableIntegerValue; - mainFunctions.Cvar_VariableString = Cvar_VariableString; - mainFunctions.Cvar_VariableStringBuffer = Cvar_VariableStringBuffer; - mainFunctions.Sys_Milliseconds = Sys_Milliseconds; - - mainFunctions.Plugin_TcpConnect = Plugin_TcpConnect_p; - mainFunctions.Plugin_TcpGetData = Plugin_TcpGetData_p; - mainFunctions.Plugin_TcpSendData = Plugin_TcpSendData_p; - mainFunctions.Plugin_TcpCloseConnection = Plugin_TcpCloseConnection_p; - mainFunctions.Plugin_UdpSendData = Plugin_UdpSendData_p; - mainFunctions.Plugin_ServerPacketEvent = Plugin_ServerPacketEvent_p; - mainFunctions.NET_StringToAdr = NET_StringToAdr; - mainFunctions.Plugin_GetClientScoreboard = Plugin_GetClientScoreboard; - mainFunctions.Plugin_Cmd_GetInvokerUid = Plugin_Cmd_GetInvokerUid; - mainFunctions.Plugin_GetPlayerUid = Plugin_GetPlayerUid; - mainFunctions.Plugin_GetSlotCount = Plugin_GetSlotCount; - mainFunctions.Plugin_IsSvRunning = Plugin_IsSvRunning; - mainFunctions.Plugin_ChatPrintf = Plugin_ChatPrintf; - mainFunctions.Plugin_BoldPrintf = Plugin_BoldPrintf; - mainFunctions.Plugin_GetPlayerName = Plugin_GetPlayerName; - mainFunctions.Plugin_AddCommand = Plugin_AddCommand; - mainFunctions.Plugin_Malloc = Plugin_Malloc_p; - mainFunctions.Plugin_Free = Plugin_Free_p; - mainFunctions.Plugin_Error = Plugin_Error; - mainFunctions.Plugin_GetLevelTime = Plugin_GetLevelTime_p; - mainFunctions.Plugin_GetServerTime = Plugin_GetServerTime_p; - - mainFunctions.Plugin_SetPlayerUID = Plugin_SetPlayerUID_p; - mainFunctions.Plugin_GetPlayerUID = Plugin_GetPlayerUID_p; - mainFunctions.Plugin_GetPlayerGUID = Plugin_GetPlayerGUID_p; - mainFunctions.Plugin_SetPlayerGUID = Plugin_SetPlayerGUID_p; - mainFunctions.Plugin_SetPlayerNoPB = Plugin_SetPlayerNoPB_p; - mainFunctions.Plugin_DoesServerUseUids = Plugin_DoesServerUseUids_p; - mainFunctions.Plugin_SetServerToUseUids = Plugin_SetServerToUseUids_p; - mainFunctions.Cvar_RegisterString = Cvar_RegisterString; - mainFunctions.Cvar_RegisterBool = Cvar_RegisterBool; - mainFunctions.Cvar_RegisterInt = Cvar_RegisterInt; - mainFunctions.Cvar_RegisterEnum = Cvar_RegisterEnum; - mainFunctions.Cvar_RegisterFloat = Cvar_RegisterFloat; - - mainFunctions.Cvar_SetInt = Cvar_SetInt; - mainFunctions.Cvar_SetBool = Cvar_SetBool; - mainFunctions.Cvar_SetString = Cvar_SetString; - mainFunctions.Cvar_SetFloat = Cvar_SetFloat; - - for(i=0;ilongDescription,"This plugin is used to prevent spam in the ingame chat. To personalize the settings, set corresponding cvars. Copyright (c) 2013 IceOps",sizeof(info->longDescription)); } -void Scr_Test() -{ - Plugin_Printf("Exec test--------"); - Plugin_Scr_AddInt(7); -} diff --git a/plugins/censor/censor.c b/plugins/censor/censor.c index 06259fdf..b9adb4f2 100644 --- a/plugins/censor/censor.c +++ b/plugins/censor/censor.c @@ -320,6 +320,93 @@ char* censor_ignoreMultiple(char *output, char *string, size_t size) } + +/***************************************************** +*** Parsing files *** +*****************************************************/ +static qboolean parse_inquotes = qfalse; +static char* parse_lastpos; + +void Com_ParseReset(){ + + parse_inquotes = qfalse; + parse_lastpos = NULL; +} + +char* Com_ParseGetToken(char* line){ + + if(parse_lastpos == line){ + + if(parse_inquotes){//In case we are inside quotes step until the end quote forward + + do{ + line++; + }while(*line != '"' && *line != ';' && *line != '\n' && *line != '\0'); + + parse_inquotes = qfalse; + } + + while(*line != ' '){ + if(*line == '\0' || *line == '\n'){ + parse_inquotes = qfalse; + parse_lastpos = NULL; + return NULL; + } + line++; + } + + + } + + while(*line == ' ' || *line == ';'){ + if(*line == '\0' || *line == '\n'){ + parse_inquotes = qfalse; + parse_lastpos = NULL; + return NULL; + } + line++; + } + + if(*line == '"'){ //Check if the next token is the beginning of a quoted string + parse_inquotes = qtrue; + line++; //Move over the quotes character to the 1st real character + } + + + if(*line == '\0' || *line == '\n'){ + parse_inquotes = qfalse; + parse_lastpos = NULL; + return NULL; + } + + parse_lastpos = line; + return line; +} + + +int Com_ParseTokenLength(char* token){ + if(token == NULL) return 0; + + char* pos = token; + int i = 0; + if(parse_inquotes){//In case we are inside quotes + while(*pos != '"' && *pos != ';' && *pos != '\n' && *pos != '\0'){ + pos++; + i++; + } + + }else{//Default case + + while(*pos != ' ' && *pos != ';' && *pos != '\n' && *pos != '\0'){ + pos++; + i++; + } + } + return i; +} + + + char* G_SayCensor(char *msg) { char token2[1024]; @@ -327,11 +414,11 @@ char* G_SayCensor(char *msg) badwordsList_t *this; char* ret = msg; while(1){ - msg = Plugin_ParseGetToken(msg); + msg = Com_ParseGetToken(msg); if(msg==NULL) break; - int size = Plugin_ParseTokenLength(msg); + int size = Com_ParseTokenLength(msg); Q_strncpyz(token,msg,size+1); removeColors(token2,token,sizeof(token2)); diff --git a/plugins/declarations.h b/plugins/declarations.h index 5147970a..ac606f2d 100644 --- a/plugins/declarations.h +++ b/plugins/declarations.h @@ -1030,7 +1030,8 @@ typedef struct client_s {//90b4f8c uint64_t clanidPending; uint64_t playerid; int steamstatus; - int free1[3]; + int free1[2]; + int mutelevel; int lastFollowedClient; byte iidata[24]; diff --git a/plugins/dlang/Readme.md b/plugins/dlang/Readme.md new file mode 100644 index 00000000..d18be305 --- /dev/null +++ b/plugins/dlang/Readme.md @@ -0,0 +1 @@ +## Plugin Interface for the D Programming Language \ No newline at end of file diff --git a/plugins/dlang/cod4x/callback_declarations.d b/plugins/dlang/cod4x/callback_declarations.d new file mode 100644 index 00000000..99f67b6a --- /dev/null +++ b/plugins/dlang/cod4x/callback_declarations.d @@ -0,0 +1,26 @@ +module cod4x.callback_declarations; + +import cod4x.structs; +import cod4x.server; + +extern (C) void OnInfoRequest(pluginInfo_t *info); +extern (C) int OnInit(); +extern (C) void OnMessageSent(char* message, int slot, qboolean *show, int mode); +extern (C) void OnPreFastRestart(); +extern (C) void OnExitLevel(); +extern (C) void OnPostFastRestart(); +extern (C) void OnSpawnServer(); +extern (C) void OnFrame(); +extern (C) void OnOneSecond(); +extern (C) void OnTenSeconds(); +extern (C) void OnUdpNetEvent(netadr_t* from, void* data, int size, qboolean* returnNow); +extern (C) void OnUdpNetSend(netadr_t* to, void* data, int len, qboolean* returnNow); +extern (C) void OnPlayerConnect(int clientnum, netadr_t* netaddress, char* pbguid, char* userinfo, int authstatus, char* deniedmsg, int deniedmsgbufmaxlen); +extern (C) void OnPlayerConnectAuthFail(netadr_t* netaddress, char* pbguid, char* userinfo, int* authstatus, qboolean *denied); +extern (C) void OnPlayerDC(client_t* client, const char* reason); +extern (C) void OnClientSpawn(gentity_t* ent); +extern (C) void OnClientEnterWorld(client_t* client); +extern (C) void OnClientUserinfoChanged(client_t* client); +extern (C) void OnClientMoveCommand(client_t* client, usercmd_t* ucmd); +extern (C) void OnPlayerWantReservedSlot(netadr_t* from, char* pbguid, char* userinfo, int authstate, qboolean *isallowed); +extern (C) void OnModuleLoaded(client_t* client, char* fullpath, long checksum); \ No newline at end of file diff --git a/plugins/dlang/cod4x/functions.d b/plugins/dlang/cod4x/functions.d new file mode 100644 index 00000000..bd546bc5 --- /dev/null +++ b/plugins/dlang/cod4x/functions.d @@ -0,0 +1,172 @@ +module cod4x.functions; + +import cod4x.server; + +extern (C) char* Plugin_Cmd_Argv(int arg); // Get a command argument with index arg. +extern (C) int Plugin_Cmd_Argc(); // Get number of command arguments +extern (C) char *Plugin_Cmd_Args( char* buff, int bufsize ); + +// == Common == +extern (C) void Plugin_G_LogPrintf( const char *fmt, ... ); +extern (C) void Plugin_Printf( const char * fmt, ... ); // Print to a correct place (rcon, player console, logs) + +extern (C) void Plugin_PrintWarning( const char *fmt, ...); // Print to a correct place (rcon, player console, logs) +extern (C) void Plugin_PrintError( const char *fmt, ...); // Print to a correct place (rcon, player console, logs) +extern (C) void Plugin_DPrintf( const char *fmt, ...); // Same as Com_Printf, only shows up when developer is set to 1 +extern (C) char* Plugin_ParseGetToken(char* line); // Tokenize a string - get next token +extern (C) int Plugin_ParseTokenLength(char* token); // Tokenize a string - get the token's length +extern (C) void Plugin_ParseReset(); // Tokenize a string - Reset the parsers position +extern (C) void Plugin_Cbuf_AddText(const char* text); + +// == Cvars == + +// All of the Cvars module functions are self explanatory +extern (C) void* Plugin_Cvar_RegisterString(const char *var_name, const char *var_value, int flags, const char *var_description); +extern (C) void* Plugin_Cvar_RegisterBool(const char *var_name, qboolean var_value, int flags, const char *var_description); +extern (C) void* Plugin_Cvar_RegisterInt(const char *var_name, int var_value, int min_value, int max_value, int flags, const char *var_description); +// extern (C) void* Plugin_Cvar_RegisterEnum(const char *var_name, char** valnames, int defaultval, int flags, const char *var_description); +extern (C) void* Plugin_Cvar_RegisterFloat(const char *var_name, float var_value, float min_value, float max_value, int flags, const char *var_description); +extern (C) void Plugin_Cvar_SetInt(void* var, int val); +extern (C) void Plugin_Cvar_SetBool(void* var, qboolean val); +extern (C) void Plugin_Cvar_SetString(void* var, char* string); +extern (C) void Plugin_Cvar_SetFloat(void* var, float val); +extern (C) int Plugin_Cvar_GetInteger(void *var); +extern (C) qboolean Plugin_Cvar_GetBoolean(void *var); +extern (C) float Plugin_Cvar_GetValue(void *var); +extern (C) immutable(char)* Plugin_Cvar_GetString(immutable(char)* var); + +extern (C) void Plugin_Cvar_VariableStringBuffer(const char* cvarname, char* buff, size_t size); +extern (C) float Plugin_Cvar_VariableValue( const char *var_name ); +extern (C) int Plugin_Cvar_VariableIntegerValue( const char *var_name ); +extern (C) int Plugin_Cvar_VariableBooleanValue( const char *var_name ); +extern (C) char* Plugin_Cvar_VariableString( const char *var_name ); +// Sets a cvar by name and by a string value which gets interpreted correctly depending on the cvar type +extern (C) void Plugin_Cvar_Set( const char *var_name, const char* value ); + + +// == File handling functions == - Do we really need those? + +extern (C) int Plugin_FS_SV_FOpenFileRead(const char *filename, void *fp); // Open a file for reading +extern (C) void Plugin_FS_SV_FOpenFileWrite(const char *filename); // Open a file for writing +//extern (C) int Plugin_FS_Read(void *buffer, int len, void f); // Read data from file +//extern (C) int Plugin_FS_ReadLine(void *buffer, int len, void f); // Read a line from file +//extern (C) int Plugin_FS_Write(const void *buffer, int len, void h); // Write to file +//extern (C) qboolean Plugin_FS_FCloseFile(void f); // Cloase an open file + +//Writes the provided buffer into the file named by qpath. This is the most easiest way to write a file +extern (C) int Plugin_FS_SV_WriteFile( const char *qpath, const void *buffer, int size); + + +// == Networking == + +extern (C) int Plugin_NET_StringToAdr(const char* string, netadr_t* , netadrtype_t); +extern (C) qboolean Plugin_NET_CompareAdr (netadr_t *a, netadr_t *b); +extern (C) qboolean Plugin_NET_CompareBaseAdrMask(netadr_t *a, netadr_t *b, int netmask); +extern (C) qboolean Plugin_NET_CompareBaseAdr (netadr_t *a, netadr_t *b); +extern (C) char *Plugin_NET_AdrToString (netadr_t *a); +extern (C) char *Plugin_NET_AdrToStringShort (netadr_t *a); + + + +// == Plugin Handler's functions == + +extern (C) clientScoreboard_t Plugin_GetClientScoreboard(int clientNum); // Get the scoreboard of a player +extern (C) int Plugin_Cmd_GetInvokerUid(); // Get UID of command invoker +extern (C) int Plugin_Cmd_GetInvokerSlot(); // Get slot number of command invoker +extern (C) int Plugin_GetPlayerUid(int slot); // Get UID of a plyer +extern (C) int Plugin_GetSlotCount(); // Get number of server slots +extern (C) qboolean Plugin_IsSvRunning(); // Is server running? +extern (C) void Plugin_ChatPrintf(int slot, const char *fmt, ...); // Print to player's chat (-1 for all) +extern (C) void Plugin_BoldPrintf(int slot, const char *fmt, ...); // Print to the player's screen (-1 for all) +extern (C) char *Plugin_GetPlayerName(int slot); // Get a name of a player +//extern (C) void Plugin_AddCommand(char *name, xcommand_t command, int defaultpower); // Add a server command +extern (C) void *Plugin_Malloc(size_t size); // Same as stdlib.h function malloc +extern (C) void Plugin_Free(void *ptr); // Same as stdlib.h function free +extern (C) void Plugin_Error(int code, const char *fmt, ...); // Notify the server of an error, action depends on code parameter +extern (C) int Plugin_GetLevelTime(); // Self explanatory +extern (C) int Plugin_GetServerTime(); // Self explanatory + +// -- Functions for clients -- + +extern (C) void Plugin_DropClient( int clientnum, const char *reason ); // Kicks the client from server +extern (C) void Plugin_BanClient( uint clientnum, int seconds, int invokerid, char *reason ); //Bans the client for seconds from server. Seconds can be "-1" to create a permanent ban. invokerid can be 0 or the numeric uid. banreason can be NULL or a valid char* pointer. + +// -- TCP Connection functions -- +/* +connection is a static constant number. Every plugin can use a connection 0 up to 3. This is not a socket. This is handled internal. +You can not use the same number for 2 open connections on the same time. + +*/ +extern (C) qboolean Plugin_TcpConnect(int connection, const char* remote); // Open a new TCP connection - Returns qfalse if failed, remote can be a domainname +extern (C) int Plugin_TcpGetData(int connection, void *buf, int size); // Receive TCP data - buf and size is the receiving buffer. It returns -1 if the connection is closed. It returns 0 when no new data is available. All other return values is the number of bytes received. +extern (C) qboolean Plugin_TcpSendData(int connection, void *data, int len); // Send TCP data - buf and len point to the buffer which has the data to send. Len is the amount to bytes to send. Returns qfalse if something has failed. +extern (C) void Plugin_TcpCloseConnection(int connection); // Close an open TCP connection +extern (C) qboolean Plugin_UdpSendData(netadr_t* to, void* data, int len); // Send UDP data +extern (C) void Plugin_ServerPacketEvent(netadr_t* to, void* data, int len); // Receive UDP data + + +// -- UIDS / GUIDs -- + +extern (C) void Plugin_SetPlayerUID(int clientslot, int uid); // Set player's UID +extern (C) uint Plugin_GetPlayerUID(uint clientslot); // Get player's UID +extern (C) immutable(char)* Plugin_GetPlayerGUID(int clientslot); // Get player's GUID +extern (C) void Plugin_SetPlayerGUID(int clientslot, const char* guid); // Set player's GUID +extern (C) int Plugin_DoesServerUseUids(); // Self explanatory +extern (C) void Plugin_SetServerToUseUids(int useuids); // Self explanatory + + +// == System functions == + +extern (C) int Plugin_Milliseconds(); // Milliseconds since server start +extern (C) void Plugin_RandomBytes( byte *string, int len ); + +// == Scriptfunctions == + +extern(C) alias Fun = void function(); +extern (C) void Plugin_ScrAddFunction(immutable(char)* name, Fun fun); +//extern (C) void Plugin_ScrAddMethod(char *name, void (*function)(scr_entref_t object)); +extern (C) void Plugin_ScrReplaceFunction(immutable(char)* name, Fun fun); +//extern (C) void Plugin_ScrReplaceMethod(char *name, xfunction_t function); + +extern (C) void Plugin_Scr_AddEntity(gentity_t* ent); +extern (C) int Plugin_Scr_GetNumParam(); +extern (C) int Plugin_Scr_GetInt( int ); +extern (C) float Plugin_Scr_GetFloat( int ); +extern (C) char* Plugin_Scr_GetString( int ); +extern (C) gentity_t* Plugin_Scr_GetEntity( int ); +extern (C) short Plugin_Scr_GetConstString( int ); +extern (C) int Plugin_Scr_GetType( int ); +extern (C) void Plugin_Scr_GetVector( int, vec3_t* ); +extern (C) void Plugin_Scr_Error( const char *string); +extern (C) void Plugin_Scr_ParamError( int, const char *string); +extern (C) void Plugin_Scr_ObjectError( const char *string); +extern (C) void Plugin_Scr_AddInt(int value); +extern (C) void Plugin_Scr_AddFloat(float); +extern (C) void Plugin_Scr_AddBool(qboolean); +extern (C) void Plugin_Scr_AddString(const char *string); +extern (C) void Plugin_Scr_AddUndefined(); +extern (C) void Plugin_Scr_AddVector( vec3_t vec ); +extern (C) void Plugin_Scr_AddArray( ); +extern (C) void Plugin_Scr_MakeArray( ); +extern (C) short Plugin_Scr_ExecEntThread( gentity_t* ent, int callbackHook, int numArgs); +extern (C) short Plugin_Scr_ExecThread( int callbackHook, int numArgs); +extern (C) void Plugin_Scr_FreeThread( short threadId); + + + +extern (C) void Plugin_Scr_NotifyLevel(int constString, int numArgs); +extern (C) void Plugin_Scr_NotifyNum(int entityNum, int entType, int constString, int numArgs); +extern (C) void Plugin_Scr_Notify(gentity_t* ent, ushort constString, int numArgs); +extern (C) ushort Plugin_Scr_AllocString(const char*); + + + +extern (C) playerState_t *Plugin_SV_GameClientNum( int num ); //Retrives the playerState_t* object from a client number + +extern (C) gentity_t* Plugin_GetGentityForEntityNum(int entnum); +extern (C) client_t* Plugin_GetClientForClientNum(int clientnum); + +extern (C) char* Plugin_SL_ConvertToString(int index); + +extern (C) void Plugin_SV_SetConfigstring(int index, const char *text); +extern (C) void Plugin_SV_GetConfigstring( int index, char *buffer, int bufferSize ); \ No newline at end of file diff --git a/plugins/dlang/cod4x/plugin_declarations.d b/plugins/dlang/cod4x/plugin_declarations.d new file mode 100644 index 00000000..0635c8eb --- /dev/null +++ b/plugins/dlang/cod4x/plugin_declarations.d @@ -0,0 +1,90 @@ +/* Converted to D from plugin_declarations.h by htod */ +module cod4x.plugin_declarations; +/* +=========================================================================== + Copyright (C) 2010-2013 Ninja and TheKelm of the IceOps-Team + + This file is part of IceOps Plugin Handler source code. + + IceOps Plugin Handler source code is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + IceOps Plugin Handler source code is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see +=========================================================================== +*/ + +//C #define PLUGIN_HANDLER_VERSION_MAJOR 2 +//C #define PLUGIN_HANDLER_VERSION_MINOR 302 +const PLUGIN_HANDLER_VERSION_MAJOR = 2; +//PHandler v. 2.2 +const PLUGIN_HANDLER_VERSION_MINOR = 302; + +//C enum Plugin_Err{ // To be used as the code argument for Plugin_Error() +//C P_ERROR_WARNING, // Save the error string to serverlog - for minor errors +//C P_ERROR_DISABLE, // Save the error string to serverlog and disable the plugin - for serious errors +//C P_ERROR_TERMINATE // Save the error string to serverlog and close the server - for critical errors +//C }; +enum Plugin_Err +{ + P_ERROR_WARNING, + P_ERROR_DISABLE, + P_ERROR_TERMINATE, +} +//C typedef enum{ +//C P_HASH_SHA1, +//C P_HASH_SHA256, +//C P_HASH_TIGER +//C }pluginHash_t; +enum +{ + P_HASH_SHA1, + P_HASH_SHA256, + P_HASH_TIGER, +} +extern (C): +alias int pluginHash_t; + +//C typedef enum{ +//C P_CIPHER_AES, +//C P_CIPHER_SERPENT +//C }pluginCipher_t; +enum +{ + P_CIPHER_AES, + P_CIPHER_SERPENT, +} +alias int pluginCipher_t; + +//C typedef struct{ +//C int major; +//C int minor; +//C }version_t; +struct version_t +{ + int major; + int minor; +} + +//C typedef struct{ // To be used in OnInfoRequest +//C version_t handlerVersion; // Requested plugin handler version - mandatory field +//C version_t pluginVersion; // Version of your plugin - optional +//C char fullName[64]; // Full plugin name, short name is the filename without extension - optional +//C char shortDescription[128]; // Describe in a few words what this plugin does - optional +//C char longDescription[1024]; // Full description - optional +//C }pluginInfo_t; +struct pluginInfo_t +{ + version_t handlerVersion; + version_t pluginVersion; + char [64]fullName; + char [128]shortDescription; + char [1024]longDescription; +} diff --git a/plugins/dlang/cod4x/server.d b/plugins/dlang/cod4x/server.d new file mode 100644 index 00000000..077b5c91 --- /dev/null +++ b/plugins/dlang/cod4x/server.d @@ -0,0 +1,1495 @@ +/* Converted to D from CoD4X17a_testing/src/server.h by htod */ +module cod4x.server; + +// MAX_CHALLENGES is made large to prevent a denial +// of service attack that could cycle all of them +// out before legitimate users connected +//C #define MAX_CHALLENGES 1024 +// Allow a certain amount of challenges to have the same IP address +const MAX_CHALLENGES = 1024; +// to make it a bit harder to DOS one single IP address from connecting +// while not allowing a single ip to grab all challenge resources +//C #define MAX_CHALLENGES_MULTI (MAX_CHALLENGES / 2) +const GENTITYNUM_BITS = 10; // JPW NERVE put q3ta default back for testing // don't need to send any more +//#define GENTITYNUM_BITS 11 // don't need to send any more (SA) upped 4/21/2001 adjusted: tr_local.h (802-822), tr_main.c (1501), sv_snapshot (206) +const MAX_GENTITIES = ( 1 << GENTITYNUM_BITS ); + +// entitynums are communicated with GENTITY_BITS, so any reserved +// values thatare going to be communcated over the net need to +// also be in this range +const ENTITYNUM_NONE = ( MAX_GENTITIES - 1 ); + +/**********************************************************/ + +const ENTITYNUM_WORLD = ( MAX_GENTITIES - 2 ); +const ENTITYNUM_MAX_NORMAL = ( MAX_GENTITIES - 2 ); + +//C #define CLIENT_BASE_ADDR 0x90b4f8C + +const client_t* CLIENT_BASE_ADDR = cast(client_t*)0x90b4f8C; +//C #define MAX_QPATH 64 +//C #define GENTITYNUM_BITS 10 // JPW NERVE put q3ta default back for testing // don't need to send any more +const MAX_QPATH = 64; +//#define GENTITYNUM_BITS 11 // don't need to send any more (SA) upped 4/21/2001 adjusted: tr_local.h (802-822), tr_main.c (1501), sv_snapshot (206) +//C #define MAX_GENTITIES ( 1 << GENTITYNUM_BITS ) +//C #define MAX_STRING_CHARS 1024 +//C #define MAX_INFO_STRING 1024 +const MAX_STRING_CHARS = 1024; +//C #define MAX_RELIABLE_COMMANDS 128 +const MAX_INFO_STRING = 1024; +//C #define MAX_NAME_LENGTH 16 +const MAX_RELIABLE_COMMANDS = 128; +//C #define MAX_DOWNLOAD_WINDOW 8 +const MAX_NAME_LENGTH = 16; +//C #define MAX_OSPATH 256 +const MAX_DOWNLOAD_WINDOW = 8; +//C #define PACKET_BACKUP 32 +const MAX_OSPATH = 256; +//C #define MAX_CLIENTS 64 +const PACKET_BACKUP = 32; +//C #define NETCHAN_UNSENTBUFFER_SIZE 0x20000 +const MAX_CLIENTS = 64; +//C #define NETCHAN_FRAGMENTBUFFER_SIZE 0x800 +const NETCHAN_UNSENTBUFFER_SIZE = 0x20000; +//C #define MAX_ENT_CLUSTERS 16 +const NETCHAN_FRAGMENTBUFFER_SIZE = 0x800; +//C #define MAX_CLIENTS 64 +const MAX_ENT_CLUSTERS = 16; +//C #define MAX_CONFIGSTRINGS 2442 + +const MAX_CONFIGSTRINGS = 2442; +//C #define COD4X17A + +//C typedef enum { +//C CS_FREE, // can be reused for a new connection +//C CS_ZOMBIE, // client has been disconnected, but don't reuse + // connection for a couple seconds +//C CS_CONNECTED, // has been assigned to a client_t, but no gamestate yet +//C CS_PRIMED, // gamestate has been sent, but client hasn't sent a usercmd +//C CS_ACTIVE // client is fully in game +//C }clientState_t; +enum +{ + CS_FREE, + CS_ZOMBIE, + CS_CONNECTED, + CS_PRIMED, + CS_ACTIVE, +} +extern (C): +alias int clientState_t; + + +//******************************************************************************* + +//C struct sharedEntity_t; + +//C typedef char byte; +//C typedef int qboolean; +alias qboolean = int; +//C typedef float vec_t; +alias float vec_t; +//C typedef vec_t vec2_t[2]; +alias vec_t [2]vec2_t; +//C typedef vec_t vec3_t[3]; +alias vec_t [3]vec3_t; +//C typedef vec_t vec4_t[4]; +alias vec_t [4]vec4_t; +//C typedef vec_t vec5_t[5]; +alias vec_t [5]vec5_t; +//C typedef int clipHandle_t; +alias int clipHandle_t; + +//C typedef enum { +//C UN_VERIFYNAME, +//C UN_NEEDUID, +//C UN_OK +//C }username_t; +enum +{ + UN_VERIFYNAME, + UN_NEEDUID, + UN_OK, +} +alias int username_t; + + +//C typedef struct +//C { +//C char num; +//C char data[256]; +//C int dataLen; +//C }voices_t; +align(1) struct _N3 +{align(1): + char num; + char [256]data; + int dataLen; +} +alias _N3 voices_t; + +//C typedef struct{ +//C char command[MAX_STRING_CHARS]; +//C int cmdTime; +//C int cmdType; +//C }reliableCommands_t; +align(1) struct _N4 +{align(1): + char [1024]command; + int cmdTime; + int cmdType; +} +alias _N4 reliableCommands_t; + +//C typedef enum { +//C NS_CLIENT, +//C NS_SERVER +//C } netsrc_t; +enum +{ + NS_CLIENT, + NS_SERVER, +} +alias int netsrc_t; + +//C typedef enum { +//C NA_BAD = 0, // an address lookup failed +//C NA_BOT = 0, +//C NA_LOOPBACK = 2, +//C NA_BROADCAST = 3, +//C NA_IP = 4, +//C NA_IP6 = 5, +//C NA_TCP = 6, +//C NA_TCP6 = 7, +//C NA_MULTICAST6 = 8, +//C NA_UNSPEC = 9, +//C NA_DOWN = 10, +//C } netadrtype_t; +enum +{ + NA_BAD, + NA_BOT = 0, + NA_LOOPBACK = 2, + NA_BROADCAST, + NA_IP, + NA_IP6, + NA_TCP, + NA_TCP6, + NA_MULTICAST6, + NA_UNSPEC, + NA_DOWN, +} +alias int netadrtype_t; + +//C typedef align(1) struct { align(1)://Not Known +//C byte offHandIndex; +//C byte field_16; +//C byte field_17; +//C int field_18; +//C int field_1C; +//C } usercmd_t; +struct usercmd_t +{ + byte[32] dummy; +} + +//C typedef align(1) struct { align(1): +//C netadrtype_t type; +//C int scope_id; +//C unsigned short port; +//C int sock; //Socket FD. 0 = any socket +//C union{ +//C byte ip[4]; +//C byte ipx[10]; +//C byte ip6[16]; +//C }; + +//C }netadr_t; +align(1) struct netadr_t +{align(1): + netadrtype_t type; + int scope_id; + ushort port; + int sock; + union + { + byte [4]ip; + byte [10]ipx; + byte [16]ip6; + } +} + +//C typedef align(1) struct { align(1): + // sequencing variables +//C int outgoingSequence; +//C netsrc_t sock; +//C int dropped; // between last packet and previous +//C int incomingSequence; + + //Remote address +//C netadr_t remoteAddress; // (0x10) +//C unsigned short qport; // qport value to write when transmitting (0x24) +//C unsigned short upperqport; + // incoming fragment assembly buffer +//C int fragmentSequence; +//C int fragmentLength; +//C byte *fragmentBuffer; // Old: (0x30) +//C int fragmentBufferSize; + + // outgoing fragment buffer + // we need to space out the sending of large fragmented messages +//C qboolean unsentFragments; +//C int unsentFragmentStart; +//C int unsentLength; +//C byte *unsentBuffer; //Old: (0x44) +//C int unsentBufferSize; +//C } netchan_t; +align(1) struct netchan_t +{ +align(1): + int outgoingSequence; + netsrc_t sock; + int dropped; + int incomingSequence; + netadr_t remoteAddress; + ushort qport; + ushort upperqport; + int fragmentSequence; + int fragmentLength; + byte *fragmentBuffer; + int fragmentBufferSize; + qboolean unsentFragments; + int unsentFragmentStart; + int unsentLength; + byte *unsentBuffer; + int unsentBufferSize; +} + +//C typedef enum { +//C TR_STATIONARY, +//C TR_INTERPOLATE, // non-parametric, but interpolate between snapshots +//C TR_LINEAR, +//C TR_LINEAR_STOP, +//C TR_SINE, // value = base + sin( time / duration ) * delta +//C TR_GRAVITY +//C } trType_t; +enum +{ + TR_STATIONARY, + TR_INTERPOLATE, + TR_LINEAR, + TR_LINEAR_STOP, + TR_SINE, + TR_GRAVITY, +} +alias int trType_t; + +//C typedef align(1) struct { align(1): +//C trType_t trType; +//C int trTime; +//C int trDuration; // if non 0, trTime + trDuration = stop time +//C vec3_t trBase; +//C vec3_t trDelta; // velocity, etc +//C } trajectory_t; +align(1) struct _N11 +{ + trType_t trType; + int trTime; + int trDuration; + vec3_t trBase; + vec3_t trDelta; +} +alias _N11 trajectory_t; + + +//C typedef struct{ +//C int cullDist; +//C int period; +//C }lerp_loopFx_t; +align(1) struct _N12 +{ + int cullDist; + int period; +} +alias _N12 lerp_loopFx_t; + + +//C typedef struct{ +//C int bodyPitch; +//C int bodyRoll; +//C int steerYaw; +//C int materialTime; +//C int gunPitch; +//C int gunYaw; +//C int teamAndOwnerIndex; +//C }lerp_vehicle_t; +align(1) struct _N13 +{ +align(1): + int bodyPitch; + int bodyRoll; + int steerYaw; + int materialTime; + int gunPitch; + int gunYaw; + int teamAndOwnerIndex; +} +alias _N13 lerp_vehicle_t; + + +//C typedef struct{ +//C int lerp; +//C }lerp_soundBlend_t; +align(1) struct _N14 +{align(1): + int lerp; +} +alias _N14 lerp_soundBlend_t; + + +//C typedef struct{ +//C int launchTime; +//C }lerp_missile_t; +align(1) struct _N15 +{align(1): + int launchTime; +} +alias _N15 lerp_missile_t; + + +//C typedef struct{ +//C int leanf; +//C int movementDir; +//C }lerp_player_t; +align(1) struct _N16 +{align(1): + int leanf; + int movementDir; +} +alias _N16 lerp_player_t; + + +//C typedef struct{ +//C int data[6]; +//C }lerp_anonymous_t; +align(1) struct _N17 +{align(1): + int [6]data; +} +alias _N17 lerp_anonymous_t; + +//C typedef align(1) struct { align(1): +//C int eFlags; +//C trajectory_t pos; // for calculating position 0x0c +//C trajectory_t apos; // for calculating angles 0x30 +//C union{ +//C lerp_anonymous_t anonymous; +//C lerp_player_t player; +//C lerp_missile_t missile; +//C lerp_soundBlend_t soundBlend; +//C lerp_loopFx_t loopFx; +//C lerp_vehicle_t vehicle; +//C }u; +union _N19 +{ + lerp_anonymous_t anonymous; + lerp_player_t player; + lerp_missile_t missile; + lerp_soundBlend_t soundBlend; + lerp_loopFx_t loopFx; + lerp_vehicle_t vehicle; +} +//C }lerp_t; +align(1) struct _N18 +{align(1): + int eFlags; + trajectory_t pos; + trajectory_t apos; + _N19 u; +} +alias _N18 lerp_t; + +// entityState_t is the information conveyed from the server +// in an update message about entities that the client will +// need to render in some way +// Different eTypes may use the information in different ways +// The messages are delta compressed, so it doesn't really matter if +// the structure size is fairly large + +//C typedef align(1) struct { align(1)://Confirmed names and offsets but not types + +//C int number; // entity index //0x00 +//C int eType; // entityType_t //0x04 + +//C lerp_t lerp; + +//C int time2; //0x70 + + +//C int otherEntityNum; //0x74 shotgun sources, etc +//C int attackerEntityNum; //0x78 + +//C int groundEntityNum; //0x7c -1 = in air + +//C int loopSound; //0x80 constantly loop this sound +//C int surfType; //0x84 + + +//C clipHandle_t index; //0x88 +//C int clientNum; //0x8c 0 to (MAX_CLIENTS - 1), for players and corpses +//C int iHeadIcon; //0x90 +//C int iHeadIconTeam; //0x94 + +//C int solid; //0x98 for client side prediction, trap_linkentity sets this properly 0x98 + +//C int eventParm; //0x9c impulse events -- muzzle flashes, footsteps, etc +//C int eventSequence; //0xa0 + +//C vec4_t events; //0xa4 +//C vec4_t eventParms; //0xb4 + + // for players +//C int weapon; //0xc4 determines weapon and flash model, etc +//C int weaponModel; //0xc8 +//C int legsAnim; //0xcc mask off ANIM_TOGGLEBIT +//C int torsoAnim; //0xd0 mask off ANIM_TOGGLEBIT + +//C union{ +//C int helicopterStage; //0xd4 +//C }un1; +union _N20 +{ + int helicopterStage; +} +//C int un2; //0xd8 +//C int fTorsoPitch; //0xdc +//C int fWaistPitch; //0xe0 +//C vec4_t partBits; //0xe4 +//C } entityState_t; //sizeof(entityState_t): 0xf4 +align(1) struct entityState_s +{align(1): + int number; + int eType; + lerp_t lerp; + int time2; + int otherEntityNum; + int attackerEntityNum; + int groundEntityNum; + int loopSound; + int surfType; + clipHandle_t index; + int clientNum; + int iHeadIcon; + int iHeadIconTeam; + int solid; + int eventParm; + int eventSequence; + vec4_t events; + vec4_t eventParms; + int weapon; + int weaponModel; + int legsAnim; + int torsoAnim; + _N20 un1; + int un2; + int fTorsoPitch; + int fWaistPitch; + vec4_t partBits; +} +alias entityState_s entityState_t; + + +//C typedef align(1) struct { align(1): + //entityState_t s; //Duplicated struct is removed +//C byte linked; //0xf4 qfalse if not in any good cluster + +//C byte bmodel; //0xf5 if false, assume an explicit mins / maxs bounding box + // only set by trap_SetBrushModel +//C short unknown1; +//C int unknown2[4]; + +//C vec3_t mins, maxs; //0x108 //0x114 from SharedEntity_t + +//C int contents; // CONTENTS_TRIGGER, CONTENTS_SOLID, CONTENTS_BODY, etc + // a non-solid entity should set to 0 + +//C vec3_t absmin, absmax; //0x124 //0x130 derived from mins/maxs and origin + rotation + + // currentOrigin will be used for all collision detection and world linking. + // it will not necessarily be the same as the trajectory evaluation for the current + // time, because each entity must be moved one at a time after time is advanced + // to avoid simultanious collision issues +//C vec3_t currentOrigin; //0x13c +//C vec3_t currentAngles; //0x148 + + // when a trace call is made and passEntityNum != ENTITYNUM_NONE, + // an ent will be excluded from testing if: + // ent->s.number == passEntityNum (don't interact with self) + // ent->r.ownerNum == passEntityNum (don't interact with your own missiles) + // entity[ent->r.ownerNum].r.ownerNum == passEntityNum (don't interact with other missiles from owner) +//C short ownerNum; //0x154 +//C short unknown3; +//C int eventTime; +//C } entityShared_t; +align(1) struct _N21 +{align(1): + byte linked; + byte bmodel; + short unknown1; + int [4]unknown2; + vec3_t mins; + vec3_t maxs; + int contents; + vec3_t absmin; + vec3_t absmax; + vec3_t currentOrigin; + vec3_t currentAngles; + short ownerNum; + short unknown3; + int eventTime; +} +alias _N21 entityShared_t; + + +// the server looks at a sharedEntity, which is the start of the game's gentity_t structure +//C typedef align(1) struct { align(1): +//C entityState_t s; // communicated by server to clients +//C entityShared_t r; // shared by both the server system and game +//C } sharedEntity_t; +align(1) struct _N22 +{align(1): + entityState_t s; + entityShared_t r; +} +alias _N22 sharedEntity_t; + +//C typedef struct gentity_s gentity_t; +alias gentity_s gentity_t; + + +align(1) struct gentity_s +{align(1): + entityState_t s; + entityShared_t r; + gclient_s *client; + qboolean inuse; + int vehicle; + int field_168; + int field_16C; + int classname; + int field_174; + int field_178; + int spawnflags; + char [244]unknown; +} + +align(1) struct client_t { +align(1)://90b4f8c + clientState_t state; + int unksnapshotvar; // must timeout a few frames in a row so debugging doesn't break + int deltaMessage; // (0x8) frame last client usercmd message + qboolean rateDelayed; // true if nextSnapshotTime was set based on rate instead of snapshotMsec + netchan_t netchan; //(0x10) + //DemoData + byte[284] demofile; + qboolean demorecording; + qboolean demowaiting; + char[MAX_QPATH] demoName; + int demoArchiveIndex; + int demoMaxDeltaFrames; + int demoDeltaFrameCount; + + int authentication; + qboolean playerauthorized; + qboolean noPb; + username_t usernamechanged; + int bantime; + int clienttimeout; + int uid; + char OS; + int power; + char[33] originguid; + qboolean firstSpawn; + void *hudMsg; + int msgType; + uint currentAd; + int enteredWorldTime; + byte[MAX_GENTITIES / 8] entityNotSolid;//One bit for entity + byte[MAX_GENTITIES / 8] entityInvisible;//One bit for entity + uint clFrames; + uint clFrameCalcTime; + uint clFPS; + float jumpHeight; + int gravity; + int playerMoveSpeed; + qboolean needPassword; + qboolean needPasswordNotified; + char[32] loginname; + //Free Space + qboolean enteredWorldForFirstTime; + uint connectedTime; + char[8] xversion; + int protocol; + qboolean needupdate; + qboolean updateconnOK; + byte[110] dummy767; + byte[518] free; + + char[64] name; + + int unknownUsercmd1; //0x63c + int unknownUsercmd2; //0x640 + int unknownUsercmd3; //0x644 + int unknownUsercmd4; //0x648 + + const char* delayDropMsg; //0x64c + char[MAX_INFO_STRING] userinfo; // name, etc (0x650) + reliableCommands_t[MAX_RELIABLE_COMMANDS] reliableCommands; // (0xa50) + int reliableSequence; // (0x20e50)last added reliable message, not necesarily sent or acknowledged yet + int reliableAcknowledge; // (0x20e54)last acknowledged reliable message + int reliableSent; // last sent reliable message, not necesarily acknowledged yet + int messageAcknowledge; // (0x20e5c) + int gamestateMessageNum; // (0x20e60) netchan->outgoingSequence of gamestate + int challenge; //0x20e64 +//Unknown where the offset error is + usercmd_t lastUsercmd; //(0x20e68) + int lastClientCommand; //(0x20e88) reliable client message sequence + char[MAX_STRING_CHARS] lastClientCommandString; //(0x20e8c) + void *gentity; //(0x2128c) + + char[MAX_NAME_LENGTH] shortname; //(0x21290) extracted from userinfo, high bits masked + int wwwDl_var01; + // downloading + char[MAX_QPATH] downloadName; //(0x212a4) if not empty string, we are downloading + int download; //(0x212e4) file being downloaded + int downloadSize; //(0x212e8) total bytes (can't use EOF because of paks) + int downloadCount; //(0x212ec) bytes sent + int downloadClientBlock; //(0x212f0) last block we sent to the client, awaiting ack + int downloadCurrentBlock; //(0x212f4) current block number + int downloadXmitBlock; //(0x212f8) last block we xmited + byte *[MAX_DOWNLOAD_WINDOW]downloadBlocks; //(0x212fc) the buffers for the download blocks + int[MAX_DOWNLOAD_WINDOW] downloadBlockSize; //(0x2131c) + qboolean downloadEOF; //(0x2133c) We have sent the EOF block + int downloadSendTime; //(0x21340) time we last got an ack from the client + char[MAX_OSPATH] wwwDownloadURL; //(0x21344) URL from where the client should download the current file + + qboolean wwwDownload; // (0x21444) + qboolean wwwDownloadStarted; // (0x21448) + qboolean wwwDl_var02; // (0x2144c) + qboolean wwwDl_var03; + int nextReliableTime; // (0x21454) svs.time when another reliable command will be allowed + int floodprotect; // (0x21458) + int lastPacketTime; // (0x2145c)svs.time when packet was last received + int lastConnectTime; // (0x21460)svs.time when connection started + int nextSnapshotTime; // (0x21464) send another snapshot when svs.time >= nextSnapshotTime + int timeoutCount; + byte[0x2f84][PACKET_BACKUP] frames; // (0x2146c) updates can be delta'd from here + int ping; //(0x804ec) + int rate; //(0x804f0) // bytes / second + int snapshotMsec; //(0x804f4) // requests a snapshot every snapshotMsec unless rate choked + int unknown6; + int pureAuthentic; //(0x804fc) + byte[NETCHAN_UNSENTBUFFER_SIZE] unsentBuffer; //(0x80500) + byte[NETCHAN_FRAGMENTBUFFER_SIZE] fragmentBuffer; //(0xa0500) + char[33] pbguid; //0xa0d00 + byte pad; + short clscriptid; //0xa0d22 + int canNotReliable; + int serverId; //0xa0d28 + voices_t[40] voicedata; + int unsentVoiceData;//(0xa35f4) + byte[MAX_CLIENTS] mutedClients; + byte hasVoip;//(0xa3638) + byte[8192] stats; //(0xa3639) + byte receivedstats; //(0xa5639) + byte dummy1; + byte dummy2; +};//0x0a563c + + + +align(1) struct challenge_t { align(1): + netadr_t adr; + int challenge; + int clientChallenge; + int time; // time the last packet was sent to the autherize server + int pingTime; // time the challenge response was sent to client + int firstTime; // time the adr was first used, for authorize timeout checks + char[33] pbguid; + qboolean connected; + int ipAuthorize; +}; + + +const MAX_STREAM_SERVERS = 6; +// this structure will be cleared only when the game dll changes +const MAX_MASTER_SERVERS = 8; + + +align(1) struct connectqueue_t{ +align(1): +int challengeslot; +int firsttime; +int lasttime; +int attempts; +}; //For fair queuing players who wait for an empty slot + + + +align(1) struct _N25 +{ +align(1): + char[32] cmdname; + char[1024] cmdargument; +} +alias _N25 translatedCmds_t; + +/* + +Some Info: +svs.nextSnapshotEntities 0x13f18f94 +svs.numSnapshotEntites 0x13f18f8c +svc_snapshot = 6; +svs.snapflagServerbit 0x13f18f88 //copied from real svs. to something else + +*/ + + +//C typedef struct{ +//C int score; //0x2f78 +//C int deaths; //0x2f7c +//C int kills; //0x2f80 +//C int assists; //0x2f84 +//C }clientScoreboard_t; +align(1) struct _N26 +{ +align(1): + int score; + int deaths; + int kills; + int assists; +} +alias _N26 clientScoreboard_t; + +//C typedef struct{ +//C int sprintButtonUpRequired; +//C int sprintDelay; +//C int lastSprintStart; +//C int lastSprintEnd; +//C int sprintStartMaxLength; +//C }sprintState_t; +align(1) struct _N27 +{align(1): + int sprintButtonUpRequired; + int sprintDelay; + int lastSprintStart; + int lastSprintEnd; + int sprintStartMaxLength; +} +alias _N27 sprintState_t; + +//C typedef struct{ +//C int yaw; +//C int timer; +//C int transIndex; +//C int flags; +//C }mantleState_t; +align(1) struct _N28 +{align(1): + int yaw; + int timer; + int transIndex; + int flags; +} +alias _N28 mantleState_t; + + + +//C typedef enum { +//C CON_DISCONNECTED, +//C CON_CONNECTING, +//C CON_CONNECTED +//C } clientConnected_t; +enum +{ + CON_DISCONNECTED, + CON_CONNECTING, + CON_CONNECTED, +} +alias int clientConnected_t; + +//C typedef enum { +//C SPECTATOR_NOT, +//C SPECTATOR_FREE, +//C SPECTATOR_FOLLOW, +//C SPECTATOR_SCOREBOARD +//C } spectatorState_t; +enum +{ + SPECTATOR_NOT, + SPECTATOR_FREE, + SPECTATOR_FOLLOW, + SPECTATOR_SCOREBOARD, +} +alias int spectatorState_t; + +//C typedef enum { +//C TEAM_BEGIN, // Beginning a team game, spawn at base +//C TEAM_ACTIVE // Now actively playing +//C } playerTeamStateState_t; +enum +{ + TEAM_BEGIN, + TEAM_ACTIVE, +} +alias int playerTeamStateState_t; + +//C typedef align(1) struct { align(1): +//C playerTeamStateState_t state; + +//C int location; + +//C int captures; +//C int basedefense; +//C int carrierdefense; +//C int flagrecovery; +//C int fragcarrier; +//C int assists; + +//C float lasthurtcarrier; +//C float lastreturnedflag; +//C float flagsince; +//C float lastfraggedcarrier; +//C } playerTeamState_t; +align(1) struct _N32 +{align(1): + playerTeamStateState_t state; + int location; + int captures; + int basedefense; + int carrierdefense; + int flagrecovery; + int fragcarrier; + int assists; + float lasthurtcarrier; + float lastreturnedflag; + float flagsince; + float lastfraggedcarrier; +} +alias _N32 playerTeamState_t; + +//C typedef enum { +//C TEAM_FREE, +//C TEAM_RED, +//C TEAM_BLUE, +//C TEAM_SPECTATOR, +//C TEAM_NUM_TEAMS +//C }team_t; +enum +{ + TEAM_FREE, + TEAM_RED, + TEAM_BLUE, + TEAM_SPECTATOR, + TEAM_NUM_TEAMS, +} +alias int team_t; + +//C #pragma pack(push, 1) + +//C typedef struct +//C { +//C int buffer; +//C int msgsize; + +//C }svArchiveBuf_t; +align(1) struct _N34 +{align(1): + int buffer; + int msgsize; +} +alias _N34 svArchiveBuf_t; + +//C typedef struct clientState_s +//C { +//C int number; +//C byte b[0x60]; +//C }clientState_ts; +align(1) struct clientState_s +{align(1): + int number; + byte [96]b; +} +alias clientState_s clientState_ts; + + + +align(1) struct playerState_t +{ +align(1): + int commandTime; + int pm_type; + int bobCycle; + int pm_flags; + int weapFlags; + int otherFlags; + int pm_time; + vec3_t origin; + vec3_t velocity; + int var_01; + int var_02; + int weaponTime; + int weaponDelay; + int grenadeTimeLeft; + int throwBackGrenadeOwner; + int throwBackGrenadeTimeLeft; + int weaponRestrictKickTime; + int foliageSoundTime; + int gravity; + int leanf; + int speed; + vec3_t delta_angles; + int groundEntityNum; + vec3_t vLadderVec; + int jumpTime; + float jumpOriginZ; + int legsTimer; + int legsAnim; + int torsoTimer; + int torsoAnim; + int var_03; + int var_04; + int damageTimer; + int damageDuration; + int flinchYawAnim; + int movementDir; + int eFlags; + int eventSequence; + vec4_t events; + vec4_t eventParms; + int var_05; + int clientNum; + int offHandIndex; + int offhandSecondary; + int weapon; + int weaponstate; + int weaponShotCount; + int fWeaponPosFrac; + int adsDelayTime; + int spreadOverride; + int spreadOverrideState; + int viewmodelIndex; + vec3_t viewangles; + float viewHeightTarget; + float viewHeightCurrent; + int viewHeightLerpTime; + int viewHeightLerpTarget; + int viewHeightLerpDown; + vec2_t viewAngleClampBase; + vec2_t viewAngleClampRange; + int damageEvent; + int damageYaw; + int damagePitch; + int damageCount; + int [261]unk1; + vec4_t weapons; + vec4_t weaponold; + vec4_t weaponrechamber; + int proneDirection; + int proneDirectionPitch; + int proneTorsoPitch; + int viewlocked; + int viewlocked_entNum; + int cursorHint; + int cursorHintString; + int cursorHintEntIndex; + int iCompassPlayerInfo; + int radarEnabled; + int locationSelectionInfo; + sprintState_t sprintState; + int fTorsoPitch; + int fWaistPitch; + int holdBreathScale; + int holdBreathTimer; + int moveSpeedScaleMultiplier; + mantleState_t mantleState; + int meleeChargeYaw; + int meleeChargeDist; + int meleeChargeTime; + int perks; + vec4_t actionSlotType; + vec4_t actionSlotParam; + int var_06; + int weapAnim; + int aimSpreadScale; + int shellshockIndex; + int shellshockTime; + int shellshockDuration; + int dofNearStart; + int dofNearEnd; + int dofFarStart; + int dofFarEnd; + float dofNearBlur; + float dofFarBlur; + int dofViewmodelStart; + int dofViewmodelEnd; + int [145]unk2; + int deltaTime; + int killCamEntity; + int [2480]unk3; +} + + + + enum serverState_t{ + SS_DEAD, // no map loaded + SS_LOADING, // spawning level entities + SS_GAME // actively running +} ; + +align(1) struct svEntity_s +{align(1): + svEntity_s *nextEntityInWorldSector; + entityState_t baseline; + int numClusters; + int [16]clusternums; + int lastCluster; + int areanum; + int areanum2; + int snapshotCounter; + int [11]unk; +} +alias svEntity_s svEntity_t; + + + +const MAX_BPS_WINDOW = 20; + +align(1) struct server_t +{ +align(1): + serverState_t state; + int timeResidual; + int frameusec; + qboolean restarting; + int serverId; + int checksumFeed; + byte [2048]unk; + ushort unkConfigIndex; + ushort [2442]configstringIndex; + short unk3; + svEntity_t [1024]svEntities; + sharedEntity_t *gentities; + int gentitySize; + int num_entities; + playerState_t *gameClients; + int gameClientSize; + int field_5FB44; + int field_5FB48; + int [20]bpsWindow; + int bpsWindowSteps; + int bpsTotalBytes; + int bpsMaxBytes; + int [20]ubpsWindow; + int ubpsTotalBytes; + int ubpsMaxBytes; + float ucompAve; + int ucompNum; + char [64]gametype; + qboolean unk5; + qboolean unk6; +} + +//C #pragma pack(pop) + + + +// the auto following clients don't follow a specific client +// number, but instead follow the first two active players +//C #define FOLLOW_ACTIVE1 -1 +//C #define FOLLOW_ACTIVE2 -2 +const FOLLOW_ACTIVE1 = -1; + +const FOLLOW_ACTIVE2 = -2; +// client data that stays across multiple levels or tournament restarts +// this is achieved by writing all the data to cvar strings at game shutdown +// time and reading them back at connection time. Anything added here +// MUST be dealt with in G_InitSessionData() / G_ReadSessionData() / G_WriteSessionData() +//C typedef align(1) struct { align(1): + +//C int clientState; // 0x300c + //Most is not active +//C team_t sessionTeam; //0x3010 +//C int spectatorTime; // for determining next-in-line to play +//C spectatorState_t spectatorState; +//C int spectatorClient_Unknown; // for chasecam and follow mode +//C int wins, losses; // tournament stats +//C int playerType; // DHM - Nerve :: for GT_WOLF +//C int playerWeapon; // DHM - Nerve :: for GT_WOLF +// int playerItem; // DHM - Nerve :: for GT_WOLF +//C int playerTagIndex; //0x3030 +//C int playerSkin; // DHM - Nerve :: for GT_WOLF +// int spawnObjectiveIndex; // JPW NERVE index of objective to spawn nearest to (returned from UI) +//C int latchPlayerType; // DHM - Nerve :: for GT_WOLF not archived +//C int latchPlayerWeapon; // DHM - Nerve :: for GT_WOLF not archived +//C int latchPlayerItem; // DHM - Nerve :: for GT_WOLF not archived +//C int latchPlayerSkin; // DHM - Nerve :: for GT_WOLF not archived +//C char netname[MAX_NAME_LENGTH]; //0x3048 +//C int lastFollowedClient; +//C int rank; //0x305c +//C int prestige; //0x3060 +//C int perkIndex; //0x3064 +//C int vehicleOwnerNum; //0x3068 //Mybe vehicletype ? +//C int vehicleRideSlot; //0x306c +//C int PSOffsetTime; //0x3070 ??? +//C int spectatorClient; //0x3074 for chasecam and follow mode +//C } clientSession_t; +align(1) struct clientSession_t +{align(1): + int clientState; + team_t sessionTeam; + int spectatorTime; + spectatorState_t spectatorState; + int spectatorClient_Unknown; + int wins; + int losses; + int playerType; + int playerWeapon; + int playerTagIndex; + int playerSkin; + int latchPlayerType; + int latchPlayerWeapon; + int latchPlayerItem; + int latchPlayerSkin; + char [16]netname; + int lastFollowedClient; + int rank; + int prestige; + int perkIndex; + int vehicleOwnerNum; + int vehicleRideSlot; + int PSOffsetTime; + int spectatorClient; +} + +//C #define MAX_NETNAME 16 + +const MAX_NETNAME = 16; +//C #define PICKUP_ACTIVATE 0 // pickup items only when using "+activate" +//C #define PICKUP_TOUCH 1 // pickup items when touched +const PICKUP_ACTIVATE = 0; +//C #define PICKUP_FORCE 2 // pickup the next item when touched (and reset to PICKUP_ACTIVATE when done) +const PICKUP_TOUCH = 1; + +const PICKUP_FORCE = 2; +// client data that stays across multiple respawns, but is cleared +// on each level change or team change at ClientBegin() +//C typedef align(1) struct { align(1): + +//C enum{ STATE_PLAYING, STATE_DEAD, +//C STATE_SPECTATOR, STATE_INTERMISSION +//C }playerState;//0x2f64 +enum +{ + STATE_PLAYING, + STATE_DEAD, + STATE_SPECTATOR, + STATE_INTERMISSION, +} + +//C int unknownStateVar; //0x2f68 +//C int unknownStateVar2; //0x2f6c +//C int unknown[2]; //0x2f70 + +//C clientScoreboard_t scoreboard; //0x2f78 +//C qboolean initialSpawn; //0x2f88 the first spawn should be at a cool location +//C clientConnected_t connected; //0x2f8c maybe +//C usercmd_t cmd; //0x2f90 we would lose angles if not persistant +//C usercmd_t oldcmd; //0x2fb0 previous command processed by pmove() +//C qboolean localClient; //0x2fd0 true if "ip" info key is "localhost" + +//C qboolean predictItemPickup; //0x2fd4 based on cg_predictItems userinfo +//C char netname[MAX_NETNAME]; //0x2fd8 + +//C int maxHealth; // 0x2fe8 for handicapping +//C int enterTime; // 0x2fec level.time the client entered the game +//C int connectTime; // DHM - Nerve :: level.time the client first connected to the server // N/A +// playerTeamState_t teamState; // status in teamplay games +//C int voteCount; // 0x2ff4 to prevent people from constantly calling votes +//C int teamVoteCount; // to prevent people from constantly calling votes // N/A + +//C int moveSpeedScale; // 0x2ffc + +//C int viewModel; // 0x3000 //Model-index + +//C int clientCanSpectate; // 0x3004 +//C int freeaddr1; // 0x3008 + +//C } clientPersistant_t; +align(1) struct _N46 +{align(1): + int playerState; + int unknownStateVar; + int unknownStateVar2; + int [2]unknown; + clientScoreboard_t scoreboard; + qboolean initialSpawn; + clientConnected_t connected; + usercmd_t cmd; + usercmd_t oldcmd; + qboolean localClient; + qboolean predictItemPickup; + char [16]netname; + int maxHealth; + int enterTime; + int connectTime; + int voteCount; + int teamVoteCount; + int moveSpeedScale; + int viewModel; + int clientCanSpectate; + int freeaddr1; +} +alias _N46 clientPersistant_t; + + +//C typedef align(1) struct { align(1): +//C vec3_t mins; +//C vec3_t maxs; + +//C vec3_t origin; + +//C int time; +//C int servertime; +//C } clientMarker_t; +align(1) struct _N48 +{align(1): + vec3_t mins; + vec3_t maxs; + vec3_t origin; + int time; + int servertime; +} +alias _N48 clientMarker_t; + +//C #define MAX_CLIENT_MARKERS 10 + +const MAX_CLIENT_MARKERS = 10; +//C #define LT_SPECIAL_PICKUP_MOD 3 // JPW NERVE # of times (minus one for modulo) LT must drop ammo before scoring a point +//C #define MEDIC_SPECIAL_PICKUP_MOD 4 // JPW NERVE same thing for medic +const LT_SPECIAL_PICKUP_MOD = 3; + +const MEDIC_SPECIAL_PICKUP_MOD = 4; + + + +//C typedef align(1) struct { align(1): +//C void* dummy; +//C }animModelInfo_t; //Dummy +align(1) struct _N49 +{align(1): + void *dummy; +} +alias _N49 animModelInfo_t; + + +//C typedef align(1) struct { align(1): +//C qboolean bAutoReload; // do we predict autoreload of weapons +//C int blockCenterViewTime; // don't let centerview happen for a little while + + // Arnout: MG42 aiming +//C float varc, harc; +//C vec3_t centerangles; + +//C } pmoveExt_t; // data used both in client and server - store it here +align(1) struct _N50 +{align(1): + qboolean bAutoReload; + int blockCenterViewTime; + float varc; + float harc; + vec3_t centerangles; +} +alias _N50 pmoveExt_t; + + +//C typedef struct gclient_s gclient_t; +alias gclient_s gclient_t; + + +// this structure is cleared on each ClientSpawn(), +// except for 'client->pers' and 'client->sess' +//C align(1) struct { align(1): + // ps MUST be the first element, because the server expects it +//C playerState_t ps; //0x00 communicated by server to clients + + // the rest of the structure is private to game + +//C clientPersistant_t pers; //0x2f64 +//C clientSession_t sess; //0x3010 + +//C qboolean noclip; //0x3078 +//C qboolean ufo; //0x307c +//C qboolean freezeControls; //0x3080 + +//C int lastCmdTime; //0x3084 level.time of last usercmd_t, for EF_CONNECTION + // we can't just use pers.lastCommand.time, because + // of the g_sycronousclients case + //Buttonlogic/exact addresses is not known but scope +//C int buttons; //0x3088 +//C int oldbuttons; +//C int unk1; +//C int latched_buttons; //0x3094 + +//C int wbuttons; +//C int oldwbuttons; +//C int latched_wbuttons; + + // sum up damage over an entire frame, so + // shotgun blasts give a single big kick +//C int damage_armor; //0x30a4 damage absorbed by armor +//C int damage_blood; // damage taken out of health +//C int damage_knockback; // impact damage +//C vec3_t damage_from; //0x30b0 origin for vector calculation +//C qboolean damage_fromWorld; //0x30bc if true, don't use the damage_from vector + +//C int accurateCount; // for "impressive" reward sound N/A + +//C int accuracy_shots; // total number of shots N/A +//C int accuracy_hits; // total number of hits N/A + + // +// int lastkilled_client; // last client that this client killed +// int lasthurt_client; // last client that damaged this client +// int lasthurt_mod; // type of damage the client did + + // timers +// int respawnTime; // can respawn when time > this, force after g_forcerespwan +//C int inactivityTime; //0x30cc kick players when time > this +//C qboolean inactivityWarning; //0x30d0 qtrue if the five second warning has been given +//C int playerTalkTime; //0x30d4 ?? +//C int rewardTime; // clear the EF_AWARD_IMPRESSIVE, etc when time > this N/A +//C vec3_t unk; //0x30dc + + +//C int airOutTime; //0x30e8 Unknown only reset + +//C int lastKillTime; // ???for multiple kill rewards +//C int dummy34; + +//C qboolean fireHeld; // ???used for hook +//C gentity_t *hook; //0x30f8 grapple hook if out + +//C int switchTeamTime; //0x30fc time the player switched teams + + + +//C int IMtooLazy[33]; + //Not anymore resolved + + // timeResidual is used to handle events that happen every second + // like health / armor countdowns and regeneration +/* int timeResidual; + + float currentAimSpreadScale; + + int medicHealAmt; + + // RF, may be shared by multiple clients/characters + animModelInfo_t *modelInfo; + + // ------------------------------------------------------------------------------------------- + // if working on a post release patch, new variables should ONLY be inserted after this point + + gentity_t *persistantPowerup; + int portalID; + int ammoTimes[WP_NUM_WEAPONS]; + int invulnerabilityTime; + + gentity_t *cameraPortal; // grapple hook if out + vec3_t cameraOrigin; + + int dropWeaponTime; // JPW NERVE last time a weapon was dropped + int limboDropWeapon; // JPW NERVE weapon to drop in limbo + int deployQueueNumber; // JPW NERVE player order in reinforcement FIFO queue + int sniperRifleFiredTime; // JPW NERVE last time a sniper rifle was fired (for muzzle flip effects) + float sniperRifleMuzzleYaw; // JPW NERVE for time-dependent muzzle flip in multiplayer + int lastBurnTime; // JPW NERVE last time index for flamethrower burn + int PCSpecialPickedUpCount; // JPW NERVE used to count # of times somebody's picked up this LTs ammo (or medic health) (for scoring) + int saved_persistant[MAX_PERSISTANT]; // DHM - Nerve :: Save ps->persistant here during Limbo + + // g_antilag.c + int topMarker; + clientMarker_t clientMarkers[MAX_CLIENT_MARKERS]; + clientMarker_t backupMarker; + + gentity_t *tempHead; // Gordon: storing a temporary head for bullet head shot detection + + pmoveExt_t pmext;*/ +//C };//Size: 0x3184 +align(1) struct gclient_s +{align(1): + playerState_t ps; + clientPersistant_t pers; + clientSession_t sess; + qboolean noclip; + qboolean ufo; + qboolean freezeControls; + int lastCmdTime; + int buttons; + int oldbuttons; + int unk1; + int latched_buttons; + int wbuttons; + int oldwbuttons; + int latched_wbuttons; + int damage_armor; + int damage_blood; + int damage_knockback; + vec3_t damage_from; + qboolean damage_fromWorld; + int accurateCount; + int accuracy_shots; + int accuracy_hits; + int inactivityTime; + qboolean inactivityWarning; + int playerTalkTime; + int rewardTime; + vec3_t unk; + int airOutTime; + int lastKillTime; + int dummy34; + qboolean fireHeld; + gentity_t *hook; + int switchTeamTime; + //int [33]IMtooLazy; + + int[6] unknown; + float pitch; + float yaw; + + float delta0; + float delta1; + float delta2; + + float[3] animationStuff; + int[4] padding; + float playing; // [0,1] after spawn, stays 1 while playing, 0 when spectating + + float[3] vec1; + float[3] vec2; + + int[2] someTimeCounters; + int weisnicht; + int alive; // == 18 alive + int[4] unkown; +} + + +//C char* SV_IsGUID(char* guid); +char * SV_IsGUID(char *guid); + + + + + diff --git a/plugins/dlang/cod4x/structs.d b/plugins/dlang/cod4x/structs.d new file mode 100644 index 00000000..6b497530 --- /dev/null +++ b/plugins/dlang/cod4x/structs.d @@ -0,0 +1,39 @@ +module cod4x.structs; + +import std.conv; +import cod4x.plugin_declarations; + +const PLUGIN_HANDLER_VERSION_MAJOR = 2; +const PLUGIN_HANDLER_VERSION_MINOR = 302; + +alias qboolean = int; + +align(1) struct pluginInfo_t{ // To be used in OnInfoRequest +align(1): + version_t handlerVersion; // Requested plugin handler version - mandatory field + version_t pluginVersion; // Version of your plugin - optional + char[64] fullName; // Full plugin name, short name is the filename without extension - optional + char[128] shortDescription; // Describe in a few words what this plugin does - optional + char[1024] longDescription; // Full description - optional +} + +enum netadrtype_t { + NA_BAD = 0, // an address lookup failed + NA_BOT = 0, + NA_LOOPBACK = 2, + NA_BROADCAST = 3, + NA_IP = 4, + NA_IP6 = 5, + NA_TCP = 6, + NA_TCP6 = 7, + NA_MULTICAST6 = 8, + NA_UNSPEC = 9, + NA_DOWN = 10, +} ; + +enum netsrc_t { + NS_CLIENT, + NS_SERVER +} ; + +const NET_ADDRSTRMAXLEN = 48; // maximum length of an IPv6 address string including trailing '\0' diff --git a/plugins/dlang/functions.d b/plugins/dlang/functions.d new file mode 100644 index 00000000..52d9a3d7 --- /dev/null +++ b/plugins/dlang/functions.d @@ -0,0 +1,131 @@ +module functions; + +import std.string; +import cod4x.functions; +import misc; + +int Plugin_Milliseconds() { + return cod4x.functions.Plugin_Milliseconds(); +} + +auto Plugin_GetPlayerUID(int slot) +{ + return cod4x.functions.Plugin_GetPlayerUID(slot); +} + +auto Plugin_GetPlayerName(int slot) +{ + char* rawname = cod4x.functions.Plugin_GetPlayerName(slot); + import std.conv : to; + return fromStringz(rawname).to!string; +} + +GUID Plugin_GetPlayerGUID(int slot) +{ + immutable(char)* erg = cod4x.functions.Plugin_GetPlayerGUID(slot); + GUID g; + for(int i = 0; i < 32; i++) + g[i] = *(erg+i); + return g; +} + +void Plugin_Printf(string str) +{ + cod4x.functions.Plugin_Printf(str.toStringz()); +} + +void Plugin_Printf(string str, int i) +{ + cod4x.functions.Plugin_Printf(str.toStringz(), i); +} + +void Plugin_ChatPrintf(int slot, string str) +{ + cod4x.functions.Plugin_ChatPrintf(slot, str.toStringz()); +} + +void Plugin_BoldPrintf(int slot, string str) +{ + cod4x.functions.Plugin_BoldPrintf(slot, str.toStringz()); +} + +void Plugin_DropClient(int slot, string reason) +{ + cod4x.functions.Plugin_DropClient(slot, reason.toStringz()); +} + +string Plugin_Cvar_GetString(string var) +{ + immutable(char)* arg = toStringz(var); + immutable(char)* erg = cod4x.functions.Plugin_Cvar_GetString(arg); + return fromStringz(erg); +} + +int Plugin_Cvar_VariableIntegerValue(string var) +{ + immutable(char)* arg = toStringz(var); + return cod4x.functions.Plugin_Cvar_VariableIntegerValue(arg); +} + +string Plugin_Cvar_VariableString(string var) +{ + immutable(char)* arg = toStringz(var); + char* erg = cod4x.functions.Plugin_Cvar_VariableString(arg); + + import std.conv; + return fromStringz(erg).to!string; +} + +/*void Plugin_Cvar_SetString(string var, string val) +{ + import std.conv; + cod4x.functions.Plugin_Cvar_SetString(toStringz(var), toStringz(val)); +}*/ + +void Plugin_Exec(string cmd) +{ + char* arg = cast(char*)toStringz(cmd); + Plugin_Cbuf_AddText(arg); +} + +void Plugin_Scr_AddString(string str) +{ + cod4x.functions.Plugin_Scr_AddString(str.toStringz); +} + +void Plugin_Scr_AddInt(int value) +{ + cod4x.functions.Plugin_Scr_AddInt(value); +} + +void PluginNotifyPlayer(int slot, ushort str, int args) +{ + cod4x.server.gentity_t* ent = cod4x.functions.Plugin_GetGentityForEntityNum(slot); + cod4x.functions.Plugin_Scr_Notify(ent, str, args); +} + +/*void PluginNotifyLevel(ushort str, int args) +{ + cod4x.functions.Plugin_Scr_Notify(str, args); +}*/ + +ushort Plugin_Scr_AllocString(string message) +{ + return cod4x.functions.Plugin_Scr_AllocString(message.toStringz); +} + +/*void PluginNotifyPlayer(int slot, ushort str, int args) +{ + cod4x.server.gentity_t* ent = cod4x.functions.Plugin_GetGentityForEntityNum(slot); + cod4x.functions.Plugin_Scr_Notify(ent, str, args); +}*/ + +/*void Plugin_Scr_NotifyLevel(ushort str, int numArgs) +{ + cod4x.functions.Plugin_Scr_NotifyLevel(str, numArgs); +}*/ + +void Cvar_RegisterString(string variable, string value, string desc) +{ + cod4x.functions.Plugin_Cvar_RegisterString(variable.toStringz,value.toStringz,0,desc.toStringz); +} \ No newline at end of file diff --git a/plugins/function_declarations.h b/plugins/function_declarations.h index 752539ff..a3a8b8e8 100644 --- a/plugins/function_declarations.h +++ b/plugins/function_declarations.h @@ -36,6 +36,12 @@ __cdecl int Plugin_Cmd_Argc(); // Get number of command arguments __cdecl char *Plugin_Cmd_Args( char* buff, int bufsize ); + //Retrives the player info + __cdecl uint64_t Plugin_SV_Cmd_GetPlayerSteamIDByHandle( const char* handle); + __cdecl const char* Plugin_SV_Cmd_GetPlayerNameByHandle( const char* handle); + __cdecl client_t* Plugin_SV_Cmd_GetPlayerClByHandle( const char* handle); + __cdecl uint64_t Plugin_SV_Cmd_GetPlayerIDByHandle( const char* handle); + // == Common == __cdecl void Plugin_G_LogPrintf( const char *fmt, ... ); __cdecl void Plugin_Printf( const char *fmt, ...); // Print to a correct place (rcon, player console, logs) @@ -163,8 +169,6 @@ // == Plugin Handler's functions == __cdecl clientScoreboard_t Plugin_GetClientScoreboard(int clientNum); // Get the scoreboard of a player - __cdecl int Plugin_Cmd_GetInvokerUid(); // Get UID of command invoker - __cdecl int Plugin_Cmd_GetInvokerSlot(); // Get slot number of command invoker __cdecl int Plugin_GetPlayerUid(int slot); // Get UID of a plyer __cdecl int Plugin_GetSlotCount(); // Get number of server slots __cdecl qboolean Plugin_IsSvRunning(); // Is server running? @@ -183,21 +187,28 @@ // -- Functions for clients -- __cdecl void Plugin_DropClient( int clientnum, const char *reason ); // Kicks the client from server - __cdecl void Plugin_BanClient( unsigned int clientnum, int seconds, int invokerid, char *reason ); //Bans the client for seconds from server. Seconds can be "-1" to create a permanent ban. invokerid can be 0 or the numeric uid. banreason can be NULL or a valid char* pointer. + __cdecl void Plugin_BanClient( unsigned int clientnum, int minutes, int invokerid, char *reason ); //Bans the client for minutes from server. minutes can be "-1" to create a permanent ban. invokerid can be 0 or the numeric uid. banreason can be NULL or a valid char* pointer. // -- TCP Connection functions -- /* connection is a static constant number. Every plugin can use a connection 0 up to 3. This is not a socket. This is handled internal. You can not use the same number for 2 open connections on the same time. + !!!Attention: Behaviour has changed!!! */ __cdecl qboolean Plugin_TcpConnect(int connection, const char* remote); // Open a new TCP connection - Returns qfalse if failed, remote can be a domainname + __cdecl qboolean Plugin_TcpConnectMT(int pluginID, int connection, const char* remote); //Threadsafe needs plugin ID __cdecl int Plugin_TcpGetData(int connection, void *buf, int size); // Receive TCP data - buf and size is the receiving buffer. It returns -1 if the connection is closed. It returns 0 when no new data is available. All other return values is the number of bytes received. - __cdecl qboolean Plugin_TcpSendData(int connection, void *data, int len); // Send TCP data - buf and len point to the buffer which has the data to send. Len is the amount to bytes to send. Returns qfalse if something has failed. + __cdecl int Plugin_TcpGetDataMT(int pluginID, int connection, void *buf, int size); //Threadsafe needs plugin ID + __cdecl int Plugin_TcpSendData(int connection, void *data, int len); // Send TCP data - buf and len point to the buffer which has the data to send. Len is the amount to bytes to send. Returns -1 if connection got closed. Returns 0 if nothing could be sent. All other values are the sent data + __cdecl int Plugin_TcpSendDataMT(int pluginID, int connection, void *data, int len); //Threadsafe needs plugin ID __cdecl void Plugin_TcpCloseConnection(int connection); // Close an open TCP connection + __cdecl void Plugin_TcpCloseConnectionMT(int pluginID, int connection); //Threadsafe needs plugin ID __cdecl qboolean Plugin_UdpSendData(netadr_t* to, void* data, int len); // Send UDP data __cdecl void Plugin_ServerPacketEvent(netadr_t* to, void* data, int len); // Receive UDP data + //Plugin ID + __cdecl int Plugin_GetPluginID(); //Call this from the mainthread after init and store it in a global/static variable // -- UIDS / GUIDs -- __cdecl uint64_t Plugin_GetPlayerID(unsigned int clientslot);//Get the ID from player @@ -267,12 +278,15 @@ __cdecl void Plugin_SV_GetConfigstring( int index, char *buffer, int bufferSize ); /* If someone called a command the following functions return data about who invoked it */ + __cdecl int Plugin_Cmd_GetInvokerSlot(); //clientnum of commandinvoker. -1 if undefined __cdecl int Plugin_Cmd_GetInvokerUID(); //UID of commandinvoker. 0 if undefined __cdecl int Plugin_Cmd_GetInvokerClnum(); //Client slot number of invoker. -1 if undefined __cdecl int Plugin_Cmd_GetInvokerPower(); //Power points of command invoker. 100 if undefined or have all permissions __cdecl uint64_t Plugin_Cmd_GetInvokerSteamID(); //Steam ID of invoker. 0 if undefined __cdecl const char* Plugin_Cmd_GetInvokerName(char *buf, int len); //Playername/stored name of command invoker. "" if undefined + __cdecl qboolean Plugin_CanPlayerUseCommand(int clientnum, const char* commandname); //Returns if the player is allowed to use this command (power) + /* For converting IDs */ void Plugin_SteamIDToString(uint64_t steamid, char* string, int length); void Plugin_SteamIDTo64String(uint64_t steamid, char* string, int length); diff --git a/plugins/legacybanlist/main.c b/plugins/legacybanlist/main.c index c8251b5d..3707cf0f 100644 --- a/plugins/legacybanlist/main.c +++ b/plugins/legacybanlist/main.c @@ -18,13 +18,13 @@ along with this program. If not, see =========================================================================== */ - -#include "../pinc.h" -#include "q_shared.h" #include #include #include +#include "../pinc.h" +#include "q_shared.h" + #define MAX_NAME_LENGTH 33 #define BANLIST_DEFAULT_SIZE sizeof(banList_t)*128 diff --git a/plugins/legacybanlist/makedll.sh b/plugins/legacybanlist/makedll.sh new file mode 100644 index 00000000..3c2490bd --- /dev/null +++ b/plugins/legacybanlist/makedll.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +echo Compiling: release +gcc -m32 -Wall -O1 -s -fvisibility=hidden -mtune=core2 -c *.c + +echo Linking +gcc -m32 -s -shared -o legacybanlist.so *.o +echo Cleaning up +rm *.o + diff --git a/plugins/legacybanlist/makedll_win32.cmd b/plugins/legacybanlist/makedll_win32.cmd index a823c15e..357b0a3c 100644 --- a/plugins/legacybanlist/makedll_win32.cmd +++ b/plugins/legacybanlist/makedll_win32.cmd @@ -7,7 +7,7 @@ echo Compiling: release gcc -m32 -Wall -O1 -s -mtune=core2 -c *.c echo Linking -gcc -m32 -s -shared -o simplebanlist.dll *.o -L..\ -lcom_plugin +gcc -m32 -s -shared -o legacybanlist.dll *.o -L..\ -lcom_plugin echo Cleaning up del *.o diff --git a/plugins/legacybanlist/q_shared.h b/plugins/legacybanlist/q_shared.h index 37ab0b1c..7bbe1fa7 100644 --- a/plugins/legacybanlist/q_shared.h +++ b/plugins/legacybanlist/q_shared.h @@ -27,7 +27,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // A user mod should never modify this file #include #include - +#include #ifdef _MSC_VER /* #pragma warning(disable : 4018) // signed/unsigned mismatch diff --git a/plugins/legacybanlist/qshared.c b/plugins/legacybanlist/qshared.c index b97fc9be..41666d64 100644 --- a/plugins/legacybanlist/qshared.c +++ b/plugins/legacybanlist/qshared.c @@ -19,16 +19,16 @@ along with this program. If not, see =========================================================================== */ - -#include "../pinc.h" -#include "q_shared.h" - #include #include #include #include #include +#include "../pinc.h" +#include "q_shared.h" + + short ShortSwap (short l) { byte b1,b2; @@ -495,7 +495,11 @@ int QDECL Com_sprintfUni(wchar_t *dest, size_t size, const wchar_t *fmt, ...) numchar = size / sizeof(wchar_t); va_start (argptr,fmt); +#ifdef _WIN32 len = vsnwprintf (dest, numchar, fmt, argptr ); +#else + len = vswprintf (dest, numchar, fmt, argptr ); +#endif va_end (argptr); if(len < 0 || len >= numchar) diff --git a/plugins/libcom_plugin.a b/plugins/libcom_plugin.a index c09f59c3..36e45516 100644 Binary files a/plugins/libcom_plugin.a and b/plugins/libcom_plugin.a differ diff --git a/plugins/pchat/makedll.sh b/plugins/pchat/makedll.sh new file mode 100644 index 00000000..d474764c --- /dev/null +++ b/plugins/pchat/makedll.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +echo Compiling: release +gcc -m32 -Wall -O1 -g -fvisibility=hidden -mtune=core2 -c *.c + +echo Linking +gcc -m32 -g -shared -o pchat.so *.o +echo Cleaning up +rm *.o + diff --git a/plugins/pchat/pchat.c b/plugins/pchat/pchat.c new file mode 100644 index 00000000..77c17ad7 --- /dev/null +++ b/plugins/pchat/pchat.c @@ -0,0 +1,97 @@ +/* This file has been generated by the Hex-Rays decompiler. + Copyright (c) 2007-2014 Hex-Rays + + Detected compiler: GNU C++ +*/ + +#include +#include +#include +#include +#include "../pinc.h" + +#define CMDNAME "pchat" + + +//------------------------------------------------------------------------- +// Function declarations + +void __cdecl SendChatToAllAdmins(const char *a1, const char *line); +void SV_PChatCmd_f(); + +//------------------------------------------------------------------------- +// Data declarations + + +//----- (00000720) -------------------------------------------------------- +void __cdecl SendChatToAllAdmins(const char *a1, const char *line) +{ + int i; // ebx@1 + + for ( i = 0; i < Plugin_GetSlotCount(); ++i ) + { + if ( Plugin_CanPlayerUseCommand(i, CMDNAME) ) + { + Plugin_ChatPrintf(i, "^3[^0AdminChat^3]^7 (%s^7): %s", a1, line); + } + } +} +// 1C48: using guessed type int Plugin_GetSlotCount(void); +// 1C5C: using guessed type int Plugin_ChatPrintf(_DWORD, const char *, ...); +// 1C6C: using guessed type int __cdecl Plugin_GetClientForClientNum(_DWORD); + +//----- (0000077D) -------------------------------------------------------- +void SV_PChatCmd_f() +{ + int clientnum; // eax@5 + const char *chattername; // eax@5 + char line[256]; // [sp+10h] [bp-108h]@3 + + if ( Plugin_Cmd_Argc() > 1 ) + { + Plugin_Cmd_Args(line, sizeof(line)); + if ( Plugin_Cmd_GetInvokerSlot() >= 0 ) + { + clientnum = Plugin_Cmd_GetInvokerSlot(); + chattername = Plugin_GetPlayerName(clientnum); + SendChatToAllAdmins(chattername, line); + } + else + { + SendChatToAllAdmins("Server", line); + } + } + else + { + Plugin_Printf("Usage: $pchat \n^3This command is used to send messages to other admins.\n^3Only admins who are logged in will be able to see your messages and communicate using the admin chat system\n"); + } +} +// 1C54: using guessed type int Plugin_Cmd_Argc(void); +// 1C58: using guessed type int __cdecl Plugin_Cmd_Args(_DWORD, _DWORD); +// 1C64: using guessed type int __cdecl Plugin_Printf(_DWORD); +// 1C74: using guessed type int Plugin_Cmd_GetInvokerSlot(void); + + +PCL void OnInfoRequest(pluginInfo_t *info){ // Function used to obtain information about the plugin + // Memory pointed by info is allocated by the server binary, just fill in the fields + + // ===== MANDATORY FIELDS ===== + info->handlerVersion.major = PLUGIN_HANDLER_VERSION_MAJOR; + info->handlerVersion.minor = PLUGIN_HANDLER_VERSION_MINOR; // Requested handler version + + // ===== OPTIONAL FIELDS ===== + info->pluginVersion.major = 1; + info->pluginVersion.minor = 0; // Plugin version + strncpy(info->fullName,"Private Chat Plugin by NNJ", sizeof(info->fullName)); //Full plugin name + strncpy(info->shortDescription,"Private Chat Plugin by NNJ",sizeof(info->shortDescription)); // Short plugin description + strncpy(info->longDescription,"This plugin is used to privately chat with admins while in-game. Plugin By NNJ.",sizeof(info->longDescription)); +} + +//----- (00000878) -------------------------------------------------------- +int OnInit() +{ + Plugin_AddCommand(CMDNAME, SV_PChatCmd_f, 10); + return 0; +} + +// ALL OK, 10 function(s) have been successfully decompiled diff --git a/plugins/plugin_declarations.h b/plugins/plugin_declarations.h index 68859c83..7d9c5f33 100644 --- a/plugins/plugin_declarations.h +++ b/plugins/plugin_declarations.h @@ -19,8 +19,8 @@ =========================================================================== */ -#define PLUGIN_HANDLER_VERSION_MAJOR 2 -#define PLUGIN_HANDLER_VERSION_MINOR 302 +#define PLUGIN_HANDLER_VERSION_MAJOR 3 +#define PLUGIN_HANDLER_VERSION_MINOR 100 //PHandler v. 2.2 enum Plugin_Err{ // To be used as the code argument for Plugin_Error() diff --git a/plugins/simplebanlist/main.c b/plugins/simplebanlist/main.c index 01979929..a71bbb97 100644 --- a/plugins/simplebanlist/main.c +++ b/plugins/simplebanlist/main.c @@ -20,11 +20,13 @@ */ #include "../pinc.h" -#include "q_shared.h" +#include #include #include #include +#include "q_shared.h" + #define MAX_NAME_LENGTH 33 #define BANLIST_DEFAULT_SIZE sizeof(banList_t)*128 diff --git a/plugins/simplebanlist/makedll.sh b/plugins/simplebanlist/makedll.sh new file mode 100644 index 00000000..a98f3445 --- /dev/null +++ b/plugins/simplebanlist/makedll.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +echo Compiling: release +gcc -m32 -Wall -O1 -g -fvisibility=hidden -mtune=core2 -c *.c + +echo Linking +gcc -m32 -g -shared -o simplebanlist.so *.o +echo Cleaning up +rm *.o + diff --git a/plugins/simplebanlist/qshared.c b/plugins/simplebanlist/qshared.c index b97fc9be..aec748e6 100644 --- a/plugins/simplebanlist/qshared.c +++ b/plugins/simplebanlist/qshared.c @@ -21,13 +21,14 @@ */ #include "../pinc.h" -#include "q_shared.h" - #include #include #include #include + #include +#include "q_shared.h" + short ShortSwap (short l) { @@ -495,7 +496,11 @@ int QDECL Com_sprintfUni(wchar_t *dest, size_t size, const wchar_t *fmt, ...) numchar = size / sizeof(wchar_t); va_start (argptr,fmt); +#ifdef _WIN32 len = vsnwprintf (dest, numchar, fmt, argptr ); +#else + len = vswprintf (dest, numchar, fmt, argptr ); +#endif va_end (argptr); if(len < 0 || len >= numchar) diff --git a/plugins/sourcebansplugin/main.c b/plugins/sourcebansplugin/main.c index b6956c37..1b607239 100644 --- a/plugins/sourcebansplugin/main.c +++ b/plugins/sourcebansplugin/main.c @@ -18,29 +18,15 @@ along with this program. If not, see =========================================================================== */ - - - - -/* -#include "qcommon_io.h" -#include "qcommon.h" -#include "filesystem.h" -#include "cvar.h" -#include "sys_net.h" -#include "sys_main.h" -#include "server.h" -#include "cmd.h" -#include "plugin_handler.h" -*/ -#include "../pinc.h" -#include "q_shared.h" - #include #include #include #include +#include "../pinc.h" +#include "q_shared.h" + + #define MAX_NAME_LENGTH 33 #define UPDATE_INTERVAL 120 //2 minutes #define MAX_CACHED_ENTRIES 64 @@ -67,7 +53,7 @@ typedef struct{ /*** Shared used objects. Access only inside critical sections ****/ static banList_t cachedBanlist[MAX_CACHED_ENTRIES]; static permissionList_t cachedPermissionlist[MAX_CACHED_ENTRIES]; -static qboolean cacheupdated; +static qboolean cacheupdated; //Parsing the cache if true and check players on server against it /******************************************************************/ typedef struct @@ -80,35 +66,192 @@ static cvar_t* identkey; static cvar_t *banlisthandlerurl; static int serverport; +static void ClearCachedBan(baninfo_t* baninfo); static void ListCachedBans_f(); + static void SV_DumpBanlist_f() { Plugin_Printf("%s\n", paramters.showbanlistmessage); } -/* +void SM_Chat(const char* line, int clnum) +{ + char chattername[256]; + char cleanname[256]; + int i; + + if(line[0] == 0) + { + return; + } + + if ( clnum >= 0 ) + { + Q_strncpyz(cleanname, Plugin_GetPlayerName(clnum), sizeof(cleanname)); + Q_CleanStr(cleanname); + if(Plugin_CanPlayerUseCommand(clnum, "sm_chat")) + { + Com_sprintf(chattername, sizeof(chattername), "^3%s", cleanname); + }else{ + Com_sprintf(chattername, sizeof(chattername), "^2%s", cleanname); + } + }else{ + Q_strncpyz(chattername, "^1Console", sizeof(chattername)); + } -PCL void OnPlayerAddBan(baninfo_t* baninfo) + for ( i = 0; i < Plugin_GetSlotCount(); ++i ) + { + if ( Plugin_CanPlayerUseCommand(i, "sm_chat") || i == clnum) + { + Plugin_ChatPrintf(i, "^3[^0AdminChat^3]^7 (%s^7): %s", chattername, line); + } + } +} + +void SM_Chat_f() { - time_t aclock; - time(&aclock); - baninfo->created = aclock; - SV_AddBanToInternalList(baninfo->uid, baninfo->adminuid, baninfo->pbguid, baninfo->playername, &baninfo->adr, baninfo->expire, baninfo->message); + char line[256]; + + if ( Plugin_Cmd_Argc() < 2 ) + { + Plugin_Printf("Usage: sm_chat \nSends your message to all connected admins\n"); + return; + } + + Plugin_Cmd_Args(line, sizeof(line)); + + int invoker = Plugin_Cmd_GetInvokerSlot(); + + SM_Chat(line, invoker); } +//For using chat with @@ prefix +static void SM_PSay(const char* msg, int source) +{ + int i; + char message[1024]; + char cleannames[128]; + char cleannamed[128]; + + Cmd_TokenizeString(msg); + + if(Cmd_Argc() < 2) + { + Plugin_ChatPrintf(source, "Usage: @@player message"); + return; + } -PCL void OnPlayerRemoveBan(baninfo_t* baninfo) + client_t* cl = Plugin_SV_Cmd_GetPlayerClByHandle(Cmd_Argv(0)); + + if(cl == NULL) + { + Plugin_ChatPrintf(source, "No player for %s found", Cmd_Argv(0)); + return; + } + if(cl->state < CS_ACTIVE) + { + Plugin_ChatPrintf(source, "Player %s is not in active", cl->name); + return; + } + + message[0] = '\0'; + for(i = 1; i < Cmd_Argc(); ++i) + { + Q_strcat(message, sizeof(message), Cmd_Argv(i)); + Q_strcat(message, sizeof(message), " "); + } + + int destination = NUMFORCLIENT(cl); + + if(source == destination) + { + Plugin_ChatPrintf(source, "Why would you send a message to yourself?"); + return; + } + + Q_strncpyz(cleannames, Plugin_GetPlayerName(source), sizeof(cleannames)); + Q_strncpyz(cleannamed, cl->name, sizeof(cleannamed)); + + Q_CleanStr(cleannames); + Q_CleanStr(cleannamed); + + Plugin_ChatPrintf(source, "^7%s ^1>> ^7%s: %s", cleannames, cleannamed, message); + Plugin_ChatPrintf(destination, "^7%s ^1>> ^7%s: %s", cleannames, cleannamed, message); +} + +//For invoking command sm_psay +static void SM_PSay_f() { - if(baninfo->pbguid[0]) + int i; + char message[1024]; + + if(Plugin_Cmd_Argc() < 3) { - SV_RemoveBanFromInternalList(0, baninfo->pbguid, NULL); - }else if(baninfo->uid > 0){ - SV_RemoveBanFromInternalList(baninfo->uid, NULL, NULL); - }else{ - SV_RemoveBanFromInternalList(0, NULL, baninfo->playername); + Plugin_Printf("Usage: sm_psay \n"); + return; + } + + const char* name = Plugin_Cmd_Argv(1); + message[0] = '\0'; + + for(i = 2; i < Plugin_Cmd_Argc(); ++i) + { + Q_strcat(message, sizeof(message), Plugin_Cmd_Argv(i)); + } + + for(i = 0; i < Plugin_GetSlotCount(); ++i) + { + client_t* cl = Plugin_GetClientForClientNum(i); + if(cl->state < CS_ACTIVE) + { + continue; + } + if(strcmp(cl->name, name) == 0) + { + Plugin_ChatPrintf(i, "^2Admin{SB} to ^7%s^2: ^7%s", name, message); + } } + } -*/ + + + +PCL void OnMessageSent(char* message, int slot, qboolean* show, int mode) +{ + const char* rawmsg; + int numat = 1; + + if(message[0] != '@' && (message[0] != 0x15 || message[1] != '@') ) + { + return; + } + *show = qfalse; + + if(message[0] == 0x15) + rawmsg = message +2; + else + rawmsg = message +1; + + if(rawmsg[0] == '@') + { + ++rawmsg; + ++numat; + } + if(rawmsg[0] == '@') + { + ++rawmsg; + ++numat; + } + + if(numat == 1) + { + SM_Chat(rawmsg, slot); + }else if(numat == 2){ + SM_PSay(rawmsg, slot); + } +} + + /* * public domain strtok_r() by Charlie Gordon @@ -120,7 +263,7 @@ PCL void OnPlayerRemoveBan(baninfo_t* baninfo) * (Declaration that it's public domain): * http://groups.google.com/group/comp.lang.c/msg/7c7b39328fefab9c */ - +#ifndef strtok_r static char* strtok_r(char *str, const char *delim, char **nextp) { char *ret; @@ -150,7 +293,7 @@ static char* strtok_r(char *str, const char *delim, char **nextp) return ret; } - +#endif PCL void OnInfoRequest(pluginInfo_t *info){ // Function used to obtain information about the plugin // Memory pointed by info is allocated by the server binary, just fill in the fields @@ -161,9 +304,9 @@ PCL void OnInfoRequest(pluginInfo_t *info){ // Function used to obtain informati // ===== OPTIONAL FIELDS ===== info->pluginVersion.major = 1; info->pluginVersion.minor = 0; // Plugin version - strncpy(info->fullName,"Webserver powered banlist plugin by Fraggy", sizeof(info->fullName)); //Full plugin name - strncpy(info->shortDescription,"Plugin to work as banlist.",sizeof(info->shortDescription)); // Short plugin description - strncpy(info->longDescription,"This plugin is used to manage a banlist over a webapi so players can be banned from multiple gameservers and ban managed from webservers.",sizeof(info->longDescription)); + strncpy(info->fullName,"SourceBans plugin by Ninja", sizeof(info->fullName)); //Full plugin name + strncpy(info->shortDescription,"Plugin to work as banlist powered by Sourcebans.",sizeof(info->shortDescription)); // Short plugin description + strncpy(info->longDescription,"This plugin is used to manage a banlist on a modified version of the Sourcebans backend so players can be banned from multiple gameservers at once and bans can be easy managed from Sourcebans.",sizeof(info->longDescription)); } @@ -210,13 +353,13 @@ PCL int OnInit(){ // Funciton called on server initiation int len, code; httpPostVals_t values; - identkey = Plugin_Cvar_RegisterString("webbanapi_identkey", "", 0, "Key used to authenticate on web banlist api interface"); + identkey = Plugin_Cvar_RegisterString("sourcebans_identkey", "", 0, "Key used to authenticate on sourcebans serverexec script"); serverport = Plugin_Cvar_VariableIntegerValue("net_port"); - banlisthandlerurl = Plugin_Cvar_RegisterString("webbanapi_url", "", 0, "URL of the banlist handler"); + banlisthandlerurl = Plugin_Cvar_RegisterString("sourcebans_url", "", 0, "URL of the Sourcebans serverexec script"); - if(banlisthandlerurl->string[0] == 0) + if(banlisthandlerurl->string[0] == 0 || identkey->string[0] == 0) { - Plugin_PrintError("Init failure. Cvar webbanapi_url is not set\n"); + Plugin_PrintError("Init failure. Cvar sourcebans_url or sourcebans_identkey is not set\n"); return -1; } data[0] = 0; @@ -224,7 +367,12 @@ PCL int OnInit(){ // Funciton called on server initiation Com_sprintf(portstr, sizeof(portstr), "%hu", serverport); Plugin_HTTP_CreateString_x_www_form_urlencoded(data, sizeof(data), "command", "HELO"); Plugin_HTTP_CreateString_x_www_form_urlencoded(data, sizeof(data), "identkey", identkey->string); + Plugin_HTTP_CreateString_x_www_form_urlencoded(data, sizeof(data), "adminsteamid", "0"); Plugin_HTTP_CreateString_x_www_form_urlencoded(data, sizeof(data), "serverport", portstr); + Plugin_HTTP_CreateString_x_www_form_urlencoded(data, sizeof(data), "gamename", "Call of Duty 4 - Modern Warfare X18"); + Plugin_HTTP_CreateString_x_www_form_urlencoded(data, sizeof(data), "gamedir", "cod4"); + Plugin_HTTP_CreateString_x_www_form_urlencoded(data, sizeof(data), "rcon", Plugin_Cvar_VariableString("rcon_password")); + len = sizeof(data); code = HTTP_DoBlockingQuery(banlisthandlerurl->string, data, &len); if(code != 200) @@ -236,13 +384,15 @@ PCL int OnInit(){ // Funciton called on server initiation const char *status = Plugin_HTTP_GetFormDataItem(&values, "status"); if(Q_stricmp(status, "okay")) { - Plugin_PrintError("Init failure. WebAPI backend said: %s\n", status); + Plugin_PrintError("Init failure. Sourcebans backend script said: %s\n", status); return -1; } Q_strncpyz(paramters.showbanlistmessage, Plugin_HTTP_GetFormDataItem(&values, "showbanlistmessage"), sizeof(paramters.showbanlistmessage)); - Plugin_Printf("Web banlist plugin is ready to work\n"); + Plugin_Printf("Sourcebans plugin is ready to work\n"); Plugin_AddCommand("dumpbanlist", SV_DumpBanlist_f, 30); Plugin_AddCommand("dumpbanlistcache", ListCachedBans_f, 100); + Plugin_AddCommand("sm_psay", SM_PSay_f, 100); + Plugin_AddCommand("sm_chat", SM_Chat_f, 30); return 0; } @@ -277,6 +427,22 @@ static void ListCachedBans_f() //Debug function to test banlist cache Plugin_LeaveCriticalSection(); } +static void ClearCachedBan(baninfo_t* baninfo) +{ + int i; + + Plugin_EnterCriticalSection(); + + for(i = 0; i < MAX_CACHED_ENTRIES; ++i) + { + if((baninfo->playerid && cachedBanlist[i].playerid == baninfo->playerid) || (baninfo->adr.type >= NA_IP && Plugin_NET_CompareBaseAdr(&baninfo->adr, &cachedBanlist[i].remote))) + { + + memset(&cachedBanlist[i], 0, sizeof(cachedBanlist[i])); + } + } + Plugin_LeaveCriticalSection(); +} static banList_t* CheckForCachedBans(baninfo_t* baninfo) //Will also check for just received bans after querying as the ban info does receive in an independed worker thread @@ -363,6 +529,9 @@ static void* QueryThreadForPlayer(void* q) Com_sprintf(tmp, sizeof(tmp), "%llu", baninfo->steamid); Plugin_HTTP_CreateString_x_www_form_urlencoded(querystring, sizeof(querystring), "steamid", tmp); } + + Plugin_HTTP_CreateString_x_www_form_urlencoded(querystring, sizeof(querystring), "adminsteamid", "0"); + if(baninfo->playername[0]) { Plugin_HTTP_CreateString_x_www_form_urlencoded(querystring, sizeof(querystring), "playername", baninfo->playername); @@ -393,12 +562,47 @@ static void* QueryThreadForPlayer(void* q) { Plugin_Printf("WebbanlistAPI: server returned code %d\n", code); }else{ - // Plugin_Printf("WebbanlistAPI: server returned %s\n", querystring); + Plugin_Printf("WebbanlistAPI: server returned %s\n", querystring); Plugin_HTTP_ParseFormDataBody(querystring, &values); const char* status = Plugin_HTTP_GetFormDataItem(&values, "status"); - if(Q_stricmp(status, "active")) + if(!Q_stricmpn(status, "Ban Not Found", 13)) + { + ClearCachedBan(baninfo); + free(baninfo); + return NULL; + } + if(!Q_stricmp(status, "mute")) { + for(i = 0; i < MAX_CLIENTS; ++i) + { + client_t* cl = Plugin_GetClientForClientNum(i); + if(cl->state >= CS_CONNECTED && cl->playerid == baninfo->playerid) + { + cl->mutelevel = 1; //Only voice - !!!Race condition!!! + } + } + ClearCachedBan(baninfo); + free(baninfo); + return NULL; + } + if(!Q_stricmp(status, "chat")) + { + for(i = 0; i < MAX_CLIENTS; ++i) + { + client_t* cl = Plugin_GetClientForClientNum(i); + if(cl->state >= CS_CONNECTED && cl->playerid == baninfo->playerid) + { + cl->mutelevel = 2; //Voice and chat - !!!Race condition!!! + } + } + ClearCachedBan(baninfo); + free(baninfo); + return NULL; + } + if(Q_stricmp(status, "active"))//If full ban active don't return here + { + free(baninfo); return NULL; } uint64_t playerid = Plugin_StringToSteamID( Plugin_HTTP_GetFormDataItem(&values, "playerid")); @@ -422,8 +626,6 @@ static void* QueryThreadForPlayer(void* q) b.lastqueried = Plugin_GetServerTime(); b.lastupdated = Plugin_GetServerTime(); - - Plugin_EnterCriticalSection(); for(i = 0; i < MAX_CACHED_ENTRIES; ++i) @@ -606,7 +808,7 @@ static void* BanUnbanPlayerThread(void* q) } } - Plugin_Free(baninfo); + free(baninfo); return NULL; } @@ -647,9 +849,12 @@ static void* GetPlayerPermissionsThread(void* q) querystring[0] = 0; Com_sprintf(tmp, sizeof(tmp), "%llu", steamid); Plugin_HTTP_CreateString_x_www_form_urlencoded(querystring, sizeof(querystring), "steamid", tmp); + Plugin_HTTP_CreateString_x_www_form_urlencoded(querystring, sizeof(querystring), "adminsteamid", tmp); Plugin_HTTP_CreateString_x_www_form_urlencoded(querystring, sizeof(querystring), "identkey", identkey->string); Com_sprintf(tmp, sizeof(tmp), "%u", serverport); Plugin_HTTP_CreateString_x_www_form_urlencoded(querystring, sizeof(querystring), "serverport", tmp); + Plugin_HTTP_CreateString_x_www_form_urlencoded(querystring, sizeof(querystring), "gamename", "Call of Duty 4 - Modern Warfare X18"); + Plugin_HTTP_CreateString_x_www_form_urlencoded(querystring, sizeof(querystring), "gamedir", "cod4"); Plugin_HTTP_CreateString_x_www_form_urlencoded(querystring, sizeof(querystring), "command", "querypermissions"); //3 attempts to put data @@ -744,19 +949,14 @@ static void SendPermissionQuery(uint64_t steamid) PCL void OnPlayerGetBanStatus(baninfo_t* baninfo, char* message, int len) { banList_t* l; + //Send a query + SendQueryForPlayer(baninfo); l = CheckForCachedBans(baninfo); if(l == NULL) { - //Send a query - SendQueryForPlayer(baninfo); return; } - if(l->lastupdated + UPDATE_INTERVAL < Plugin_GetRealtime()) - { - //Send a query - SendQueryForPlayer(baninfo); - } //deal with that player here Q_strncpyz(message, baninfo->message, len); } diff --git a/plugins/sourcebansplugin/makedll.sh b/plugins/sourcebansplugin/makedll.sh new file mode 100644 index 00000000..234315e6 --- /dev/null +++ b/plugins/sourcebansplugin/makedll.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +echo Compiling: release +gcc -m32 -Wall -O1 -g -fvisibility=hidden -mtune=core2 -c *.c + +echo Linking +gcc -m32 -g -shared -o sourcebansplugin.so *.o +echo Cleaning up +rm *.o + diff --git a/plugins/sourcebansplugin/makedll_win32.cmd b/plugins/sourcebansplugin/makedll_win32.cmd index 473bdd8d..1a278cb2 100644 --- a/plugins/sourcebansplugin/makedll_win32.cmd +++ b/plugins/sourcebansplugin/makedll_win32.cmd @@ -7,7 +7,7 @@ echo Compiling: release gcc -m32 -Wall -O1 -g -mtune=core2 -c *.c echo Linking -gcc -m32 -g -shared -o webbanlist.dll *.o -L..\ -lcom_plugin +gcc -m32 -g -shared -o sourcebansplugin.dll *.o -L..\ -lcom_plugin echo Cleaning up del *.o diff --git a/plugins/sourcebansplugin/q_shared.h b/plugins/sourcebansplugin/q_shared.h index 37ab0b1c..6c148f02 100644 --- a/plugins/sourcebansplugin/q_shared.h +++ b/plugins/sourcebansplugin/q_shared.h @@ -27,6 +27,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // A user mod should never modify this file #include #include + #include #ifdef _MSC_VER /* @@ -592,4 +593,13 @@ int QDECL Com_sprintfUni(wchar_t *dest, size_t size, const wchar_t *fmt, ...); void Q_strcatUni( wchar_t *dest, int size, const wchar_t *src ); void CharToHexUni(wchar_t* string, char* hexstring, int size); void HexToCharUni(char* hexstring, wchar_t* string, int size); + +int Cmd_Argc( void ); +char *Cmd_Argv( int arg ); +void Cmd_ArgvBuffer( int arg, char *buffer, int bufferLength ); +char *Cmd_Args( void ); +void Cmd_ArgsBuffer( char *buffer, int bufferLength ); +void Cmd_TokenizeString( const char *text_in ); + #endif // __Q_SHARED_H + diff --git a/plugins/sourcebansplugin/qshared.c b/plugins/sourcebansplugin/qshared.c index b97fc9be..5b393ff6 100644 --- a/plugins/sourcebansplugin/qshared.c +++ b/plugins/sourcebansplugin/qshared.c @@ -19,16 +19,16 @@ along with this program. If not, see =========================================================================== */ - -#include "../pinc.h" -#include "q_shared.h" - #include #include #include #include #include +#include "../pinc.h" +#include "q_shared.h" + + short ShortSwap (short l) { byte b1,b2; @@ -495,7 +495,11 @@ int QDECL Com_sprintfUni(wchar_t *dest, size_t size, const wchar_t *fmt, ...) numchar = size / sizeof(wchar_t); va_start (argptr,fmt); +#ifdef _WIN32 len = vsnwprintf (dest, numchar, fmt, argptr ); +#else + len = vswprintf (dest, numchar, fmt, argptr ); +#endif va_end (argptr); if(len < 0 || len >= numchar) @@ -804,3 +808,185 @@ void Info_SetValueForKey( char *s, const char *key, const char *value ) { strcat (newi, s); strcpy (s, newi); } + + + + +static int cmd_argc; +static char *cmd_argv[MAX_STRING_TOKENS]; // points into cmd_tokenized +static char cmd_tokenized[MAX_STRING_CHARS+MAX_STRING_TOKENS]; // will have 0 bytes inserted + +/* +============ +Cmd_Argc +============ +*/ +int Cmd_Argc( void ) { + return cmd_argc; +} + +/* +============ +Cmd_Argv +============ +*/ +char *Cmd_Argv( int arg ) { + if ( (unsigned)arg >= cmd_argc ) { + return ""; + } + return cmd_argv[arg]; +} + +/* +============ +Cmd_ArgvBuffer + +The interpreted versions use this because +they can't have pointers returned to them +============ +*/ +void Cmd_ArgvBuffer( int arg, char *buffer, int bufferLength ) { + Q_strncpyz( buffer, Cmd_Argv( arg ), bufferLength ); +} + + +/* +============ +Cmd_Args + +Returns a single string containing argv(1) to argv(argc()-1) +============ +*/ +char *Cmd_Args( void ) { + static char cmd_args[MAX_STRING_CHARS]; + int i; + + cmd_args[0] = 0; + for ( i = 1 ; i < cmd_argc ; i++ ) { + strcat( cmd_args, cmd_argv[i] ); + if ( i != cmd_argc ) { + strcat( cmd_args, " " ); + } + } + + return cmd_args; +} + + +/* +============ +Cmd_ArgsBuffer + +The interpreted versions use this because +they can't have pointers returned to them +============ +*/ +void Cmd_ArgsBuffer( char *buffer, int bufferLength ) { + Q_strncpyz( buffer, Cmd_Args(), bufferLength ); +} + + +/* +============ +Cmd_TokenizeString + +Parses the given string into command line tokens. +The text is copied to a seperate buffer and 0 characters +are inserted in the apropriate place, The argv array +will point into this temporary buffer. +============ +*/ +void Cmd_TokenizeString( const char *text_in ) { + const char *text; + char *textOut; + + // clear previous args + cmd_argc = 0; + + if ( !text_in ) { + return; + } + + text = text_in; + textOut = cmd_tokenized; + + while ( 1 ) { + if ( cmd_argc == MAX_STRING_TOKENS ) { + return; // this is usually something malicious + } + + while ( 1 ) { + // skip whitespace + while ( *text && *text <= ' ' ) { + text++; + } + if ( !*text ) { + return; // all tokens parsed + } + + // skip // comments + if ( text[0] == '/' && text[1] == '/' ) { + return; // all tokens parsed + } + + // skip /* */ comments + if ( text[0] == '/' && text[1] =='*' ) { + while ( *text && ( text[0] != '*' || text[1] != '/' ) ) { + text++; + } + if ( !*text ) { + return; // all tokens parsed + } + text += 2; + } else { + break; // we are ready to parse a token + } + } + + // handle quoted strings + if ( *text == '"' ) { + cmd_argv[cmd_argc] = textOut; + cmd_argc++; + text++; + while ( *text && *text != '"' ) { + *textOut++ = *text++; + } + *textOut++ = 0; + if ( !*text ) { + return; // all tokens parsed + } + text++; + continue; + } + + // regular token + cmd_argv[cmd_argc] = textOut; + cmd_argc++; + + // skip until whitespace, quote, or command + while ( *text > ' ' ) { + if ( text[0] == '"' ) { + break; + } + + if ( text[0] == '/' && text[1] == '/' ) { + break; + } + + // skip /* */ comments + if ( text[0] == '/' && text[1] =='*' ) { + break; + } + + *textOut++ = *text++; + } + + *textOut++ = 0; + + if ( !*text ) { + return; // all tokens parsed + } + } + +} + diff --git a/plugins/warn/makedll.sh b/plugins/warn/makedll.sh new file mode 100644 index 00000000..ac4cf668 --- /dev/null +++ b/plugins/warn/makedll.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +echo Compiling: release +gcc -m32 -Wall -O1 -g -fvisibility=hidden -mtune=core2 -c *.c + +echo Linking +gcc -m32 -g -shared -o warn.so *.o +echo Cleaning up +rm *.o + diff --git a/plugins/warn/warn.c b/plugins/warn/warn.c new file mode 100644 index 00000000..d5595ae7 --- /dev/null +++ b/plugins/warn/warn.c @@ -0,0 +1,289 @@ +/* This file has been generated by the Hex-Rays decompiler. + Copyright (c) 2007-2014 Hex-Rays + + Detected compiler: GNU C++ +*/ + +#include +#include +#include +#include +#include "../pinc.h" + + +//------------------------------------------------------------------------- +// Function declarations + +signed int __cdecl Q_stricmpn(const char *a1, const char *a2, int a3); // idb +signed int __cdecl Q_stricmp(int a1, int a2); +void OpenWarnFile(void); +int SV_DisplayWarnCmd(); // weak +int SV_ClearWarnCmd(); // weak +char *__cdecl Q_strncpyz(char *dest, char *src, int a3); +char *__cdecl Q_strcat(char *, int a2, const char *src); +void __cdecl SV_IssueWarnCmd(); + +cvar_t *c_wlimit; +cvar_t *c_wbantime; +FILE *w_filehandle; // idb +int savedwarns[MAX_CLIENTS]; + +//----- (00000AD3) -------------------------------------------------------- +signed int __cdecl Q_stricmp(int a1, int a2) +{ + signed int result; // eax@3 + + if ( a1 && a2 ) + result = Q_stricmpn((const char *)a1, (const char *)a2, 99999); + else + result = -1; + return result; +} + +//----- (00000B04) -------------------------------------------------------- +void __cdecl OnPlayerDC(client_t *client, const char* reason) +{ + savedwarns[NUMFORCLIENT(client)] = 0; +} + +//----- (00000B25) -------------------------------------------------------- +void OpenWarnFile(void) +{ + char filename[512]; // [sp+10h] [bp-208h]@1 + + snprintf(filename, 0x200u, "%s/warn.dat", Plugin_Cvar_VariableString("fs_homepath")); + w_filehandle = fopen(filename, "a+"); + Plugin_Printf("Warn_System: File has been opened!\n"); +} + +//----- (00000B87) -------------------------------------------------------- +void OnExitLevel() +{ + fclose(w_filehandle); + OpenWarnFile(); +} + +//----- (00000BA1) -------------------------------------------------------- +void SV_DisplayWarnCmd_f() +{ + client_t *wcl; // eax@1 + int clientnum; + + if(Plugin_Cmd_Argc() > 2) + { + Plugin_Printf("Plugin_WarnCount_Usage: %s ()\n", Plugin_Cmd_Argv(0)); + return; + } + wcl = NULL; + int invokernum = Plugin_Cmd_GetInvokerSlot(); + + if(Plugin_Cmd_Argc() == 2) + { + wcl = Plugin_SV_Cmd_GetPlayerClByHandle(Plugin_Cmd_Argv(1));//Prints message if bad in most cases + if(wcl == NULL) + { + if(invokernum < 0 || invokernum >= MAX_CLIENTS) + { + Plugin_Printf("Can't display warnings for such a player\n"); + }else{ + Plugin_ChatPrintf(invokernum, "Can't display warnings for such a player\n"); + } + return; + } + clientnum = NUMFORCLIENT(wcl); + if(invokernum < 0 || invokernum >= MAX_CLIENTS) + { + Plugin_Printf( "Player %s^7 has %i warnings out of %i\n", wcl->name, savedwarns[clientnum], c_wlimit->integer); + }else{ + Plugin_ChatPrintf(invokernum, "^1Server_Warning^7: %s^7 has %i warnings out of %i\n", wcl->name, savedwarns[clientnum], c_wlimit->integer); + } + }else{ + //One argument only + if(invokernum < 0 || invokernum >= MAX_CLIENTS) + { + //One argument but not from a player + Plugin_Printf("Plugin_WarnCount_Usage: %s \n", Plugin_Cmd_Argv(0)); + return; + } + //Print to the invoking client the own status + Plugin_ChatPrintf(invokernum, "^1Server_Warning: You have %i warnings out of %i\n", savedwarns[invokernum], c_wlimit->integer); + } + +} + +// BA1: using guessed type int SV_DisplayWarnCmd(); +// 27B0: using guessed type int Plugin_Cmd_Argc(void); +// 27B4: using guessed type int Plugin_ChatPrintf(_DWORD, const char *, ...); +// 27C8: using guessed type int Plugin_Cmd_GetInvokerSlot(void); + +//----- (00000C66) -------------------------------------------------------- +void SV_ClearWarnCmd_f() +{ + int clientnum; // esi@1 + client_t *wcl; // eax@1 + int v7; // [sp+1Ch] [bp-1Ch]@1 + + if(Plugin_Cmd_Argc() != 2) + { + Plugin_Printf("Plugin_RemoveWarnings_Usage: %s \n", Plugin_Cmd_Argv(0)); + return; + } + + v7 = Plugin_Cmd_GetInvokerSlot(); + + wcl = Plugin_SV_Cmd_GetPlayerClByHandle(Plugin_Cmd_Argv(1));//Prints message if bad in most cases + if(wcl == NULL) + { + if(v7 < 0 || v7 >= MAX_CLIENTS) + { + Plugin_Printf("Can't clear warn for such a player\n"); + }else{ + Plugin_ChatPrintf(v7, "Can't clear warn for such a player\n"); + } + return; + } + + clientnum = NUMFORCLIENT(wcl); + + if ( wcl->state < CS_PRIMED ) + { + Plugin_PrintError("^7This player is not in world\n"); + return; + } + savedwarns[clientnum] = 0; + Plugin_ChatPrintf(clientnum, "^1Server_Warning: ^7Warnings removed\n"); + if(v7 < 0 || v7 >= MAX_CLIENTS) + { + Plugin_Printf("^1Server_Warning: ^7Removed Warnings for %s at slot %i\n", wcl->name, savedwarns[clientnum]); + }else{ + Plugin_ChatPrintf(v7, "^1Server_Warning: ^7Removed Warnings for %s at slot %i\n", wcl->name, savedwarns[clientnum]); + } + +} +// C66: using guessed type int SV_ClearWarnCmd(); +// 27B0: using guessed type int Plugin_Cmd_Argc(void); +// 27B4: using guessed type int Plugin_ChatPrintf(_DWORD, const char *, ...); +// 27C8: using guessed type int Plugin_Cmd_GetInvokerSlot(void); + +//----- (00000D40) -------------------------------------------------------- + +//----- (00000DBF) -------------------------------------------------------- +char *__cdecl Q_strncpyz(char *dest, char *src, int a3) +{ + char *result; // eax@1 + + result = strncpy(dest, src, a3 - 1); + dest[a3 - 1] = 0; + return result; +} + +//----- (00000DF4) -------------------------------------------------------- +PCL int OnInit() +{ + Plugin_AddCommand("warn", SV_IssueWarnCmd, 60); + c_wlimit = Plugin_Cvar_RegisterInt("wlimit", 3, 1, 10, 0, "Maximum number of warnings to be banned after them."); + c_wbantime = Plugin_Cvar_RegisterInt("wbantime", 32*60, -1, 43200, 0, "Warning system ban duration."); + Plugin_AddCommand("warnr", SV_ClearWarnCmd_f, 80); + Plugin_AddCommand("warnc", SV_DisplayWarnCmd_f, 1); + OpenWarnFile(); + return 0; +} +// BA1: using guessed type int SV_DisplayWarnCmd(); +// C66: using guessed type int SV_ClearWarnCmd(); +// 27BC: using guessed type int __cdecl Plugin_AddCommand(_DWORD, _DWORD, _DWORD); + +//----- (00000ECC) -------------------------------------------------------- +char *__cdecl Q_strcat(char *a1, int a2, const char *src) +{ + unsigned int v3; // kr04_4@1 + + v3 = strlen(a1) + 1; + return Q_strncpyz(&a1[v3 - 1], (char *)src, a2 - (v3 - 1)); +} + +//----- (00000F08) -------------------------------------------------------- +void __cdecl SV_IssueWarnCmd() +{ + int numargs; // ebx@1 + int clientnum; // edi@1 + int i; // ebx@4 + const char *cmdname; // eax@10 + client_t *wcl; // [sp+2Ch] [bp-11Ch]@1 + char v12[256]; // [sp+30h] [bp-118h]@1 + char adrbuf[128]; + char steamidstr[128]; + char playeridstr[128]; + char invname[128]; + + numargs = Plugin_Cmd_Argc(); + + v12[0] = 0; + if ( numargs <= 2 ) + { + cmdname = Plugin_Cmd_Argv(0); + Plugin_Printf("Plugin_Warn_Usage: %s \n", cmdname); + Plugin_Printf("Plugin_Warn: The limit is %i", c_wlimit->integer); + return; + } + + wcl = Plugin_SV_Cmd_GetPlayerClByHandle(Plugin_Cmd_Argv(1));//Prints message if bad in most cases + if(wcl == NULL) + { + Plugin_Printf("Can't warn such a player\n"); + return; + } + + clientnum = NUMFORCLIENT(wcl); + + if ( wcl->state < CS_ACTIVE) + { + Plugin_PrintError("^7This player is not in world\n"); + return; + } + + for ( i = 2; i < Plugin_Cmd_Argc(); ++i ) + { + Q_strcat(v12, sizeof(v12), Plugin_Cmd_Argv(i)); + Q_strcat(v12, sizeof(v12), " "); + } + ++savedwarns[clientnum]; + Plugin_ChatPrintf(clientnum, "^1Server_Warning: You have been warned with reason: %s\n", v12); + if(savedwarns[clientnum] == (c_wlimit->integer - 1)) + { + Plugin_ChatPrintf(clientnum, "^1Attention^7: If you get one more warning you face a %d hours cooldown\n", c_wbantime->integer / 60); + } + + Plugin_SteamIDToString(Plugin_Cmd_GetInvokerSteamID(), steamidstr, sizeof(steamidstr)); + Plugin_SteamIDToString(wcl->playerid, playeridstr, sizeof(playeridstr)); + + fprintf(w_filehandle, "AdminName: %s Admin: %s PlayerName: %s PlayerGUID\\UID: %s PLayer IP: %s\n", Plugin_Cmd_GetInvokerName(invname, sizeof(invname)), steamidstr, wcl->name, playeridstr, Plugin_NET_AdrToStringMT(&wcl->netchan.remoteAddress, adrbuf, sizeof(adrbuf))); + if ( savedwarns[clientnum] == c_wlimit->integer ) + { + char banreason[1024]; + snprintf(banreason, sizeof(banreason), "Too many warnings received in one session. Last warning is: %s", v12); + banreason[1023] = 0; + Plugin_BanClient(clientnum, c_wbantime->integer, 0, banreason); + savedwarns[clientnum] = 0; + } +} + +// ALL OK, 18 function(s) have been successfully decompiled + + + + + +PCL void OnInfoRequest(pluginInfo_t *info){ // Function used to obtain information about the plugin + // Memory pointed by info is allocated by the server binary, just fill in the fields + + // ===== MANDATORY FIELDS ===== + info->handlerVersion.major = PLUGIN_HANDLER_VERSION_MAJOR; + info->handlerVersion.minor = PLUGIN_HANDLER_VERSION_MINOR; // Requested handler version + + // ===== OPTIONAL FIELDS ===== + info->pluginVersion.major = 1; + info->pluginVersion.minor = 0; // Plugin version + strncpy(info->fullName,"Warn system plugin by DeltaMX", sizeof(info->fullName)); //Full plugin name + strncpy(info->shortDescription,"This plugin will enable admins to warn players before being banned.",sizeof(info->shortDescription)); // Short plugin description + strncpy(info->longDescription,"This plugin will enable admins to issue warnings to players at which after a certain limit will ban these players",sizeof(info->longDescription)); +} \ No newline at end of file diff --git a/run.sh b/run.sh new file mode 100644 index 00000000..ea876ef1 --- /dev/null +++ b/run.sh @@ -0,0 +1,2 @@ +cd bin +./cod4x18_dedrun +exec server.cfg +map mp_killhouse +set fs_homepath . +set developer 1 +set sv_nosteamnames 1 diff --git a/src/cmd.c b/src/cmd.c index c1dbf40c..3a1d2c96 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -843,10 +843,10 @@ static void Cmd_TokenizeString2( const char *text_in, qboolean ignore_quotes ) { tokenStrings.cmd_argcList[tokenStrings.currentString] = param.cmd_argc - oldargc; tokenStrings.cmd_argc = param.cmd_argc; + tokenStrings.currentString++; }else{ Com_PrintError("Cmd_TokenizeString(): MAX_TOKENIZE_STRINGS exceeded\n"); } - tokenStrings.currentString++; } /* @@ -1081,10 +1081,11 @@ void Cmd_ExecuteString( const char *text ) }else if(!Q_stricmp(arg0, "cmdpowerlist")){ Q_strncpyz(arg0, "AdminListCommands", sizeof(arg0)); Com_PrintWarning("\"cmdpowerlist\" is deprecated and will be removed soon. Use \"AdminListCommands\" instead\n"); - } - else if(!Q_stricmp(arg0, "setCmdMinPower")){ + }else if(!Q_stricmp(arg0, "setCmdMinPower")){ Q_strncpyz(arg0, "AdminChangeCommandPower", sizeof(arg0)); Com_PrintWarning("\"setCmdMinPower\" is deprecated and will be removed soon. Use \"AdminChangeCommandPower\" instead\n"); + }else if(!Q_stricmp(arg0, "kickid")){ + Q_strncpyz(arg0, "kick", sizeof(arg0)); } // check registered command functions for ( prev = &cmd_functions ; *prev ; prev = &cmd->next ) { diff --git a/src/cvar.c b/src/cvar.c index 93802d14..c55cf617 100644 --- a/src/cvar.c +++ b/src/cvar.c @@ -30,6 +30,7 @@ #include "cmd_completion.h" #include "filesystem.h" #include "sys_main.h" +#include "sys_thread.h" // nothing outside the Cvar_*() functions should modify these fields! #include @@ -39,6 +40,7 @@ #include #include + cvar_t *cvar_vars; cvar_t *cvar_cheats; int cvar_modifiedFlags; @@ -114,12 +116,16 @@ static long generateHashValue( const char *fname ) { void Cvar_AddFlags(cvar_t* var, unsigned short flags) { + Sys_EnterCriticalSection(CRIT_CVAR); var->flags |= flags; + Sys_LeaveCriticalSection(CRIT_CVAR); } void Cvar_ClearFlags(cvar_t* var, unsigned short flags) { + Sys_EnterCriticalSection(CRIT_CVAR); var->flags &= ~flags; + Sys_LeaveCriticalSection(CRIT_CVAR); } /* @@ -168,8 +174,9 @@ cvar_t *Cvar_FindVar( const char *var_name ) { Cvar_VariableValue ============ */ -float Cvar_VariableValue( const char *var_name ) { +float Cvar_VariableValueInternal( const char *var_name ) { cvar_t *var; + Sys_EnterCriticalSection(CRIT_CVAR); var = Cvar_FindVar (var_name); if (!var) @@ -181,14 +188,19 @@ float Cvar_VariableValue( const char *var_name ) { else return 0.0; } - - +float Cvar_VariableValue( const char *var_name ) +{ + Sys_EnterCriticalSection(CRIT_CVAR); + float v = Cvar_VariableValueInternal(var_name); + Sys_LeaveCriticalSection(CRIT_CVAR); + return v; +} /* ============ Cvar_VariableIntegerValue ============ */ -int Cvar_VariableIntegerValue( const char *var_name ) { +int Cvar_VariableIntegerValueInternal( const char *var_name ) { cvar_t *var; var = Cvar_FindVar (var_name); @@ -203,13 +215,19 @@ int Cvar_VariableIntegerValue( const char *var_name ) { else return 0; } - +int Cvar_VariableIntegerValue( const char *var_name ) +{ + Sys_EnterCriticalSection(CRIT_CVAR); + int i = Cvar_VariableIntegerValueInternal(var_name); + Sys_LeaveCriticalSection(CRIT_CVAR); + return i; +} /* ============ Cvar_VariableBooleanValue ============ */ -qboolean Cvar_VariableBooleanValue( const char *var_name ) { +qboolean Cvar_VariableBooleanValueInternal( const char *var_name ) { cvar_t *var; var = Cvar_FindVar (var_name); @@ -234,7 +252,13 @@ qboolean Cvar_VariableBooleanValue( const char *var_name ) { else return 0; } - +qboolean Cvar_VariableBooleanValue( const char *var_name ) +{ + Sys_EnterCriticalSection(CRIT_CVAR); + qboolean b = Cvar_VariableBooleanValueInternal(var_name); + Sys_LeaveCriticalSection(CRIT_CVAR); + return b; +} /* diff --git a/src/g_sv_client.c b/src/g_sv_client.c index 93e87ffa..f6746ae3 100644 --- a/src/g_sv_client.c +++ b/src/g_sv_client.c @@ -377,9 +377,10 @@ __cdecl void ClientUserinfoChanged( int clientNum ) { } else { client->sess.predictItemPickup = qtrue; } +/* SV_GetUsername(clientNum, name, sizeof(name)); ClientSetUsername(clientNum, name); - +*/ } void ClientSetUsername(int clientNum, const char* username) diff --git a/src/g_sv_cmds.c b/src/g_sv_cmds.c index 6625d5fc..2bbd1a98 100644 --- a/src/g_sv_cmds.c +++ b/src/g_sv_cmds.c @@ -555,6 +555,12 @@ __cdecl void G_Say( gentity_t *ent, gentity_t *target, int mode, const char *cha if(!show) return; + if(svs.clients[ent->s.number].mutelevel >= 2) + { + SV_GameSendServerCommand(ent->s.number, 0, "h \"^1Error^7: You are no longer allowed to use the chat\""); + return; + } + /* Removed. Create a plugin if you want to capature chat. if(Scr_PlayerSay(ent, mode, textptr)) diff --git a/src/hl2rcon.c b/src/hl2rcon.c index 82015d5e..02fd993a 100644 --- a/src/hl2rcon.c +++ b/src/hl2rcon.c @@ -34,6 +34,8 @@ #include "net_game.h" #include "g_sv_shared.h" #include "sv_auth.h" +#include "q_platform.h" +#include "sapi.h" #include #include @@ -45,6 +47,7 @@ Source Rcon facility ======================================================================== */ +void HL2Rcon_StatusCommand(); #ifndef MAX_MSGLEN #define MAX_MSGLEN 0x20000 @@ -121,39 +124,75 @@ void HL2Rcon_SourceRconDisconnect(netadr_t *from, int connectionId) } -tcpclientstate_t HL2Rcon_SourceRconAuth(netadr_t *from, msg_t *msg, int *connectionId){ +qboolean HL2Rcon_SourceRconIdentEvent(netadr_t *from, msg_t *msg, int *connectionId){ int packetlen; int packettype; - int packetid; - char* loginstring; - char* username; - char* password; - byte msgbuf[32]; - msg_t sendmsg; rconUser_t* user; int i; - char buf[MAX_STRING_CHARS]; - char stringlinebuf[MAX_STRING_CHARS]; MSG_BeginReading(msg); packetlen = MSG_ReadLong(msg); if(packetlen != msg->cursize - 4){//Not a source rcon packet - Com_Printf("Not a source rcon packet: len %d size %d\n", packetlen, msg->cursize); + //Com_Printf("Not a source rcon packet: len %d size %d\n", packetlen, msg->cursize); - return TCP_AUTHNOTME; + return qfalse; } - packetid = MSG_ReadLong(msg); + //packetid = + MSG_ReadLong(msg); packettype = MSG_ReadLong(msg); if(packettype != SERVERDATA_AUTH)//Not a source rcon auth-packet - return TCP_AUTHNOTME; + return qfalse; + + + for(i = 0, user = sourceRcon.activeRconUsers; i < MAX_RCONUSERS; i++, user++){ + if(user->remote.type == NA_BAD) + break; + } + + if(i == MAX_RCONUSERS){ + *connectionId = -1;//need to close that on 1st read event + return qtrue; + } + + + user->remote = *from; + user->steamid = -1; + user->rconUsername[0] = '\0'; + user->streamchat = 0; + user->streamlog = 0; + user->lastpacketid = 0; + *connectionId = i; + + return qtrue; +} + +qboolean HL2Rcon_SourceRconAuth(netadr_t *from, msg_t *msg, rconUser_t* user){ + + //int packettype; + int packetid; + char* loginstring; + char* username; + char* password; + byte msgbuf[32]; + msg_t sendmsg; + //int i; + char buf[MAX_STRING_CHARS]; + char stringlinebuf[MAX_STRING_CHARS]; + int steamid; + + //packetlen = + MSG_ReadLong(msg); + packetid = MSG_ReadLong(msg); + //packettype = + MSG_ReadLong(msg); if(SV_PlayerBannedByip(from, buf, sizeof(buf))){ - return TCP_AUTHBAD; + return qfalse; } MSG_Init(&sendmsg, msgbuf, sizeof(msgbuf)); @@ -161,9 +200,9 @@ tcpclientstate_t HL2Rcon_SourceRconAuth(netadr_t *from, msg_t *msg, int *connect MSG_WriteLong(&sendmsg, 0); MSG_WriteLong(&sendmsg, SERVERDATA_RESPONSE_VALUE); MSG_WriteShort(&sendmsg, 0); - if(NET_SendData(from->sock, &sendmsg) < 1) + if(NET_SendData(from->sock, &sendmsg) != sendmsg.cursize) { - return TCP_AUTHBAD; + return qfalse; } MSG_Init(&sendmsg, msgbuf, sizeof(msgbuf)); @@ -171,55 +210,48 @@ tcpclientstate_t HL2Rcon_SourceRconAuth(netadr_t *from, msg_t *msg, int *connect loginstring = MSG_ReadStringLine(msg, stringlinebuf, sizeof(stringlinebuf)); - Cmd_TokenizeString(loginstring); - - if(Cmd_Argc() != 2){ - goto badrcon; - } - username = Cmd_Argv(0); - password = Cmd_Argv(1); - - if(strlen(password) < 6){ - goto badrcon; - } - - if(Auth_Authorize(username, password) < 0) + if(strlen( sv_rconPassword->string) < 8 || strcmp (loginstring, sv_rconPassword->string )) { - goto badrcon; - } + Cmd_TokenizeString(loginstring); - Com_Printf("Rcon login from: %s Name: %s\n", NET_AdrToString (from), username); + if(Cmd_Argc() != 2){ + goto badrcon; + } + username = Cmd_Argv(0); + password = Cmd_Argv(1); - Cmd_EndTokenizedString(); + if(strlen(password) < 6){ + goto badrcon; + } - for(i = 0, user = sourceRcon.activeRconUsers; i < MAX_RCONUSERS; i++, user++){ - if(user->remote.type == NA_BAD) - break; - } + if(Auth_Authorize(username, password) < 0) + { + goto badrcon; + } - if(i == MAX_RCONUSERS){ - return TCP_AUTHBAD; //Close connection - } + Com_Printf("Rcon login from: %s Name: %s\n", NET_AdrToString (from), username); + Cmd_EndTokenizedString(); + steamid = Auth_GetSteamID(username); + }else{ + steamid = 0; + username = "console"; + Com_Printf("Rcon login from: %s with rcon password\n", NET_AdrToString (from)); + } - user->remote = *from; - user->steamid = Auth_GetSteamID(username); -// user->rconPower = login->power; + user->steamid = steamid; Q_strncpyz(user->rconUsername, username, sizeof(user->rconUsername)); - user->streamchat = 0; - user->streamlog = 0; user->lastpacketid = packetid; - *connectionId = i; MSG_WriteLong(&sendmsg, user->lastpacketid); MSG_WriteLong(&sendmsg, SERVERDATA_AUTH_RESPONSE); MSG_WriteShort(&sendmsg, 0); - if(NET_SendData(from->sock, &sendmsg) < 1) + if(NET_SendData(from->sock, &sendmsg) != sendmsg.cursize) { - return TCP_AUTHBAD; + return qfalse; } - return TCP_AUTHSUCCESSFULL; + return qtrue; badrcon: @@ -235,7 +267,7 @@ tcpclientstate_t HL2Rcon_SourceRconAuth(netadr_t *from, msg_t *msg, int *connect MSG_WriteLong(&sendmsg, SERVERDATA_AUTH_RESPONSE); MSG_WriteShort(&sendmsg, 0); NET_SendData(from->sock, &sendmsg); - return TCP_AUTHBAD; + return qfalse; } @@ -382,7 +414,10 @@ void HL2Rcon_SourceRconFlushRedirect(char* outputbuf, qboolean lastcommand){ updatelen = (int32_t*)msg.data; *updatelen = msg.cursize - 4; - NET_SendData(user->remote.sock, &msg); + if(NET_SendData(user->remote.sock, &msg) != msg.cursize) + { + sourceRcon.writeerror = 1; + } } @@ -427,11 +462,16 @@ void HL2Rcon_ExecuteConsoleCommand(const char* command, uint64_t steamid) oldinvokersteamid = Cmd_GetInvokerSteamID(); Cmd_GetInvokerName(oldinvokername, sizeof(oldinvokername)); - power = Auth_GetClPowerBySteamID(steamid); - name = Auth_GetNameBySteamID(steamid); + if(steamid != 0) + { + power = Auth_GetClPowerBySteamID(steamid); + name = Auth_GetNameBySteamID(steamid); + }else{ + power = 100; + name = "console"; + } Cmd_SetCurrentInvokerInfo(power, -1, steamid, name); - Com_BeginRedirect (sv_outputbuf, SV_OUTPUTBUF_LENGTH, HL2Rcon_SourceRconFlushRedirect); if(power < 100) @@ -460,16 +500,24 @@ void HL2Rcon_ExecuteConsoleCommand(const char* command, uint64_t steamid) Cmd_ExecuteSingleCommand(0,0, buffer); } }else{ - Cmd_ExecuteSingleCommand(0,0, command); + + //Special commands for HL2 + if(!Q_stricmpn(command, "status", 6)) + { + HL2Rcon_StatusCommand(); + }else{ + Cmd_ExecuteSingleCommand(0,0, command); + } } Com_EndRedirect(); Cmd_SetCurrentInvokerInfo(oldpower, oldinvokerclnum, oldinvokersteamid, oldinvokername); + } -qboolean HL2Rcon_SourceRconEvent(netadr_t *from, msg_t *msg, int connectionId){ +int HL2Rcon_SourceRconEvent(netadr_t *from, msg_t *msg, int connectionId){ int packettype; int type; @@ -481,21 +529,31 @@ qboolean HL2Rcon_SourceRconEvent(netadr_t *from, msg_t *msg, int connectionId){ char sv_outputbuf[HL2RCON_SOURCEOUTPUTBUF_LENGTH]; msg_t msg2; byte data[20000]; - char stringbuf[8 * MAX_STRING_CHARS]; + char stringbuf[8 * MAX_STRING_CHARS]; MSG_BeginReading(msg); + if(connectionId < 0 || connectionId >= MAX_RCONUSERS) + return -1; //Close it + + rconUser_t* user; + user = &sourceRcon.activeRconUsers[connectionId]; + + if(user->rconUsername[0] == '\0') + { + if(HL2Rcon_SourceRconAuth(from, msg, user) == qfalse) + { + return -1; + }else{ + return 0; + } + } + while(msg->readcount < msg->cursize) { //packetlen = MSG_ReadLong(msg); - if(connectionId < 0 || connectionId >= MAX_RCONUSERS) - return qtrue; - - rconUser_t* user; - user = &sourceRcon.activeRconUsers[connectionId]; - user->lastpacketid = MSG_ReadLong(msg); packettype = MSG_ReadLong(msg); @@ -517,7 +575,10 @@ qboolean HL2Rcon_SourceRconEvent(netadr_t *from, msg_t *msg, int connectionId){ //Adjust the length updatelen = (int32_t*)msg2.data; *updatelen = msg2.cursize - 4; - NET_SendData(from->sock, &msg2); + if(NET_SendData(from->sock, &msg2) != msg2.cursize) + { + return -1; //We couldn't send everything. Just error out here. Too lazy to buffer data to send + } break; case SERVERDATA_EXECCOMMAND: @@ -530,8 +591,17 @@ qboolean HL2Rcon_SourceRconEvent(netadr_t *from, msg_t *msg, int connectionId){ Com_Printf("Rcon from: %s command: %s\n", NET_AdrToString(from), command); sourceRcon.redirectUser = connectionId+1; - HL2Rcon_ExecuteConsoleCommand(command, user->steamid); + sourceRcon.writeerror = 0; + + if(user->steamid != 0 || strcmp(user->rconUsername, "console") == 0) + { + HL2Rcon_ExecuteConsoleCommand(command, user->steamid); + } sourceRcon.redirectUser = 0; + if(sourceRcon.writeerror) + { + return -1; + } break; case SERVERDATA_TURNONSTREAM: @@ -542,10 +612,15 @@ qboolean HL2Rcon_SourceRconEvent(netadr_t *from, msg_t *msg, int connectionId){ MSG_ReadByte(msg); sourceRcon.redirectUser = connectionId+1; + sourceRcon.writeerror = 0; Com_BeginRedirect (sv_outputbuf, sizeof(sv_outputbuf), HL2Rcon_SourceRconFlushRedirect); HL2Rcon_SourceRconStreaming_enable( type, user->steamid ); Com_EndRedirect (); sourceRcon.redirectUser = 0; + if(sourceRcon.writeerror) + { + return -1; + } break; case SERVERDATA_SAY: @@ -564,10 +639,10 @@ qboolean HL2Rcon_SourceRconEvent(netadr_t *from, msg_t *msg, int connectionId){ default: //Not a source rcon packet Com_Printf("Not a valid source rcon packet from: %s received. Type: %d - Closing connection\n", NET_AdrToString(from), packettype); - return qtrue; + return -1; //Close it } } - return qfalse; + return 0; } @@ -586,7 +661,7 @@ void HL2Rcon_Init(){ // Cmd_AddCommand ("rconaddadmin", HL2Rcon_SetSourceRconAdmin_f); // Cmd_AddCommand ("rconlistadmins", HL2Rcon_ListSourceRconAdmins_f); - NET_TCPAddEventType(HL2Rcon_SourceRconEvent, HL2Rcon_SourceRconAuth, HL2Rcon_SourceRconDisconnect, 9038723); + NET_TCPAddEventType(HL2Rcon_SourceRconEvent, HL2Rcon_SourceRconIdentEvent, HL2Rcon_SourceRconDisconnect, 9038723); Com_AddRedirect(HL2Rcon_SourceRconSendConsole); G_PrintAddRedirect(HL2Rcon_SourceRconSendGameLog); @@ -639,3 +714,90 @@ void HL2Rcon_EventClientEnterTeam(int cid, int team){ HL2Rcon_SourceRconSendDataToEachClient( data, 3, SERVERDATA_EVENT); } + + +void HL2Rcon_StatusCommand() +{ + int bots, humans, i; + char psti[128]; + char timestr[256]; + char state[256]; + client_t* cl; + char cleanhostname[1024]; + + Q_strncpyz(cleanhostname, sv_hostname->string, sizeof(cleanhostname)); + Q_CleanStr(cleanhostname); + + Com_Printf("hostname: %s\n", cleanhostname); + Com_Printf("version : %s\n", com_version->string); + netadr_t* outadr = NET_GetDefaultCommunicationSocket(); + Com_Printf("udp/ip : %s\n", NET_AdrToString(outadr)); + Com_Printf("os : %s\n", OS_STRING); + Com_Printf("type : dedicated server\n"); + Com_Printf("map : %s\n", sv_mapname->string); + + // don't count privateclients + bots = humans = 0; + for ( i = 0 ; i < sv_maxclients->integer ; i++ ) + { + if ( svs.clients[i].state >= CS_CONNECTED ) { + + if (svs.clients[i].netchan.remoteAddress.type != NA_BOT) { + humans++; + }else{ + bots++; + } + } + } + Com_Printf("players : %d humans, %d bots (%d/%d)\n\n", humans, bots, sv_maxclients->integer, humans + bots); + + Com_Printf("# userid name uniqueid connected ping loss state rate adr\n"); + for (i=0,cl=svs.clients; i < sv_maxclients->integer ; i++, cl++) + { + if (!cl->state) + continue; + + SV_SApiSteamIDToString(cl->playerid, psti, sizeof(psti)); + + int contime = (svs.time - cl->connectedTime) / 1000; + + if(cl->connectedTime == 0) + { + contime = 0; + } + + int h = contime / (60*60); + contime = contime % (60*60); + int m = contime / 60; + contime = contime % (60); + int s = contime; + + if(h > 0) + { + Com_sprintf(timestr, sizeof(timestr), "%02u:%02u:%02u", h,m,s); + }else{ + Com_sprintf(timestr, sizeof(timestr), "%02u:%02u", m,s); + } + int ping = cl->ping < 999 ? cl->ping : 999; + if(ping == -1) + { + ping = 0; + } + switch(cl->state) + { + case CS_ACTIVE: + strcpy(state, "active"); + break; + case CS_PRIMED: + strcpy(state, "primed"); + break; + case CS_CONNECTED: + strcpy(state, "connected"); + break; + default: + strcpy(state, "zombie"); + } + Com_Printf("# %d \"%s\" %s %s %d %d %s %d %s\n", i, cl->name, psti, timestr, ping, 0, state, cl->rate, NET_AdrToString(&cl->netchan.remoteAddress)); + } + Com_Printf("#end\n"); +} diff --git a/src/hl2rcon.h b/src/hl2rcon.h index 0cccbacf..fe175b6b 100644 --- a/src/hl2rcon.h +++ b/src/hl2rcon.h @@ -54,6 +54,7 @@ typedef struct{ rconUser_t activeRconUsers[MAX_RCONUSERS]; //For redirect int redirectUser; + qboolean writeerror; }sourceRcon_t; typedef enum{ @@ -87,13 +88,12 @@ void HL2Rcon_ChangeSourceRconAdminPassword( const char* password ); qboolean HL2Rcon_AddSourceRconAdminToList(const char* username, const char* password, const char* salt, int power); void HL2Rcon_ClearSourceRconAdminList( void ); void HL2Rcon_SourceRconDisconnect(netadr_t *from, int connectionId); -tcpclientstate_t HL2Rcon_SourceRconAuth(netadr_t *from, msg_t *msg, int *connectionId); void HL2Rcon_SourceRconSendConsole( const char* data, int msglen); void HL2Rcon_SourceRconSendChat( const char* data, int clientnum, int type); void HL2Rcon_SourceRconSendDataToEachClient( const byte* data, int msglen, int type); void HL2Rcon_SourceRconFlushRedirect(char* outputbuf, qboolean lastcommand); -qboolean HL2Rcon_SourceRconEvent(netadr_t *from, msg_t *msg, int connectionId); +int HL2Rcon_SourceRconEvent(netadr_t *from, msg_t *msg, int connectionId); void HL2Rcon_AddSourceAdminCommands(); void HL2Rcon_SourceRconSendGameLog( const char* data, int msglen); void HL2Rcon_SourceRconSendChatToEachClient( const char *text, rconUser_t *self, int cid, qboolean onlyme); diff --git a/src/httpftp.c b/src/httpftp.c index d5580aa3..22092dc8 100644 --- a/src/httpftp.c +++ b/src/httpftp.c @@ -1421,6 +1421,10 @@ static int FTP_ReceiveData(ftRequest_t* request) newsize = 2 * request->transfermsg.maxsize; if(request->finallen > 0 && newsize > request->finallen) { + if(request->finallen < request->transfermsg.cursize) + { + return -1; + } newsize = request->finallen; } @@ -1441,7 +1445,7 @@ static int FTP_ReceiveData(ftRequest_t* request) } /* Receive new bytes */ - int len = request->recvmsg.maxsize - request->recvmsg.cursize; + int len = request->transfermsg.maxsize - request->transfermsg.cursize; status = NET_TcpClientGetData( request->transfersocket, request->transfermsg.data + request->transfermsg.cursize, len, NULL, 0); if(status == NET_WANT_READ) @@ -1451,7 +1455,7 @@ static int FTP_ReceiveData(ftRequest_t* request) if(status > 0) { - request->recvmsg.cursize += status; + request->transfermsg.cursize += status; request->transfertotalreceivedbytes += status; return 1; } @@ -1819,8 +1823,6 @@ static int FTP_SendReceiveData(ftRequest_t* request) break; case 10000: - request->transferactive = qfalse; - if(request->socket >= 0) { NET_TcpCloseSocket(request->socket); @@ -1840,14 +1842,16 @@ static int FTP_SendReceiveData(ftRequest_t* request) { request->stage = -1; Com_PrintError("\nReceived complete message but message buffer is NULL!\n"); - break; + return -1; } request->stage = 10001; request->code = 200; Q_strncpyz(request->status, "OK", sizeof(request->status)); - break; - case 10001: - Com_Printf("\n"); + request->transferactive = qfalse; + Com_Printf("FTP File transfer completed\n"); + return 1; + + case 10001: return 1; default: return 0; @@ -2076,14 +2080,21 @@ qboolean HTTPServer_WriteMessage( ftRequest_t* request, netadr_t* from) bytes = NET_TcpSendData(from->sock, request->sendmsg.data + request->sentBytes, request->sendmsg.cursize - request->sentBytes, errormsg, sizeof(errormsg)); if(bytes == NET_WANT_WRITE) { - return qtrue; + return 1; +//Want write } if(bytes < 0 || bytes > (request->sendmsg.cursize - request->sentBytes)) { - return qtrue; + return -1; +//Error close it } request->sentBytes += bytes; - return qfalse; + + if(request->sendmsg.cursize != request->sentBytes) + { + return 1;//Want write + } + return -1;//We are done so close it } @@ -2255,7 +2266,7 @@ void HTTPServer_ClearConnectionId(int id) } -qboolean HTTPServer_Event(netadr_t* from, msg_t* msg, int connectionId) +int HTTPServer_Event(netadr_t* from, msg_t* msg, int connectionId) { char sessionkey[128]; httpPostVals_t values[MAX_POST_VALS]; @@ -2265,16 +2276,16 @@ qboolean HTTPServer_Event(netadr_t* from, msg_t* msg, int connectionId) if(request == NULL) { - return qtrue; + return -1; } if (request->finallen == -1 || request->recvmsg.cursize < request->finallen) { ret = HTTPServer_ReadMessage(from, msg, request); if(ret == -1) { - return qtrue; + return -1; }else if (ret == 0) { - return qfalse; + return 0; } } /* Received full message */ @@ -2292,7 +2303,7 @@ qboolean HTTPServer_Event(netadr_t* from, msg_t* msg, int connectionId) } /* Detecting the clientside protocol and process the 1st chunk of data if it is a http client */ -tcpclientstate_t HTTPServer_AuthEvent(netadr_t* from, msg_t* msg, int *connectionId) +qboolean HTTPServer_IdentEvent(netadr_t* from, msg_t* msg, int *connectionId) { ftRequest_t* request; *connectionId = 0; @@ -2305,32 +2316,27 @@ tcpclientstate_t HTTPServer_AuthEvent(netadr_t* from, msg_t* msg, int *connectio line = MSG_ReadStringLine(msg, protocol, sizeof(protocol)); if (line != NULL) { if ( Q_strncmp(line, "GET", 3) && Q_strncmp(line, "POST", 4) && Q_strncmp(line, "HEAD", 4) ) { - return TCP_AUTHNOTME; + return qfalse; } if( strstr(line, "HTTP/1.0") == NULL && strstr(line, "HTTP/1.1") == NULL ) { /* Is not a HTTP client */ - return TCP_AUTHNOTME; + return qfalse; } } request = FT_CreateRequest(NULL, NULL); if(request == NULL) - return TCP_AUTHBAD; + return qfalse; *connectionId = HTTPServer_NewConnectionId(request); if(*connectionId < 1) { FT_FreeRequest(request); - return TCP_AUTHBAD; - } - if (HTTPServer_Event(from, msg, *connectionId) == qtrue) - { - return TCP_AUTHBAD; + return qfalse; } - - return TCP_AUTHSUCCESSFULL; + return qtrue; } @@ -2350,11 +2356,12 @@ void HTTPServer_Init() char magic[] = { 'h','t','t','p' }; /* Register the events */ - NET_TCPAddEventType( HTTPServer_Event, HTTPServer_AuthEvent, HTTPServer_Disconnect, *(int*)magic); + NET_TCPAddEventType( HTTPServer_Event, HTTPServer_IdentEvent, HTTPServer_Disconnect, *(int*)magic); } + #endif /* ===================================================================== diff --git a/src/mbedtls/Makefile b/src/mbedtls/Makefile index 1dedb9d1..f31b7130 100644 --- a/src/mbedtls/Makefile +++ b/src/mbedtls/Makefile @@ -1,9 +1,9 @@ # Also see "include/mbedtls/config.h" -CFLAGS ?= -O2 +CFLAGS ?= -O2 -m32 WARNING_CFLAGS ?= -Wall -W -Wdeclaration-after-statement -LDFLAGS ?= +LDFLAGS ?= -m32 LOCAL_CFLAGS = $(WARNING_CFLAGS) -I../ -D_FILE_OFFSET_BITS=64 LOCAL_LDFLAGS = @@ -27,7 +27,7 @@ endif ifdef SHARED # all code is position-indep with mingw, avoid warning about useless flag ifndef WINDOWS_BUILD -LOCAL_CFLAGS += -fPIC -fpic +LOCAL_CFLAGS += -fPIC -fpic -m32 endif endif diff --git a/src/msg.c b/src/msg.c index 4c593908..1b41255a 100644 --- a/src/msg.c +++ b/src/msg.c @@ -77,13 +77,8 @@ void MSG_Init( msg_t *buf, byte *data, int length ) { void MSG_InitReadOnly( msg_t *buf, byte *data, int length ) { MSG_Init( buf, data, length); - buf->data = data; buf->cursize = length; buf->readonly = qtrue; - buf->splitdata = NULL; - buf->maxsize = length; - buf->splitcursize = 0; - buf->readcount = 0; } void MSG_InitReadOnlySplit( msg_t *buf, byte *data, int length, byte* arg4, int arg5 ) { @@ -1890,5 +1885,23 @@ void MSG_WriteReliableCommandToBuffer(const char *source, char *destination, int } +/* Must not be combined with functions messing with lasrefentity */ +void MSG_BeginWriteMessageLength(msg_t* msg) +{ + if ( msg->maxsize - msg->cursize < 1 ) { + msg->overflowed = qtrue; + return; + } + msg->lengthoffset = msg->cursize; + MSG_WriteLong(msg, 0); //Messagelen needs to be updated later on msg->lengthoffset +} +void MSG_EndWriteMessageLength(msg_t* msg) +{ + int messageend = msg->cursize; + msg->cursize = msg->lengthoffset; //Shift the messagewrite pointer to the place where messagelen should be stored + int messagestart = msg->lengthoffset + sizeof(uint32_t); + MSG_WriteLong(msg, messageend - messagestart); //Messagelen gets updated now + msg->cursize = messageend; //Shift it to the end again +} diff --git a/src/msg.h b/src/msg.h index 780900ac..acfb28f2 100644 --- a/src/msg.h +++ b/src/msg.h @@ -51,7 +51,10 @@ typedef struct { int splitcursize; //0x18 int readcount; //0x1c int bit; //0x20 // for bitwise reads and writes - int lastRefEntity; //0x24 + union{ + int lastRefEntity; //0x24 + int lengthoffset; + }; } msg_t; //Size: 0x28 @@ -103,6 +106,8 @@ void __cdecl MSG_ReadDeltaUsercmdKey( msg_t *msg, int key, struct usercmd_s *fro void __cdecl MSG_SetDefaultUserCmd( struct playerState_s *ps, struct usercmd_s *ucmd ); void MSG_WriteBase64(msg_t* msg, byte* inbuf, int len); void MSG_ReadBase64(msg_t* msg, byte* outbuf, int len); +void MSG_BeginWriteMessageLength(msg_t* msg); +void MSG_EndWriteMessageLength(msg_t* msg); #endif diff --git a/src/net_game.c b/src/net_game.c index 61d9e2e8..c156a48e 100644 --- a/src/net_game.c +++ b/src/net_game.c @@ -60,7 +60,6 @@ unsigned int NET_TimeGetTime() return (unsigned int)com_frameTime; } - /* ================= NET_ReadTcpPackets @@ -72,10 +71,9 @@ NET_ReadTcpPackets typedef struct { int serviceId; - tcpclientstate_t (*tcpauthevent)(netadr_t* from, msg_t* msg, int *connectionId); - qboolean (*tcpevent)(netadr_t* from, msg_t* msg, int connectionId); + int (*tcpevent)(netadr_t* from, msg_t* msg, int connectionId); void (*tcpconncloseevent)(netadr_t* from, int connectionId); - + qboolean (*tcpidentevent)(netadr_t* from, msg_t* msg, int *connectionId); }tcpevent_t; tcpevent_t tcpevents[MAX_TCPEVENTS]; @@ -98,102 +96,112 @@ void NET_TCPConnectionClosed(netadr_t* adr, int connectionId, int serviceId) } } -tcpclientstate_t NET_TCPAuthPacketEvent(netadr_t* from, byte* bufData, int len, int* connectionId, int *serviceId) -{ - - int i; - msg_t msg; - tcpclientstate_t ret; - - msg.data = bufData; - msg.cursize = len; - msg.maxsize = len; - msg.readcount = 0; - msg.bit = 0; - msg.readonly = qtrue; - msg.overflowed = qfalse; - Com_DPrintf("Auth Packet event from: %s\n", NET_AdrToString(from)); +qboolean NET_TCPPacketEvent(netadr_t* from, byte* bufData, int len, int* connectionId, int* serviceId) //Returns qtrue if it wants to write data to socket +{ + int i, r; + qboolean ret; + msg_t msg; + if(*serviceId == -1) + { + if(len == 0) + { + return qfalse; + } + if(len < 4) + { + NET_TcpCloseSocket(from->sock); + return qfalse; //Close connection + } for(i = 0; i < MAX_TCPEVENTS; i++) { - - if(tcpevents[i].tcpauthevent == NULL) + if(tcpevents[i].tcpidentevent == NULL) + { continue; - - ret = tcpevents[i].tcpauthevent(from, &msg, connectionId); - if(ret != TCP_AUTHNOTME) + } + msg.data = bufData; + msg.cursize = len; + msg.maxsize = len; + msg.readcount = 0; + msg.bit = 0; + msg.readonly = qtrue; + msg.overflowed = qfalse; + + ret = tcpevents[i].tcpidentevent(from, &msg, connectionId); + if(ret) { *serviceId = tcpevents[i].serviceId; - return ret; + break; } } - Com_DPrintf("^5Bad TCP-Packet from: %s\n", NET_AdrToString(from)); - return TCP_AUTHBAD; //Close connection -} -void NET_TCPPacketEvent(netadr_t* from, byte* bufData, int len, int connectionId, int serviceId) -{ - int i; - msg_t msg; + } - Com_DPrintf("Packet event from: %s\n", NET_AdrToString(from)); + if(*serviceId == -1) + { + return qfalse; + } - - for(i = 0; i < MAX_TCPEVENTS; i++) + for(i = 0; i < MAX_TCPEVENTS; i++) + { + if(tcpevents[i].serviceId == *serviceId) { - if(tcpevents[i].serviceId == serviceId) + msg.data = bufData; + msg.cursize = len; + msg.maxsize = len; + msg.readcount = 0; + msg.bit = 0; + msg.readonly = qtrue; + msg.overflowed = qfalse; + r = tcpevents[i].tcpevent(from, &msg, *connectionId); + if(r == -1) { - - msg.data = bufData; - msg.cursize = len; - msg.maxsize = len; - msg.readcount = 0; - msg.bit = 0; - msg.readonly = qtrue; - msg.overflowed = qfalse; - - if(tcpevents[i].tcpevent(from, &msg, connectionId)) - { - NET_TcpCloseSocket(from->sock); - } - return; + NET_TcpCloseSocket(from->sock); + return qfalse; + }else if(r == 1){ + return qtrue; } + return qfalse; } - - Com_PrintError("NET_TCPPacketEvent: Bad serviceId: %x\n", serviceId); - NET_TcpCloseSocket(from->sock); - return; //Close connection + } + Com_PrintError("NET_TCPPacketEvent: Bad serviceId: %x\n", serviceId); + NET_TcpCloseSocket(from->sock); + return qfalse; //Close connection } + + + void NET_TCPAddEventType( - qboolean (*tcpevent)(netadr_t* from, msg_t* msg, int connectionId), - tcpclientstate_t (*tcpauthevent)(netadr_t* from, msg_t* msg, int *connectionId), + int (*tcpevent)(netadr_t* from, msg_t* msg, int connectionId), //returns -1 to close connection, 0 waiting for more data to read, 1 if it wants to write more data + qboolean (*tcpserviceidentevent)(netadr_t* from, msg_t* msg, int *connectionId), void (*tcpconncloseevent)(netadr_t* from, int connectionId), int serviceId ){ - - int i; - if(tcpevent == NULL || tcpauthevent == NULL) + if(tcpevent == NULL || tcpserviceidentevent == NULL) { - Com_Error(ERR_FATAL, "NET_TCPAddEventType: NULL tcpevent handler or NULL tcpauthevent handler"); + Com_Error(ERR_FATAL, "NET_TCPAddEventType: NULL tcpevent or tcpserviceidentevent handler"); + return; + } + if(serviceId == 0) + { + Com_Error(ERR_FATAL, "NET_TCPAddEventType: NULL serviceId"); return; } - for(i = 0; i < MAX_TCPEVENTS; i++) { - if(tcpevents[i].tcpevent == tcpevent) + if(tcpevents[i].tcpidentevent == tcpserviceidentevent) { Com_Error(ERR_FATAL, "NET_TCPAddEventType: Attempt to add an already defined redirect function twice."); return; } - if(tcpevents[i].tcpevent == NULL) { tcpevents[i].tcpevent = tcpevent; - tcpevents[i].tcpauthevent = tcpauthevent; + tcpevents[i].tcpidentevent = tcpserviceidentevent; tcpevents[i].tcpconncloseevent = tcpconncloseevent; tcpevents[i].serviceId = serviceId; return; @@ -202,4 +210,3 @@ void NET_TCPAddEventType( Com_Error(ERR_FATAL, "NET_TCPAddEventType: Out of redirect handles. Increase MAX_TCPEVENTS to add more redirect destinations"); } - diff --git a/src/net_game.h b/src/net_game.h index b30ae052..cea5a8e9 100644 --- a/src/net_game.h +++ b/src/net_game.h @@ -33,14 +33,13 @@ unsigned int NET_TimeGetTime(); void NET_TCPConnectionClosed(netadr_t* adr, int connectionId, int serviceId); tcpclientstate_t NET_TCPAuthPacketEvent(netadr_t* remote, byte* bufData, int cursize, int* connectionId, int *serviceId); -void NET_TCPPacketEvent(netadr_t* remote, byte* bufData, int cursize, int connectionId, int serviceId); +qboolean NET_TCPPacketEvent(netadr_t* remote, byte* bufData, int cursize, int *connectionId, int *serviceId); void NET_TCPAddEventType( - qboolean (*tcpevent)(netadr_t* from, msg_t* msg, int connectionId), - tcpclientstate_t (*tcpauthevent)(netadr_t* from, msg_t* msg, int *connectionId), + int (*tcpevent)(netadr_t* from, msg_t* msg, int connectionId), + qboolean (*tcpserviceidentevent)(netadr_t* from, msg_t* msg, int *connectionId), void (*tcpconncloseevent)(netadr_t* from, int connectionId), int serviceId ); #endif - diff --git a/src/plugin_events.h b/src/plugin_events.h index b786ef82..f0d4a821 100644 --- a/src/plugin_events.h +++ b/src/plugin_events.h @@ -55,7 +55,7 @@ enum PluginEvents{ PLUGINS_ONPLAYERADDBAN, PLUGINS_ONPLAYERGETBANSTATUS, PLUGINS_ONPLAYERREMOVEBAN, - PLUGINS_ONMODULELOADED, + PLUGINS_ONMODULELOADED, PLUGINS_ITEMCOUNT }; diff --git a/src/plugin_exports.c b/src/plugin_exports.c index cc72d9d3..819a5185 100644 --- a/src/plugin_exports.c +++ b/src/plugin_exports.c @@ -141,12 +141,9 @@ P_P_F void Plugin_AddCommand(char *name, xcommand_t xcommand, int power) } -/* -P_P_F qboolean Plugin_TcpConnect( int connection, const char* remote) + +P_P_F qboolean Plugin_TcpConnectMT( int pID, int connection, const char* remote) { - int pID; - //Identify the calling plugin - pID = PHandler_CallerID(); if(pID<0){ Com_Printf("Plugins: Error! Tried open a TCP-Connection for unknown plugin!\n"); return qfalse; @@ -163,12 +160,18 @@ P_P_F qboolean Plugin_TcpConnect( int connection, const char* remote) } -P_P_F int Plugin_TcpGetData(int connection, void* buf, int size) +P_P_F qboolean Plugin_TcpConnect( int connection, const char* remote) { int pID; //Identify the calling plugin pID = PHandler_CallerID(); - if(pID<0){ + return Plugin_TcpConnectMT(pID, connection, remote); +} + + +P_P_F int Plugin_TcpGetDataMT(int pID, int connection, void* buf, int size) +{ + if(pID<0 || pID >= MAX_PLUGINS){ Com_Printf("Plugin_TcpGetData: Error! Tried get TCP data for unknown plugin!\n"); return -1; } @@ -188,15 +191,18 @@ P_P_F int Plugin_TcpGetData(int connection, void* buf, int size) return PHandler_TcpGetData(pID, connection, buf, size); } - -P_P_F qboolean Plugin_TcpSendData(int connection, void* data, int len) +P_P_F int Plugin_TcpGetData(int connection, void* buf, int size) { - - int pID; //Identify the calling plugin pID = PHandler_CallerID(); - if(pID<0){ + return Plugin_TcpGetDataMT(pID, connection, buf, size); +} + + +P_P_F qboolean Plugin_TcpSendDataMT(int pID, int connection, void* data, int len) +{ + if(pID<0 || pID >= MAX_PLUGINS){ Com_Printf("Plugin_TcpSendData: Error! Tried get TCP data for unknown plugin!\n"); return qfalse; } @@ -216,12 +222,18 @@ P_P_F qboolean Plugin_TcpSendData(int connection, void* data, int len) return PHandler_TcpSendData(pID, connection, data, len); } -P_P_F void Plugin_TcpCloseConnection(int connection) +P_P_F qboolean Plugin_TcpSendData(int connection, void* data, int len) { int pID; //Identify the calling plugin pID = PHandler_CallerID(); - if(pID<0){ + return Plugin_TcpSendDataMT(pID, connection, data, len); +} + +P_P_F void Plugin_TcpCloseConnectionMT(int pID, int connection) +{ + //Identify the calling plugin + if(pID<0 || pID >= MAX_PLUGINS){ Com_Printf("Plugin_TcpCloseConnection: Error! Tried get close a connection for unknown plugin!\n"); return; } @@ -235,7 +247,15 @@ P_P_F void Plugin_TcpCloseConnection(int connection) } PHandler_TcpCloseConnection(pID, connection); } -*/ + +P_P_F void Plugin_TcpCloseConnection(int connection) +{ + int pID; + //Identify the calling plugin + pID = PHandler_CallerID(); + Plugin_TcpCloseConnectionMT(pID, connection); +} + P_P_F qboolean Plugin_UdpSendData(netadr_t* to, void* data, int len) { @@ -877,3 +897,10 @@ P_P_F qboolean Plugin_CreateCallbackThread(void* threadMain,...) tcb->isActive = qtrue; return success; } + + +P_P_F int Plugin_GetPluginID() //Only from mainthread callable +{ + int PID = PHandler_CallerID(); + return PID; +} diff --git a/src/plugin_handler.h b/src/plugin_handler.h index d320adab..12e4017b 100644 --- a/src/plugin_handler.h +++ b/src/plugin_handler.h @@ -202,7 +202,7 @@ void PHandler_FreeAll(int); void PHandler_Error(int,int, char *); qboolean PHandler_TcpConnect(int,const char *,int); int PHandler_TcpGetData(int, int, void*, int); -qboolean PHandler_TcpSendData(int,int, void*, int); +int PHandler_TcpSendData(int,int, void*, int); void PHandler_TcpCloseConnection(int,int); int PHandler_CallerID(); void PHandler_ChatPrintf(int,char *,...); diff --git a/src/plugin_internal.c b/src/plugin_internal.c index 91300839..e541126f 100644 --- a/src/plugin_internal.c +++ b/src/plugin_internal.c @@ -39,7 +39,7 @@ TCP module ============ */ -/* + qboolean PHandler_TcpConnect(int pID, const char* remote, int connection) { if(pluginFunctions.plugins[pID].sockets[connection].sock < 1){ @@ -87,7 +87,7 @@ int PHandler_TcpGetData(int pID, int connection, void* buf, int size ) } -qboolean PHandler_TcpSendData(int pID, int connection, void* data, int len) +int PHandler_TcpSendData(int pID, int connection, void* data, int len) { int state; @@ -95,18 +95,23 @@ qboolean PHandler_TcpSendData(int pID, int connection, void* data, int len) if(ptcs->sock < 1){ Com_PrintWarning("Plugin_TcpSendData: called on a non open socket for plugin ID: #%d\n", pID); - return qfalse; + return -1; } - state = NET_TcpSendData(ptcs->sock, data, len); + state = NET_TcpSendData(ptcs->sock, data, len, NULL, 0); Com_DPrintf("PHandler_TcpSendData: Sent data from socket %d @ %d\n", ptcs->sock, connection); - if(state == -1 || state == NET_WANT_WRITE) + if(state == NET_WANT_WRITE) + { + return 0; + } + + if(state == -1) { NET_TcpCloseSocket(ptcs->sock); ptcs->sock = -1; - return qfalse; + return -1; } - return qtrue; + return state; } void PHandler_TcpCloseConnection(int pID, int connection) @@ -121,7 +126,7 @@ void PHandler_TcpCloseConnection(int pID, int connection) Com_DPrintf("PHandler_TcpCloseConnection: Closed socket %d @ %d\n", ptcs->sock, connection); ptcs->sock = -1; } -*/ + /* ===================================== Functionality providers for exports diff --git a/src/pluginexports.asm b/src/pluginexports.asm index 8979eb22..33f78a44 100644 --- a/src/pluginexports.asm +++ b/src/pluginexports.asm @@ -53,10 +53,6 @@ ralias Plugin_PrintWarning, Com_PrintWarning ralias Plugin_PrintError, Com_PrintError ralias Plugin_DPrintf, Com_DPrintf -ralias Plugin_ParseGetToken, Com_ParseGetToken -ralias Plugin_ParseTokenLength, Com_ParseTokenLength -ralias Plugin_ParseReset, Com_ParseReset - ralias Plugin_RandomBytes, Com_RandomBytes ralias Plugin_GetRealtime, Com_GetRealtime @@ -73,6 +69,10 @@ ralias Plugin_StringToSteamID, SV_SApiStringToID ralias Plugin_SteamIDIsIndividual, SV_SApiSteamIDIndividual ralias Plugin_SteamIDIsIndividualAndSteamAccount, SV_SApiSteamIDIndividualSteamOnly ralias Plugin_AddCommandForClientToWhitelist, Auth_AddCommandForClientToWhitelist +ralias Plugin_CanPlayerUseCommand, Auth_CanPlayerUseCommand +ralias Plugin_SV_Cmd_GetPlayerClByHandle ,SV_GetPlayerClByHandle +ralias Plugin_SV_Cmd_GetPlayerNameByHandle, SV_GetPlayerNameByHandle +ralias Plugin_SV_Cmd_GetPlayerSteamIDByHandle, SV_GetPlayerSteamIDByHandle pexport Cmd_GetInvokerClnum pexport Cmd_GetInvokerPower @@ -83,6 +83,7 @@ pexport Cmd_Argv pexport Cmd_Argc pexport Cmd_Args + pexport Cvar_VariableStringBuffer pexport Cvar_VariableValue pexport Cvar_VariableIntegerValue diff --git a/src/qcommon_parsecmdline.c b/src/qcommon_parsecmdline.c index d81eaa99..4e1da46e 100644 --- a/src/qcommon_parsecmdline.c +++ b/src/qcommon_parsecmdline.c @@ -221,8 +221,8 @@ qboolean Com_SafeMode( void ) { Cmd_EndTokenizedString( ); return qtrue; } + Cmd_EndTokenizedString( ); } - Cmd_EndTokenizedString( ); return qfalse; } diff --git a/src/qshared.c b/src/qshared.c index f405d044..9f3886a6 100644 --- a/src/qshared.c +++ b/src/qshared.c @@ -1270,9 +1270,9 @@ void XML_Init( xml_t *base, char *s, int size, char* encoding) { ================== */ void XML_Escape( char* buffer, size_t size, const char* string){ - int i; + char* basebuf = buffer; - for(i = 7; i < size && *string != 0; i++, string++){ + for(; (buffer - basebuf + 7) < size && *string != 0; string++){ switch(*string){ @@ -1319,11 +1319,16 @@ qboolean QDECL XML_OpenTag( xml_t *base, char* root, int count,... ) { char* key; char* value; - char buffer[1024]; - char smallbuff[128]; + char buffer[8192]; + char smallbuff[512]; int i; buffer[0] = 0; + if(base->parents*6 +1 >= sizeof(smallbuff)) + { + Com_Printf("^3Warning: XML_OpenTag would overflow. Too many open tags\n"); + return qfalse; + } Com_Memset(&smallbuff[1],' ',base->parents*6); smallbuff[0] = '\n'; smallbuff[base->parents*6] = 0; diff --git a/src/sapi.c b/src/sapi.c index 6d48f2d2..7e93a82a 100644 --- a/src/sapi.c +++ b/src/sapi.c @@ -12,8 +12,9 @@ #include "sapi.h" #include "sys_main.h" #include "cmd.h" +#include "sec_crypto.h" -void (*Init)(imports_t* imports, exports_t* exports); +void (*Init)(imports_t* sapi_imports, exports_t* exports); void SV_SApiSteamIDTo64String(uint64_t steamid, char* string, int length) @@ -306,23 +307,149 @@ void SV_SApiSteamIDToString(uint64_t steamid, char* string, int length) Com_sprintf(string, length, "[%c:%u:%u]", accounttypechars[accounttype], universe, accountid); } +/** + Execute LTC_PKCS #5 v2 + @param password The input password (or key) + @param password_len The length of the password (octets) + @param salt The salt (or nonce) + @param salt_len The length of the salt (octets) + @param iteration_count # of iterations desired for LTC_PKCS #5 v2 [read specs for more] + @param hash_idx The index of the hash desired + @param out [out] The destination for this algorithm + @param outlen [in/out] The max size and resulting size of the algorithm output + @return CRYPT_OK if successful +*/ +/* +Copied from libtomcrypt so here a sleep can be included for less blocking the main thread while this function is operating +*/ + + +int pkcs_5_alg2_200sleep(const unsigned char *password, unsigned long password_len, + const unsigned char *salt, unsigned long salt_len, + int iteration_count, int hash_idx, + unsigned char *out, unsigned long *outlen) +{ + int err, itts, i; + ulong32 blkno; + unsigned long stored, left, x, y; + unsigned char *buf[2]; + hmac_state *hmac; + + LTC_ARGCHK(password != NULL); + LTC_ARGCHK(salt != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* test hash IDX */ + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + return err; + } + + buf[0] = XMALLOC(MAXBLOCKSIZE * 2); + hmac = XMALLOC(sizeof(hmac_state)); + if (hmac == NULL || buf[0] == NULL) { + if (hmac != NULL) { + XFREE(hmac); + } + if (buf[0] != NULL) { + XFREE(buf[0]); + } + return CRYPT_MEM; + } + /* buf[1] points to the second block of MAXBLOCKSIZE bytes */ + buf[1] = buf[0] + MAXBLOCKSIZE; + + left = *outlen; + blkno = 1; + stored = 0; + while (left != 0) { + /* process block number blkno */ + zeromem(buf[0], MAXBLOCKSIZE*2); + + /* store current block number and increment for next pass */ + STORE32H(blkno, buf[1]); + ++blkno; + + /* get PRF(P, S||int(blkno)) */ + if ((err = hmac_init(hmac, hash_idx, password, password_len)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = hmac_process(hmac, salt, salt_len)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = hmac_process(hmac, buf[1], 4)) != CRYPT_OK) { + goto LBL_ERR; + } + x = MAXBLOCKSIZE; + if ((err = hmac_done(hmac, buf[0], &x)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* now compute repeated and XOR it in buf[1] */ + XMEMCPY(buf[1], buf[0], x); + for (itts = 1; itts < iteration_count; ++itts) { + for(i = 0; i < 200; ++i) + { + if ((err = hmac_memory(hash_idx, password, password_len, buf[0], x, buf[0], &x)) != CRYPT_OK) { + goto LBL_ERR; + } + for (y = 0; y < x; y++) { + buf[1][y] ^= buf[0][y]; + } + } + Sys_SleepSec(0); + } + + /* now emit upto x bytes of buf[1] to output */ + for (y = 0; y < x && left != 0; ++y) { + out[stored++] = buf[1][y]; + --left; + } + } + *outlen = stored; + + err = CRYPT_OK; +LBL_ERR: + XFREE(hmac); + XFREE(buf[0]); + + return err; +} + + +static const unsigned char playerid_salt[] = +{ + 0x83, 0xf3, 0x65, 0x90, 0x6c, 0x75, 0x33, 0xe1, 0x81, 0xaf, 0xc1, 0x44, 0xe1, 0x3e, 0xf0, 0x66, + 0x77, 0xec, 0x0e, 0x62, 0x6a, 0xe2, 0xf3, 0xba, 0x58, 0x1a, 0x72, 0x62, 0x2a, 0xc4, 0xcc, 0x61, + 0x49, 0x4b, 0xf5, 0xb9, 0x49, 0xea, 0x2b, 0xdf, 0x0f, 0x99, 0xe2, 0x8e, 0xb8, 0x7e, 0x50, 0x63, + 0xc6, 0xd5, 0x44, 0xdd, 0x0b, 0x56, 0x96, 0x19, 0x94, 0x76, 0x98, 0x90, 0x17, 0xb2, 0x66, 0xfa, + 0x23, 0x7c, 0xcd, 0x31, 0x49, 0x4b, 0x85, 0x31, 0xc2, 0xfe, 0x86, 0x3d, 0x80, 0xcd, 0xe5, 0x3a, + 0xe9, 0x43, 0xc3, 0x7c, 0x19, 0xc3, 0x9c, 0xbe, 0x19, 0x33, 0x5c, 0x22, 0x34, 0x16, 0xc9, 0xc2, + 0xce, 0xd2, 0x25, 0x2d, 0x5f, 0x2e, 0x32, 0x81, 0x97, 0xcf, 0x14, 0x96, 0x6b, 0x15, 0x59, 0xce, + 0xbd, 0x36, 0xdb, 0xbc, 0x23, 0x16, 0x74, 0x68, 0xa1, 0x4f, 0x0c, 0x46, 0xbc, 0x1e, 0x19, 0x12, + 0x8a, 0x86, 0x16, 0x2d, 0xe9, 0x3f, 0x22, 0x49, 0x0d, 0xaa, 0x6e, 0x15, 0x47, 0xe8, 0x19, 0x17, + 0xa2, 0xf1, 0xcc, 0xca, 0x49, 0x38, 0xa0, 0xa7, 0xb3, 0xcc, 0x92, 0xb5, 0x7c, 0x0c, 0xd4, 0x25, + 0x6a, 0x3e, 0x55, 0xc4, 0x72, 0x39, 0x81, 0x22, 0x0d, 0x1a, 0xc7, 0x1e, 0xf4, 0x96, 0xe4, 0xc6, + 0x6d, 0x6c, 0x43, 0x81, 0xcf, 0x64, 0x49, 0xa1, 0x10, 0x73, 0x46, 0x7a, 0x05, 0xdb, 0xdb, 0xd4, + 0x94, 0x3f, 0x04, 0x52, 0xd8, 0x23, 0x9d, 0x85, 0x59, 0x3a, 0x29, 0xfc, 0xfc, 0xd5, 0x06, 0xc9, + 0xdf, 0x58, 0xc3, 0x7e, 0x49, 0xe4, 0xbe, 0x79, 0x37, 0x97, 0x51, 0xc2, 0xf0, 0x0c, 0x38, 0x6f, + 0x96, 0x58, 0xaf, 0xb0, 0x43, 0x10, 0x41, 0x57, 0xef, 0xc6, 0xfa, 0x40, 0x6f, 0xa4, 0xc5, 0xc6, + 0x67, 0x08, 0xd3, 0x65, 0x0f, 0xb0, 0xa4, 0x4d, 0x54, 0xe4, 0x87, 0xc7, 0x0f, 0x52, 0xe2, 0xc6 +}; + + uint64_t SV_SApiGUID2PlayerID(const char* guid) { - uint32_t digest[5]; - uint32_t workspace[80]; - char data[64]; uint8_t diggest2[16]; char digit2[3]; int len = strlen(guid); - int i, k; + int i; if(len != 32) { return 0; } - sha_init(digest); - for(i = 0; i < sizeof(diggest2); ++i) { digit2[i] = guid[2*i]; @@ -330,28 +457,30 @@ uint64_t SV_SApiGUID2PlayerID(const char* guid) digit2[i+2] = 0; diggest2[i] = strtol(digit2, NULL, 16);; } - for(i = 0; i < sizeof(data); ++i) - { - data[i] = diggest2[i % 16] ^ i; - } - for(i = 0; i < 200*100; ++i) + + //Random account id + uint32_t accountid; + uint32_t universe = 32; //Custom universe 32 for HW auth players + uint32_t accounttype = 1; + uint32_t instance = 1; + + unsigned long outlen = sizeof(accountid); + + int hash_idx = find_hash("sha256"); + + if(pkcs_5_alg2(diggest2, sizeof(diggest2), playerid_salt, sizeof(playerid_salt), 100, hash_idx, (unsigned char *)&accountid, &outlen) != CRYPT_OK) //This function is special. It sleeps { - sha_transform(digest, data, workspace); - for(k = 0; k < 64; ++k) - { - data[k] = ((uint32_t)data[k] ^ (uint32_t)digest[k % 5]) ; - } + //Com_PrintError("Couldn't create hash for playerid. Player id is invalid\n"); + accountid = 0; } - uint32_t accountid = *(uint32_t*)&data[15]; - uint64_t universe = 32; - uint64_t accounttype = 1; - uint64_t instance = 1; + uint64_t steamid = ((uint64_t)universe << 56) | ((uint64_t)accounttype << 52) | ((uint64_t)instance << 32) | accountid; return steamid; } -exports_t imp; +exports_t sapi_imp; + void SV_GetSS_f(); @@ -372,8 +501,11 @@ void SV_InitSApi() exports.SV_SendReliableServerCommand = SV_SendReliableServerCommand; exports.SV_AddBanForClient = SV_AddBanForClient; exports.SV_ScreenshotArrived = SV_ScreenshotArrived; + exports.SV_ModuleArrived = SV_ModuleArrived; exports.FS_SV_HomeWriteFile = FS_SV_HomeWriteFile; exports.Sys_Milliseconds = Sys_Milliseconds; + exports.pkcs_5_alg2 = pkcs_5_alg2_200sleep; + exports.find_hash = find_hash; hmodule = Sys_LoadLibrary("steam_api" DLL_EXT); if(hmodule == NULL) @@ -388,28 +520,28 @@ void SV_InitSApi() Com_PrintError("Init entrypoint not found. Steam is not going to work.\n"); return; } - Init(&exports, &imp); + Init(&exports, &sapi_imp); Cmd_AddPCommand ("getss", SV_GetSS_f, 45); } void SV_RunSApiFrame() { - if(imp.RunFrame) - imp.RunFrame(); + if(sapi_imp.RunFrame) + sapi_imp.RunFrame(); } void SV_NotifySApiDisconnect(client_t* drop) { - if(imp.NotifyDisconnect) - imp.NotifyDisconnect(drop); + if(sapi_imp.NotifyDisconnect) + sapi_imp.NotifyDisconnect(drop); } int SV_ConnectSApi(client_t* client) { - if(imp.Connect) + if(sapi_imp.Connect) { - return imp.Connect(client); + return sapi_imp.Connect(client); } //Q_strncpyz(client->shortname, client->name, sizeof(client->shortname)); return 1; @@ -418,9 +550,9 @@ int SV_ConnectSApi(client_t* client) void SV_SApiData(client_t* cl, msg_t* msg) { - if(imp.Data) + if(sapi_imp.Data) { - imp.Data(cl, msg); + sapi_imp.Data(cl, msg); if(cl->state > CS_CONNECTED) { ClientUserinfoChanged( cl - svs.clients ); @@ -431,19 +563,33 @@ void SV_SApiData(client_t* cl, msg_t* msg) void SV_SApiShutdown() { - if(imp.Shutdown) - imp.Shutdown(); + if(sapi_imp.Shutdown) + sapi_imp.Shutdown(); } void SV_SApiReadSS( client_t* cl, msg_t* msg ) { - if(imp.ReadSS) - imp.ReadSS( cl, msg ); + if(sapi_imp.ReadSS) + sapi_imp.ReadSS( cl, msg ); } void SV_SApiTakeSS(client_t* cl, const char* savename) { - if(imp.TakeSS) - imp.TakeSS( cl, savename ); + if(sapi_imp.TakeSS) + sapi_imp.TakeSS( cl, savename ); +} + +void SV_SApiSendModuleRequest(client_t* cl) +{ + if(sapi_imp.SendModuleRequest) + { + sapi_imp.SendModuleRequest(cl); + } +} + +void SV_SApiProcessModules( client_t* cl, msg_t* msg ) +{ + if(sapi_imp.ProcessModules) + sapi_imp.ProcessModules(cl, msg); } diff --git a/src/sapi.h b/src/sapi.h index d0c5f340..d02bc006 100644 --- a/src/sapi.h +++ b/src/sapi.h @@ -18,7 +18,10 @@ uint64_t SV_SApiStringToID(const char* steamidstring); qboolean SV_SApiSteamIDIndividual(uint64_t steamid); qboolean SV_SApiSteamIDIndividualSteamOnly(uint64_t steamid); //void SV_SApiReadModules( client_t* cl, msg_t* msg ); -void SV_SApiRequestModules( client_t* cl, msg_t* msg ); +//void SV_SApiRequestModules( client_t* cl, msg_t* msg ); +void SV_SApiSendModuleRequest(client_t* cl); +void SV_SApiProcessModules( client_t* cl, msg_t* msg ); + uint64_t SV_SApiGUID2PlayerID(const char* guid); #endif @@ -40,15 +43,22 @@ typedef struct{ void (*SV_SendReliableServerCommand)(client_t* client, msg_t *msg); void (*SV_AddBanForClient)(client_t* cl, int bantime, const char* banreason); void (*SV_ScreenshotArrived)(client_t* cl, const char* filename); + void (*SV_ModuleArrived)(client_t* cl, const char* filename, long checksum); #else void (*SV_DropClientNoNotify)( void *drop, const char *reason ); void (*SV_DropClient)( void *drop, const char *reason ); void (*SV_SendReliableServerCommand)(void* client, void *msg); void (*SV_AddBanForClient)(void* cl, int bantime, const char* banreason); void (*SV_ScreenshotArrived)(void* cl, const char* filename); + void (*SV_ModuleArrived)(void* cl, const char* filename, long checksum); #endif int (*FS_SV_HomeWriteFile)( const char *qpath, const void *buffer, int size); unsigned int (*Sys_Milliseconds)(); + int (*pkcs_5_alg2)(const unsigned char *password, unsigned long password_len, + const unsigned char *salt, unsigned long salt_len, + int iteration_count, int hash_idx, + unsigned char *out, unsigned long *outlen); + int (*find_hash)(const char* name); }imports_t; @@ -56,6 +66,8 @@ typedef struct{ typedef struct{ void (*TakeSS)(client_t* cl, const char* savename); void (*ReadSS)( client_t* cl, msg_t* msg ); + void (*SendModuleRequest)(client_t* cl); + void (*ProcessModules)(client_t* cl, msg_t* msg); void (*Shutdown)(); void (*Data)(client_t* cl, msg_t* msg); int (*Connect)(client_t* client); diff --git a/src/sec_common.c b/src/sec_common.c index 8bbc3088..8be9b4a2 100644 --- a/src/sec_common.c +++ b/src/sec_common.c @@ -38,7 +38,7 @@ int SecCryptErr; char *Sec_CryptErrStr(int code){ switch(code){ - + case CRYPT_OK: return "CRYPT_OK"; case CRYPT_ERROR: return "CRYPT_ERROR"; case CRYPT_NOP: return "CRYPT_NOP"; @@ -81,7 +81,7 @@ char *Sec_CryptErrStr(int code){ Hash descriptors from tomcrypt ================================ */ - +#if 0 volatile const struct ltc_hash_descriptor sec_sha1_desc = { "sha1", @@ -110,7 +110,7 @@ volatile const struct ltc_hash_descriptor sec_sha256_desc = /* OID */ { 2, 16, 840, 1, 101, 3, 4, 2, 1, }, 9, - + &sha256_init, &sha256_process, &sha256_done, @@ -135,8 +135,8 @@ volatile const struct ltc_hash_descriptor sec_tiger_desc = &tiger_test, NULL }; - +#endif /* unsigned long sec_test = sec_tiger_desc.hashsize; -unsigned long sec_test2 = tiger_desc.hashsize;*/ \ No newline at end of file +unsigned long sec_test2 = tiger_desc.hashsize;*/ diff --git a/src/sec_crypto.c b/src/sec_crypto.c index 99e1af65..43bd90b9 100644 --- a/src/sec_crypto.c +++ b/src/sec_crypto.c @@ -22,9 +22,6 @@ #include "sec_crypto.h" #include "sec_common.h" -struct ltc_hash_descriptor sec_hashes[SEC_HASH_SIZE__]; - - qboolean Sec_BinaryToHex(char *in,unsigned long inSize,char *out, unsigned long *outSize){ if(*outSize < inSize * 2+1){ @@ -45,50 +42,55 @@ qboolean Sec_BinaryToHex(char *in,unsigned long inSize,char *out, unsigned long return qtrue; } -qboolean Sec_HashMemory(sec_hash_e algo, void *in, size_t inSize, void *out, long unsigned int *outSize,qboolean binaryOutput){ +qboolean Sec_HashMemory(int algo, void *in, size_t inSize, void *out, long unsigned int *outSize,qboolean binaryOutput){ //__asm__("int $3"); - if(in == NULL || out == NULL || *outSize < 1 || inSize < 1 || algo >= SEC_HASH_SIZE__){ + if(in == NULL || out == NULL || *outSize < 1 || inSize < 1 || algo >= TAB_SIZE){ SecCryptErr = CRYPT_INVALID_ARG; return qfalse; } if(!Sec_Initialized()){ return qfalse; } - + hash_state md; int result; long unsigned int size; unsigned char *buff = NULL,*buff2 = NULL; - struct ltc_hash_descriptor *hs = &sec_hashes[algo]; - + struct ltc_hash_descriptor *hs = &hash_descriptor[algo]; + + if(hs->name == NULL){ + SecCryptErr = CRYPT_INVALID_ARG; + return qfalse; + } + SecCryptErr = CRYPT_OK; size = (binaryOutput ? hs->hashsize / 4: hs->hashsize); - + if(size > *outSize){ SecCryptErr = CRYPT_MEM; return qfalse; } - + if(!binaryOutput) {buff = (unsigned char *)Sec_Malloc(sizeof(unsigned char) * size); buff2 = buff; } else {buff2 = NULL; buff = out; } - + if((result = hs->init(&md)) != CRYPT_OK) { Sec_Free(buff2); SecCryptErr = result; return qfalse; } if((result = hs->process(&md, in, inSize)) != CRYPT_OK){ Sec_Free(buff2); SecCryptErr = result; return qfalse; } if((result = hs->done(&md,buff)) != CRYPT_OK) { Sec_Free(buff2); SecCryptErr = result; return qfalse; } - + if(!binaryOutput){ Sec_BinaryToHex((char *)buff,hs->hashsize,out,outSize); } else *outSize = hs->hashsize; - + Sec_Free(buff2); - + return (SecCryptErr == CRYPT_OK); } -qboolean Sec_HashFile(sec_hash_e algo, const char *fname, void *out, long unsigned *outSize,qboolean binaryOutput) +qboolean Sec_HashFile(int algo, const char *fname, void *out, long unsigned *outSize,qboolean binaryOutput) { - if(fname == NULL || out == NULL || outSize == NULL || *outSize < 1 || algo < 0 || algo >= SEC_HASH_SIZE__){ + if(fname == NULL || out == NULL || outSize == NULL || *outSize < 1 || algo < 0 || algo >= TAB_SIZE){ SecCryptErr = CRYPT_INVALID_ARG; return qfalse; } @@ -100,15 +102,21 @@ qboolean Sec_HashFile(sec_hash_e algo, const char *fname, void *out, long unsign unsigned char buff[1024]; unsigned char *ptr; int x,result,size; - struct ltc_hash_descriptor *hs = &sec_hashes[algo]; + struct ltc_hash_descriptor *hs = &hash_descriptor[algo]; SecCryptErr = CRYPT_OK; + + if(hs->name == NULL){ + SecCryptErr = CRYPT_INVALID_ARG; + return qfalse; + } + size = binaryOutput ? hs->hashsize / 4 : hs->hashsize; if(size > *outSize){ SecCryptErr = CRYPT_MEM; return qfalse; } unsigned long dbg = 0; - + if((result = hs->init(&md))!=CRYPT_OK){ SecCryptErr=result; return qfalse; } fp = fopen(fname,"rb"); if(fp==NULL){ @@ -117,7 +125,7 @@ qboolean Sec_HashFile(sec_hash_e algo, const char *fname, void *out, long unsign } do{ x = fread(buff, 1, sizeof(buff), fp); - + if ((result = hs->process(&md, buff, x)) != CRYPT_OK){ SecCryptErr = result; fclose(fp); diff --git a/src/sec_crypto.h b/src/sec_crypto.h index 4edae803..809987dc 100644 --- a/src/sec_crypto.h +++ b/src/sec_crypto.h @@ -25,17 +25,12 @@ #include "q_shared.h" #include "tomcrypt/tomcrypt.h" +extern int SEC_HASH_SHA1; +extern int SEC_HASH_SHA256; +extern int SEC_HASH_TIGER; -typedef enum{ - SEC_HASH_SHA1, - SEC_HASH_SHA256, - SEC_HASH_TIGER, - SEC_HASH_SIZE__ -}sec_hash_e; - -qboolean Sec_HashMemory(sec_hash_e algo, void *in, size_t inSize, void *out, long unsigned int *outSize,qboolean binaryOutput); -qboolean Sec_HashFile(sec_hash_e algo, const char *fname, void *out, long unsigned *outSize,qboolean binaryOutput); +qboolean Sec_HashMemory(int algo, void *in, size_t inSize, void *out, long unsigned int *outSize,qboolean binaryOutput); +qboolean Sec_HashFile(int algo, const char *fname, void *out, long unsigned *outSize,qboolean binaryOutput); qboolean Sec_BinaryToHex(char *in,unsigned long inSize,char *out,unsigned long *outSize); -extern struct ltc_hash_descriptor sec_hashes[SEC_HASH_SIZE__]; -#endif \ No newline at end of file +#endif diff --git a/src/sec_init.c b/src/sec_init.c index 3dd5bf4b..59dac475 100644 --- a/src/sec_init.c +++ b/src/sec_init.c @@ -29,6 +29,9 @@ qboolean initialized = qfalse; +int SEC_HASH_SHA1; +int SEC_HASH_SHA256; +int SEC_HASH_TIGER; qboolean Sec_Initialized(){ return initialized; @@ -40,85 +43,39 @@ void Sec_Init(void) // Connect the math library with the crypt library ltc_mp = ltm_desc; //Cmd_AddCommand("createCert", Sec_MakeCert_f); - sec_hashes[SEC_HASH_SHA1].name="SHA1"; - sec_hashes[SEC_HASH_SHA1].ID=SEC_HASH_SHA1; - sec_hashes[SEC_HASH_SHA1].hashsize=20; - sec_hashes[SEC_HASH_SHA1].blocksize=64; - - sec_hashes[SEC_HASH_SHA1].OID[0]=1; - sec_hashes[SEC_HASH_SHA1].OID[1]=3; - sec_hashes[SEC_HASH_SHA1].OID[2]=14; - sec_hashes[SEC_HASH_SHA1].OID[3]=3; - sec_hashes[SEC_HASH_SHA1].OID[4]=2; - sec_hashes[SEC_HASH_SHA1].OID[5]=26; - - sec_hashes[SEC_HASH_SHA1].OIDlen=6; - sec_hashes[SEC_HASH_SHA1].init=&sha1_init; - sec_hashes[SEC_HASH_SHA1].process=&sha1_process; - sec_hashes[SEC_HASH_SHA1].done=&sha1_done; - sec_hashes[SEC_HASH_SHA1].test=&sha1_test; - sec_hashes[SEC_HASH_SHA1].hmac_block=NULL; - - /* ------------------------------------------------------------ */ - - sec_hashes[SEC_HASH_SHA256].name="SHA256"; - sec_hashes[SEC_HASH_SHA256].ID=SEC_HASH_SHA256; - sec_hashes[SEC_HASH_SHA256].hashsize=32; - sec_hashes[SEC_HASH_SHA256].blocksize=64; - - sec_hashes[SEC_HASH_SHA256].OID[0]=2; - sec_hashes[SEC_HASH_SHA256].OID[1]=16; - sec_hashes[SEC_HASH_SHA256].OID[2]=840; - sec_hashes[SEC_HASH_SHA256].OID[3]=1; - sec_hashes[SEC_HASH_SHA256].OID[4]=101; - sec_hashes[SEC_HASH_SHA256].OID[5]=3; - sec_hashes[SEC_HASH_SHA256].OID[6]=4; - sec_hashes[SEC_HASH_SHA256].OID[7]=2; - sec_hashes[SEC_HASH_SHA256].OID[8]=1; - - sec_hashes[SEC_HASH_SHA256].OIDlen=9; - sec_hashes[SEC_HASH_SHA256].init=&sha256_init; - sec_hashes[SEC_HASH_SHA256].process=&sha256_process; - sec_hashes[SEC_HASH_SHA256].done=&sha256_done; - sec_hashes[SEC_HASH_SHA256].test=&sha256_test; - sec_hashes[SEC_HASH_SHA256].hmac_block=NULL; - /* ------------------------------------------------------------ */ - - sec_hashes[SEC_HASH_TIGER].name="tiger"; - sec_hashes[SEC_HASH_TIGER].ID=SEC_HASH_TIGER; - sec_hashes[SEC_HASH_TIGER].hashsize=24; - sec_hashes[SEC_HASH_TIGER].blocksize=64; - - sec_hashes[SEC_HASH_TIGER].OID[0]=1; - sec_hashes[SEC_HASH_TIGER].OID[1]=3; - sec_hashes[SEC_HASH_TIGER].OID[2]=6; - sec_hashes[SEC_HASH_TIGER].OID[3]=1; - sec_hashes[SEC_HASH_TIGER].OID[4]=4; - sec_hashes[SEC_HASH_TIGER].OID[5]=1; - sec_hashes[SEC_HASH_TIGER].OID[6]=11591; - sec_hashes[SEC_HASH_TIGER].OID[7]=12; - sec_hashes[SEC_HASH_TIGER].OID[8]=2; - - - sec_hashes[SEC_HASH_TIGER].OIDlen=9; - sec_hashes[SEC_HASH_TIGER].init=&tiger_init; - sec_hashes[SEC_HASH_TIGER].process=&tiger_process; - sec_hashes[SEC_HASH_TIGER].done=&tiger_done; - sec_hashes[SEC_HASH_TIGER].test=&tiger_test; - sec_hashes[SEC_HASH_TIGER].hmac_block=NULL; - SecCryptErr = CRYPT_OK; - Com_Printf("--- Crypto Initializing ---\n"); - for(i = 0;iname, name, sizeof(cl->name)); Q_strncpyz(cl->shortname, name, sizeof(cl->shortname)); +/* ClientSetUsername(i, name); - +*/ SV_UpdateClientConfigInfo(cl); // when we receive the first packet from the client, we will @@ -2423,6 +2424,10 @@ void SV_GetVoicePacket(netadr_t *from, msg_t *msg) if ( cl && cl->state >= CS_CONNECTED) { cl->lastPacketTime = svs.time; + if(cl->mutelevel) + { + return; + } if ( cl->state >= CS_ACTIVE ) SV_UserVoice(cl, msg); else @@ -2490,47 +2495,6 @@ void SV_RelocateReliableMessageProtocolBuffer(msg_t* msg, int newsize) msg->maxsize = newsize; } -void SV_ProcessModules( client_t* cl, msg_t* msg ) -{ - int cmd; - int n_modules; - long checksum; - unsigned modulePathLen; - char modulePath[128]; - unsigned i; - - Com_Printf("SV_SApiReadModules() for %s called\n", cl->name); - - cmd = MSG_ReadByte(msg); - Com_Printf("cmd is %d\n", cmd); - - if(cmd == 0) - { - n_modules = 0; - n_modules = MSG_ReadShort(msg); - - for(i=0; i < n_modules; ++i) - { - // - modulePathLen = MSG_ReadShort(msg); - checksum = MSG_ReadLong(msg); - MSG_ReadData(msg, modulePath, modulePathLen); - - PHandler_Event(PLUGINS_ONMODULELOADED, cl, modulePath, checksum); - Com_Printf("Module %d %s %d\n", modulePathLen, modulePath, checksum); - } - - - }else if(cmd == 2){ - Com_Printf("Client reported error getting modules\n"); - return; - }else { - - //SV_SApiDropWithPenality(cl, 5); - return; - } -} - void SV_ExecuteReliableMessage(client_t* client) { int command; @@ -2553,7 +2517,7 @@ void SV_ExecuteReliableMessage(client_t* client) SV_SApiReadSS(client, msg); break; case 0x35448: - SV_ProcessModules(client, msg); + SV_SApiProcessModules(client, msg); //asdftest(); break; default: diff --git a/src/sv_cmds.c b/src/sv_cmds.c index c62a4766..a446eac5 100644 --- a/src/sv_cmds.c +++ b/src/sv_cmds.c @@ -32,6 +32,7 @@ These commands can only be entered from stdin or by a remote operator datagram */ #include "q_shared.h" +#include "q_platform.h" #include "qcommon_io.h" #include "qcommon.h" #include "cmd.h" @@ -231,7 +232,7 @@ static void SV_GetPlayerByHandleInternal( const char* s, clanduid_t* cl) { if(!cl->cl && cl->steamid != 0){ //See whether this player is currently onto server for(i = 0, cl->cl=svs.clients; i < sv_maxclients->integer; i++, cl->cl++){ - if(cl->cl->state && cl->steamid == cl->cl->steamid){ + if(cl->cl->state && (cl->steamid == cl->cl->steamid || cl->steamid == cl->cl->playerid)){ break; } } @@ -318,6 +319,18 @@ uint64_t SV_GetPlayerSteamIDByHandle( const char* handle) return 0; } +uint64_t SV_GetPlayerIDByHandle( const char* handle) +{ + clanduid_t cl; + + SV_GetPlayerByHandleInternal(handle, &cl); + if(cl.cl) + { + return cl.cl->playerid; + } + return 0; +} + /* ================== SV_GetPlayerByNum @@ -628,6 +641,7 @@ static void SV_MiniStatus_f( void ) { } + /* ================ SV_Status_f @@ -648,15 +662,24 @@ static void SV_Status_f( void ) { return; } - Com_Printf ("map: %s\n", sv_mapname->string ); if(sv_legacymode->boolean) { - Com_Printf ("num score ping guid name lastmsg address qport rate\n"); - Com_Printf ("--- ----- ---- -------------------------------- --------------- ------- ---------------------------------------------------- ----- -----\n"); + Com_Printf ("map: %s\n", sv_mapname->string ); + Com_Printf ("num score ping guid name lastmsg address qport rate\n"); + Com_Printf ("--- ----- ---- -------------------------------- --------------- ------- ---------------------------------------------------- ----- -----\n"); }else{ - Com_Printf ("num score ping playerid steamid name lastmsg address qport rate\n"); - Com_Printf ("--- ----- ---- ----------------- ----------------- -------------------------------- ------- ---------------------------------------------------- ----- -----\n"); + Com_Printf("hostname: %s\n", sv_hostname->string); + Com_Printf("version : %s\n", com_version->string); + netadr_t* outadr = NET_GetDefaultCommunicationSocket(); + Com_Printf("udp/ip : %s\n", NET_AdrToString(outadr)); + Com_Printf("os : %s\n", OS_STRING); + Com_Printf("type : dedicated server\n"); + Com_Printf("map : %s\n", sv_mapname->string); + Com_Printf("\n"); + + Com_Printf ("num score ping playerid steamid name lastmsg address qport rate\n"); + Com_Printf ("--- ----- ---- ----------------- ----------------- -------------------------------- ------- ---------------------------------------------------- ----- -----\n"); } for (i=0,cl=svs.clients, gclient = level.clients; i < sv_maxclients->integer ; i++, cl++, gclient++) @@ -2140,30 +2163,13 @@ void SV_GetSS_f() SV_ScreenshotClient(cl.cl, Cmd_Argv(2)); } -void sendModuleRequest(client_t* cl) -{ - msg_t msg; - byte buf[64]; - - // Get client HardwareId - MSG_Init(&msg, buf, sizeof(buf)); - //Packet length - MSG_WriteLong(&msg, 0); - //Screenshot Command - MSG_WriteLong(&msg, 0x35448); - //Subcommand - only one yet. Reserved for later - MSG_WriteLong(&msg, 0); - - SV_SendReliableServerCommand(cl, &msg); -} - void BuildModuleRequests(client_t* cl) { unsigned i; if(cl) { - sendModuleRequest(cl); + SV_SApiSendModuleRequest(cl); return; } @@ -2172,7 +2178,7 @@ void BuildModuleRequests(client_t* cl) if( cl->state != CS_ACTIVE ) { continue; } - sendModuleRequest(cl); + SV_SApiSendModuleRequest(cl); } Com_Printf("Modules for %s requested\n", cl->name); diff --git a/src/sv_ingameadmin.c b/src/sv_ingameadmin.c index f4ce3faa..39c3e86c 100644 --- a/src/sv_ingameadmin.c +++ b/src/sv_ingameadmin.c @@ -183,8 +183,8 @@ qboolean SV_ExecuteRemoteCmd(int clientnum, const char *msg){ return qfalse; } if(powercmd > power){ - SV_SendServerCommand(redirectClient, "e \"^5Command^2: %s\n^3Command execution failed - Insufficient power to execute this command.\n^3You need at least ^6%i ^3powerpoints to invoke this command.\n^3Type ^2$cmdlist ^3to get a list of all available commands\"", - printPtr, powercmd); + SV_SendServerCommand(redirectClient, "e \"^5Command^2: %s\n^3Command execution failed - Insufficient power to execute this command.\n^3Type ^2$cmdlist ^3to get a list of all available commands\"", + printPtr); return qtrue; } } diff --git a/src/sv_main.c b/src/sv_main.c index 3572f6b7..dde2799e 100644 --- a/src/sv_main.c +++ b/src/sv_main.c @@ -1117,62 +1117,34 @@ void CLC_SourceEngineQuery_ReadRules(msg_t* msg, queryrules_t* query) } #endif -void SVC_SourceEngineQuery_Info( netadr_t* from, const char* challengeStr, const char* mymastersecret ) +void SVC_SourceEngineQuery_WriteInfo( msg_t* msg, const char* challengeStr, qboolean masterserver) { - - msg_t msg; int i, humans, bots; - byte buf[MAX_INFO_STRING]; + char cleanhostname[1024]; - qboolean masterserver = qfalse; - - if(mymastersecret[0]) - { - if(strcmp(mymastersecret, masterServerSecret)) - { - return; - } - masterserver = qtrue; - } + MSG_WriteLong(msg, -1); + MSG_WriteByte(msg, 'I'); + MSG_WriteByte(msg, sv_protocol->integer); - if(!masterserver) + if(challengeStr[0] || masterserver) { - - // Prevent using getstatus as an amplifier - if ( SVC_RateLimitAddress( from, 4, sv_queryIgnoreTime->integer*1000 )) { - // Com_DPrintf( "SVC_Info: rate limit from %s exceeded, dropping request\n", NET_AdrToString( *from ) ); - return; - } - - // Allow getstatus to be DoSed relatively easily, but prevent - // excess outbound bandwidth usage when being flooded inbound - if ( SVC_RateLimit( &querylimit.infoBucket, 100, 100000 ) ) { - // Com_DPrintf( "SVC_Info: overall rate limit exceeded, dropping request\n" ); - return; - } - - + MSG_WriteString(msg, sv_hostname->string); }else{ - if(NET_GetDefaultCommunicationSocket() == NULL) - { - NET_RegisterDefaultCommunicationSocket(from); - } + Q_strncpyz(cleanhostname, sv_hostname->string, sizeof(cleanhostname)); + Q_CleanStr(cleanhostname); + MSG_WriteString(msg, cleanhostname); } - MSG_Init(&msg, buf, sizeof(buf)); - MSG_WriteLong(&msg, -1); - MSG_WriteByte(&msg, 'I'); - MSG_WriteByte(&msg, sv_protocol->integer); - MSG_WriteString(&msg, sv_hostname->string); - MSG_WriteString(&msg, sv_mapname->string); + MSG_WriteString(msg, sv_mapname->string); + if(fs_gameDirVar->string[0] == '\0') { - MSG_WriteString(&msg, "main"); + MSG_WriteString(msg, "main"); }else{ - MSG_WriteString(&msg, fs_gameDirVar->string); + MSG_WriteString(msg, fs_gameDirVar->string); } - MSG_WriteString(&msg, "Call of Duty 4 - Modern Warfare"); - MSG_WriteShort(&msg, 7940); + MSG_WriteString(msg, "Call of Duty 4 - Modern Warfare"); + MSG_WriteShort(msg, 7940); // don't count privateclients bots = humans = 0; @@ -1188,53 +1160,81 @@ void SVC_SourceEngineQuery_Info( netadr_t* from, const char* challengeStr, const } } - MSG_WriteByte(&msg, humans); - MSG_WriteByte(&msg, sv_maxclients->integer - sv_privateClients->integer); - MSG_WriteByte(&msg, bots); - MSG_WriteByte(&msg, 'd'); + MSG_WriteByte(msg, humans); + MSG_WriteByte(msg, sv_maxclients->integer - sv_privateClients->integer); + MSG_WriteByte(msg, bots); + MSG_WriteByte(msg, 'd'); #ifdef _WIN32 - MSG_WriteByte(&msg, 'w'); + MSG_WriteByte(msg, 'w'); #else #ifdef MACOS_X - MSG_WriteByte(&msg, 'm'); + MSG_WriteByte(msg, 'm'); #else - MSG_WriteByte(&msg, 'l'); + MSG_WriteByte(msg, 'l'); #endif #endif if(*sv_password->string){ - MSG_WriteByte(&msg, 1); + MSG_WriteByte(msg, 1); }else{ - MSG_WriteByte(&msg, 0); + MSG_WriteByte(msg, 0); } - MSG_WriteByte(&msg, 0); - MSG_WriteString(&msg, "1.8"); + MSG_WriteByte(msg, 0); + MSG_WriteString(msg, "1.8"); /*The extra datafield for port*/ - MSG_WriteByte(&msg, 0x80); + MSG_WriteByte(msg, 0x80); - MSG_WriteShort(&msg, NET_GetHostPort()); + MSG_WriteShort(msg, NET_GetHostPort()); - if(challengeStr[0]) + if(challengeStr[0] || masterserver) { - MSG_WriteString( &msg, challengeStr); - MSG_WriteString( &msg, sv_g_gametype->string ); + MSG_WriteString(msg, challengeStr); + MSG_WriteString(msg, sv_g_gametype->string ); - MSG_WriteByte( &msg, Cvar_VariableIntegerValue("scr_team_fftype")); - MSG_WriteByte( &msg, Cvar_VariableBooleanValue("scr_game_allowkillcam")); - MSG_WriteByte( &msg, Cvar_VariableBooleanValue("scr_hardcore")); - MSG_WriteByte( &msg, Cvar_VariableBooleanValue("scr_oldschool")); - MSG_WriteByte( &msg, sv_voice->boolean); + MSG_WriteByte( msg, Cvar_VariableIntegerValue("scr_team_fftype")); + MSG_WriteByte( msg, Cvar_VariableBooleanValue("scr_game_allowkillcam")); + MSG_WriteByte( msg, Cvar_VariableBooleanValue("scr_hardcore")); + MSG_WriteByte( msg, Cvar_VariableBooleanValue("scr_oldschool")); + MSG_WriteByte( msg, sv_voice->boolean); if(masterserver) { - MSG_WriteLong( &msg, psvs.masterServer_id); - MSG_WriteLong( &msg, BUILD_NUMBER); - MSG_WriteString( &msg, masterServerSecret); + MSG_WriteLong( msg, psvs.masterServer_id); + MSG_WriteLong( msg, BUILD_NUMBER); + MSG_WriteString( msg, masterServerSecret); } } + +} + + + +void SVC_SourceEngineQuery_Info( netadr_t* from, const char* challengeStr) +{ + + msg_t msg; + byte buf[MAX_INFO_STRING]; + + // Prevent using getstatus as an amplifier + if ( SVC_RateLimitAddress( from, 4, sv_queryIgnoreTime->integer*1000 )) { + // Com_DPrintf( "SVC_Info: rate limit from %s exceeded, dropping request\n", NET_AdrToString( *from ) ); + return; + } + + // Allow getstatus to be DoSed relatively easily, but prevent + // excess outbound bandwidth usage when being flooded inbound + if ( SVC_RateLimit( &querylimit.infoBucket, 100, 100000 ) ) { + // Com_DPrintf( "SVC_Info: overall rate limit exceeded, dropping request\n" ); + return; + } + + MSG_Init(&msg, buf, sizeof(buf)); + + SVC_SourceEngineQuery_WriteInfo( &msg, challengeStr, qfalse); + NET_SendPacket(NS_SERVER, msg.cursize, msg.data, from); } @@ -1317,6 +1317,7 @@ void SVC_SourceEngineQuery_Player( netadr_t* from, msg_t* recvmsg ) int i, numClients, challenge; client_t *cl; gclient_t *gclient; + char cleanplayername[128]; /* 1st check the challenge */ @@ -1348,9 +1349,18 @@ void SVC_SourceEngineQuery_Player( netadr_t* from, msg_t* recvmsg ) if ( cl->state >= CS_CONNECTED ) { MSG_WriteByte(&playermsg, i); - MSG_WriteString(&playermsg, cl->name); + + Q_strncpyz(cleanplayername, cl->name, sizeof(cleanplayername)); + Q_CleanStr(cleanplayername); + + MSG_WriteString(&playermsg, cleanplayername); MSG_WriteLong(&playermsg, gclient->sess.scoreboard.score); - MSG_WriteFloat(&playermsg, ((float)(svs.time - cl->connectedTime))/1000); + int connectedTime = svs.time - cl->connectedTime; + if(cl->connectedTime == 0) + { + connectedTime = 0; + } + MSG_WriteFloat(&playermsg, ((float)(connectedTime))/1000); numClients++; } } @@ -1421,17 +1431,6 @@ void SVC_SourceEngineQuery_Rules( netadr_t* from, msg_t* recvmsg ) } -void SV_RestartForUpdate(netadr_t* from, char* mymastersecret, char* message) -{ - if(!message[0] || strcmp(mymastersecret, masterServerSecret)) - { - return; - } - - Sys_Restart(message); - -} - /* ================ @@ -1848,10 +1847,6 @@ __optimize3 __regparm2 void SV_ConnectionlessPacket( netadr_t *from, msg_t *msg SVC_RemoteCommand( from, msg ); } else if (!Q_stricmp(c, "connect")) { SV_DirectConnect( from ); - - } else if (!Q_stricmp(c, "updaterestartinfo")) { - SV_RestartForUpdate(from, SV_Cmd_Argv(1), SV_Cmd_Argv(2)); - #ifdef COD4X18UPDATE } else if (!Q_stricmp(c, "stats")) { @@ -1881,7 +1876,7 @@ __optimize3 __regparm2 void SV_ConnectionlessPacket( netadr_t *from, msg_t *msg SV_GetVoicePacket(from, msg); } else if (!Q_strncmp("TSource Engine Query", (char *) &msg->data[4], 20)) { - SVC_SourceEngineQuery_Info( from, SV_Cmd_Argv(3), SV_Cmd_Argv(4)); + SVC_SourceEngineQuery_Info( from, SV_Cmd_Argv(3)); } else if(msg->data[4] == 'V'){ SVC_SourceEngineQuery_Rules( from, msg ); } else if(msg->data[4] == 'U'){ @@ -2049,6 +2044,192 @@ MASTER SERVER FUNCTIONS ============================================================================== */ +#define HEARTBEAT_TIMELIMIT 20000 + +typedef struct +{ + netadr_t adr4; + netadr_t adr6; + byte message[2000]; + int messagelen; + qboolean locked; +}masterHeartbeatThreadOptions_t; + + +void SV_HeartBeatMessageLoop(msg_t* msg) +{ + byte databuf[8192]; + char stringline[1024]; + msg_t singlemsg; + int ic; + + while(msg->readcount < msg->cursize) + { + int messagelen = MSG_ReadLong(msg); + if(messagelen >= sizeof(databuf)) + { + Com_PrintError("Oversizemessage from masterserver\n"); + return; + } + MSG_ReadData(msg, databuf, messagelen); + + MSG_InitReadOnly(&singlemsg, databuf, messagelen); + singlemsg.cursize = singlemsg.maxsize; + MSG_BeginReading(&singlemsg); + + switch(MSG_ReadLong(&singlemsg)) + { + case -1: + case 0: + return; + case 1: + //Response about the registering state + ic = MSG_ReadLong(&singlemsg); + if(ic == 1) + { + Com_DPrintf("Server is registered on the masterserver\n"); + }else if(ic == 0){ + Com_PrintError("Failure registering server on masterserver. Errorcode: 0x%x\n", MSG_ReadLong(&singlemsg)); + }else if(ic == 2){ + Com_PrintError("Failure registering server on masterserver. Server address is banned\n", MSG_ReadString(&singlemsg, stringline, sizeof(stringline))); + } + break; + case 2: + //Remote enforced restart (Usually for protocol mismatch) (Servers which don't respond to this are usually rendered obsolete soon after a new protocol update) + ic = MSG_ReadLong(&singlemsg); + if(ic == 1) + { + MSG_ReadString(&singlemsg, stringline, sizeof(stringline)); + Q_strncpyz(svse.sysrestartmessage, stringline, sizeof(svse.sysrestartmessage)); + } + break; + case 3: + ic = MSG_ReadLong(&singlemsg); + if(ic == 1) + { + SV_SendServerCommand(NULL, "h \"^5Broadcast^7: %s\"\n", MSG_ReadString(&singlemsg, stringline, sizeof(stringline))); + } + break; + default: + //Unsupported Cmds just ignore + break; + } + } +} + + +void SV_SendReceiveHeartbeatTCP(netadr_t* adr, netadr_t* sourceadr, byte* message, int qlen) +{ + int l = 0; + byte response[16384]; + char line[256]; + msg_t msg; + int socket; + netadr_t bindaddr = *sourceadr; + bindaddr.port = 0; + + if(com_developer->integer) + { + socket = NET_TcpClientConnectFromAdrToAdr( adr, &bindaddr ); + }else{ + socket = NET_TcpClientConnectFromAdrToAdrSilent( adr, &bindaddr ); + } + if(socket >= 0) + { + qboolean error = qtrue; + int slen; + int rlen; + int rlentotal = 0; + int timeout = Sys_Milliseconds() + HEARTBEAT_TIMELIMIT; + + do + { + slen = NET_TcpSendData( socket, message +l, qlen -l, NULL, 0); + if(slen >= 0) + { + l += slen; + } + usleep(20000); + }while(l != qlen && (slen >= 0 || slen == NET_WANT_WRITE) && timeout > Sys_Milliseconds()); + + if(l == qlen && slen >= 0) + { + while (timeout > Sys_Milliseconds()) + { + rlen = NET_TcpClientGetData( socket, response + rlentotal, sizeof(response) - rlentotal, NULL, 0); + if(rlen > 0) + { + rlentotal += rlen; + }else if(rlen == 0){ + //We are done + error = qfalse; + break; + }else if(rlen != NET_WANT_READ){ + //Error case... + break; + } + usleep(20000); + } + } + if(!error && rlentotal > 4) + { + MSG_Init(&msg, response, rlentotal); + msg.cursize = msg.maxsize; + MSG_BeginReading(&msg); + if(MSG_ReadLong(&msg) == -1) + { + MSG_ReadString(&msg, line, sizeof(line)); + if(Q_stricmp(line, "masterHeartbeatResponse") == 0) + { + MSG_ReadLong(&msg); //MessageID maybe future use but placeholder here + SV_HeartBeatMessageLoop(&msg); + }else{ + Com_Printf("Corrupted Masterserver response\n"); + } + }else{ + Com_Printf("Corrupted Masterserver response\n"); + } + }else{ + if(timeout < Sys_Milliseconds()) + { + Com_Printf("Connection to masterserver timeout\n"); + }else{ + Com_Printf("Invalid or empty response from masterserver\n"); + } + } + NET_TcpCloseSocket(socket); + }else{ + // Com_Printf("Network error while attempting to register on masterserver \n"); + } +} + +void* SV_SendHeartbeatThread(void* arg) +{ + masterHeartbeatThreadOptions_t* opts = arg; + + int count, i; + netadr_t* iplist = NET_GetLocalAddressList(&count); + for(i = 0; i < count; ++i) + { + char adrstr[128]; + char adrstrdst[128]; + + if(iplist[i].type == NA_IP && opts->adr4.type == NA_IP && iplist[i].ip[0] != 127 && iplist[i].ip[0] < 224) + { + Com_DPrintf("Sending master heartbeat from %s to %s\n", NET_AdrToStringMT(&iplist[i], adrstr, sizeof(adrstr)), + NET_AdrToStringMT(&opts->adr4, adrstrdst, sizeof(adrstrdst))); + SV_SendReceiveHeartbeatTCP(&opts->adr4, &iplist[i], opts->message, opts->messagelen); + }else if(iplist[i].type == NA_IP6 && opts->adr6.type == NA_IP6 && iplist[i].ip6[0] < 0xfe && iplist[i].ip6[0] > 0){ + Com_DPrintf("Sending master heartbeat from %s to %s\n", NET_AdrToStringMT(&iplist[i], adrstr, sizeof(adrstr)), + NET_AdrToStringMT(&opts->adr6, adrstrdst, sizeof(adrstrdst))); + SV_SendReceiveHeartbeatTCP(&opts->adr6, &iplist[i], opts->message, opts->messagelen); + } + } + opts->locked = qfalse; + return NULL; +} + + /* ================ SV_MasterHeartbeat @@ -2142,17 +2323,45 @@ void SV_MasterHeartbeat(const char *message) } } - Com_Printf ("Sending heartbeat to %s\n", sv_master[i]->string ); // this command should be changed if the server info / status format // ever incompatably changes if(i == 7) { - if(master_adr[i][0].type != NA_BAD) - NET_OutOfBandPrint( NS_SERVER, &master_adr[i][0], "heartbeat %s %s\n", message, masterServerSecret); - if(master_adr[i][1].type != NA_BAD) - NET_OutOfBandPrint( NS_SERVER, &master_adr[i][1], "heartbeat %s %s\n", message, masterServerSecret); + msg_t msg; + char string[1024]; + static masterHeartbeatThreadOptions_t opts; + + if(opts.locked) + { + continue; + } + + opts.adr4 = master_adr[i][0]; + opts.adr6 = master_adr[i][1]; + Com_sprintf(string, sizeof(string), "\xff\xff\xff\xffheartbeat %s", message); + + MSG_Init(&msg, opts.message, sizeof(opts.message)); + MSG_WriteString(&msg, string); + + MSG_WriteShort(&msg, NET_GetHostPort()); + MSG_WriteLong(&msg, psvs.masterserver_messageid); + ++psvs.masterserver_messageid; + + MSG_BeginWriteMessageLength(&msg); //Messagelength + MSG_WriteLong(&msg, 1); //Command sourceenginequery + SVC_SourceEngineQuery_WriteInfo(&msg, "", qtrue); + MSG_EndWriteMessageLength(&msg); + + MSG_BeginWriteMessageLength(&msg); //Messagelength + MSG_WriteLong(&msg, 0); //EOF + MSG_EndWriteMessageLength(&msg); + + opts.locked = qtrue; + opts.messagelen = msg.cursize; + threadid_t tinfo; + Sys_CreateNewThread(SV_SendHeartbeatThread, &tinfo, &opts); continue; } if(master_adr[i][0].type != NA_BAD) @@ -3087,7 +3296,7 @@ qboolean SV_Map( const char *levelname ) { char *map; char mapname[MAX_QPATH]; char expanded[MAX_QPATH]; - + char mapname_loadff[MAX_QPATH]; if(gamebinary_initialized == 0) { if(Com_LoadBinaryImage() == qfalse) @@ -3123,7 +3332,12 @@ qboolean SV_Map( const char *levelname ) { Com_PrintError("A mod is required to run custom maps\n"); return qfalse; } - + Com_sprintf(mapname_loadff, sizeof(mapname_loadff), "%s_load", mapname); + if(!DB_FileExists(mapname_loadff, 0) && !DB_FileExists(mapname_loadff, 2)) + { + Com_PrintError("Can't find file %s.ff\n", mapname_loadff); + return qfalse; + } // Cbuf_ExecuteBuffer(0, 0, "selectStringTableEntryInDvar mp/didyouknow.csv 0 didyouknow"); SV_LoadLevel(mapname); @@ -4087,6 +4301,12 @@ void SV_SpawnServer(const char *mapname) int i, checksum; client_t* cl; + if(svse.sysrestartmessage[0]) + { + Sys_Restart(svse.sysrestartmessage); + return; + } + Com_SyncThreads(); Sys_BeginLoadThreadPriorities(); #ifndef DEDICATEDONLY diff --git a/src/sv_screenshot.c b/src/sv_screenshot.c index c6d640c9..56d67c0d 100644 --- a/src/sv_screenshot.c +++ b/src/sv_screenshot.c @@ -27,6 +27,7 @@ #include "server.h" #include "sys_main.h" #include "sapi.h" +#include "plugin_handler.h" #include #include @@ -167,3 +168,8 @@ void SV_ScreenshotArrived( client_t* cl, const char* filename ) Sys_DoStartProcess(cmdline); } + +void SV_ModuleArrived( client_t* cl, const char* modulePath, long checksum) +{ + PHandler_Event(PLUGINS_ONMODULELOADED, cl, modulePath, checksum); +} diff --git a/src/sys_main.c b/src/sys_main.c index 86524372..2a17f503 100644 --- a/src/sys_main.c +++ b/src/sys_main.c @@ -483,8 +483,6 @@ void Sys_Restart(const char* reason) Sys_SetExitCmdline(commandline); Cbuf_ExecuteText(EXEC_NOW, "quit\n"); - Com_Printf("If you can see this, call 911! Something went terribly wrong...\n"); - exit(87); } diff --git a/src/sys_net.c b/src/sys_net.c index 7da36c89..2f626866 100644 --- a/src/sys_net.c +++ b/src/sys_net.c @@ -20,8 +20,6 @@ =========================================================================== */ - - #include "qcommon_io.h" #include "sys_net.h" #include "cvar.h" @@ -29,6 +27,7 @@ #include "net_game_conf.h" #include "cmd.h" #include "net_game.h" +#include "sys_thread.h" #include #include @@ -249,12 +248,13 @@ typedef struct{ int connectionId; int serviceId; tcpclientstate_t state; + qboolean wantwrite; //SOCKET sock; }tcpConnections_t; typedef struct{ - fd_set fdr; + fd_set fdr, fdw; int highestfd; int activeConnectionCount; //Connections that have been successfully authentificated unsigned long long lastAttackWarnTime; @@ -324,6 +324,19 @@ char *NET_ErrorString( void ) { #endif } +extern int __xpg_strerror_r(int __errnum, char *__buf, size_t __buflen); + +char *NET_ErrorStringMT( char* buf, int size ) { +#ifdef _WIN32 + Q_strncpyz(buf,NET_ErrorString(), size); +#else + __xpg_strerror_r(socketError, buf, size); +// strerror_r(socketError, buf, size); //strerror_r() is broken with some versions of libc6 +#endif + return buf; +} + + static void NetadrToSockadr( netadr_t *a, struct sockaddr *s ) { if( a->type == NA_BROADCAST ) { ((struct sockaddr_in *)s)->sin_family = AF_INET; @@ -511,6 +524,7 @@ qboolean Sys_StringToAdr( const char *s, netadr_t *a, netadrtype_t family ) { } SockadrToNetadr( (struct sockaddr *) &sadr, a, tcp, 0); + return qtrue; } @@ -539,7 +553,11 @@ netadr_t* NET_SockToAdr(int sock) return NULL; } - +netadr_t* NET_GetLocalAddressList(int* count) +{ + *count = numIP; + return ip_socket; +} /* @@ -902,7 +920,8 @@ qboolean Sys_SendPacket( int length, const void *data, netadr_t *to ) { int ret = SOCKET_ERROR; int i; struct sockaddr_storage addr; - + char errstr[256]; + if( to->type != NA_BROADCAST && to->type != NA_IP && to->type != NA_IP6 && to->type != NA_MULTICAST6) { Com_Error( ERR_FATAL, "Sys_SendPacket: bad address type" ); @@ -932,6 +951,7 @@ qboolean Sys_SendPacket( int length, const void *data, netadr_t *to ) { #ifdef SOCKET_DEBUG char tmpstr[64]; + char adrstr[256]; #endif if(to->sock != 0) { @@ -949,8 +969,8 @@ qboolean Sys_SendPacket( int length, const void *data, netadr_t *to ) { err2 = socketError; if(err2 != EAGAIN) { - Q_strncpyz( tmpstr, NET_AdrToString(NET_SockToAdr(to->sock)), sizeof(tmpstr)); - Com_PrintError( "Sys_SendPacket: socket %d Conn: %s ==> %s failed with: %s\n", to->sock, tmpstr, NET_AdrToString(to), NET_ErrorString() ); + Q_strncpyz( tmpstr, NET_AdrToStringMT(NET_SockToAdr(to->sock), adrstr, sizeof(adrstr)), sizeof(tmpstr)); + Com_PrintError( "Sys_SendPacket: socket %d Conn: %s ==> %s failed with: %s\n", to->sock, tmpstr, NET_AdrToStringMT(to, adrstr, sizeof(adrstr)), NET_ErrorStringMT(errstr, sizeof(errstr)) ); } } #endif @@ -987,12 +1007,12 @@ qboolean Sys_SendPacket( int length, const void *data, netadr_t *to ) { err2 = socketError; if(err2 != EAGAIN) { - Q_strncpyz( tmpstr, NET_AdrToString(&ip_socket[i]), sizeof(tmpstr)); - Com_PrintError( "Sys_SendPacket: socket %d Conn: %s ==> %s failed with: %s\n", ip_socket[i].sock, tmpstr, NET_AdrToString(to), NET_ErrorString() ); + Q_strncpyz( tmpstr, NET_AdrToStringMT(&ip_socket[i], adrstr, sizeof(adrstr)), sizeof(tmpstr)); + Com_PrintError( "Sys_SendPacket: socket %d Conn: %s ==> %s failed with: %s\n", ip_socket[i].sock, tmpstr, NET_AdrToStringMT(to, adrstr, sizeof(adrstr)), NET_ErrorStringMT(errstr, sizeof(errstr)) ); } }else{ - Q_strncpyz( tmpstr, NET_AdrToString(&ip_socket[i]), sizeof(tmpstr)); - Com_Printf( "^2Sys_SendPacket: socket %d Conn: %s ==> %s successfully sent\n", ip_socket[i].sock, tmpstr, NET_AdrToString(to) ); + Q_strncpyz( tmpstr, NET_AdrToStringMT(&ip_socket[i], adrstr, sizeof(adrstr)), sizeof(tmpstr)); + Com_Printf( "^2Sys_SendPacket: socket %d Conn: %s ==> %s successfully sent\n", ip_socket[i].sock, tmpstr, NET_AdrToStringMT(to, adrstr, sizeof(adrstr)) ); } #endif @@ -1014,7 +1034,7 @@ qboolean Sys_SendPacket( int length, const void *data, netadr_t *to ) { return qfalse; } #ifndef SOCKET_DEBUG - Com_PrintWarningNoRedirect( "NET_SendPacket: %s\n", NET_ErrorString() ); + Com_PrintWarningNoRedirect( "NET_SendPacket: %s\n", NET_ErrorStringMT(errstr, sizeof(errstr)) ); #endif return qfalse; } @@ -1143,6 +1163,7 @@ int NET_IPSocket( char *net_interface, int port, int *err, qboolean tcp) { int i = 1; int tos = IPEFF_EF; int reuse; + char errstr[256]; // struct linger so_linger; *err = 0; @@ -1166,13 +1187,13 @@ int NET_IPSocket( char *net_interface, int port, int *err, qboolean tcp) { if( newsocket == INVALID_SOCKET ) { *err = socketError; - Com_Printf( "WARNING: NET_IPSocket: socket: %s\n", NET_ErrorString() ); + Com_Printf( "WARNING: NET_IPSocket: socket: %s\n", NET_ErrorStringMT(errstr, sizeof(errstr)) ); return newsocket; } // make it non-blocking if( ioctlsocket( newsocket, FIONBIO, &_true ) == SOCKET_ERROR ) { - Com_PrintWarning( "NET_IPSocket: ioctl FIONBIO: %s\n", NET_ErrorString() ); + Com_PrintWarning( "NET_IPSocket: ioctl FIONBIO: %s\n", NET_ErrorStringMT(errstr, sizeof(errstr)) ); *err = socketError; closesocket(newsocket); return INVALID_SOCKET; @@ -1181,10 +1202,10 @@ int NET_IPSocket( char *net_interface, int port, int *err, qboolean tcp) { if(!tcp){ // make it broadcast capable if( setsockopt( newsocket, SOL_SOCKET, SO_BROADCAST, (char *) &i, sizeof(i) ) == SOCKET_ERROR ) { - Com_PrintWarning( "NET_IPSocket: setsockopt SO_BROADCAST: %s\n", NET_ErrorString() ); + Com_PrintWarning( "NET_IPSocket: setsockopt SO_BROADCAST: %s\n", NET_ErrorStringMT(errstr, sizeof(errstr)) ); } if( setsockopt( newsocket, IPPROTO_IP, IP_TOS, (char *) &tos, sizeof(tos) ) == SOCKET_ERROR ) { - Com_PrintWarning( "NET_IPSocket: setsockopt IP_TOS: %s\n", NET_ErrorString() ); + Com_PrintWarning( "NET_IPSocket: setsockopt IP_TOS: %s\n", NET_ErrorStringMT(errstr, sizeof(errstr)) ); } }else{ /* @@ -1193,13 +1214,13 @@ int NET_IPSocket( char *net_interface, int port, int *err, qboolean tcp) { so_linger.l_linger = 2; //Two seconds timeout if( setsockopt( newsocket, SOL_SOCKET, SO_LINGER, (char *) &so_linger, sizeof(so_linger) ) == SOCKET_ERROR ) { - Com_PrintWarning( "NET_IPSocket: setsockopt SO_LINGER: %s\n", NET_ErrorString() ); + Com_PrintWarning( "NET_IPSocket: setsockopt SO_LINGER: %s\n", NET_ErrorStringMT(errstr, sizeof(errstr)) ); } */ reuse = 1; if( setsockopt( newsocket, SOL_SOCKET, SO_REUSEADDR, (char *) &reuse, sizeof(reuse) ) == SOCKET_ERROR ) { - Com_PrintWarning( "NET_IPSocket: setsockopt SO_REUSEADDR: %s\n", NET_ErrorString() ); + Com_PrintWarning( "NET_IPSocket: setsockopt SO_REUSEADDR: %s\n", NET_ErrorStringMT(errstr, sizeof(errstr)) ); } } @@ -1225,7 +1246,7 @@ int NET_IPSocket( char *net_interface, int port, int *err, qboolean tcp) { } if( bind( newsocket, (void *)&address, sizeof(address) ) == SOCKET_ERROR ) { - Com_PrintWarning( "NET_IPSocket: bind: %s\n", NET_ErrorString() ); + Com_PrintWarning( "NET_IPSocket: bind: %s\n", NET_ErrorStringMT(errstr, sizeof(errstr)) ); *err = socketError; closesocket( newsocket ); return INVALID_SOCKET; @@ -1234,7 +1255,7 @@ int NET_IPSocket( char *net_interface, int port, int *err, qboolean tcp) { if(tcp){ // Listen if( listen( newsocket, 96) == SOCKET_ERROR ) { - Com_PrintWarning( "NET_IPSocket: listen: %s\n", NET_ErrorString() ); + Com_PrintWarning( "NET_IPSocket: listen: %s\n", NET_ErrorStringMT(errstr, sizeof(errstr)) ); *err = socketError; closesocket( newsocket ); return INVALID_SOCKET; @@ -1254,7 +1275,7 @@ int NET_IPSocket( char *net_interface, int port, int *err, qboolean tcp) { if(ret == SOCKET_ERROR && err2 != EAGAIN) { - Com_PrintError( "NET_IPSocket reading from open socket %d failed with: %s\n", newsocket, NET_ErrorString() ); + Com_PrintError( "NET_IPSocket reading from open socket %d failed with: %s\n", newsocket, NET_ErrorStringMT(errstr, sizeof(errstr)) ); }else { Com_Printf( "NET_IPSocket opening of socket %d was successful\n", newsocket ); @@ -1276,6 +1297,7 @@ int NET_IP6Socket( char *net_interface, int port, struct sockaddr_in6 *bindto, i ioctlarg_t _true = 1; // struct linger so_linger; int reuse; + char errstr[256]; *err = 0; if( net_interface ) @@ -1307,13 +1329,13 @@ int NET_IP6Socket( char *net_interface, int port, struct sockaddr_in6 *bindto, i if( newsocket == INVALID_SOCKET ) { *err = socketError; - Com_PrintWarning( "NET_IP6Socket: socket: %s\n", NET_ErrorString() ); + Com_PrintWarning( "NET_IP6Socket: socket: %s\n", NET_ErrorStringMT(errstr, sizeof(errstr)) ); return newsocket; } // make it non-blocking if( ioctlsocket( newsocket, FIONBIO, &_true ) == SOCKET_ERROR ) { - Com_PrintWarning( "NET_IP6Socket: ioctl FIONBIO: %s\n", NET_ErrorString() ); + Com_PrintWarning( "NET_IP6Socket: ioctl FIONBIO: %s\n", NET_ErrorStringMT(errstr, sizeof(errstr)) ); *err = socketError; closesocket(newsocket); return INVALID_SOCKET; @@ -1328,14 +1350,14 @@ int NET_IP6Socket( char *net_interface, int port, struct sockaddr_in6 *bindto, i so_linger.l_linger = 2; //Two seconds timeout if( setsockopt( newsocket, SOL_SOCKET, SO_LINGER, (char *) &so_linger, sizeof(so_linger) ) == SOCKET_ERROR ) { - Com_PrintWarning( "NET_IP6Socket: setsockopt SO_LINGER: %s\n", NET_ErrorString() ); + Com_PrintWarning( "NET_IP6Socket: setsockopt SO_LINGER: %s\n", NET_ErrorStringMT(errstr, sizeof(errstr)) ); } */ reuse = 1; if( setsockopt( newsocket, SOL_SOCKET, SO_REUSEADDR, (char *) &reuse, sizeof(reuse) ) == SOCKET_ERROR ) { - Com_PrintWarning( "NET_IP6Socket: setsockopt SO_REUSEADDR: %s\n", NET_ErrorString() ); + Com_PrintWarning( "NET_IP6Socket: setsockopt SO_REUSEADDR: %s\n", NET_ErrorStringMT(errstr, sizeof(errstr)) ); } @@ -1349,7 +1371,7 @@ int NET_IP6Socket( char *net_interface, int port, struct sockaddr_in6 *bindto, i if(setsockopt(newsocket, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &i, sizeof(i)) == SOCKET_ERROR) { // win32 systems don't seem to support this anyways. - Com_DPrintf("WARNING: NET_IP6Socket: setsockopt IPV6_V6ONLY: %s\n", NET_ErrorString()); + Com_DPrintf("WARNING: NET_IP6Socket: setsockopt IPV6_V6ONLY: %s\n", NET_ErrorStringMT(errstr, sizeof(errstr))); } } #endif @@ -1375,7 +1397,7 @@ int NET_IP6Socket( char *net_interface, int port, struct sockaddr_in6 *bindto, i } if( bind( newsocket, (void *)&address, sizeof(address) ) == SOCKET_ERROR ) { - Com_PrintWarning( "NET_IP6Socket: bind: %s\n", NET_ErrorString() ); + Com_PrintWarning( "NET_IP6Socket: bind: %s\n", NET_ErrorStringMT(errstr, sizeof(errstr)) ); *err = socketError; closesocket( newsocket ); return INVALID_SOCKET; @@ -1387,7 +1409,7 @@ int NET_IP6Socket( char *net_interface, int port, struct sockaddr_in6 *bindto, i if(tcp){ // Listen if( listen( newsocket, 96) == SOCKET_ERROR ) { - Com_PrintWarning( "NET_IP6Socket: listen: %s\n", NET_ErrorString() ); + Com_PrintWarning( "NET_IP6Socket: listen: %s\n", NET_ErrorStringMT(errstr, sizeof(errstr)) ); *err = socketError; closesocket( newsocket ); return INVALID_SOCKET; @@ -1407,10 +1429,9 @@ int NET_IP6Socket( char *net_interface, int port, struct sockaddr_in6 *bindto, i if(ret == SOCKET_ERROR && err2 != EAGAIN) { - Com_PrintError( "NET_IP6Socket reading from open socket %d failed with: %s\n", newsocket, NET_ErrorString() ); + Com_PrintError( "NET_IP6Socket reading from open socket %d failed with: %s\n", newsocket, NET_ErrorStringMT(errstr, sizeof(errstr)) ); }else { Com_Printf( "NET_IP6Socket opening of socket %d was successful\n", newsocket ); - } } #endif @@ -2336,7 +2357,6 @@ Functions for TCP networking which can be used by client and server */ - /* =============== NET_TcpCloseSocket @@ -2363,15 +2383,16 @@ void NET_TcpCloseSocket(int socket) { conn->lastMsgTime = 0; FD_CLR(conn->remote.sock, &tcpServer.fdr); - conn->state = 0; - - if(conn->state >= TCP_AUTHSUCCESSFULL) + if(conn->wantwrite) { - tcpServer.activeConnectionCount--; - NET_TCPConnectionClosed(&conn->remote, conn->connectionId, conn->serviceId); + FD_CLR(conn->remote.sock, &tcpServer.fdw); } + conn->state = 0; + + tcpServer.activeConnectionCount--; + NET_TCPConnectionClosed(&conn->remote, conn->connectionId, conn->serviceId); conn->remote.sock = INVALID_SOCKET; - NET_TcpServerRebuildFDList(); + //NET_TcpServerRebuildFDList(); return; } } @@ -2388,7 +2409,7 @@ Return -1 if an fatal error happened on this socket otherwise 0 int NET_TcpSendData( int sock, const void *data, int length, char* errormsg, int maxerrorlen ) { int state, err; - + char errstr[256]; if(sock < 1) return -1; @@ -2404,7 +2425,7 @@ int NET_TcpSendData( int sock, const void *data, int length, char* errormsg, int } if(errormsg) { - Q_strncpyz(errormsg, NET_ErrorString(), maxerrorlen); + Q_strncpyz(errormsg, NET_ErrorStringMT(errstr, sizeof(errstr)), maxerrorlen); } if(err == EPIPE || err == ECONNRESET){ return NET_CONNRESET; @@ -2431,7 +2452,8 @@ int NET_TcpServerGetPacket(tcpConnections_t *conn, void *netmsg, int maxsize, qb int err; int ret; - + char errstr[256]; + char adrstr[256]; ret = recv(conn->remote.sock, netmsg, maxsize , 0); @@ -2447,12 +2469,12 @@ int NET_TcpServerGetPacket(tcpConnections_t *conn, void *netmsg, int maxsize, qb if(ret == ECONNRESET){ if(warn){ - Com_PrintNoRedirect("Connection closed by: %s\n", NET_AdrToString(&conn->remote)); + Com_PrintNoRedirect("Connection closed by: %s\n", NET_AdrToStringMT(&conn->remote, adrstr, sizeof(adrstr))); //Connection closed } }else - Com_PrintWarningNoRedirect("NET_GetTcpPacket recv() syscall failed: %s\n", NET_ErrorString()); // BUGFIX: this causes SIGSEGV in case of an error during console stream + Com_PrintWarningNoRedirect("NET_GetTcpPacket recv() syscall failed: %s\n", NET_ErrorStringMT(errstr, sizeof(errstr))); // BUGFIX: this causes SIGSEGV in case of an error during console stream NET_TcpCloseSocket(conn->remote.sock); return -1; @@ -2461,7 +2483,7 @@ int NET_TcpServerGetPacket(tcpConnections_t *conn, void *netmsg, int maxsize, qb if(conn->state >= TCP_AUTHSUCCESSFULL) { - Com_PrintNoRedirect("Connection closed by client: %s\n", NET_AdrToString(&conn->remote)); + Com_PrintNoRedirect("Connection closed by client: %s\n", NET_AdrToStringMT(&conn->remote, adrstr, sizeof(adrstr))); } NET_TcpCloseSocket(conn->remote.sock); return -1; @@ -2480,6 +2502,7 @@ void NET_TcpServerRebuildFDList() tcpConnections_t *conn; FD_ZERO(&tcpServer.fdr); + FD_ZERO(&tcpServer.fdw); tcpServer.highestfd = -1; for(i = 0, conn = tcpServer.connections; i < MAX_TCPCONNECTIONS; i++, conn++) @@ -2487,6 +2510,10 @@ void NET_TcpServerRebuildFDList() if(conn->remote.sock > 0) { FD_SET(conn->remote.sock, &tcpServer.fdr); + if(conn->wantwrite) + { + FD_SET(conn->remote.sock, &tcpServer.fdw); + } if(conn->remote.sock > tcpServer.highestfd) { tcpServer.highestfd = conn->remote.sock; @@ -2502,6 +2529,7 @@ void NET_TcpServerInit() Com_Memset(&tcpServer, 0, sizeof(tcpServer)); FD_ZERO(&tcpServer.fdr); + FD_ZERO(&tcpServer.fdw); tcpServer.highestfd = -1; for(i = 0, conn = tcpServer.connections; i < MAX_TCPCONNECTIONS; i++, conn++) @@ -2510,6 +2538,7 @@ void NET_TcpServerInit() } } + /* ================== NET_TcpServerPacketEventLoop @@ -2527,8 +2556,10 @@ void NET_TcpServerPacketEventLoop() timeout.tv_usec = 0; int activefd, i, ret; int cursize; - fd_set fdr; + fd_set fdr, fdw; tcpConnections_t *conn; + char errstr[256]; + char adrstr[256]; byte bufData[MAX_MSGLEN]; @@ -2539,12 +2570,13 @@ void NET_TcpServerPacketEventLoop() } fdr = tcpServer.fdr; - activefd = select(tcpServer.highestfd + 1, &fdr, &fdr, NULL, &timeout); + fdw = tcpServer.fdw; + activefd = select(tcpServer.highestfd + 1, &fdr, &fdw, NULL, &timeout); if(activefd < 0) { - Com_PrintWarningNoRedirect("NET_TcpServerPacketEventLoop: select() syscall failed: %s\n", NET_ErrorString()); + Com_PrintWarningNoRedirect("NET_TcpServerPacketEventLoop: select() syscall failed: %s\n", NET_ErrorStringMT(errstr, sizeof(errstr))); return; } @@ -2552,70 +2584,46 @@ void NET_TcpServerPacketEventLoop() { return; } - for(i = 0, conn = tcpServer.connections; i < MAX_TCPCONNECTIONS; i++, conn++) { if(conn->remote.sock < 1) { continue; } - if(FD_ISSET(conn->remote.sock, &fdr)) + if(FD_ISSET(conn->remote.sock, &fdr) || FD_ISSET(conn->remote.sock, &fdw)) { - switch(conn->state) - { - case TCP_AUTHWAIT: - case TCP_AUTHAGAIN: - - cursize = 0; - - ret = NET_TcpServerGetPacket(conn, bufData, sizeof(bufData), qfalse); - - if(ret > 0) - { - cursize = ret; - }else{ - break; - } - - if(conn->lastMsgTime == 0 || conn->remote.sock < 1) - { - break; //Connection closed unexpected - //Close connection, we don't want to process huge messages as auth-packet or want to quit if the login was bad - }else if( (conn->state = NET_TCPAuthPacketEvent(&conn->remote, bufData, cursize, &conn->connectionId, &conn->serviceId)) == TCP_AUTHBAD){ - NET_TcpCloseSocket(conn->remote.sock); - - }else if(conn->state == TCP_AUTHSUCCESSFULL){ - tcpServer.activeConnectionCount++; - Com_PrintNoRedirect("New connection accepted for: %s from type: %x\n", NET_AdrToString(&conn->remote), conn->serviceId); - } - break; - - case TCP_AUTHNOTME: - case TCP_AUTHBAD: //Should not happen - NET_TcpCloseSocket(conn->remote.sock); - break; + cursize = 0; - case TCP_AUTHSUCCESSFULL: - - cursize = 0; - - ret = NET_TcpServerGetPacket(conn, bufData, sizeof(bufData), qtrue); - if(ret > 0) - { - cursize = ret; - } + ret = NET_TcpServerGetPacket(conn, bufData, sizeof(bufData), qtrue); + if(ret > 0) + { + cursize = ret; + } - if(cursize > sizeof(bufData)) - { - Com_PrintWarningNoRedirect( "NET_TcpServerPacketEventLoop: Oversize packet from %s. Must not happen!\n", NET_AdrToString (&conn->remote)); - cursize = sizeof(bufData); - } - NET_TCPPacketEvent(&conn->remote, bufData, cursize, conn->connectionId, conn->serviceId); - break; + if(cursize > sizeof(bufData)) + { + Com_PrintWarningNoRedirect( "NET_TcpServerPacketEventLoop: Oversize packet from %s. Must not happen!\n", NET_AdrToStringMT(&conn->remote, adrstr, sizeof(adrstr))); + cursize = sizeof(bufData); + } + qboolean wantwrite = NET_TCPPacketEvent(&conn->remote, bufData, cursize, &conn->connectionId, &conn->serviceId); + if(wantwrite) + { + if(!conn->wantwrite) + { + conn->wantwrite = qtrue; + FD_SET(conn->remote.sock, &tcpServer.fdw); } + }else{ + if(conn->wantwrite) + { + conn->wantwrite = qfalse; + FD_CLR(conn->remote.sock, &tcpServer.fdw); + } + } + break; - }else if(conn->lastMsgTime && conn->state < TCP_AUTHSUCCESSFULL && conn->lastMsgTime + MAX_TCPAUTHWAITTIME < NET_TimeGetTime()){ + }else if(conn->lastMsgTime + MAX_TCPAUTHWAITTIME < NET_TimeGetTime()){ NET_TcpCloseSocket(conn->remote.sock); } } @@ -2623,6 +2631,8 @@ void NET_TcpServerPacketEventLoop() + + /* ================== NET_TcpServerOpenConnection @@ -2641,6 +2651,7 @@ void NET_TcpServerOpenConnection( netadr_t *from ) int oldestAccepted = 0; int oldest = 0; int i; + char adrstr[128]; for(i = 0, conn = tcpServer.connections; i < MAX_TCPCONNECTIONS; i++, conn++) { @@ -2676,7 +2687,7 @@ void NET_TcpServerOpenConnection( netadr_t *from ) if(tcpServer.lastAttackWarnTime + MIN_TCPAUTHWAITTIME < NET_TimeGetTime()) { tcpServer.lastAttackWarnTime = NET_TimeGetTime(); - Com_PrintWarning("Possible Denial of Service Attack, Dropping connectrequest from: %s\n", NET_AdrToString(from)); + Com_PrintWarning("Possible Denial of Service Attack, Dropping connectrequest from: %s\n", NET_AdrToStringMT(from, adrstr, sizeof(adrstr))); } return; } @@ -2691,16 +2702,18 @@ void NET_TcpServerOpenConnection( netadr_t *from ) conn->state = TCP_AUTHWAIT; conn->serviceId = -1; conn->connectionId = -1; + conn->wantwrite = qfalse; FD_SET(conn->remote.sock, &tcpServer.fdr); if(tcpServer.highestfd < conn->remote.sock) tcpServer.highestfd = conn->remote.sock; - Com_DPrintf("Opening a new TCP server connection. Sock: %d Index: %d From:%s\n", conn->remote.sock, i, NET_AdrToString(&conn->remote)); + Com_DPrintf("Opening a new TCP server connection. Sock: %d Index: %d From:%s\n", conn->remote.sock, i, NET_AdrToStringMT(&conn->remote, adrstr, sizeof(adrstr))); } + /* ================== Only for Stream sockets (TCP) @@ -2718,6 +2731,7 @@ __optimize3 __regparm3 qboolean NET_TcpServerConnectRequest(netadr_t* net_from, net_from->sock = INVALID_SOCKET; int socket; ioctlarg_t _true = 1; + char errstr[256]; if(tcp_socket != INVALID_SOCKET && FD_ISSET(tcp_socket, fdr)) { @@ -2729,14 +2743,14 @@ __optimize3 __regparm3 qboolean NET_TcpServerConnectRequest(netadr_t* net_from, conerr = socketError; if( conerr != EAGAIN && conerr != ECONNRESET ) - Com_PrintWarning( "NET_TcpServerConnectRequest: %s\n", NET_ErrorString() ); + Com_PrintWarning( "NET_TcpServerConnectRequest: %s\n", NET_ErrorStringMT(errstr, sizeof(errstr)) ); return qfalse; } else { if( ioctlsocket( socket, FIONBIO, &_true ) == SOCKET_ERROR ) { - Com_PrintWarning( "NET_TcpServerConnectRequest: ioctl FIONBIO: %s\n", NET_ErrorString() ); + Com_PrintWarning( "NET_TcpServerConnectRequest: ioctl FIONBIO: %s\n", NET_ErrorStringMT(errstr, sizeof(errstr)) ); conerr = socketError; closesocket( socket ); return qfalse; @@ -2756,14 +2770,14 @@ __optimize3 __regparm3 qboolean NET_TcpServerConnectRequest(netadr_t* net_from, conerr = socketError; if( conerr != EAGAIN && conerr != ECONNRESET ) - Com_PrintWarning( "NET_TcpServerConnectRequest: %s\n", NET_ErrorString() ); + Com_PrintWarning( "NET_TcpServerConnectRequest: %s\n", NET_ErrorStringMT(errstr, sizeof(errstr)) ); return qfalse; } else { if( ioctlsocket( socket, FIONBIO, &_true ) == SOCKET_ERROR ) { - Com_PrintWarning( "NET_TcpServerConnectRequest: ioctl FIONBIO: %s\n", NET_ErrorString() ); + Com_PrintWarning( "NET_TcpServerConnectRequest: ioctl FIONBIO: %s\n", NET_ErrorStringMT(errstr, sizeof(errstr)) ); conerr = socketError; closesocket( socket ); return qfalse; @@ -2783,7 +2797,6 @@ __optimize3 __regparm1 qboolean NET_TcpServerConnectEvent(fd_set *fdr) { netadr_t from; int i; - //Give the system a possibility to abort processing network packets so it won't block execution of frames if the network getting flooded for(i = 0; i < MAX_NETPACKETS; i++) { @@ -2822,6 +2835,7 @@ int NET_TcpClientGetData(int sock, void* buf, int buflen, char* errormsg, int ma int err; int ret; + char errstr[256]; if(sock < 1) return -1; @@ -2837,7 +2851,7 @@ int NET_TcpClientGetData(int sock, void* buf, int buflen, char* errormsg, int ma } if(errormsg) { - Q_strncpyz(errormsg, NET_ErrorString(), maxerrorlen); + Q_strncpyz(errormsg, NET_ErrorStringMT(errstr, sizeof(errstr)), maxerrorlen); } if(ret == ECONNRESET || ret == EPIPE) { @@ -2853,39 +2867,85 @@ int NET_TcpClientGetData(int sock, void* buf, int buflen, char* errormsg, int ma NET_TcpClientConnect ==================== */ -int NET_TcpClientConnect( const char *remoteAdr ) { +int NET_TcpClientConnectInternal( const char *remoteAdr, netadr_t *adr, netadr_t *sourceadr, qboolean silent ) { SOCKET newsocket; - struct sockaddr_in address; + struct sockaddr_storage address, bindaddr; netadr_t remoteadr; int err = 0; int retval; fd_set fdr; struct timeval timeout; + char errstr[256]; + char adrstr[128]; + + if(remoteAdr) + { + if(!silent) Com_Printf( "Connecting to: %s\n", remoteAdr); + + if(NET_StringToAdr(remoteAdr, &remoteadr, NA_UNSPEC)) + { + if(!silent) Com_Printf( "Resolved %s to: %s\n", remoteAdr, NET_AdrToStringMT(&remoteadr, adrstr, sizeof(adrstr))); + }else{ + if(!silent) Com_PrintWarning( "Couldn't resolve: %s\n", remoteAdr); + return INVALID_SOCKET; + } + }else{ + memcpy(&remoteadr, adr, sizeof(remoteadr)); + } - Com_Printf( "Connecting to: %s\n", remoteAdr); + if(sourceadr) + { + int sourcefam, destfam; + sourcefam = sourceadr->type; + destfam = remoteadr.type; - if( ( newsocket = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP ) ) == INVALID_SOCKET ) { - Com_PrintWarning( "NET_TCPConnect: socket: %s\n", NET_ErrorString() ); + if(sourcefam == NA_TCP) + { + sourcefam = NA_IP; + }else if(sourcefam == NA_TCP6) + { + sourcefam = NA_IP6; + } + if(destfam == NA_TCP) + { + destfam = NA_IP; + }else if(destfam == NA_TCP6) + { + destfam = NA_IP6; + } + + if(sourcefam != destfam) + { + if(!silent) Com_PrintWarning( "NET_TCPConnect: Protocol family mismatch for source and destination\n"); + return INVALID_SOCKET; + } + } + NetadrToSockadr( &remoteadr, (struct sockaddr *)&address); + + if( ( newsocket = socket( address.ss_family, SOCK_STREAM, IPPROTO_TCP ) ) == INVALID_SOCKET ) { + if(!silent) Com_PrintWarning( "NET_TCPConnect: socket: %s\n", NET_ErrorStringMT(errstr, sizeof(errstr)) ); return INVALID_SOCKET; } // make it non-blocking ioctlarg_t _true = 1; if( ioctlsocket( newsocket, FIONBIO, &_true ) == SOCKET_ERROR ) { - Com_PrintWarning( "NET_TCPIPSocket: ioctl FIONBIO: %s\n", NET_ErrorString() ); + if(!silent) Com_PrintWarning( "NET_TCPIPSocket: ioctl FIONBIO: %s\n", NET_ErrorStringMT(errstr, sizeof(errstr)) ); closesocket(newsocket); return INVALID_SOCKET; } - if(NET_StringToAdr(remoteAdr, &remoteadr, NA_UNSPEC)) - { - Com_Printf( "Resolved %s to: %s\n", remoteAdr, NET_AdrToString(&remoteadr)); - }else{ - Com_PrintWarning( "Couldn't resolve: %s\n", remoteAdr); + + if(sourceadr) + { + NetadrToSockadr(sourceadr, (struct sockaddr *)&bindaddr); + if( bind( newsocket, (void *)&bindaddr, sizeof(bindaddr) ) == SOCKET_ERROR ) { + if(!silent) Com_PrintWarning( "NET_TcpClientConnect: bind: %s\n", NET_ErrorStringMT(errstr, sizeof(errstr)) ); closesocket( newsocket ); return INVALID_SOCKET; } + } + - NetadrToSockadr( &remoteadr, (struct sockaddr *)&address); if( connect( newsocket, (void *)&address, sizeof(address) ) == SOCKET_ERROR ) { @@ -2904,7 +2964,7 @@ int NET_TcpClientConnect( const char *remoteAdr ) { retval = select(newsocket +1, NULL, &fdr, NULL, &timeout); if(retval < 0){ - Com_PrintWarning("NET_TcpConnect: select() syscall failed: %s\n", NET_ErrorString()); + if(!silent) Com_PrintWarning("NET_TcpConnect: select() syscall failed: %s\n", NET_ErrorStringMT(errstr, sizeof(errstr))); closesocket( newsocket ); return INVALID_SOCKET; }else if(retval > 0){ @@ -2917,19 +2977,37 @@ int NET_TcpClientConnect( const char *remoteAdr ) { } }else{ - Com_PrintWarning("NET_TcpConnect: Connecting to: %s timed out\n", remoteAdr); + if(!silent) Com_PrintWarning("NET_TcpConnect: Connecting to: %s timed out\n", NET_AdrToStringMT(&remoteadr, adrstr, sizeof(adrstr))); closesocket( newsocket ); return INVALID_SOCKET; } } - Com_PrintWarning( "NET_TCPOpenConnection: connect: %s\n", NET_ErrorString() ); + if(!silent) Com_PrintWarning( "NET_TCPOpenConnection: connect: %s\n", NET_ErrorStringMT(errstr, sizeof(errstr)) ); closesocket( newsocket ); return INVALID_SOCKET; } return newsocket; } +int NET_TcpClientConnect( const char *remoteAdr ) +{ + return NET_TcpClientConnectInternal(remoteAdr, NULL, NULL, qfalse); +} +int NET_TcpClientConnectToAdr( netadr_t* adr ) +{ + return NET_TcpClientConnectInternal(NULL, adr, NULL, qfalse); +} + +int NET_TcpClientConnectFromAdrToAdr( netadr_t* destination, netadr_t* source ) +{ + return NET_TcpClientConnectInternal(NULL, destination, source, qfalse); +} + +int NET_TcpClientConnectFromAdrToAdrSilent( netadr_t* destination, netadr_t* source ) +{ + return NET_TcpClientConnectInternal(NULL, destination, source, qtrue); +} /* ==================== @@ -3200,3 +3278,55 @@ const char* NET_GetHostAddress(char* adrstrbuf, int len) Com_sprintf(adrstrbuf, len, "%s:%hd\n", net_ip->string, net_port->integer); return adrstrbuf; } + + +/* +================== +Sys_IsReservedAddress + +LAN clients will have their rate var ignored +================== +*/ +qboolean Sys_IsReservedAddress( netadr_t *adr ) { + + int i; + + if( adr->type == NA_LOOPBACK ) { + return qtrue; + } + + if( adr->type == NA_IP ) + { + // RFC1918: + // 10.0.0.0 - 10.255.255.255 (10/8 prefix) + // 172.16.0.0 - 172.31.255.255 (172.16/12 prefix) + // 192.168.0.0 - 192.168.255.255 (192.168/16 prefix) + if(adr->ip[0] == 10) + return qtrue; + if(adr->ip[0] == 172 && (adr->ip[1]&0xf0) == 16) + return qtrue; + if(adr->ip[0] == 192 && adr->ip[1] == 168) + return qtrue; + + if(adr->ip[0] == 127) + return qtrue; + } + else if(adr->type == NA_IP6) + { + if(adr->ip6[0] == 0xfe && (adr->ip6[1] & 0xc0) == 0x80) + return qtrue; + if((adr->ip6[0] & 0xfe) == 0xfc) + return qtrue; + + for(i = 0; i < 15; i++) + { + if(adr->ip6[i] != 0) + { + return qfalse; + } + } + if(adr->ip6[i] == 1) + return qtrue; + } + return qfalse; +} diff --git a/src/sys_net.h b/src/sys_net.h index 66591e9e..46b39026 100644 --- a/src/sys_net.h +++ b/src/sys_net.h @@ -96,6 +96,7 @@ qboolean NET_CompareBaseAdrMask(netadr_t *a, netadr_t *b, int netmask); qboolean NET_CompareBaseAdr (netadr_t *a, netadr_t *b); qboolean NET_IsLocalAddress (netadr_t adr); const char *NET_AdrToString (netadr_t *a); +const char *NET_AdrToStringMT (netadr_t *a, char*, int); const char *NET_AdrToStringShort (netadr_t *a); const char *NET_AdrToStringwPort (netadr_t *a); netadr_t *NET_SockToAdr(int socket); @@ -122,10 +123,15 @@ void NET_TcpServerPacketEventLoop(); void NET_TcpServerRebuildFDList(void); void NET_TcpServerInit(void); int NET_TcpClientConnect( const char *remoteAdr ); +int NET_TcpClientConnectToAdr( netadr_t* adr ); +int NET_TcpClientConnectFromAdrToAdr( netadr_t* destination, netadr_t* source ); +int NET_TcpClientConnectFromAdrToAdrSilent( netadr_t* destination, netadr_t* source ); int NET_TcpClientGetData(int sock, void* buf, int buflen, char* errormsg, int maxerrorlen); void NET_TcpCloseSocket(int socket); const char* NET_GetHostAddress(char* adrstrbuf, int len); int NET_GetHostPort(); +netadr_t* NET_GetLocalAddressList(int* count); +qboolean Sys_IsReservedAddress( netadr_t *adr ); typedef enum { TCP_AUTHWAIT, diff --git a/src/sys_thread.h b/src/sys_thread.h index 8555a796..c4150a17 100644 --- a/src/sys_thread.h +++ b/src/sys_thread.h @@ -56,6 +56,7 @@ typedef enum CRIT_LOGFILE = 17, CRIT_PLUGIN = 18, CRIT_HTTPS = 19, + CRIT_CVAR = 20, CRIT_SIZE }crit_section_t; diff --git a/src/tomcrypt/compile_linux.sh b/src/tomcrypt/compile_linux.sh index 4af6058e..a510b2cd 100644 --- a/src/tomcrypt/compile_linux.sh +++ b/src/tomcrypt/compile_linux.sh @@ -4,6 +4,8 @@ gcc $FLAGS hashes/*.c gcc $FLAGS misc/crypt/*.c gcc $FLAGS misc/base64/*.c gcc $FLAGS misc/*.c +gcc $FLAGS misc/pkcs5/*.c +gcc $FLAGS mac/hmac/*.c gcc $FLAGS pk/asn1/der/sequence/*.c gcc $FLAGS pk/asn1/der/bit/*.c gcc $FLAGS pk/asn1/der/boolean/*.c diff --git a/src/tomcrypt/compile_win32.cmd b/src/tomcrypt/compile_win32.cmd index 5406b15f..87c450e9 100644 --- a/src/tomcrypt/compile_win32.cmd +++ b/src/tomcrypt/compile_win32.cmd @@ -2,11 +2,13 @@ SET FLAGS=-m32 -Wall -Os -s -c -I. -DLTC_NO_ROLC -DLTC_SOURCE SET MATHFLAGS=-m32 -Wall -Os -s -c -I. -Imath -DLTC_NO_ROLC -DLTC_SOURCE -REM -Wsign-compare -W -Wshadow -Wno-unused-parameter-Wsystem-headers -Wdeclaration-after-statement -Wbad-function-cast -Wcast-align -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wpointer-arith +REM -Wsign-compare -W -Wshadow -Wno-unused-parameter-Wsystem-headers -Wdeclaration-after-statement -Wbad-function-cast -Wcast-align -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wpointer-arith gcc %FLAGS% hashes\*.c gcc %FLAGS% misc\crypt\*.c gcc %FLAGS% misc\base64\*.c +gcc %FLAGS% misc\pkcs5\*.c gcc %FLAGS% misc\*.c +gcc %FLAGS% mac\hmac\*.c gcc %FLAGS% pk\asn1\der\sequence\*.c gcc %FLAGS% pk\asn1\der\bit\*.c gcc %FLAGS% pk\asn1\der\boolean\*.c @@ -23,9 +25,9 @@ gcc %FLAGS% pk\asn1\der\utf8\*.c gcc %FLAGS% pk\asn1\der\set\*.c gcc %FLAGS% pk\rsa\*.c gcc %FLAGS% pk\pkcs1\*.c -gcc %MATHFLAGS% math\*.c +gcc %MATHFLAGS% math\*.c ar cr ../../lib/libtomcrypt_win32.a *.o DEL *.o -pause \ No newline at end of file +pause diff --git a/src/tomcrypt/mac/hmac/hmac_done.c b/src/tomcrypt/mac/hmac/hmac_done.c new file mode 100644 index 00000000..2bc08a10 --- /dev/null +++ b/src/tomcrypt/mac/hmac/hmac_done.c @@ -0,0 +1,109 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file hmac_done.c + LTC_HMAC support, terminate stream, Tom St Denis/Dobes Vandermeer +*/ + +#ifdef LTC_HMAC + +#define LTC_HMAC_BLOCKSIZE hash_descriptor[hash].blocksize + +/** + Terminate an LTC_HMAC session + @param hmac The LTC_HMAC state + @param out [out] The destination of the LTC_HMAC authentication tag + @param outlen [in/out] The max size and resulting size of the LTC_HMAC authentication tag + @return CRYPT_OK if successful +*/ +int hmac_done(hmac_state *hmac, unsigned char *out, unsigned long *outlen) +{ + unsigned char *buf, *isha; + unsigned long hashsize, i; + int hash, err; + + LTC_ARGCHK(hmac != NULL); + LTC_ARGCHK(out != NULL); + + /* test hash */ + hash = hmac->hash; + if((err = hash_is_valid(hash)) != CRYPT_OK) { + return err; + } + + /* get the hash message digest size */ + hashsize = hash_descriptor[hash].hashsize; + + /* allocate buffers */ + buf = XMALLOC(LTC_HMAC_BLOCKSIZE); + isha = XMALLOC(hashsize); + if (buf == NULL || isha == NULL) { + if (buf != NULL) { + XFREE(buf); + } + if (isha != NULL) { + XFREE(isha); + } + return CRYPT_MEM; + } + + /* Get the hash of the first LTC_HMAC vector plus the data */ + if ((err = hash_descriptor[hash].done(&hmac->md, isha)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* Create the second LTC_HMAC vector vector for step (3) */ + for(i=0; i < LTC_HMAC_BLOCKSIZE; i++) { + buf[i] = hmac->key[i] ^ 0x5C; + } + + /* Now calculate the "outer" hash for step (5), (6), and (7) */ + if ((err = hash_descriptor[hash].init(&hmac->md)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = hash_descriptor[hash].process(&hmac->md, buf, LTC_HMAC_BLOCKSIZE)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = hash_descriptor[hash].process(&hmac->md, isha, hashsize)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = hash_descriptor[hash].done(&hmac->md, buf)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* copy to output */ + for (i = 0; i < hashsize && i < *outlen; i++) { + out[i] = buf[i]; + } + *outlen = i; + + err = CRYPT_OK; +LBL_ERR: + XFREE(hmac->key); +#ifdef LTC_CLEAN_STACK + zeromem(isha, hashsize); + zeromem(buf, hashsize); + zeromem(hmac, sizeof(*hmac)); +#endif + + XFREE(isha); + XFREE(buf); + + return err; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/mac/hmac/hmac_done.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2007/05/12 14:37:41 $ */ diff --git a/src/tomcrypt/mac/hmac/hmac_file.c b/src/tomcrypt/mac/hmac/hmac_file.c new file mode 100644 index 00000000..08ae9489 --- /dev/null +++ b/src/tomcrypt/mac/hmac/hmac_file.c @@ -0,0 +1,93 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file hmac_file.c + LTC_HMAC support, process a file, Tom St Denis/Dobes Vandermeer +*/ + +#ifdef LTC_HMAC + +/** + LTC_HMAC a file + @param hash The index of the hash you wish to use + @param fname The name of the file you wish to LTC_HMAC + @param key The secret key + @param keylen The length of the secret key + @param out [out] The LTC_HMAC authentication tag + @param outlen [in/out] The max size and resulting size of the authentication tag + @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled +*/ +int hmac_file(int hash, const char *fname, + const unsigned char *key, unsigned long keylen, + unsigned char *out, unsigned long *outlen) +{ +#ifdef LTC_NO_FILE + return CRYPT_NOP; +#else + hmac_state hmac; + FILE *in; + unsigned char buf[512]; + size_t x; + int err; + + LTC_ARGCHK(fname != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + if((err = hash_is_valid(hash)) != CRYPT_OK) { + return err; + } + + if ((err = hmac_init(&hmac, hash, key, keylen)) != CRYPT_OK) { + return err; + } + + in = fopen(fname, "rb"); + if (in == NULL) { + return CRYPT_FILE_NOTFOUND; + } + + /* process the file contents */ + do { + x = fread(buf, 1, sizeof(buf), in); + if ((err = hmac_process(&hmac, buf, (unsigned long)x)) != CRYPT_OK) { + /* we don't trap this error since we're already returning an error! */ + fclose(in); + return err; + } + } while (x == sizeof(buf)); + + if (fclose(in) != 0) { + return CRYPT_ERROR; + } + + /* get final hmac */ + if ((err = hmac_done(&hmac, out, outlen)) != CRYPT_OK) { + return err; + } + +#ifdef LTC_CLEAN_STACK + /* clear memory */ + zeromem(buf, sizeof(buf)); +#endif + return CRYPT_OK; +#endif +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/mac/hmac/hmac_file.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2007/05/12 14:37:41 $ */ diff --git a/src/tomcrypt/mac/hmac/hmac_init.c b/src/tomcrypt/mac/hmac/hmac_init.c new file mode 100644 index 00000000..0fe1e2f2 --- /dev/null +++ b/src/tomcrypt/mac/hmac/hmac_init.c @@ -0,0 +1,112 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file hmac_init.c + LTC_HMAC support, initialize state, Tom St Denis/Dobes Vandermeer +*/ + +#ifdef LTC_HMAC + +#define LTC_HMAC_BLOCKSIZE hash_descriptor[hash].blocksize + +/** + Initialize an LTC_HMAC context. + @param hmac The LTC_HMAC state + @param hash The index of the hash you want to use + @param key The secret key + @param keylen The length of the secret key (octets) + @return CRYPT_OK if successful +*/ +int hmac_init(hmac_state *hmac, int hash, const unsigned char *key, unsigned long keylen) +{ + unsigned char *buf; + unsigned long hashsize; + unsigned long i, z; + int err; + + LTC_ARGCHK(hmac != NULL); + LTC_ARGCHK(key != NULL); + + /* valid hash? */ + if ((err = hash_is_valid(hash)) != CRYPT_OK) { + return err; + } + hmac->hash = hash; + hashsize = hash_descriptor[hash].hashsize; + + /* valid key length? */ + if (keylen == 0) { + return CRYPT_INVALID_KEYSIZE; + } + + /* allocate ram for buf */ + buf = XMALLOC(LTC_HMAC_BLOCKSIZE); + if (buf == NULL) { + return CRYPT_MEM; + } + + /* allocate memory for key */ + hmac->key = XMALLOC(LTC_HMAC_BLOCKSIZE); + if (hmac->key == NULL) { + XFREE(buf); + return CRYPT_MEM; + } + + /* (1) make sure we have a large enough key */ + if(keylen > LTC_HMAC_BLOCKSIZE) { + z = LTC_HMAC_BLOCKSIZE; + if ((err = hash_memory(hash, key, keylen, hmac->key, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + if(hashsize < LTC_HMAC_BLOCKSIZE) { + zeromem((hmac->key) + hashsize, (size_t)(LTC_HMAC_BLOCKSIZE - hashsize)); + } + keylen = hashsize; + } else { + XMEMCPY(hmac->key, key, (size_t)keylen); + if(keylen < LTC_HMAC_BLOCKSIZE) { + zeromem((hmac->key) + keylen, (size_t)(LTC_HMAC_BLOCKSIZE - keylen)); + } + } + + /* Create the initial vector for step (3) */ + for(i=0; i < LTC_HMAC_BLOCKSIZE; i++) { + buf[i] = hmac->key[i] ^ 0x36; + } + + /* Pre-pend that to the hash data */ + if ((err = hash_descriptor[hash].init(&hmac->md)) != CRYPT_OK) { + goto LBL_ERR; + } + + if ((err = hash_descriptor[hash].process(&hmac->md, buf, LTC_HMAC_BLOCKSIZE)) != CRYPT_OK) { + goto LBL_ERR; + } + goto done; +LBL_ERR: + /* free the key since we failed */ + XFREE(hmac->key); +done: +#ifdef LTC_CLEAN_STACK + zeromem(buf, LTC_HMAC_BLOCKSIZE); +#endif + + XFREE(buf); + return err; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/mac/hmac/hmac_init.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2007/05/12 14:37:41 $ */ diff --git a/src/tomcrypt/mac/hmac/hmac_memory.c b/src/tomcrypt/mac/hmac/hmac_memory.c new file mode 100644 index 00000000..efb47d19 --- /dev/null +++ b/src/tomcrypt/mac/hmac/hmac_memory.c @@ -0,0 +1,88 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file hmac_memory.c + LTC_HMAC support, process a block of memory, Tom St Denis/Dobes Vandermeer +*/ + +#ifdef LTC_HMAC + +/** + LTC_HMAC a block of memory to produce the authentication tag + @param hash The index of the hash to use + @param key The secret key + @param keylen The length of the secret key (octets) + @param in The data to LTC_HMAC + @param inlen The length of the data to LTC_HMAC (octets) + @param out [out] Destination of the authentication tag + @param outlen [in/out] Max size and resulting size of authentication tag + @return CRYPT_OK if successful +*/ +int hmac_memory(int hash, + const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + hmac_state *hmac; + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* make sure hash descriptor is valid */ + if ((err = hash_is_valid(hash)) != CRYPT_OK) { + return err; + } + + /* is there a descriptor? */ + if (hash_descriptor[hash].hmac_block != NULL) { + return hash_descriptor[hash].hmac_block(key, keylen, in, inlen, out, outlen); + } + + /* nope, so call the hmac functions */ + /* allocate ram for hmac state */ + hmac = XMALLOC(sizeof(hmac_state)); + if (hmac == NULL) { + return CRYPT_MEM; + } + + if ((err = hmac_init(hmac, hash, key, keylen)) != CRYPT_OK) { + goto LBL_ERR; + } + + if ((err = hmac_process(hmac, in, inlen)) != CRYPT_OK) { + goto LBL_ERR; + } + + if ((err = hmac_done(hmac, out, outlen)) != CRYPT_OK) { + goto LBL_ERR; + } + + err = CRYPT_OK; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(hmac, sizeof(hmac_state)); +#endif + + XFREE(hmac); + return err; +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/mac/hmac/hmac_memory.c,v $ */ +/* $Revision: 1.8 $ */ +/* $Date: 2007/05/12 14:37:41 $ */ diff --git a/src/tomcrypt/mac/hmac/hmac_memory_multi.c b/src/tomcrypt/mac/hmac/hmac_memory_multi.c new file mode 100644 index 00000000..af52532e --- /dev/null +++ b/src/tomcrypt/mac/hmac/hmac_memory_multi.c @@ -0,0 +1,92 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" +#include + +/** + @file hmac_memory_multi.c + LTC_HMAC support, process multiple blocks of memory, Tom St Denis/Dobes Vandermeer +*/ + +#ifdef LTC_HMAC + +/** + LTC_HMAC multiple blocks of memory to produce the authentication tag + @param hash The index of the hash to use + @param key The secret key + @param keylen The length of the secret key (octets) + @param out [out] Destination of the authentication tag + @param outlen [in/out] Max size and resulting size of authentication tag + @param in The data to LTC_HMAC + @param inlen The length of the data to LTC_HMAC (octets) + @param ... tuples of (data,len) pairs to LTC_HMAC, terminated with a (NULL,x) (x=don't care) + @return CRYPT_OK if successful +*/ +int hmac_memory_multi(int hash, + const unsigned char *key, unsigned long keylen, + unsigned char *out, unsigned long *outlen, + const unsigned char *in, unsigned long inlen, ...) + +{ + hmac_state *hmac; + int err; + va_list args; + const unsigned char *curptr; + unsigned long curlen; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* allocate ram for hmac state */ + hmac = XMALLOC(sizeof(hmac_state)); + if (hmac == NULL) { + return CRYPT_MEM; + } + + if ((err = hmac_init(hmac, hash, key, keylen)) != CRYPT_OK) { + goto LBL_ERR; + } + + va_start(args, inlen); + curptr = in; + curlen = inlen; + for (;;) { + /* process buf */ + if ((err = hmac_process(hmac, curptr, curlen)) != CRYPT_OK) { + goto LBL_ERR; + } + /* step to next */ + curptr = va_arg(args, const unsigned char*); + if (curptr == NULL) { + break; + } + curlen = va_arg(args, unsigned long); + } + if ((err = hmac_done(hmac, out, outlen)) != CRYPT_OK) { + goto LBL_ERR; + } +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(hmac, sizeof(hmac_state)); +#endif + XFREE(hmac); + va_end(args); + return err; +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/mac/hmac/hmac_memory_multi.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2007/05/12 14:37:41 $ */ diff --git a/src/tomcrypt/mac/hmac/hmac_process.c b/src/tomcrypt/mac/hmac/hmac_process.c new file mode 100644 index 00000000..bf6b291f --- /dev/null +++ b/src/tomcrypt/mac/hmac/hmac_process.c @@ -0,0 +1,43 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file hmac_process.c + LTC_HMAC support, process data, Tom St Denis/Dobes Vandermeer +*/ + +#ifdef LTC_HMAC + +/** + Process data through LTC_HMAC + @param hmac The hmac state + @param in The data to send through LTC_HMAC + @param inlen The length of the data to LTC_HMAC (octets) + @return CRYPT_OK if successful +*/ +int hmac_process(hmac_state *hmac, const unsigned char *in, unsigned long inlen) +{ + int err; + LTC_ARGCHK(hmac != NULL); + LTC_ARGCHK(in != NULL); + if ((err = hash_is_valid(hmac->hash)) != CRYPT_OK) { + return err; + } + return hash_descriptor[hmac->hash].process(&hmac->md, in, inlen); +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/mac/hmac/hmac_process.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2007/05/12 14:37:41 $ */ diff --git a/src/tomcrypt/mac/hmac/hmac_test.c b/src/tomcrypt/mac/hmac/hmac_test.c new file mode 100644 index 00000000..8a3eb47a --- /dev/null +++ b/src/tomcrypt/mac/hmac/hmac_test.c @@ -0,0 +1,316 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file hmac_test.c + LTC_HMAC support, self-test, Tom St Denis/Dobes Vandermeer +*/ + +#ifdef LTC_HMAC + +#define LTC_HMAC_BLOCKSIZE hash_descriptor[hash].blocksize + +/* + TEST CASES SOURCE: + +Network Working Group P. Cheng +Request for Comments: 2202 IBM +Category: Informational R. Glenn + NIST + September 1997 + Test Cases for LTC_HMAC-LTC_MD5 and LTC_HMAC-LTC_SHA-1 +*/ + +/** + LTC_HMAC self-test + @return CRYPT_OK if successful, CRYPT_NOP if tests have been disabled. +*/ +int hmac_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + unsigned char digest[MAXBLOCKSIZE]; + int i; + + static const struct hmac_test_case { + int num; + char *algo; + unsigned char key[128]; + unsigned long keylen; + unsigned char data[128]; + unsigned long datalen; + unsigned char digest[MAXBLOCKSIZE]; + } cases[] = { + /* + 3. Test Cases for LTC_HMAC-LTC_SHA-1 + + test_case = 1 + key = 0x0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c + key_len = 20 + data = "Hi Ther 20 + digest = 0x4c1a03424b55e07fe7f27be1d58bb9324a9a5a04 + digest-96 = 0x4c1a03424b55e07fe7f27be1 + */ + { 5, "sha1", + {0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c}, 20, + "Test With Truncation", 20, + {0x4c, 0x1a, 0x03, 0x42, 0x4b, 0x55, 0xe0, 0x7f, 0xe7, 0xf2, + 0x7b, 0xe1, 0xd5, 0x8b, 0xb9, 0x32, 0x4a, 0x9a, 0x5a, 0x04} }, + + /* + test_case = 6 + key = 0xaa repeated 80 times + key_len = 80 + data = "Test Using Larger Than Block-Size Key - Hash Key First" + data_len = 54 + digest = 0xaa4ae5e15272d00e95705637ce8a3b55ed402112 + */ + { 6, "sha1", + {0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa}, 80, + "Test Using Larger Than Block-Size Key - Hash Key First", 54, + {0xaa, 0x4a, 0xe5, 0xe1, 0x52, 0x72, 0xd0, 0x0e, + 0x95, 0x70, 0x56, 0x37, 0xce, 0x8a, 0x3b, 0x55, + 0xed, 0x40, 0x21, 0x12} }, + + /* + test_case = 7 + key = 0xaa repeated 80 times + key_len = 80 + data = "Test Using Larger Than Block-Size Key and Larger + Than One Block-Size Data" + data_len = 73 + digest = 0xe8e99d0f45237d786d6bbaa7965c7808bbff1a91 + */ + { 7, "sha1", + {0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa}, 80, + "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", 73, + {0xe8, 0xe9, 0x9d, 0x0f, 0x45, 0x23, 0x7d, 0x78, 0x6d, + 0x6b, 0xba, 0xa7, 0x96, 0x5c, 0x78, 0x08, 0xbb, 0xff, 0x1a, 0x91} }, + + /* + 2. Test Cases for LTC_HMAC-LTC_MD5 + + test_case = 1 + key = 0x0b 0b 0b 0b + 0b 0b 0b 0b + 0b 0b 0b 0b + 0b 0b 0b 0b + key_len = 16 + data = "Hi There" + data_len = 8 + digest = 0x92 94 72 7a + 36 38 bb 1c + 13 f4 8e f8 + 15 8b fc 9d + */ + { 1, "md5", + {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b}, 16, + "Hi There", 8, + {0x92, 0x94, 0x72, 0x7a, 0x36, 0x38, 0xbb, 0x1c, + 0x13, 0xf4, 0x8e, 0xf8, 0x15, 0x8b, 0xfc, 0x9d} }, + /* + test_case = 2 + key = "Jefe" + key_len = 4 + data = "what do ya want for nothing?" + data_len = 28 + digest = 0x750c783e6ab0b503eaa86e310a5db738 + */ + { 2, "md5", + "Jefe", 4, + "what do ya want for nothing?", 28, + {0x75, 0x0c, 0x78, 0x3e, 0x6a, 0xb0, 0xb5, 0x03, + 0xea, 0xa8, 0x6e, 0x31, 0x0a, 0x5d, 0xb7, 0x38} }, + + /* + test_case = 3 + key = 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + key_len 16 + data = 0xdd repeated 50 times + data_len = 50 + digest = 0x56be34521d144c88dbb8c733f0e8b3f6 + */ + { 3, "md5", + {0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa}, 16, + {0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd}, 50, + {0x56, 0xbe, 0x34, 0x52, 0x1d, 0x14, 0x4c, 0x88, + 0xdb, 0xb8, 0xc7, 0x33, 0xf0, 0xe8, 0xb3, 0xf6} }, + /* + + test_case = 4 + key = 0x0102030405060708090a0b0c0d0e0f10111213141516171819 + key_len 25 + data = 0xcd repeated 50 times + data_len = 50 + digest = 0x697eaf0aca3a3aea3a75164746ffaa79 + */ + { 4, "md5", + {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, + 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, + 0x15, 0x16, 0x17, 0x18, 0x19}, 25, + {0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd}, 50, + {0x69, 0x7e, 0xaf, 0x0a, 0xca, 0x3a, 0x3a, 0xea, + 0x3a, 0x75, 0x16, 0x47, 0x46, 0xff, 0xaa, 0x79} }, + + + /* + + test_case = 5 + key = 0x0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c + key_len = 16 + data = "Test With Truncation" + data_len = 20 + digest = 0x56461ef2342edc00f9bab995690efd4c + digest-96 0x56461ef2342edc00f9bab995 + */ + { 5, "md5", + {0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c}, 16, + "Test With Truncation", 20, + {0x56, 0x46, 0x1e, 0xf2, 0x34, 0x2e, 0xdc, 0x00, + 0xf9, 0xba, 0xb9, 0x95, 0x69, 0x0e, 0xfd, 0x4c} }, + + /* + + test_case = 6 + key = 0xaa repeated 80 times + key_len = 80 + data = "Test Using Larger Than Block-Size Key - Hash +Key First" + data_len = 54 + digest = 0x6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd + */ + { 6, "md5", + {0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa}, 80, + "Test Using Larger Than Block-Size Key - Hash Key First", 54, + {0x6b, 0x1a, 0xb7, 0xfe, 0x4b, 0xd7, 0xbf, 0x8f, + 0x0b, 0x62, 0xe6, 0xce, 0x61, 0xb9, 0xd0, 0xcd} }, + + /* + + test_case = 7 + key = 0xaa repeated 80 times + key_len = 80 + data = "Test Using Larger Than Block-Size Key and Larger + Than One Block-Size Data" + data_len = 73 + digest = 0x6f630fad67cda0ee1fb1f562db3aa53e + */ + { 7, "md5", + {0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa}, 80, + "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", 73, + {0x6f, 0x63, 0x0f, 0xad, 0x67, 0xcd, 0xa0, 0xee, + 0x1f, 0xb1, 0xf5, 0x62, 0xdb, 0x3a, 0xa5, 0x3e} } + }; + + unsigned long outlen; + int err; + int tested=0,failed=0; + for(i=0; i < (int)(sizeof(cases) / sizeof(cases[0])); i++) { + int hash = find_hash(cases[i].algo); + if (hash == -1) continue; + ++tested; + outlen = sizeof(digest); + if((err = hmac_memory(hash, cases[i].key, cases[i].keylen, cases[i].data, cases[i].datalen, digest, &outlen)) != CRYPT_OK) { +#if 0 + printf("LTC_HMAC-%s test #%d, %s\n", cases[i].algo, cases[i].num, error_to_string(err)); +#endif + return err; + } + + if(XMEMCMP(digest, cases[i].digest, (size_t)hash_descriptor[hash].hashsize) != 0) { + failed++; +#if 0 + unsigned int j; + printf("\nLTC_HMAC-%s test #%d:\n", cases[i].algo, cases[i].num); + printf( "Result: 0x"); + for(j=0; j < hash_descriptor[hash].hashsize; j++) { + printf("%2x ", digest[j]); + } + printf("\nCorrect: 0x"); + for(j=0; j < hash_descriptor[hash].hashsize; j++) { + printf("%2x ", cases[i].digest[j]); + } + printf("\n"); + return CRYPT_ERROR; +#endif + } else { + /* printf("LTC_HMAC-%s test #%d: Passed\n", cases[i].algo, cases[i].num); */ + } + } + + if (failed != 0) { + return CRYPT_FAIL_TESTVECTOR; + } else if (tested == 0) { + return CRYPT_NOP; + } else { + return CRYPT_OK; + } + #endif +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/mac/hmac/hmac_test.c,v $ */ +/* $Revision: 1.10 $ */ +/* $Date: 2007/05/12 14:37:41 $ */ diff --git a/src/tomcrypt/misc/crypt/crypt_find_hash.c b/src/tomcrypt/misc/crypt/crypt_find_hash.c new file mode 100644 index 00000000..87eb8fff --- /dev/null +++ b/src/tomcrypt/misc/crypt/crypt_find_hash.c @@ -0,0 +1,40 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file crypt_find_hash.c + Find a hash, Tom St Denis +*/ + +/** + Find a registered hash by name + @param name The name of the hash to look for + @return >= 0 if found, -1 if not present +*/ +int find_hash(const char *name) +{ + int x; + LTC_ARGCHK(name != NULL); + LTC_MUTEX_LOCK(<c_hash_mutex); + for (x = 0; x < TAB_SIZE; x++) { + if (hash_descriptor[x].name != NULL && XSTRCMP(hash_descriptor[x].name, name) == 0) { + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return x; + } + } + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return -1; +} + +/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_find_hash.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/src/tomcrypt/misc/crypt/crypt_register_hash.c b/src/tomcrypt/misc/crypt/crypt_register_hash.c new file mode 100644 index 00000000..ffdba10f --- /dev/null +++ b/src/tomcrypt/misc/crypt/crypt_register_hash.c @@ -0,0 +1,54 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file crypt_register_hash.c + Register a HASH, Tom St Denis +*/ + +/** + Register a hash with the descriptor table + @param hash The hash you wish to register + @return value >= 0 if successfully added (or already present), -1 if unsuccessful +*/ +int register_hash(const struct ltc_hash_descriptor *hash) +{ + int x; + + LTC_ARGCHK(hash != NULL); + + /* is it already registered? */ + LTC_MUTEX_LOCK(<c_hash_mutex); + for (x = 0; x < TAB_SIZE; x++) { + if (XMEMCMP(&hash_descriptor[x], hash, sizeof(struct ltc_hash_descriptor)) == 0) { + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return x; + } + } + + /* find a blank spot */ + for (x = 0; x < TAB_SIZE; x++) { + if (hash_descriptor[x].name == NULL) { + XMEMCPY(&hash_descriptor[x], hash, sizeof(struct ltc_hash_descriptor)); + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return x; + } + } + + /* no spot */ + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return -1; +} + +/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_register_hash.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/src/tomcrypt/misc/crypt/crypt_unregister_hash.c b/src/tomcrypt/misc/crypt/crypt_unregister_hash.c new file mode 100644 index 00000000..34b88c04 --- /dev/null +++ b/src/tomcrypt/misc/crypt/crypt_unregister_hash.c @@ -0,0 +1,44 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file crypt_unregister_hash.c + Unregister a hash, Tom St Denis +*/ + +/** + Unregister a hash from the descriptor table + @param hash The hash descriptor to remove + @return CRYPT_OK on success +*/ +int unregister_hash(const struct ltc_hash_descriptor *hash) +{ + int x; + + LTC_ARGCHK(hash != NULL); + + /* is it already registered? */ + LTC_MUTEX_LOCK(<c_hash_mutex); + for (x = 0; x < TAB_SIZE; x++) { + if (XMEMCMP(&hash_descriptor[x], hash, sizeof(struct ltc_hash_descriptor)) == 0) { + hash_descriptor[x].name = NULL; + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return CRYPT_OK; + } + } + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return CRYPT_ERROR; +} + +/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_unregister_hash.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2006/12/28 01:27:24 $ */ diff --git a/src/tomcrypt/misc/pkcs5/pkcs_5_2.c b/src/tomcrypt/misc/pkcs5/pkcs_5_2.c new file mode 100644 index 00000000..26b624ad --- /dev/null +++ b/src/tomcrypt/misc/pkcs5/pkcs_5_2.c @@ -0,0 +1,129 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include + +/** + @file pkcs_5_2.c + LTC_PKCS #5, Algorithm #2, Tom St Denis +*/ +#ifdef LTC_PKCS_5 + +/** + Execute LTC_PKCS #5 v2 + @param password The input password (or key) + @param password_len The length of the password (octets) + @param salt The salt (or nonce) + @param salt_len The length of the salt (octets) + @param iteration_count # of iterations desired for LTC_PKCS #5 v2 [read specs for more] + @param hash_idx The index of the hash desired + @param out [out] The destination for this algorithm + @param outlen [in/out] The max size and resulting size of the algorithm output + @return CRYPT_OK if successful +*/ +int pkcs_5_alg2(const unsigned char *password, unsigned long password_len, + const unsigned char *salt, unsigned long salt_len, + int iteration_count, int hash_idx, + unsigned char *out, unsigned long *outlen) +{ + int err, itts; + ulong32 blkno; + unsigned long stored, left, x, y; + unsigned char *buf[2]; + hmac_state *hmac; + + LTC_ARGCHK(password != NULL); + LTC_ARGCHK(salt != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* test hash IDX */ + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + return err; + } + + buf[0] = XMALLOC(MAXBLOCKSIZE * 2); + hmac = XMALLOC(sizeof(hmac_state)); + if (hmac == NULL || buf[0] == NULL) { + if (hmac != NULL) { + XFREE(hmac); + } + if (buf[0] != NULL) { + XFREE(buf[0]); + } + return CRYPT_MEM; + } + /* buf[1] points to the second block of MAXBLOCKSIZE bytes */ + buf[1] = buf[0] + MAXBLOCKSIZE; + + left = *outlen; + blkno = 1; + stored = 0; + while (left != 0) { + /* process block number blkno */ + zeromem(buf[0], MAXBLOCKSIZE*2); + + /* store current block number and increment for next pass */ + STORE32H(blkno, buf[1]); + ++blkno; + + /* get PRF(P, S||int(blkno)) */ + if ((err = hmac_init(hmac, hash_idx, password, password_len)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = hmac_process(hmac, salt, salt_len)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = hmac_process(hmac, buf[1], 4)) != CRYPT_OK) { + goto LBL_ERR; + } + x = MAXBLOCKSIZE; + if ((err = hmac_done(hmac, buf[0], &x)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* now compute repeated and XOR it in buf[1] */ + XMEMCPY(buf[1], buf[0], x); + for (itts = 1; itts < iteration_count; ++itts) { + if ((err = hmac_memory(hash_idx, password, password_len, buf[0], x, buf[0], &x)) != CRYPT_OK) { + goto LBL_ERR; + } + for (y = 0; y < x; y++) { + buf[1][y] ^= buf[0][y]; + } + } + + /* now emit upto x bytes of buf[1] to output */ + for (y = 0; y < x && left != 0; ++y) { + out[stored++] = buf[1][y]; + --left; + } + } + *outlen = stored; + + err = CRYPT_OK; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(buf[0], MAXBLOCKSIZE*2); + zeromem(hmac, sizeof(hmac_state)); +#endif + + XFREE(hmac); + XFREE(buf[0]); + + return err; +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/misc/pkcs5/pkcs_5_2.c,v $ */ +/* $Revision: 1.7 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/src/version.h b/src/version.h index b994be1b..01696d2d 100644 --- a/src/version.h +++ b/src/version.h @@ -1,2 +1,2 @@ #include "version_build.h" -#define SYS_COMMONVERSION 15.8 \ No newline at end of file +#define SYS_COMMONVERSION 15.9 \ No newline at end of file diff --git a/src/version_build.h b/src/version_build.h index 58c68f26..60df8ee3 100644 --- a/src/version_build.h +++ b/src/version_build.h @@ -1 +1 @@ -#define BUILD_NUMBER 1105 +#define BUILD_NUMBER 1379 diff --git a/src/xassets.c b/src/xassets.c index b16b7603..e80c51be 100644 --- a/src/xassets.c +++ b/src/xassets.c @@ -90,7 +90,7 @@ typedef enum{ XModelPieces, PhysPreset, XAnimParts, - XModel, + XModel, Material, TechinqueSet, // techset GfxImage, // image @@ -216,7 +216,7 @@ qboolean DB_XAssetNoAlloc(XAssetType_t i) return qtrue; if(i == StringTable) return qtrue; - + return qfalse; } @@ -274,33 +274,33 @@ void DB_ParseRequestedXAssetNum() Com_Memcpy(XAssetRequestedCount, XAssetStdCount, sizeof(XAssetRequestedCount)); Com_sprintf(toparse, sizeof(toparse), " %s", r_xassetnum->string); - + for(i = 0; i < NumXAssets; ++i) - { + { if(DB_XAssetNoAlloc(i) || i == menuDef_t || i == WeaponDef || i == StringTable) { continue; } - + typename = DB_GetXAssetTypeName[ i ]; - + Com_sprintf(scanstring, sizeof(scanstring), " %s=", typename); - + scanpos = strstr(toparse, scanstring); if(scanpos == NULL) { continue; } - + scanpos += strlen(scanstring); - + count = atoi(scanpos); if(count < 1 || count > 65535) { continue; } - + if(count <= DB_GetXAssetStdCount(i)) { continue; @@ -327,9 +327,9 @@ void DB_CustomAllocOnce(XAssetType_t type) void DB_RelocateXAssetMem() { int i, typesize, count; - + void* newmem; - + for(i = 0; i < NumXAssets; ++i) { if(DB_XAssetNoAlloc(i)) @@ -342,12 +342,12 @@ void DB_RelocateXAssetMem() //Only allocate if we need more than what is already allocated continue; } - + count = XAssetRequestedCount[i]; typesize = DB_GetXAssetTypeSize(i); - + newmem = Z_Malloc(count * typesize); - + if(newmem == NULL) { continue; @@ -407,7 +407,7 @@ typedef struct unsigned int size; }XBlock; -typedef struct +typedef struct { XBlock blocks[9]; int allocVertexBuffer; @@ -485,19 +485,19 @@ void DB_UnloadXAssetsMemoryForZone(byte freeflags) { byte bitmask; int i; - + for(bitmask = 64; bitmask > 0 ; bitmask >>= 1) { if(bitmask == 2) bitmask >>= 1; - + if(!(freeflags & bitmask)) continue; //DB_UnloadXAssetsMemory() inlined here for ( i = g_zoneCount - 1; i >= 0; --i ) { - + if ( g_zones[g_zoneHandles[i]].zoneinfo.flags & bitmask ) { DB_UnloadXAssetsMemoryInternal(&g_zones[g_zoneHandles[i]]); @@ -539,12 +539,20 @@ void DB_LoadXAssets_Hook(XZoneInfo *zoneinfo, unsigned int assetscount) int DB_FileSize(const char *filename, int FF_DIR) { char ospath[MAX_OSPATH]; - + DB_BuildOSPath(filename, FF_DIR, sizeof(ospath), ospath); - + return FS_filelengthForOSPath(ospath); } +qboolean DB_FileExists(const char* filename, int FF_DIR) +{ + char ospath[MAX_OSPATH]; + + DB_BuildOSPath(filename, FF_DIR, sizeof(ospath), ospath); + + return FS_FileExistsOSPath(ospath); +} void DB_ReferencedFastFiles(char* g_zoneSumList, char* g_zoneNameList, int maxsize) { @@ -563,27 +571,39 @@ void DB_ReferencedFastFiles(char* g_zoneSumList, char* g_zoneNameList, int maxsi { continue; } + + if ( zone->ff_dir == 1 ) + { + if ( g_zoneNameList[0] ) + { + Q_strcat(g_zoneNameList, maxsize, " "); + } + Q_strcat(g_zoneNameList, maxsize, fs_gameDirVar->string); + Q_strcat(g_zoneNameList, maxsize, "/"); + Q_strcat(g_zoneNameList, maxsize, zone->zoneinfo.name); if ( g_zoneSumList[0] ) { Q_strcat(g_zoneSumList, maxsize, " "); } - if ( g_zoneNameList[0] ) - { - Q_strcat(g_zoneNameList, maxsize, " "); - } Com_sprintf(checkSum, sizeof(checkSum), "%u", zone->zoneSize); Q_strcat(g_zoneSumList, maxsize, checkSum); - - if ( zone->ff_dir == 1 ) - { - Q_strcat(g_zoneNameList, maxsize, fs_gameDirVar->string); - Q_strcat(g_zoneNameList, maxsize, "/"); - Q_strcat(g_zoneNameList, maxsize, zone->zoneinfo.name); + continue; - } + } if ( zone->ff_dir != 2 ) { - Q_strcat(g_zoneNameList, maxsize, zone->zoneinfo.name); + if ( g_zoneNameList[0] ) + { + Q_strcat(g_zoneNameList, maxsize, " "); + } + Q_strcat(g_zoneNameList, maxsize, zone->zoneinfo.name); + if ( g_zoneSumList[0] ) + { + Q_strcat(g_zoneSumList, maxsize, " "); + } + Com_sprintf(checkSum, sizeof(checkSum), "%u", zone->zoneSize); + Q_strcat(g_zoneSumList, maxsize, checkSum); + continue; } @@ -600,18 +620,17 @@ void DB_ReferencedFastFiles(char* g_zoneSumList, char* g_zoneNameList, int maxsi continue; } - Q_strcat(g_zoneNameList, maxsize, " "); - Q_strcat(g_zoneNameList, maxsize, "usermaps"); - Q_strcat(g_zoneNameList, maxsize, "/"); - Q_strcat(g_zoneNameList, maxsize, zone->zoneinfo.name); + if ( g_zoneSumList[0] ) + { + Q_strcat(g_zoneSumList, maxsize, " "); + } + Com_sprintf(checkSum, sizeof(checkSum), "%u %u", zone->zoneSize, filesize); + Q_strcat(g_zoneSumList, maxsize, checkSum); - Q_strcat(g_zoneSumList, maxsize, " "); - Com_sprintf(checkSum, sizeof(checkSum), "%u", filesize); - Q_strcat(g_zoneSumList, maxsize, checkSum); - Q_strcat(g_zoneNameList, maxsize, " "); - Q_strcat(g_zoneNameList, maxsize, "usermaps"); - Q_strcat(g_zoneNameList, maxsize, "/"); + Q_strcat(g_zoneNameList, maxsize, " usermaps/"); + Q_strcat(g_zoneNameList, maxsize, zone->zoneinfo.name); + Q_strcat(g_zoneNameList, maxsize, " usermaps/"); Q_strcat(g_zoneNameList, maxsize, zone->zoneinfo.name); Q_strcat(g_zoneNameList, maxsize, "_load"); @@ -634,20 +653,20 @@ void DB_EnumXAssets(XAssetType_t type, void (__cdecl *callback)(XAssetHeader_t * { for(index = db_hashTable[i]; index; index = listselector->nextListIndex) { - listselector = &g_assetEntryPool[index]; + listselector = &g_assetEntryPool[index]; - if ( listselector->this.type != type ) - continue; - - callback(listselector->header, cbargs); - if ( !a4 ) - continue; - - for(sindex = listselector->field_C; sindex; sindex = slistselect->field_C) - { - slistselect = &g_assetEntryPool[sindex]; - callback(slistselect->header, cbargs); - } + if ( listselector->this.type != type ) + continue; + + callback(listselector->header, cbargs); + if ( !a4 ) + continue; + + for(sindex = listselector->field_C; sindex; sindex = slistselect->field_C) + { + slistselect = &g_assetEntryPool[sindex]; + callback(slistselect->header, cbargs); + } } } /* @@ -711,7 +730,7 @@ void DB_CountXAssets(int *count, int len ,qboolean a4) if ( !a4 ) continue; - + for(sindex = listselector->field_C; sindex; sindex = slistselect->field_C) { slistselect = &g_assetEntryPool[sindex]; @@ -852,4 +871,4 @@ char g_zoneNameList[2080]; #if 0 -#endif \ No newline at end of file +#endif diff --git a/src/xassets.h b/src/xassets.h index cae8ec3a..0368208a 100644 --- a/src/xassets.h +++ b/src/xassets.h @@ -45,7 +45,7 @@ typedef struct void R_Init(); void __cdecl DB_SetInitializing(qboolean); -byte __cdecl DB_FileExists(const char* filename, int mode); +qboolean __cdecl DB_FileExists(const char* filename, int mode); qboolean __cdecl DB_ModFileExists(void); void __cdecl DB_LoadXAssets(XZoneInfo*, unsigned int assetscount, int); int __cdecl DB_GetXAssetTypeSize(int type); diff --git a/src/xassets_hooks.asm b/src/xassets_hooks.asm index b0b35c7b..4e3520fd 100644 --- a/src/xassets_hooks.asm +++ b/src/xassets_hooks.asm @@ -35,10 +35,6 @@ global DB_SetInitializing DB_SetInitializing: jmp dword [oDB_SetInitializing] -global DB_FileExists -DB_FileExists: - jmp dword [oDB_FileExists] - global DB_ModFileExists DB_ModFileExists: jmp dword [oDB_ModFileExists] @@ -75,7 +71,6 @@ BG_FillInAllWeaponItems: SECTION .rodata oDB_SetInitializing dd 0x820337c -oDB_FileExists dd 0x8204424 oDB_ModFileExists dd 0x8204470 oDB_LoadXAssets dd 0x8205e86 oDB_GetXAssetTypeSize dd 0x81da6ce