void Dynvar_CallListeners( dynvar_t *dynvar, void *value ) { dynvar_listener_node_t *n; dynvar->listeners_immutable = qtrue; // protect against concurrent Dynvar_RemoveListener // call listeners for( n = dynvar->listeners; n; n = n->next ) { assert( n->listener ); n->listener( value ); } dynvar->listeners_immutable = qfalse; // allow Dynvar_RemoveListener to modify dynvar->listeners // perform pending removals if( dynvar->to_remove ) { dynvar_listener_node_t *n, *prev = NULL; for( n = dynvar->to_remove; n; n = n->next ) { Dynvar_RemoveListener( dynvar, n->listener ); Mem_ZoneFree( prev ); prev = n; } Mem_ZoneFree( prev ); dynvar->to_remove = NULL; } }
/* * CL_MouseFilterBufferSizeSet_f */ static dynvar_set_status_t CL_MouseFilterBufferSizeSet_f( void *size ) { static const unsigned int MIN_SIZE = 1; static const unsigned int MAX_SIZE = 32; // more is pointless (probably anything more than 5) const unsigned int desiredSize = atoi( (char *) size ); if( desiredSize >= MIN_SIZE && desiredSize <= MAX_SIZE ) { // reallocate buffer if( m_filter->integer != M_FILTER_EXTRAPOLATE ) Com_Printf( "Warning: \"m_filterBufferSize\" has no effect unless \"m_filter " M_DOUBLEQUOTE( M_FILTER_EXTRAPOLATE ) "\" is set.\n" ); Mem_ZoneFree( buf_x ); Mem_ZoneFree( buf_y ); buf_x = (float *) Mem_ZoneMalloc( sizeof( float ) * desiredSize ); buf_y = (float *) Mem_ZoneMalloc( sizeof( float ) * desiredSize ); // reset to 0 memset( buf_x, 0, sizeof( float ) * desiredSize ); memset( buf_y, 0, sizeof( float ) * desiredSize ); buf_size = desiredSize; return DYNVAR_SET_OK; } else { Com_Printf( "\"m_filterBufferSize\" must be between \"%d\" and \"%d\".\n", MIN_SIZE, MAX_SIZE ); return DYNVAR_SET_INVALID; } }
/* * CL_StopServerDownload */ void CL_StopServerDownload( void ) { if( cls.download.filenum > 0 ) { FS_FCloseFile( cls.download.filenum ); cls.download.filenum = 0; } if( cls.download.cancelled ) { FS_RemoveBaseFile( cls.download.tempname ); } Mem_ZoneFree( cls.download.name ); cls.download.name = NULL; Mem_ZoneFree( cls.download.tempname ); cls.download.tempname = NULL; cls.download.offset = 0; cls.download.size = 0; cls.download.percent = 0; cls.download.timeout = 0; cls.download.retries = 0; cls.download.web = qfalse; Cvar_ForceSet( "cl_download_name", "" ); Cvar_ForceSet( "cl_download_percent", "0" ); }
/* * SV_Demo_Stop */ static void SV_Demo_Stop( bool cancel, bool silent ) { if( !svs.demo.file ) { if( !silent ) { Com_Printf( "No server demo recording in progress\n" ); } return; } if( cancel ) { Com_Printf( "Canceled server demo recording: %s\n", svs.demo.filename ); } else { SNAP_StopDemoRecording( svs.demo.file ); Com_Printf( "Stopped server demo recording: %s\n", svs.demo.filename ); } FS_FCloseFile( svs.demo.file ); svs.demo.file = 0; if( cancel ) { if( !FS_RemoveFile( svs.demo.tempname ) ) Com_Printf( "Error: Failed to delete the temporary server demo file\n" ); } else { // write some meta information about the match/demo SV_SetDemoMetaKeyValue( "hostname", sv.configstrings[CS_HOSTNAME] ); SV_SetDemoMetaKeyValue( "localtime", va( "%u", svs.demo.localtime ) ); SV_SetDemoMetaKeyValue( "multipov", "1" ); SV_SetDemoMetaKeyValue( "duration", va( "%u", (int)ceil( svs.demo.duration/1000.0f ) ) ); SV_SetDemoMetaKeyValue( "mapname", sv.configstrings[CS_MAPNAME] ); SV_SetDemoMetaKeyValue( "gametype", sv.configstrings[CS_GAMETYPENAME] ); SV_SetDemoMetaKeyValue( "levelname", sv.configstrings[CS_MESSAGE] ); SV_SetDemoMetaKeyValue( "matchname", sv.configstrings[CS_MATCHNAME] ); SV_SetDemoMetaKeyValue( "matchscore", sv.configstrings[CS_MATCHSCORE] ); SV_SetDemoMetaKeyValue( "matchuuid", sv.configstrings[CS_MATCHUUID] ); SNAP_WriteDemoMetaData( svs.demo.tempname, svs.demo.meta_data, svs.demo.meta_data_realsize ); if( !FS_MoveFile( svs.demo.tempname, svs.demo.filename ) ) Com_Printf( "Error: Failed to rename the server demo file\n" ); } svs.demo.localtime = 0; svs.demo.basetime = svs.demo.duration = 0; SNAP_FreeClientFrames( &svs.demo.client ); Mem_ZoneFree( svs.demo.filename ); svs.demo.filename = NULL; Mem_ZoneFree( svs.demo.tempname ); svs.demo.tempname = NULL; }
/* * TV_Upstream_StopDemoRecord */ void TV_Upstream_StopDemoRecord( upstream_t *upstream, qboolean silent, qboolean cancel ) { assert( upstream ); if( !upstream->demo.recording ) { if( !silent ) Com_Printf( "Not recording a demo.\n" ); return; } // finish up SNAP_StopDemoRecording( upstream->demo.filehandle ); FS_FCloseFile( upstream->demo.filehandle ); // cancel the demos if( cancel ) { // remove the file that correspond to cls.demo.file if( !silent ) Com_Printf( "Canceling demo: %s\n", upstream->demo.filename ); if( !FS_RemoveFile( upstream->demo.tempname ) && !silent ) Com_Printf( "Error canceling demo." ); } else { // write some meta information about the match/demo TV_Upstream_SetDemoMetaKeyValue( upstream, "hostname", upstream->configstrings[CS_HOSTNAME] ); TV_Upstream_SetDemoMetaKeyValue( upstream, "localtime", va( "%u", upstream->demo.localtime ) ); TV_Upstream_SetDemoMetaKeyValue( upstream, "multipov", "1" ); TV_Upstream_SetDemoMetaKeyValue( upstream, "duration", va( "%u", (int)ceil( upstream->demo.duration/1000.0f ) ) ); TV_Upstream_SetDemoMetaKeyValue( upstream, "mapname", upstream->configstrings[CS_MAPNAME] ); TV_Upstream_SetDemoMetaKeyValue( upstream, "gametype", upstream->configstrings[CS_GAMETYPENAME] ); TV_Upstream_SetDemoMetaKeyValue( upstream, "levelname", upstream->configstrings[CS_MESSAGE] ); TV_Upstream_SetDemoMetaKeyValue( upstream, "matchname", upstream->configstrings[CS_MATCHNAME] ); TV_Upstream_SetDemoMetaKeyValue( upstream, "matchscore", upstream->configstrings[CS_MATCHSCORE] ); TV_Upstream_SetDemoMetaKeyValue( upstream, "matchuuid", upstream->configstrings[CS_MATCHUUID] ); SNAP_WriteDemoMetaData( upstream->demo.tempname, upstream->demo.meta_data, upstream->demo.meta_data_realsize ); if( !FS_MoveFile( upstream->demo.tempname, upstream->demo.filename ) ) Com_Printf( "Error: Failed to rename the demo file\n" ); } if( !silent ) Com_Printf( "Stopped demo: %s\n", upstream->demo.filename ); upstream->demo.filehandle = 0; // file id Mem_ZoneFree( upstream->demo.filename ); upstream->demo.filename = NULL; Mem_ZoneFree( upstream->demo.tempname ); upstream->demo.tempname = NULL; upstream->demo.recording = qfalse; upstream->demo.autorecording = qfalse; }
/* * CL_FreeDownloadList */ void CL_FreeDownloadList( void ) { download_list_t *next; while( cls.download.list ) { next = cls.download.list->next; Mem_ZoneFree( cls.download.list->filename ); Mem_ZoneFree( cls.download.list ); cls.download.list = next; } }
static void Dynvar_FreeDynvar( dynvar_t *dynvar ) { dynvar_listener_node_t *next, *cur; cur = dynvar->listeners; for( cur = dynvar->listeners; cur; cur = next ) { next = cur->next; Mem_ZoneFree( cur ); } Mem_ZoneFree( (char *) dynvar->name ); Mem_ZoneFree( dynvar ); }
/* * CL_ShutdownInput */ void CL_ShutdownInput( void ) { if( !in_initialized ) return; Cmd_RemoveCommand( "in_restart" ); IN_Shutdown(); Cmd_RemoveCommand( "centerview" ); Cmd_RemoveCommand( "+moveup" ); Cmd_RemoveCommand( "-moveup" ); Cmd_RemoveCommand( "+movedown" ); Cmd_RemoveCommand( "-movedown" ); Cmd_RemoveCommand( "+left" ); Cmd_RemoveCommand( "-left" ); Cmd_RemoveCommand( "+right" ); Cmd_RemoveCommand( "-right" ); Cmd_RemoveCommand( "+forward" ); Cmd_RemoveCommand( "-forward" ); Cmd_RemoveCommand( "+back" ); Cmd_RemoveCommand( "-back" ); Cmd_RemoveCommand( "+lookup" ); Cmd_RemoveCommand( "-lookup" ); Cmd_RemoveCommand( "+lookdown" ); Cmd_RemoveCommand( "-lookdown" ); Cmd_RemoveCommand( "+strafe" ); Cmd_RemoveCommand( "-strafe" ); Cmd_RemoveCommand( "+moveleft" ); Cmd_RemoveCommand( "-moveleft" ); Cmd_RemoveCommand( "+moveright" ); Cmd_RemoveCommand( "-moveright" ); Cmd_RemoveCommand( "+speed" ); Cmd_RemoveCommand( "-speed" ); Cmd_RemoveCommand( "+attack" ); Cmd_RemoveCommand( "-attack" ); Cmd_RemoveCommand( "+use" ); Cmd_RemoveCommand( "-use" ); Cmd_RemoveCommand( "+klook" ); Cmd_RemoveCommand( "-klook" ); // wsw Cmd_RemoveCommand( "+special" ); Cmd_RemoveCommand( "-special" ); Cmd_RemoveCommand( "+zoom" ); Cmd_RemoveCommand( "-zoom" ); Dynvar_Destroy( Dynvar_Lookup( "m_filterBufferDecay" ) ); Dynvar_Destroy( Dynvar_Lookup( "m_filterBufferSize" ) ); Mem_ZoneFree( buf_x ); Mem_ZoneFree( buf_y ); in_initialized = true; }
/* * IN_RawInput_Shutdown */ static void IN_RawInput_Shutdown( void ) { if( rawmicecount < 1 ) { return; } IN_RawInput_DeRegister(); Mem_ZoneFree( rawmice ); Mem_ZoneFree( raw ); // dealloc mouse structure rawmicecount = 0; }
/* * SV_ReloadPureList */ static void SV_ReloadPureList( void ) { char **paks; int i, numpaks; Com_FreePureList( &svs.purelist ); // game modules if( sv_pure_forcemodulepk3->string[0] ) { if( Q_strnicmp( COM_FileBase( sv_pure_forcemodulepk3->string ), "modules", strlen( "modules" ) ) || !FS_IsPakValid( sv_pure_forcemodulepk3->string, NULL ) ) { Com_Printf( "Warning: Invalid value for sv_pure_forcemodulepk3, disabling\n" ); Cvar_ForceSet( "sv_pure_forcemodulepk3", "" ); } else { SV_AddPurePak( sv_pure_forcemodulepk3->string ); } } if( !sv_pure_forcemodulepk3->string[0] ) { char *libname; int libname_size; libname_size = strlen( LIB_PREFIX ) + 5 + strlen( ARCH ) + strlen( LIB_SUFFIX ) + 1; libname = Mem_TempMalloc( libname_size ); Q_snprintfz( libname, libname_size, LIB_PREFIX "game_" ARCH LIB_SUFFIX ); if( !FS_PakNameForFile( libname ) ) { if( sv_pure->integer ) { Com_Printf( "Warning: Game module not in pk3, disabling pure mode\n" ); Com_Printf( "sv_pure_forcemodulepk3 can be used to force the pure system to use a different module\n" ); Cvar_ForceSet( "sv_pure", "0" ); } } else { SV_AddPureFile( libname ); } Mem_TempFree( libname ); libname = NULL; } // *pure.(pk3|pak) paks = NULL; numpaks = FS_GetExplicitPurePakList( &paks ); if( numpaks ) { for( i = 0; i < numpaks; i++ ) { SV_AddPurePak( paks[i] ); Mem_ZoneFree( paks[i] ); } Mem_ZoneFree( paks ); } }
/* * Cvar_GetLatchedVars * * Any variables with CVAR_LATCHED will now be updated */ void Cvar_GetLatchedVars( cvar_flag_t flags ) { unsigned int i; struct trie_dump_s *dump; cvar_flag_t latchFlags; Cvar_FlagsClear( &latchFlags ); Cvar_FlagSet( &latchFlags, CVAR_LATCH ); Cvar_FlagSet( &latchFlags, CVAR_LATCH_VIDEO ); Cvar_FlagSet( &latchFlags, CVAR_LATCH_SOUND ); Cvar_FlagUnset( &flags, ~latchFlags ); if( !flags ) return; assert( cvar_trie ); Trie_DumpIf( cvar_trie, "", TRIE_DUMP_VALUES, Cvar_IsLatched, &flags, &dump ); for( i = 0; i < dump->size; ++i ) { cvar_t *const var = (cvar_t *) dump->key_value_vector[i].value; if( !strcmp( var->name, "fs_game" ) ) { FS_SetGameDirectory( var->latched_string, qfalse ); return; } Mem_ZoneFree( var->string ); var->string = var->latched_string; var->latched_string = NULL; var->value = atof( var->string ); var->integer = Q_rint( var->value ); } Trie_FreeDump( dump ); }
/* * CL_DownloadDone */ void CL_DownloadDone( void ) { qboolean requestnext; Mem_ZoneFree( cls.download.requestname ); cls.download.requestname = NULL; requestnext = cls.download.requestnext; cls.download.requestnext = qfalse; cls.download.requestpak = qfalse; cls.download.timeout = 0; cls.download.timestart = 0; cls.download.offset = cls.download.baseoffset = 0; cls.download.web = qfalse; cls.download.filenum = 0; cls.download.cancelled = qfalse; // the server has changed map during the download if( cls.download.pending_reconnect ) { cls.download.pending_reconnect = qfalse; CL_FreeDownloadList(); CL_ServerReconnect_f(); return; } if( requestnext && cls.state > CA_DISCONNECTED ) CL_RequestNextDownload(); }
/* * ML_Shutdown * Free map list memory */ void ML_Shutdown( void ) { mapinfo_t *map; if( !ml_initialized ) return; ML_BuildCache(); ml_initialized = false; Cmd_RemoveCommand( "maplist" ); Trie_Destroy( mlist_filenames_trie ); Trie_Destroy( mlist_fullnames_trie ); while( maplist ) { map = maplist; maplist = map->next; Mem_ZoneFree( map ); } ml_flush = true; }
void SV_ClientCloseDownload( client_t *client ) { if( client->download.file ) FS_FCloseFile( client->download.file ); if( client->download.name ) Mem_ZoneFree( client->download.name ); memset( &client->download, 0, sizeof( client->download ) ); }
/* * CL_FreeServerlist */ static void CL_FreeServerlist( serverlist_t **serversList ) { serverlist_t *ptr; while( *serversList ) { ptr = *serversList; *serversList = ptr->pnext; Mem_ZoneFree( ptr ); } }
void free_word_hash_table( WORD_HASH_TABLE *table_ptr) { struct swline **hash_array = table_ptr->hash_array; if ( !hash_array ) return; Mem_ZoneFree((MEM_ZONE **)&table_ptr->mem_zone); table_ptr->hash_array = NULL; table_ptr->hash_size = 0; table_ptr->count = 0; }
/* * CL_MasterAddressCache_Shutdown */ static void CL_MasterAddressCache_Shutdown( void ) { masteradrcache_t *next; // free allocated memory Trie_Destroy( serverlist_masters_trie ); while( serverlist_masters_head ) { next = serverlist_masters_head->next; Mem_ZoneFree( serverlist_masters_head ); serverlist_masters_head = next; } }
/* * NET_Shutdown */ void NET_Shutdown( void ) { if( !net_initialized ) return; if( errorstring ) { Mem_ZoneFree( errorstring ); errorstring = NULL; errorstring_size = 0; } Sys_NET_Shutdown(); net_initialized = qfalse; }
/* * NET_SetErrorString */ void NET_SetErrorString( const char *format, ... ) { va_list argptr; char msg[MAX_PRINTMSG]; va_start( argptr, format ); Q_vsnprintfz( msg, sizeof( msg ), format, argptr ); va_end( argptr ); if( errorstring_size < strlen( msg ) + 1 ) { if( errorstring ) Mem_ZoneFree( errorstring ); errorstring_size = strlen( msg ) + 1 + 64; errorstring = ( char* )Mem_ZoneMalloc( errorstring_size ); } Q_strncpyz( errorstring, msg, errorstring_size ); }
void Dynvar_RemoveListener( dynvar_t *dynvar, dynvar_listener_f listener ) { assert( dynvar ); assert( listener ); if( !dynvar->listeners_immutable ) { // modification of dynvar->listeners allowed dynvar_listener_node_t *cur, *prev; prev = NULL; cur = dynvar->listeners; while( cur ) { if( cur->listener == listener ) { if( prev ) { // remove middle or tail node prev->next = cur->next; } else { // remove head node assert( cur == dynvar->listeners ); dynvar->listeners = cur->next; } Mem_ZoneFree( cur ); break; // remove only one instance } prev = cur; cur = cur->next; } } else { // do not modify dynvar->listeners, but prepend to dynvar->to_remove for deferred removal dynvar->to_remove = Dynvar_NewListener( listener, dynvar->to_remove ); } }
/* * Cvar_FixCheatVars * * All cheat variables with be reset to default unless cheats are allowed */ void Cvar_FixCheatVars( void ) { struct trie_dump_s *dump; unsigned int i; cvar_flag_t flags = CVAR_CHEAT; if( Cvar_CheatsAllowed() ) return; assert( cvar_trie ); Trie_DumpIf( cvar_trie, "", TRIE_DUMP_VALUES, Cvar_HasFlags, &flags, &dump ); for( i = 0; i < dump->size; ++i ) { cvar_t *const var = (cvar_t *) dump->key_value_vector[i].value; Mem_ZoneFree( var->string ); var->string = ZoneCopyString( var->dvalue ); var->value = atof( var->string ); var->integer = Q_rint( var->value ); } Trie_FreeDump( dump ); }
/* * Key_SetBinding */ void Key_SetBinding( int keynum, const char *binding ) { if( keynum == -1 ) return; // free old bindings if( keybindings[keynum] ) { if( !Q_stricmp( keybindings[keynum], "toggleconsole" ) ) consolebinded--; Mem_ZoneFree( keybindings[keynum] ); keybindings[keynum] = NULL; } if( !binding ) return; // allocate memory for new binding keybindings[keynum] = ZoneCopyString( binding ); if( !Q_stricmp( keybindings[keynum], "toggleconsole" ) ) consolebinded++; }
/* * TV_Upstream_StartDemoRecord */ void TV_Upstream_StartDemoRecord( upstream_t *upstream, const char *demoname, qboolean silent ) { char *servername, *temp; size_t name_size; assert( upstream ); assert( demoname ); if( upstream->demo.playing ) { if( !silent ) Com_Printf( "You can't record from another demo.\n" ); return; } if( upstream->demo.recording ) { if( !silent ) Com_Printf( "Already recording.\n" ); return; } // strip the port number from servername servername = TempCopyString( upstream->servername ); temp = strstr( servername, ":" ); if( temp ) *temp = '\0'; // store the name name_size = sizeof( char ) * ( strlen( "demos/tvserver" ) + 1 + strlen( servername ) + 1 + strlen( demoname ) + strlen( APP_DEMO_EXTENSION_STR ) + 1 ); upstream->demo.filename = Mem_ZoneMalloc( name_size ); Q_snprintfz( upstream->demo.filename, name_size, "demos/tvserver/%s/%s", servername, demoname ); COM_SanitizeFilePath( upstream->demo.filename ); COM_DefaultExtension( upstream->demo.filename, APP_DEMO_EXTENSION_STR, name_size ); Mem_TempFree( servername ); if( !COM_ValidateRelativeFilename( upstream->demo.filename ) ) { if( !silent ) Com_Printf( "Invalid filename.\n" ); Mem_ZoneFree( upstream->demo.filename ); return; } // temp name name_size = sizeof( char ) * ( strlen( upstream->demo.filename ) + strlen( ".rec" ) + 1 ); upstream->demo.tempname = Mem_ZoneMalloc( name_size ); Q_snprintfz( upstream->demo.tempname, name_size, "%s.rec", upstream->demo.filename ); // open the demo file if( FS_FOpenFile( upstream->demo.tempname, &upstream->demo.filehandle, FS_WRITE|SNAP_DEMO_GZ ) == -1 ) { Com_Printf( "Error: Couldn't create the demo file.\n" ); Mem_ZoneFree( upstream->demo.tempname ); upstream->demo.tempname = NULL; Mem_ZoneFree( upstream->demo.filename ); upstream->demo.filename = NULL; return; } if( !silent ) Com_Printf( "Recording demo: %s\n", upstream->demo.filename ); upstream->demo.recording = qtrue; upstream->demo.localtime = 0; upstream->demo.basetime = upstream->demo.duration = 0; // don't start saving messages until a non-delta compressed message is received TV_Upstream_AddReliableCommand( upstream, "nodelta" ); // request non delta compressed frame from server upstream->demo.waiting = qtrue; // the rest of the demo file will be individual frames }
/* * SV_BeginDownload_f * Responds to reliable download packet with reliable initdownload packet */ static void SV_BeginDownload_f( client_t *client ) { const char *requestname; const char *uploadname; size_t alloc_size; unsigned checksum; char *url; const char *errormsg = NULL; qboolean allow, requestpak; qboolean local_http = SV_Web_Running() && sv_uploads_http->integer != 0; requestpak = ( atoi( Cmd_Argv( 1 ) ) == 1 ); requestname = Cmd_Argv( 2 ); if( !requestname[0] || !COM_ValidateRelativeFilename( requestname ) ) { SV_DenyDownload( client, "Invalid filename" ); return; } if( !SV_FilenameForDownloadRequest( requestname, requestpak, &uploadname, &errormsg ) ) { assert( errormsg != NULL ); SV_DenyDownload( client, errormsg ); return; } if( FS_CheckPakExtension( uploadname ) ) { allow = qfalse; // allow downloading paks from the pure list, if not spawned if( client->state < CS_SPAWNED ) { purelist_t *purefile; purefile = svs.purelist; while( purefile ) { if( !strcmp( uploadname, purefile->filename ) ) { allow = qtrue; break; } purefile = purefile->next; } } // game module has a change to allow extra downloads if( !allow && !SV_GameAllowDownload( client, requestname, uploadname ) ) { SV_DenyDownload( client, "Downloading of this file is not allowed" ); return; } } else { if( !SV_GameAllowDownload( client, requestname, uploadname ) ) { SV_DenyDownload( client, "Downloading of this file is not allowed" ); return; } } // we will just overwrite old download, if any if( client->download.name ) { if( client->download.data ) { FS_FreeBaseFile( client->download.data ); client->download.data = NULL; } Mem_ZoneFree( client->download.name ); client->download.name = NULL; client->download.size = 0; client->download.timeout = 0; } client->download.size = FS_LoadBaseFile( uploadname, NULL, NULL, 0 ); if( client->download.size == -1 ) { Com_Printf( "Error getting size of %s for uploading\n", uploadname ); client->download.size = 0; SV_DenyDownload( client, "Error getting file size" ); return; } checksum = FS_ChecksumBaseFile( uploadname ); client->download.timeout = svs.realtime + 1000 * 60 * 60; // this is web download timeout alloc_size = sizeof( char ) * ( strlen( uploadname ) + 1 ); client->download.name = Mem_ZoneMalloc( alloc_size ); Q_strncpyz( client->download.name, uploadname, alloc_size ); Com_Printf( "Offering %s to %s\n", client->download.name, client->name ); if( FS_CheckPakExtension( uploadname ) && ( local_http || sv_uploads_baseurl->string[0] != 0 ) ) { // .pk3 and .pak download from the web if( local_http ) { url = TempCopyString( va( "files/%s", uploadname ) ); } else { alloc_size = sizeof( char ) * ( strlen( sv_uploads_baseurl->string ) + 1 ); url = Mem_TempMalloc( alloc_size ); Q_snprintfz( url, alloc_size, "%s/", sv_uploads_baseurl->string ); } } else if( SV_IsDemoDownloadRequest( requestname ) && ( local_http || sv_uploads_demos_baseurl->string[0] != 0 ) ) { // demo file download from the web if( local_http ) { url = TempCopyString( va( "files/%s", uploadname ) ); } else { alloc_size = sizeof( char ) * ( strlen( sv_uploads_demos_baseurl->string ) + 1 ); url = Mem_TempMalloc( alloc_size ); Q_snprintfz( url, alloc_size, "%s/", sv_uploads_demos_baseurl->string ); } } else { url = NULL; } // start the download SV_InitClientMessage( client, &tmpMessage, NULL, 0 ); SV_SendServerCommand( client, "initdownload \"%s\" %i %u %i \"%s\"", client->download.name, client->download.size, checksum, local_http ? 1 : 0, ( url ? url : "" ) ); SV_AddReliableCommandsToMessage( client, &tmpMessage ); SV_SendMessageToClient( client, &tmpMessage ); if( url ) { Mem_TempFree( url ); url = NULL; } }
/* * SV_DropClient * * Called when the player is totally leaving the server, either willingly * or unwillingly. This is NOT called if the entire server is quiting * or crashing. */ void SV_DropClient( client_t *drop, int type, const char *format, ... ) { va_list argptr; char *reason; char string[1024]; if( format ) { va_start( argptr, format ); Q_vsnprintfz( string, sizeof( string ), format, argptr ); va_end( argptr ); reason = string; } else { Q_strncpyz( string, "User disconnected", sizeof( string ) ); reason = NULL; } // remove the rating of the client if( drop->edict ) ge->RemoveRating( drop->edict ); // add the disconnect if( drop->edict && ( drop->edict->r.svflags & SVF_FAKECLIENT ) ) { ge->ClientDisconnect( drop->edict, reason ); SV_ClientResetCommandBuffers( drop ); // make sure everything is clean } else { SV_InitClientMessage( drop, &tmpMessage, NULL, 0 ); SV_SendServerCommand( drop, "disconnect %i \"%s\"", type, string ); SV_AddReliableCommandsToMessage( drop, &tmpMessage ); SV_SendMessageToClient( drop, &tmpMessage ); Netchan_PushAllFragments( &drop->netchan ); if( drop->state >= CS_CONNECTED ) { // call the prog function for removing a client // this will remove the body, among other things ge->ClientDisconnect( drop->edict, reason ); } else if( drop->name[0] ) { Com_Printf( "Connecting client %s%s disconnected (%s%s)\n", drop->name, S_COLOR_WHITE, reason, S_COLOR_WHITE ); } } SV_MM_ClientDisconnect( drop ); SNAP_FreeClientFrames( drop ); if( drop->download.name ) { if( drop->download.data ) { FS_FreeBaseFile( drop->download.data ); drop->download.data = NULL; } Mem_ZoneFree( drop->download.name ); drop->download.name = NULL; drop->download.size = 0; drop->download.timeout = 0; } if( drop->individual_socket ) NET_CloseSocket( &drop->socket ); if( drop->mv ) { sv.num_mv_clients--; drop->mv = qfalse; } drop->tvclient = qfalse; drop->state = CS_ZOMBIE; // become free in a few seconds drop->name[0] = 0; }
/* * CL_InitDownload_f * * Hanldles server's initdownload message, starts web or server download if possible */ static void CL_InitDownload_f( void ) { const char *filename; const char *url; int size, alloc_size; unsigned checksum; qboolean allow_localhttpdownload; download_list_t *dl; // ignore download commands coming from demo files if( cls.demo.playing ) return; // read the data filename = Cmd_Argv( 1 ); size = atoi( Cmd_Argv( 2 ) ); checksum = strtoul( Cmd_Argv( 3 ), NULL, 10 ); allow_localhttpdownload = ( atoi( Cmd_Argv( 4 ) ) != 0 ) && cls.httpbaseurl != NULL; url = Cmd_Argv( 5 ); if( !cls.download.requestname ) { Com_Printf( "Got init download message without request\n" ); return; } if( cls.download.filenum || cls.download.web ) { Com_Printf( "Got init download message while already downloading\n" ); return; } if( size == -1 ) { // means that download was refused Com_Printf( "Server refused download request: %s\n", url ); // if it's refused, url field holds the reason CL_DownloadDone(); return; } if( size <= 0 ) { Com_Printf( "Server gave invalid size, not downloading\n" ); CL_DownloadDone(); return; } if( checksum == 0 ) { Com_Printf( "Server didn't provide checksum, not downloading\n" ); CL_DownloadDone(); return; } if( !COM_ValidateRelativeFilename( filename ) ) { Com_Printf( "Not downloading, invalid filename: %s\n", filename ); CL_DownloadDone(); return; } if( FS_CheckPakExtension( filename ) && !cls.download.requestpak ) { Com_Printf( "Got a pak file when requesting normal one, not downloading\n" ); CL_DownloadDone(); return; } if( !FS_CheckPakExtension( filename ) && cls.download.requestpak ) { Com_Printf( "Got a non pak file when requesting pak, not downloading\n" ); CL_DownloadDone(); return; } if( !strchr( filename, '/' ) ) { Com_Printf( "Refusing to download file with no gamedir: %s\n", filename ); CL_DownloadDone(); return; } // check that it is in game or basegame dir if( strlen( filename ) < strlen( FS_GameDirectory() )+1 || strncmp( filename, FS_GameDirectory(), strlen( FS_GameDirectory() ) ) || filename[strlen( FS_GameDirectory() )] != '/' ) { if( strlen( filename ) < strlen( FS_BaseGameDirectory() )+1 || strncmp( filename, FS_BaseGameDirectory(), strlen( FS_BaseGameDirectory() ) ) || filename[strlen( FS_BaseGameDirectory() )] != '/' ) { Com_Printf( "Can't download, invalid game directory: %s\n", filename ); CL_DownloadDone(); return; } } if( FS_CheckPakExtension( filename ) ) { if( strchr( strchr( filename, '/' ) + 1, '/' ) ) { Com_Printf( "Refusing to download pack file to subdirectory: %s\n", filename ); CL_DownloadDone(); return; } if( !Q_strnicmp( COM_FileBase( filename ), "modules", strlen( "modules" ) ) ) { if( !CL_CanDownloadModules() ) { CL_DownloadDone(); return; } } if( FS_FOpenBaseFile( filename, NULL, FS_READ ) != -1 ) { Com_Printf( "Can't download, file already exists: %s\n", filename ); CL_DownloadDone(); return; } } else { if( strcmp( cls.download.requestname, strchr( filename, '/' ) + 1 ) ) { Com_Printf( "Can't download, got different file than requested: %s\n", filename ); CL_DownloadDone(); return; } } if( cls.download.requestnext ) { dl = cls.download.list; while( dl != NULL ) { if( !Q_stricmp( dl->filename, filename ) ) { Com_Printf( "Skipping, already tried downloading: %s\n", filename ); CL_DownloadDone(); return; } dl = dl->next; } } cls.download.name = ZoneCopyString( filename ); alloc_size = strlen( filename ) + strlen( ".tmp" ) + 1; cls.download.tempname = Mem_ZoneMalloc( alloc_size ); Q_snprintfz( cls.download.tempname, alloc_size, "%s.tmp", filename ); cls.download.web = qfalse; cls.download.cancelled = qfalse; cls.download.disconnect = qfalse; cls.download.size = size; cls.download.checksum = checksum; cls.download.percent = 0; cls.download.timeout = 0; cls.download.retries = 0; cls.download.timestart = Sys_Milliseconds(); cls.download.offset = 0; cls.download.baseoffset = 0; cls.download.pending_reconnect = qfalse; Cvar_ForceSet( "cl_download_name", COM_FileBase( cls.download.name ) ); Cvar_ForceSet( "cl_download_percent", "0" ); if( cls.download.requestnext ) { dl = Mem_ZoneMalloc( sizeof( download_list_t ) ); dl->filename = ZoneCopyString( cls.download.name ); dl->next = cls.download.list; cls.download.list = dl; } if( cl_downloads_from_web->integer && allow_localhttpdownload && url && url[0] != 0 ) { cls.download.web = qtrue; Com_Printf( "Web download: %s from %s%s\n", cls.download.tempname, cls.httpbaseurl, url ); } else if( cl_downloads_from_web->integer && url && url[0] != 0 ) { cls.download.web = qtrue; Com_Printf( "Web download: %s from %s\n", cls.download.tempname, url ); } else { Com_Printf( "Server download: %s\n", cls.download.tempname ); } cls.download.baseoffset = cls.download.offset = FS_FOpenBaseFile( cls.download.tempname, &cls.download.filenum, FS_APPEND ); if( !cls.download.filenum ) { Com_Printf( "Can't download, couldn't open %s for writing\n", cls.download.tempname ); Mem_ZoneFree( cls.download.name ); cls.download.name = NULL; Mem_ZoneFree( cls.download.tempname ); cls.download.tempname = NULL; cls.download.filenum = 0; cls.download.offset = 0; cls.download.size = 0; CL_DownloadDone(); return; } if( cls.download.web ) { char *referer, *fullurl; const char *headers[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL }; alloc_size = strlen( APP_URI_SCHEME ) + strlen( NET_AddressToString( &cls.serveraddress ) ) + 1; referer = Mem_ZoneMalloc( alloc_size ); Q_snprintfz( referer, alloc_size, APP_URI_SCHEME "%s", NET_AddressToString( &cls.serveraddress ) ); Q_strlwr( referer ); if( allow_localhttpdownload ) { alloc_size = strlen( cls.httpbaseurl ) + 1 + strlen( url ) + 1; fullurl = Mem_ZoneMalloc( alloc_size ); Q_snprintfz( fullurl, alloc_size, "%s/%s", cls.httpbaseurl, url ); } else { size_t url_len = strlen( url ); alloc_size = url_len + 1 + strlen( filename ) * 3 + 1; fullurl = Mem_ZoneMalloc( alloc_size ); Q_snprintfz( fullurl, alloc_size, "%s/", url ); Q_urlencode_unsafechars( filename, fullurl + url_len + 1, alloc_size - url_len - 1 ); } headers[0] = "Referer"; headers[1] = referer; CL_AddSessionHttpRequestHeaders( fullurl, &headers[2] ); CL_AsyncStreamRequest( fullurl, headers, cl_downloads_from_web_timeout->integer / 100, cls.download.offset, CL_WebDownloadReadCb, CL_WebDownloadDoneCb, NULL, NULL, qfalse ); Mem_ZoneFree( fullurl ); Mem_ZoneFree( referer ); return; } // have to use Sys_Milliseconds because cls.realtime might be old from Web_Get cls.download.timeout = Sys_Milliseconds() + 3000; cls.download.retries = 0; CL_AddReliableCommand( va( "nextdl \"%s\" %i", cls.download.name, cls.download.offset ) ); }
/* * SV_Demo_Start_f * * Begins server demo recording. */ void SV_Demo_Start_f( void ) { int demofilename_size, i; if( Cmd_Argc() < 2 ) { Com_Printf( "Usage: serverrecord <demoname>\n" ); return; } if( svs.demo.file ) { Com_Printf( "Already recording\n" ); return; } if( sv.state != ss_game ) { Com_Printf( "Must be in a level to record\n" ); return; } for( i = 0; i < sv_maxclients->integer; i++ ) { if( svs.clients[i].state >= CS_SPAWNED && svs.clients[i].edict && !( svs.clients[i].edict->r.svflags & SVF_NOCLIENT ) ) break; } if( i == sv_maxclients->integer ) { Com_Printf( "No players in game, can't record a demo\n" ); return; } // // open the demo file // // real name demofilename_size = sizeof( char ) * ( strlen( SV_DEMO_DIR ) + 1 + strlen( Cmd_Args() ) + strlen( APP_DEMO_EXTENSION_STR ) + 1 ); svs.demo.filename = Mem_ZoneMalloc( demofilename_size ); Q_snprintfz( svs.demo.filename, demofilename_size, "%s/%s", SV_DEMO_DIR, Cmd_Args() ); COM_SanitizeFilePath( svs.demo.filename ); if( !COM_ValidateRelativeFilename( svs.demo.filename ) ) { Mem_ZoneFree( svs.demo.filename ); svs.demo.filename = NULL; Com_Printf( "Invalid filename.\n" ); return; } COM_DefaultExtension( svs.demo.filename, APP_DEMO_EXTENSION_STR, demofilename_size ); // temp name demofilename_size = sizeof( char ) * ( strlen( svs.demo.filename ) + strlen( ".rec" ) + 1 ); svs.demo.tempname = Mem_ZoneMalloc( demofilename_size ); Q_snprintfz( svs.demo.tempname, demofilename_size, "%s.rec", svs.demo.filename ); // open it if( FS_FOpenFile( svs.demo.tempname, &svs.demo.file, FS_WRITE|SNAP_DEMO_GZ ) == -1 ) { Com_Printf( "Error: Couldn't open file: %s\n", svs.demo.tempname ); Mem_ZoneFree( svs.demo.filename ); svs.demo.filename = NULL; Mem_ZoneFree( svs.demo.tempname ); svs.demo.tempname = NULL; return; } Com_Printf( "Recording server demo: %s\n", svs.demo.filename ); SV_Demo_InitClient(); // write serverdata, configstrings and baselines svs.demo.duration = 0; svs.demo.basetime = svs.gametime; svs.demo.localtime = time( NULL ); SV_Demo_WriteStartMessages(); // write one nodelta frame svs.demo.client.nodelta = true; SV_Demo_WriteSnap(); svs.demo.client.nodelta = false; }
/* * Cvar_Get * Creates the variable if it doesn't exist. * If the variable already exists, the value will not be set * The flags will be or'ed and default value overwritten in if the variable exists. */ cvar_t *Cvar_Get( const char *var_name, const char *var_value, cvar_flag_t flags ) { cvar_t *var; if( !var_name || !var_name[0] ) return NULL; if( Cvar_FlagIsSet( flags, CVAR_USERINFO ) || Cvar_FlagIsSet( flags, CVAR_SERVERINFO ) ) { if( !Cvar_InfoValidate( var_name, qtrue ) ) { Com_Printf( "invalid info cvar name\n" ); return NULL; } } assert( cvar_trie ); Trie_Find( cvar_trie, var_name, TRIE_EXACT_MATCH, (void **)&var ); if( var ) { assert( var_value ); if( !var->dvalue || strcmp( var->dvalue, var_value ) ) { if( var->dvalue ) Mem_ZoneFree( var->dvalue ); // free the old default value string var->dvalue = ZoneCopyString( (char *) var_value ); } #ifdef PUBLIC_BUILD if( Cvar_FlagIsSet( flags, CVAR_READONLY ) || Cvar_FlagIsSet( flags, CVAR_DEVELOPER ) ) { #else if( Cvar_FlagIsSet( flags, CVAR_READONLY ) ) { #endif if( !var->string || strcmp( var->string, var_value ) ) { if( var->string ) Mem_ZoneFree( var->string ); var->string = ZoneCopyString( (char *) var_value ); var->value = atof( var->string ); var->integer = Q_rint( var->value ); } var->flags = flags; } if( Cvar_FlagIsSet( flags, CVAR_USERINFO ) && !Cvar_FlagIsSet( var->flags, CVAR_USERINFO ) ) userinfo_modified = qtrue; // transmit at next oportunity Cvar_FlagSet( &var->flags, flags ); return var; } if( !var_value ) return NULL; if( Cvar_FlagIsSet( flags, CVAR_USERINFO ) || Cvar_FlagIsSet( flags, CVAR_SERVERINFO ) ) { if( !Cvar_InfoValidate( var_value, qfalse ) ) { Com_Printf( "invalid info cvar value\n" ); return NULL; } } var = Mem_ZoneMalloc( (int)( sizeof( *var ) + strlen( var_name ) + 1 ) ); var->name = (char *)( (qbyte *)var + sizeof( *var ) ); strcpy( var->name, var_name ); var->dvalue = ZoneCopyString( (char *) var_value ); var->string = ZoneCopyString( (char *) var_value ); Cvar_SetModified( var ); var->value = atof( var->string ); var->integer = Q_rint( var->value ); var->flags = flags; Trie_Insert( cvar_trie, var_name, var ); return var; } /* * Cvar_Set2 */ static cvar_t *Cvar_Set2( const char *var_name, const char *value, qboolean force ) { cvar_t *var = Cvar_Find( var_name ); if( !var ) { // create it return Cvar_Get( var_name, value, 0 ); } if( Cvar_FlagIsSet( var->flags, CVAR_USERINFO ) || Cvar_FlagIsSet( var->flags, CVAR_SERVERINFO ) ) { if( !Cvar_InfoValidate( value, qfalse ) ) { Com_Printf( "invalid info cvar value\n" ); return var; } } if( !force ) { #ifdef PUBLIC_BUILD if( Cvar_FlagIsSet( var->flags, CVAR_NOSET ) || Cvar_FlagIsSet( var->flags, CVAR_READONLY ) || Cvar_FlagIsSet( var->flags, CVAR_DEVELOPER ) ) { #else if( Cvar_FlagIsSet( var->flags, CVAR_NOSET ) || Cvar_FlagIsSet( var->flags, CVAR_READONLY ) ) { #endif Com_Printf( "%s is write protected.\n", var_name ); return var; } if( Cvar_FlagIsSet( var->flags, CVAR_CHEAT ) && strcmp( value, var->dvalue ) ) { if( !Cvar_CheatsAllowed() ) { Com_Printf( "%s is cheat protected.\n", var_name ); return var; } } if( Cvar_FlagIsSet( var->flags, CVAR_LATCH ) || Cvar_FlagIsSet( var->flags, CVAR_LATCH_VIDEO ) || Cvar_FlagIsSet( var->flags, CVAR_LATCH_SOUND ) ) { if( var->latched_string ) { if( !strcmp( value, var->latched_string ) ) return var; Mem_ZoneFree( var->latched_string ); } else { if( !strcmp( value, var->string ) ) return var; } if( Com_ServerState() ) { Com_Printf( "%s will be changed upon restarting.\n", var->name ); var->latched_string = ZoneCopyString( (char *) value ); } else { if( Cvar_FlagIsSet( var->flags, CVAR_LATCH_VIDEO ) ) { Com_Printf( "%s will be changed upon restarting video.\n", var->name ); var->latched_string = ZoneCopyString( (char *) value ); } else if( Cvar_FlagIsSet( var->flags, CVAR_LATCH_SOUND ) ) { Com_Printf( "%s will be changed upon restarting sound.\n", var->name ); var->latched_string = ZoneCopyString( (char *) value ); } else { if( !strcmp( var->name, "fs_game" ) ) { FS_SetGameDirectory( value, qfalse ); return var; } Mem_ZoneFree( var->string ); // free the old value string var->string = ZoneCopyString( value ); var->value = atof( var->string ); var->integer = Q_rint( var->value ); Cvar_SetModified( var ); } } return var; } } else { if( var->latched_string ) { Mem_ZoneFree( var->latched_string ); var->latched_string = NULL; } } if( !strcmp( value, var->string ) ) return var; // not changed Cvar_SetModified( var ); if( Cvar_FlagIsSet( var->flags, CVAR_USERINFO ) ) userinfo_modified = qtrue; // transmit at next oportunity Mem_ZoneFree( var->string ); // free the old value string var->string = ZoneCopyString( (char *) value ); var->value = atof( var->string ); var->integer = Q_rint( var->value ); return var; } /* * Cvar_ForceSet * Set the variable even if NOSET or LATCH */ cvar_t *Cvar_ForceSet( const char *var_name, const char *value ) { return Cvar_Set2( var_name, value, qtrue ); } /* * Cvar_Set * Create the variable if it doesn't exist */ cvar_t *Cvar_Set( const char *var_name, const char *value ) { return Cvar_Set2( var_name, value, qfalse ); } /* * Cvar_FullSet */ cvar_t *Cvar_FullSet( const char *var_name, const char *value, cvar_flag_t flags, qboolean overwrite_flags ) { cvar_t *var; var = Cvar_Find( var_name ); if( !var ) return Cvar_Get( var_name, value, flags ); if( overwrite_flags ) { var->flags = flags; } else { Cvar_FlagSet( &var->flags, flags ); } // if we overwrite the flags, we will also force the value return Cvar_Set2( var_name, value, overwrite_flags ); }
/* * SV_NextDownload_f * * Responds to reliable nextdl packet with unreliable download packet * If nextdl packet's offet information is negative, download will be stopped */ static void SV_NextDownload_f( client_t *client ) { int blocksize; int offset; if( !client->download.name ) { Com_Printf( "nextdl message for client with no download active, from: %s\n", client->name ); return; } if( Q_stricmp( client->download.name, Cmd_Argv( 1 ) ) ) { Com_Printf( "nextdl message for wrong filename, from: %s\n", client->name ); return; } offset = atoi( Cmd_Argv( 2 ) ); if( offset > client->download.size ) { Com_Printf( "nextdl message with too big offset, from: %s\n", client->name ); return; } if( offset == -1 ) { Com_Printf( "Upload of %s to %s%s completed\n", client->download.name, client->name, S_COLOR_WHITE ); if( client->download.data ) { FS_FreeBaseFile( client->download.data ); client->download.data = NULL; } Mem_ZoneFree( client->download.name ); client->download.name = NULL; client->download.size = 0; client->download.timeout = 0; return; } if( offset < 0 ) { Com_Printf( "Upload of %s to %s%s failed\n", client->download.name, client->name, S_COLOR_WHITE ); if( client->download.data ) { FS_FreeBaseFile( client->download.data ); client->download.data = NULL; } Mem_ZoneFree( client->download.name ); client->download.name = NULL; client->download.size = 0; client->download.timeout = 0; return; } if( !client->download.data ) { Com_Printf( "Starting server upload of %s to %s\n", client->download.name, client->name ); FS_LoadBaseFile( client->download.name, (void **)&client->download.data, NULL, 0 ); if( !client->download.data ) { Com_Printf( "Error loading %s for uploading\n", client->download.name ); Mem_ZoneFree( client->download.name ); client->download.name = NULL; client->download.size = 0; client->download.timeout = 0; return; } } SV_InitClientMessage( client, &tmpMessage, NULL, 0 ); SV_AddReliableCommandsToMessage( client, &tmpMessage ); blocksize = client->download.size - offset; // jalfixme: adapt download to user rate setting and sv_maxrate setting. if( blocksize > FRAGMENT_SIZE * 2 ) blocksize = FRAGMENT_SIZE * 2; if( offset + blocksize > client->download.size ) blocksize = client->download.size - offset; MSG_WriteByte( &tmpMessage, svc_download ); MSG_WriteString( &tmpMessage, client->download.name ); MSG_WriteLong( &tmpMessage, offset ); MSG_WriteLong( &tmpMessage, blocksize ); MSG_CopyData( &tmpMessage, client->download.data + offset, blocksize ); SV_SendMessageToClient( client, &tmpMessage ); client->download.timeout = svs.realtime + 10000; }
/* * Cvar_Shutdown * * Reads in all archived cvars */ void Cvar_Shutdown( void ) { if( cvar_initialized ) { unsigned int i; struct trie_dump_s *dump; extern cvar_t *developer, *developerMemory; #ifndef DEDICATED_ONLY extern cvar_t *con_printText; #endif assert( cvar_trie ); // NULL out some console variables so that we won't try to read from // the memory pointers after the data has already been freed but before we // reset the pointers to NULL developer = NULL; developerMemory = NULL; dedicated = NULL; #ifndef DEDICATED_ONLY con_printText = NULL; #endif Cmd_RemoveCommand( "set" ); Cmd_RemoveCommand( "seta" ); Cmd_RemoveCommand( "setau" ); Cmd_RemoveCommand( "setas" ); Cmd_RemoveCommand( "setu" ); Cmd_RemoveCommand( "sets" ); Cmd_RemoveCommand( "reset" ); Cmd_RemoveCommand( "toggle" ); Cmd_RemoveCommand( "cvarlist" ); #ifndef PUBLIC_BUILD Cmd_RemoveCommand( "cvararchivelist" ); #endif Trie_Dump( cvar_trie, "", TRIE_DUMP_VALUES, &dump ); for( i = 0; i < dump->size; ++i ) { cvar_t *const var = dump->key_value_vector[i].value; if( var->string ) Mem_ZoneFree( var->string ); if( var->dvalue ) Mem_ZoneFree( var->dvalue ); Mem_ZoneFree( var ); } Trie_FreeDump( dump ); cvar_initialized = qfalse; } if( cvar_preinitialized ) { assert( cvar_trie ); Trie_Destroy( cvar_trie ); cvar_trie = NULL; cvar_preinitialized = qfalse; } }