/* * 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_InitInputDynvars */ void CL_InitInputDynvars( void ) { Dynvar_Create( "m_filterBufferSize", true, CL_MouseFilterBufferSizeGet_f, CL_MouseFilterBufferSizeSet_f ); Dynvar_Create( "m_filterBufferDecay", true, CL_MouseFilterBufferDecayGet_f, CL_MouseFilterBufferDecaySet_f ); // we could simply call Dynvar_SetValue(m_filterBufferSize, "5") here, but then the user would get a warning in the console if m_filter was != M_FILTER_EXTRAPOLATE buf_size = DEFAULT_BUF_SIZE; buf_x = (float *) Mem_ZoneMalloc( sizeof( float ) * buf_size ); buf_y = (float *) Mem_ZoneMalloc( sizeof( float ) * buf_size ); memset( buf_x, 0, sizeof( float ) * buf_size ); memset( buf_y, 0, sizeof( float ) * buf_size ); }
/* * CL_ResolveMasterAddress */ static void CL_ResolveMasterAddress( const char *master, netadr_t *adr ) { trie_error_t err; masteradrcache_t *cache; // check memory cache err = Trie_Find( serverlist_masters_trie, master, TRIE_EXACT_MATCH, (void **)&cache ); if( err == TRIE_OK ) { if( adr ) *adr = cache->adr; return; } // send a unicast packet cache = Mem_ZoneMalloc( sizeof( *cache ) ); NET_StringToAddress( master, &cache->adr ); if( adr ) *adr = cache->adr; cache->next = serverlist_masters_head; serverlist_masters_head = cache; Trie_Insert( serverlist_masters_trie, master, (void *)cache ); }
static dynvar_t *Dynvar_NewDynvar( const char *name, qboolean console, dynvar_getter_f getter, dynvar_setter_f setter ) { dynvar_t *dynvar = (dynvar_t *) Mem_ZoneMalloc( sizeof( dynvar_t ) ); dynvar->name = (char *) Mem_ZoneMalloc( strlen( name ) + 1 ); strcpy( (char *) dynvar->name, name ); *( (qboolean *) &dynvar->console ) = console; dynvar->getter = getter; dynvar->setter = setter; dynvar->listeners_immutable = qfalse; dynvar->to_remove = NULL; return dynvar; }
static dynvar_listener_node_t *Dynvar_NewListener( dynvar_listener_f listener, dynvar_listener_node_t *next ) { dynvar_listener_node_t *n = (dynvar_listener_node_t *) Mem_ZoneMalloc( sizeof( dynvar_listener_node_t ) ); n->listener = listener; n->next = next; return n; }
/* * CL_DownloadRequest * * Request file download * return qfalse if couldn't request it for some reason * Files with .pk3 or .pak extension have to have gamedir attached * Other files must not have gamedir */ qboolean CL_DownloadRequest( const char *filename, qboolean requestpak ) { if( cls.download.requestname ) { Com_Printf( "Can't download: %s. Download already in progress.\n", filename ); return qfalse; } if( !COM_ValidateRelativeFilename( filename ) ) { Com_Printf( "Can't download: %s. Invalid filename.\n", filename ); return qfalse; } if( FS_CheckPakExtension( filename ) ) { if( FS_FOpenBaseFile( filename, NULL, FS_READ ) != -1 ) { Com_Printf( "Can't download: %s. File already exists.\n", filename ); return qfalse; } if( !Q_strnicmp( COM_FileBase( filename ), "modules", strlen( "modules" ) ) ) { if( !CL_CanDownloadModules() ) return qfalse; } } else { if( FS_FOpenFile( filename, NULL, FS_READ ) != -1 ) { Com_Printf( "Can't download: %s. File already exists.\n", filename ); return qfalse; } } if( cls.socket->type == SOCKET_LOOPBACK ) { Com_DPrintf( "Can't download: %s. Loopback server.\n", filename ); return qfalse; } Com_Printf( "Asking to download: %s\n", filename ); cls.download.requestpak = requestpak; cls.download.requestname = Mem_ZoneMalloc( sizeof( char ) * ( strlen( filename ) + 1 ) ); Q_strncpyz( cls.download.requestname, filename, sizeof( char ) * ( strlen( filename ) + 1 ) ); cls.download.timeout = Sys_Milliseconds() + 5000; CL_AddReliableCommand( va( "download %i \"%s\"", requestpak, filename ) ); return qtrue; }
/* * SCR_PlayCinematic */ static void SCR_PlayCinematic( char *arg ) { int len; size_t name_size; static cinematics_t clientCin; cinematics_t *cin = cl.cin = &clientCin; roq_chunk_t *chunk = &cin->chunk; name_size = strlen( "video/" ) + strlen( arg ) + strlen( ".roq" ) + 1; cin->name = Mem_ZoneMalloc( name_size ); Q_snprintfz( cin->name, name_size, "video/%s", arg ); COM_DefaultExtension( cin->name, ".roq", name_size ); // nasty hack cin->s_rate = 22050; cin->s_width = 2; cin->width = cin->height = 0; cin->frame = 0; len = FS_FOpenFile( cin->name, &cin->file, FS_READ ); if( !cin->file || len < 1 ) { Com_Printf( "Couldn't find %s\n", cin->name ); SCR_StopCinematic(); return; } // read header RoQ_ReadChunk( cin ); if( chunk->id != RoQ_HEADER1 || chunk->size != RoQ_HEADER2 || chunk->argument != RoQ_HEADER3 ) { Com_Printf( "Invalid video file %s\n", cin->name ); SCR_StopCinematic(); return; } SCR_EndLoadingPlaque(); cin->headerlen = FS_Tell( cin->file ); cin->frame = 0; cin->pic = cin->pic_pending = SCR_ReadNextCinematicFrame(); cin->time = cls.realtime + 1; // add 1 msec so SCR_GetCinematicTime is also valid for early commands CL_SetClientState( CA_ACTIVE ); CL_SoundModule_StopAllSounds(); }
/* * ML_AddMap * Handles assigning memory for map and adding it to the list * in alphabetical order */ static void ML_AddMap( const char *filename, const char *fullname ) { mapinfo_t *map; char *buffer; char fullname_[MAX_CONFIGSTRING_CHARS]; if( !ML_ValidateFilename( filename ) ) return; if( !strcmp(filename, "ui") ) return; if( !fullname ) { ML_GetFullnameFromMap( filename, fullname_, sizeof( fullname_ ) ); fullname = fullname_; } if( !ML_ValidateFullname( fullname ) && *fullname ) // allow empty fullnames return; if( !strcmp(fullname, "ui") ) return; ml_flush = true; // tell everyone that maplist has changed buffer = ( char* )Mem_ZoneMalloc( sizeof( mapinfo_t ) + strlen( filename ) + 1 + strlen( fullname ) + 1 ); map = ( mapinfo_t * )buffer; buffer += sizeof( mapinfo_t ); map->filename = buffer; strcpy( map->filename, filename ); COM_StripExtension( map->filename ); buffer += strlen( filename ) + 1; map->fullname = buffer; strcpy( map->fullname, fullname ); COM_RemoveColorTokens( map->fullname ); Q_strlwr( map->fullname ); Trie_Insert( mlist_filenames_trie, map->filename, map ); Trie_Insert( mlist_fullnames_trie, map->fullname, map ); map->next = maplist; maplist = map; }
/* * 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 ); }
/* * CL_AddServerToList */ static qboolean CL_AddServerToList( serverlist_t **serversList, char *adr, unsigned int days ) { serverlist_t *newserv; netadr_t nadr; if( !adr || !strlen( adr ) ) return qfalse; if( !NET_StringToAddress( adr, &nadr ) ) return qfalse; newserv = CL_ServerFindInList( *serversList, adr ); if( newserv ) { // ignore excessive updates for about a second or so, which may happen // when we're querying multiple master servers at once if( !newserv->masterServerUpdateSeq || newserv->lastUpdatedByMasterServer + 1000 < Sys_Milliseconds() ) { newserv->lastUpdatedByMasterServer = Sys_Milliseconds(); newserv->masterServerUpdateSeq = masterServerUpdateSeq; } return qfalse; } newserv = (serverlist_t *)Mem_ZoneMalloc( sizeof( serverlist_t ) ); Q_strncpyz( newserv->address, adr, sizeof( newserv->address ) ); newserv->pingTimeStamp = 0; if( days == 0 ) newserv->lastValidPing = Com_DaysSince1900(); else newserv->lastValidPing = days; newserv->lastUpdatedByMasterServer = Sys_Milliseconds(); newserv->masterServerUpdateSeq = masterServerUpdateSeq; newserv->pnext = *serversList; *serversList = newserv; return qtrue; }
/* * 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 ) ); }
/* * IN_RawInput_Init * * Returns false if rawinput is not available */ bool IN_RawInput_Init( void ) { int inputdevices, i, j, mtemp; PRAWINPUTDEVICELIST pRawInputDeviceList; char dname[MAX_RI_DEVICE_SIZE]; HMODULE user32 = LoadLibrary( "user32.dll" ); _GRIDL = NULL; _GRID = NULL; _GRIDIA = NULL; _RRID = NULL; rawmice = NULL; rawmicecount = 0; raw = NULL; ribuffersize = 0; if( !user32 ) { Com_Printf( "Raw input: unable to load user32.dll\n" ); return false; } if( !( _RRID = ( pRegisterRawInputDevices )GetProcAddress( user32, "RegisterRawInputDevices" ) ) ) { Com_Printf( "Raw input: function RegisterRawInputDevices could not be registered\n" ); return false; } if( !( _GRIDL = ( pGetRawInputDeviceList )GetProcAddress( user32, "GetRawInputDeviceList" ) ) ) { Com_Printf( "Raw input: function GetRawInputDeviceList could not be registered\n" ); return false; } if( !( _GRIDIA = ( pGetRawInputDeviceInfoA )GetProcAddress( user32, "GetRawInputDeviceInfoA" ) ) ) { Com_Printf( "Raw input: function GetRawInputDeviceInfoA could not be registered\n" ); return false; } if( !( _GRID = ( pGetRawInputData )GetProcAddress( user32, "GetRawInputData" ) ) ) { Com_Printf( "Raw input: function GetRawInputData could not be registered\n" ); return false; } // 1st call to GetRawInputDeviceList: Pass NULL to get the number of devices. if( ( *_GRIDL )( NULL, &inputdevices, sizeof( RAWINPUTDEVICELIST ) ) != 0 ) { Com_Printf( "Raw input: unable to count raw input devices\n" ); return false; } // Allocate the array to hold the DeviceList pRawInputDeviceList = Mem_ZoneMalloc( sizeof( RAWINPUTDEVICELIST ) * inputdevices ); // 2nd call to GetRawInputDeviceList: Pass the pointer to our DeviceList and GetRawInputDeviceList() will fill the array if( ( *_GRIDL )( pRawInputDeviceList, &inputdevices, sizeof( RAWINPUTDEVICELIST ) ) == -1 ) { Com_Printf( "Raw input: unable to get raw input device list\n" ); return false; } // Loop through all devices and count the mice for( i = 0, mtemp = 0; i < inputdevices; i++ ) { if( pRawInputDeviceList[i].dwType == RIM_TYPEMOUSE ) { j = MAX_RI_DEVICE_SIZE; // Get the device name and use it to determine if it's the RDP Terminal Services virtual device. if( ( *_GRIDIA )( pRawInputDeviceList[i].hDevice, RIDI_DEVICENAME, dname, &j ) < 0 ) { dname[0] = 0; } if( IN_RawInput_IsRDPMouse( dname ) ) { // ignore rdp mouse continue; } // advance temp device count mtemp++; } } // exit out if no devices found if( !mtemp ) { Com_Printf( "Raw input: no usable device found\n" ); return false; } // Loop again and bind devices rawmice = Mem_ZoneMalloc( sizeof( rawmouse_t ) * mtemp ); for( i = 0; i < inputdevices; i++ ) { if( pRawInputDeviceList[i].dwType == RIM_TYPEMOUSE ) { j = MAX_RI_DEVICE_SIZE; // Get the device name and use it to determine if it's the RDP Terminal Services virtual device. if( ( *_GRIDIA )( pRawInputDeviceList[i].hDevice, RIDI_DEVICENAME, dname, &j ) < 0 ) { dname[0] = 0; } if( IN_RawInput_IsRDPMouse( dname ) ) { // ignore rdp mouse continue; } // print pretty message about the mouse dname[MAX_RI_DEVICE_SIZE - 1] = 0; for( mtemp = strlen( dname ); mtemp >= 0; mtemp-- ) { if( dname[mtemp] == '#' ) { dname[mtemp + 1] = 0; break; } } Com_Printf( "Raw input: [%i] %s\n", i, dname ); // set handle rawmice[rawmicecount].rawinputhandle = pRawInputDeviceList[i].hDevice; rawmice[rawmicecount].numbuttons = 10; rawmice[rawmicecount].pos[0] = RI_INVALID_POS; rawmicecount++; } } // free the RAWINPUTDEVICELIST Mem_ZoneFree( pRawInputDeviceList ); // alloc raw input buffer raw = Mem_ZoneMalloc( INIT_RIBUFFER_SIZE ); ribuffersize = INIT_RIBUFFER_SIZE; return true; }
/* * 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; } }
/* * Com_LoadGameLibrary */ void *Com_LoadGameLibrary( const char *basename, const char *apifuncname, void **handle, void *parms, bool pure, char *manifest ) { static int randomizer = 0; // random part of tempmodules dir, always the same for one launch of Warsow static int64_t randomizer_time; const char *temppath; char *tempname, *libname; int libname_size; void *( *APIfunc )(void *); gamelib_t *gamelib; *handle = 0; if( !randomizer ) { randomizer_time = time( NULL ); srand( randomizer_time ); randomizer = brandom( 1, 9999 ); } gamelib = ( gamelib_t* )Mem_ZoneMalloc( sizeof( gamelib_t ) ); gamelib->lib = NULL; gamelib->fullname = NULL; libname_size = strlen( LIB_PREFIX ) + strlen( basename ) + 1 + strlen( ARCH ) + strlen( LIB_SUFFIX ) + 1; libname = ( char* )Mem_TempMalloc( libname_size ); Q_snprintfz( libname, libname_size, LIB_PREFIX "%s_" ARCH LIB_SUFFIX, basename ); // it exists? if( FS_FOpenFile( libname, NULL, FS_READ ) == -1 ) { Com_Printf( "LoadLibrary (%s):(File not found)\n", libname ); Mem_TempFree( libname ); Mem_ZoneFree( gamelib ); return NULL; } // pure check if( pure && !FS_IsPureFile( libname ) ) { Com_Printf( "LoadLibrary (%s):(Unpure file)\n", libname ); Mem_TempFree( libname ); Mem_ZoneFree( gamelib ); return NULL; } temppath = Sys_Library_GetGameLibPath( libname, randomizer_time, randomizer ); tempname = ( char * )Mem_ZoneMalloc( strlen( temppath ) + 1 ); strcpy( tempname, temppath ); if( FS_FOpenFile( tempname, NULL, FS_READ ) == -1 ) { if( !FS_ExtractFile( libname, tempname ) ) { Com_Printf( "LoadLibrary (%s):(FS_ExtractFile failed)\n", libname ); Mem_TempFree( libname ); Mem_ZoneFree( tempname ); Mem_ZoneFree( gamelib ); return NULL; } } gamelib->fullname = COM_SanitizeFilePath( tempname ); gamelib->lib = Sys_Library_Open( gamelib->fullname ); gamelib->next = gamelibs; gamelibs = gamelib; if( !( gamelib->lib ) ) { Com_Printf( "LoadLibrary (%s):(%s)\n", tempname, Sys_Library_ErrorString() ); Mem_TempFree( libname ); Com_UnloadGameLibrary( (void **)&gamelib ); return NULL; } APIfunc = ( void* ( * )( void* ) )Sys_Library_ProcAddress( gamelib->lib, apifuncname ); if( !APIfunc ) { Com_Printf( "LoadLibrary (%s):(%s)\n", tempname, Sys_Library_ErrorString() ); Mem_TempFree( libname ); Com_UnloadGameLibrary( (void **)&gamelib ); return NULL; } *handle = gamelib; if( manifest ) Com_LoadGameLibraryManifest( libname, manifest ); Mem_TempFree( libname ); return APIfunc( parms ); }
/* * CL_DownloadRequest * * Request file download * return false if couldn't request it for some reason * Files with .pk3 or .pak extension have to have gamedir attached * Other files must not have gamedir */ bool CL_DownloadRequest( const char *filename, bool requestpak ) { if( cls.download.requestname ) { Com_Printf( "Can't download: %s. Download already in progress.\n", filename ); return false; } if( !COM_ValidateRelativeFilename( filename ) ) { Com_Printf( "Can't download: %s. Invalid filename.\n", filename ); return false; } if( FS_CheckPakExtension( filename ) ) { if( FS_PakFileExists( filename ) ) { Com_Printf( "Can't download: %s. File already exists.\n", filename ); return false; } if( !Q_strnicmp( COM_FileBase( filename ), "modules", strlen( "modules" ) ) ) { if( !CL_CanDownloadModules() ) return false; } } else { if( FS_FOpenFile( filename, NULL, FS_READ ) != -1 ) { Com_Printf( "Can't download: %s. File already exists.\n", filename ); return false; } if( !requestpak ) { const char *extension; // only allow demo downloads extension = COM_FileExtension( filename ); if( !extension || Q_stricmp( extension, APP_DEMO_EXTENSION_STR ) ) { Com_Printf( "Can't download, got arbitrary file type: %s\n", filename ); return false; } } } if( cls.socket->type == SOCKET_LOOPBACK ) { Com_DPrintf( "Can't download: %s. Loopback server.\n", filename ); return false; } Com_Printf( "Asking to download: %s\n", filename ); cls.download.requestpak = requestpak; cls.download.requestname = Mem_ZoneMalloc( sizeof( char ) * ( strlen( filename ) + 1 ) ); Q_strncpyz( cls.download.requestname, filename, sizeof( char ) * ( strlen( filename ) + 1 ) ); cls.download.timeout = Sys_Milliseconds() + 5000; CL_AddReliableCommand( va( "download %i \"%s\"", requestpak, filename ) ); return true; }
/* * 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_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; }