aboutsummaryrefslogtreecommitdiffstats
path: root/code/client
diff options
context:
space:
mode:
Diffstat (limited to 'code/client')
-rw-r--r--code/client/cl_curl.c358
-rw-r--r--code/client/cl_curl.h101
-rw-r--r--code/client/cl_main.c90
-rw-r--r--code/client/cl_parse.c22
-rw-r--r--code/client/client.h15
5 files changed, 582 insertions, 4 deletions
diff --git a/code/client/cl_curl.c b/code/client/cl_curl.c
new file mode 100644
index 0000000..38498ee
--- /dev/null
+++ b/code/client/cl_curl.c
@@ -0,0 +1,358 @@
+/*
+===========================================================================
+Copyright (C) 2006 Tony J. White (tjw@tjw.org)
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Quake III Arena source code; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+
+#if USE_CURL
+#include "client.h"
+cvar_t *cl_cURLLib;
+
+#if USE_CURL_DLOPEN
+
+#if USE_SDL_VIDEO
+#include "SDL.h"
+#include "SDL_loadso.h"
+#define OBJTYPE void *
+#define OBJLOAD(x) SDL_LoadObject(x)
+#define SYMLOAD(x,y) SDL_LoadFunction(x,y)
+#define OBJFREE(x) SDL_UnloadObject(x)
+
+#elif defined _WIN32
+#include <windows.h>
+#define OBJTYPE HMODULE
+#define OBJLOAD(x) LoadLibrary(x)
+#define SYMLOAD(x,y) GetProcAddress(x,y)
+#define OBJFREE(x) FreeLibrary(x)
+
+#elif defined __linux__ || defined __FreeBSD__ || defined MACOS_X || defined __sun
+#include <dlfcn.h>
+#define OBJTYPE void *
+#define OBJLOAD(x) dlopen(x, RTLD_LAZY | RTLD_GLOBAL)
+#define SYMLOAD(x,y) dlsym(x,y)
+#define OBJFREE(x) dlclose(x)
+#else
+
+#error "Your platform has no lib loading code or it is disabled"
+#endif
+
+#if defined __linux__ || defined __FreeBSD__ || defined MACOS_X
+#include <unistd.h>
+#include <sys/types.h>
+#endif
+
+char* (*qcurl_version)(void);
+
+CURL* (*qcurl_easy_init)(void);
+CURLcode (*qcurl_easy_setopt)(CURL *curl, CURLoption option, ...);
+CURLcode (*qcurl_easy_perform)(CURL *curl);
+void (*qcurl_easy_cleanup)(CURL *curl);
+CURLcode (*qcurl_easy_getinfo)(CURL *curl, CURLINFO info, ...);
+CURL* (*qcurl_easy_duphandle)(CURL *curl);
+void (*qcurl_easy_reset)(CURL *curl);
+const char *(*qcurl_easy_strerror)(CURLcode);
+
+CURLM* (*qcurl_multi_init)(void);
+CURLMcode (*qcurl_multi_add_handle)(CURLM *multi_handle,
+ CURL *curl_handle);
+CURLMcode (*qcurl_multi_remove_handle)(CURLM *multi_handle,
+ CURL *curl_handle);
+CURLMcode (*qcurl_multi_fdset)(CURLM *multi_handle,
+ fd_set *read_fd_set,
+ fd_set *write_fd_set,
+ fd_set *exc_fd_set,
+ int *max_fd);
+CURLMcode (*qcurl_multi_perform)(CURLM *multi_handle,
+ int *running_handles);
+CURLMcode (*qcurl_multi_cleanup)(CURLM *multi_handle);
+CURLMsg *(*qcurl_multi_info_read)(CURLM *multi_handle,
+ int *msgs_in_queue);
+const char *(*qcurl_multi_strerror)(CURLMcode);
+
+static OBJTYPE cURLLib = NULL;
+
+/*
+=================
+GPA
+=================
+*/
+static void *GPA(char *str)
+{
+ void *rv;
+
+ rv = SYMLOAD(cURLLib, str);
+ if(!rv)
+ {
+ Com_Printf("Can't load symbol %s\n", str);
+ clc.cURLEnabled = qfalse;
+ return NULL;
+ }
+ else
+ {
+ Com_DPrintf("Loaded symbol %s (0x%08X)\n", str, rv);
+ return rv;
+ }
+}
+#endif /* USE_CURL_DLOPEN */
+
+/*
+=================
+CL_cURL_Init
+=================
+*/
+qboolean CL_cURL_Init()
+{
+#if USE_CURL_DLOPEN
+ if(cURLLib)
+ return qtrue;
+
+
+ Com_Printf("Loading \"%s\"...", cl_cURLLib->string);
+ if( (cURLLib = OBJLOAD(cl_cURLLib->string)) == 0 )
+ {
+#ifdef _WIN32
+ return qfalse;
+#else
+ char fn[1024];
+ getcwd(fn, sizeof(fn));
+ strncat(fn, "/", sizeof(fn));
+ strncat(fn, cl_cURLLib->string, sizeof(fn));
+
+ if( (cURLLib = OBJLOAD(fn)) == 0 )
+ {
+ return qfalse;
+ }
+#endif /* _WIN32 */
+ }
+
+ clc.cURLEnabled = qtrue;
+
+ qcurl_version = GPA("curl_version");
+
+ qcurl_easy_init = GPA("curl_easy_init");
+ qcurl_easy_setopt = GPA("curl_easy_setopt");
+ qcurl_easy_perform = GPA("curl_easy_perform");
+ qcurl_easy_cleanup = GPA("curl_easy_cleanup");
+ qcurl_easy_getinfo = GPA("curl_easy_getinfo");
+ qcurl_easy_duphandle = GPA("curl_easy_duphandle");
+ qcurl_easy_reset = GPA("curl_easy_reset");
+ qcurl_easy_strerror = GPA("curl_easy_strerror");
+
+ qcurl_multi_init = GPA("curl_multi_init");
+ qcurl_multi_add_handle = GPA("curl_multi_add_handle");
+ qcurl_multi_remove_handle = GPA("curl_multi_remove_handle");
+ qcurl_multi_fdset = GPA("curl_multi_fdset");
+ qcurl_multi_perform = GPA("curl_multi_perform");
+ qcurl_multi_cleanup = GPA("curl_multi_cleanup");
+ qcurl_multi_info_read = GPA("curl_multi_info_read");
+ qcurl_multi_strerror = GPA("curl_multi_strerror");
+
+ if(!clc.cURLEnabled)
+ {
+ CL_cURL_Shutdown();
+ Com_Printf("FAIL One or more symbols not found\n");
+ return qfalse;
+ }
+ Com_Printf("OK\n");
+
+ return qtrue;
+#else
+ clc.cURLEnabled = qtrue;
+ return qtrue;
+#endif /* USE_CURL_DLOPEN */
+}
+
+/*
+=================
+CL_cURL_Shutdown
+=================
+*/
+void CL_cURL_Shutdown( void )
+{
+ CL_cURL_Cleanup();
+#if USE_CURL_DLOPEN
+ if(cURLLib)
+ {
+ OBJFREE(cURLLib);
+ cURLLib = NULL;
+ }
+ qcurl_easy_init = NULL;
+ qcurl_easy_setopt = NULL;
+ qcurl_easy_perform = NULL;
+ qcurl_easy_cleanup = NULL;
+ qcurl_easy_getinfo = NULL;
+ qcurl_easy_duphandle = NULL;
+ qcurl_easy_reset = NULL;
+
+ qcurl_multi_init = NULL;
+ qcurl_multi_add_handle = NULL;
+ qcurl_multi_remove_handle = NULL;
+ qcurl_multi_fdset = NULL;
+ qcurl_multi_perform = NULL;
+ qcurl_multi_cleanup = NULL;
+ qcurl_multi_info_read = NULL;
+ qcurl_multi_strerror = NULL;
+#endif /* USE_CURL_DLOPEN */
+}
+
+void CL_cURL_Cleanup(void)
+{
+ if(clc.downloadCURLM) {
+ if(clc.downloadCURL) {
+ qcurl_multi_remove_handle(clc.downloadCURLM,
+ clc.downloadCURL);
+ qcurl_easy_cleanup(clc.downloadCURL);
+ }
+ qcurl_multi_cleanup(clc.downloadCURLM);
+ clc.downloadCURLM = NULL;
+ clc.downloadCURL = NULL;
+ }
+ else if(clc.downloadCURL) {
+ qcurl_easy_cleanup(clc.downloadCURL);
+ clc.downloadCURL = NULL;
+ }
+}
+
+static int CL_cURL_CallbackProgress( void *dummy, double dltotal, double dlnow,
+ double ultotal, double ulnow )
+{
+ clc.downloadSize = (int)dltotal;
+ Cvar_SetValue( "cl_downloadSize", clc.downloadSize );
+ clc.downloadCount = (int)dlnow;
+ Cvar_SetValue( "cl_downloadCount", clc.downloadCount );
+ return 0;
+}
+
+static int CL_cURL_CallbackWrite(void *buffer, size_t size, size_t nmemb,
+ void *stream)
+{
+ FS_Write( buffer, size*nmemb, ((fileHandle_t*)stream)[0] );
+ return size*nmemb;
+}
+
+void CL_cURL_BeginDownload( const char *localName, const char *remoteURL )
+{
+ clc.cURLUsed = qtrue;
+ Com_Printf("URL: %s\n", remoteURL);
+ Com_DPrintf("***** CL_cURL_BeginDownload *****\n"
+ "Localname: %s\n"
+ "RemoteURL: %s\n"
+ "****************************\n", localName, remoteURL);
+ CL_cURL_Cleanup();
+ Q_strncpyz(clc.downloadURL, remoteURL, sizeof(clc.downloadURL));
+ Q_strncpyz(clc.downloadName, localName, sizeof(clc.downloadName));
+ Com_sprintf(clc.downloadTempName, sizeof(clc.downloadTempName),
+ "%s.tmp", localName);
+
+ // Set so UI gets access to it
+ Cvar_Set("cl_downloadName", localName);
+ Cvar_Set("cl_downloadSize", "0");
+ Cvar_Set("cl_downloadCount", "0");
+ Cvar_SetValue("cl_downloadTime", cls.realtime);
+
+ clc.downloadBlock = 0; // Starting new file
+ clc.downloadCount = 0;
+
+ clc.downloadCURL = qcurl_easy_init();
+ if(!clc.downloadCURL) {
+ Com_Error(ERR_DROP, "CL_cURL_BeginDownload: qcurl_easy_init() "
+ "failed\n");
+ return;
+ }
+ clc.download = FS_SV_FOpenFileWrite(clc.downloadTempName);
+ if(!clc.download) {
+ Com_Error(ERR_DROP, "CL_cURL_BeginDownload: failed to open "
+ "%s for writing\n", clc.downloadTempName);
+ return;
+ }
+ qcurl_easy_setopt(clc.downloadCURL, CURLOPT_WRITEDATA, clc.download);
+ if(com_developer->integer)
+ qcurl_easy_setopt(clc.downloadCURL, CURLOPT_VERBOSE, 1);
+ qcurl_easy_setopt(clc.downloadCURL, CURLOPT_URL, clc.downloadURL);
+ qcurl_easy_setopt(clc.downloadCURL, CURLOPT_TRANSFERTEXT, 0);
+ qcurl_easy_setopt(clc.downloadCURL, CURLOPT_REFERER, va("ioQ3://%s",
+ NET_AdrToString(clc.serverAddress)));
+ qcurl_easy_setopt(clc.downloadCURL, CURLOPT_USERAGENT, va("%s %s",
+ Q3_VERSION, qcurl_version()));
+ qcurl_easy_setopt(clc.downloadCURL, CURLOPT_WRITEFUNCTION,
+ CL_cURL_CallbackWrite);
+ qcurl_easy_setopt(clc.downloadCURL, CURLOPT_WRITEDATA, &clc.download);
+ qcurl_easy_setopt(clc.downloadCURL, CURLOPT_NOPROGRESS, 0);
+ qcurl_easy_setopt(clc.downloadCURL, CURLOPT_PROGRESSFUNCTION,
+ CL_cURL_CallbackProgress);
+ qcurl_easy_setopt(clc.downloadCURL, CURLOPT_PROGRESSDATA, NULL);
+ qcurl_easy_setopt(clc.downloadCURL, CURLOPT_FAILONERROR, 1);
+ clc.downloadCURLM = qcurl_multi_init();
+ if(!clc.downloadCURLM) {
+ qcurl_easy_cleanup(clc.downloadCURL);
+ clc.downloadCURL = NULL;
+ Com_Error(ERR_DROP, "CL_cURL_BeginDownload: qcurl_multi_init() "
+ "failed\n");
+ return;
+ }
+ qcurl_multi_add_handle(clc.downloadCURLM, clc.downloadCURL);
+
+ if(!(clc.sv_allowDownload & DLF_NO_DISCONNECT) &&
+ !clc.cURLDisconnected) {
+
+ CL_AddReliableCommand("disconnect");
+ CL_WritePacket();
+ CL_WritePacket();
+ CL_WritePacket();
+ clc.cURLDisconnected = qtrue;
+ }
+}
+
+void CL_cURL_PerformDownload(void)
+{
+ CURLMcode res;
+ CURLMsg *msg;
+ int c;
+ int i = 0;
+
+ res = qcurl_multi_perform(clc.downloadCURLM, &c);
+ while(res == CURLM_CALL_MULTI_PERFORM && i < 100) {
+ res = qcurl_multi_perform(clc.downloadCURLM, &c);
+ i++;
+ }
+ if(res == CURLM_CALL_MULTI_PERFORM)
+ return;
+ msg = qcurl_multi_info_read(clc.downloadCURLM, &c);
+ if(msg == NULL) {
+ return;
+ }
+ FS_FCloseFile(clc.download);
+ if(msg->msg == CURLMSG_DONE && msg->data.result == CURLE_OK) {
+ FS_SV_Rename(clc.downloadTempName, clc.downloadName);
+ clc.downloadRestart = qtrue;
+ }
+ else {
+ long code;
+
+ qcurl_easy_getinfo(msg->easy_handle, CURLINFO_RESPONSE_CODE,
+ &code);
+ Com_Error(ERR_DROP, "Download Error: %s Code: %d URL: %s",
+ qcurl_easy_strerror(msg->data.result),
+ code, clc.downloadURL);
+ }
+ *clc.downloadTempName = *clc.downloadName = 0;
+ Cvar_Set( "cl_downloadName", "" );
+ CL_NextDownload();
+}
+#endif /* USE_CURL */
diff --git a/code/client/cl_curl.h b/code/client/cl_curl.h
new file mode 100644
index 0000000..57ed216
--- /dev/null
+++ b/code/client/cl_curl.h
@@ -0,0 +1,101 @@
+/*
+===========================================================================
+Copyright (C) 2006 Tony J. White (tjw@tjw.org)
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Quake III Arena source code; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+
+
+#ifndef __QCURL_H__
+#define __QCURL_H__
+
+extern cvar_t *cl_cURLLib;
+
+#include "../qcommon/q_shared.h"
+#include "../qcommon/qcommon.h"
+
+#ifdef WIN32
+#define DEFAULT_CURL_LIB "libcurl-3.dll"
+#elif defined(MACOS_X)
+#define DEFAULT_CURL_LIB "libcurl.dylib"
+#else
+#define DEFAULT_CURL_LIB "libcurl.so.3"
+#endif
+
+#if USE_LOCAL_HEADERS
+ #include "../libcurl/curl/curl.h"
+#else
+ #include <curl/curl.h>
+#endif
+
+
+#if USE_CURL_DLOPEN
+extern char* (*qcurl_version)(void);
+
+extern CURL* (*qcurl_easy_init)(void);
+extern CURLcode (*qcurl_easy_setopt)(CURL *curl, CURLoption option, ...);
+extern CURLcode (*qcurl_easy_perform)(CURL *curl);
+extern void (*qcurl_easy_cleanup)(CURL *curl);
+extern CURLcode (*qcurl_easy_getinfo)(CURL *curl, CURLINFO info, ...);
+extern void (*qcurl_easy_reset)(CURL *curl);
+extern const char *(*qcurl_easy_strerror)(CURLcode);
+
+extern CURLM* (*qcurl_multi_init)(void);
+extern CURLMcode (*qcurl_multi_add_handle)(CURLM *multi_handle,
+ CURL *curl_handle);
+extern CURLMcode (*qcurl_multi_remove_handle)(CURLM *multi_handle,
+ CURL *curl_handle);
+extern CURLMcode (*qcurl_multi_fdset)(CURLM *multi_handle,
+ fd_set *read_fd_set,
+ fd_set *write_fd_set,
+ fd_set *exc_fd_set,
+ int *max_fd);
+extern CURLMcode (*qcurl_multi_perform)(CURLM *multi_handle,
+ int *running_handles);
+extern CURLMcode (*qcurl_multi_cleanup)(CURLM *multi_handle);
+extern CURLMsg *(*qcurl_multi_info_read)(CURLM *multi_handle,
+ int *msgs_in_queue);
+extern const char *(*qcurl_multi_strerror)(CURLMcode);
+#else
+#define qcurl_version curl_version
+
+#define qcurl_easy_init curl_easy_init
+#define qcurl_easy_setopt curl_easy_setopt
+#define qcurl_easy_perform curl_easy_perform
+#define qcurl_easy_cleanup curl_easy_cleanup
+#define qcurl_easy_getinfo curl_easy_getinfo
+#define qcurl_easy_duphandle curl_easy_duphandle
+#define qcurl_easy_reset curl_easy_reset
+#define qcurl_easy_strerror curl_easy_strerror
+
+#define qcurl_multi_init curl_multi_init
+#define qcurl_multi_add_handle curl_multi_add_handle
+#define qcurl_multi_remove_handle curl_multi_remove_handle
+#define qcurl_multi_fdset curl_multi_fdset
+#define qcurl_multi_perform curl_multi_perform
+#define qcurl_multi_cleanup curl_multi_cleanup
+#define qcurl_multi_info_read curl_multi_info_read
+#define qcurl_multi_strerror curl_multi_strerror
+#endif
+
+qboolean CL_cURL_Init( void );
+void CL_cURL_Shutdown( void );
+void CL_cURL_BeginDownload( const char *localName, const char *remoteURL );
+void CL_cURL_PerformDownload( void );
+void CL_cURL_Cleanup( void );
+#endif // __QCURL_H__
diff --git a/code/client/cl_main.c b/code/client/cl_main.c
index e05a640..4c5b403 100644
--- a/code/client/cl_main.c
+++ b/code/client/cl_main.c
@@ -608,6 +608,9 @@ CL_ShutdownAll
*/
void CL_ShutdownAll(void) {
+#if USE_CURL
+ CL_cURL_Shutdown();
+#endif
// clear sounds
S_DisableSounds();
// shutdown CGame
@@ -1331,6 +1334,23 @@ Called when all downloading has been completed
*/
void CL_DownloadsComplete( void ) {
+#if USE_CURL
+ // if we downloaded with cURL
+ if(clc.cURLUsed) {
+ clc.cURLUsed = qfalse;
+ CL_cURL_Shutdown();
+ if( clc.cURLDisconnected ) {
+ if(clc.downloadRestart) {
+ FS_Restart(clc.checksumFeed);
+ clc.downloadRestart = qfalse;
+ }
+ clc.cURLDisconnected = qfalse;
+ CL_Reconnect_f();
+ return;
+ }
+ }
+#endif
+
// if we downloaded files we need to restart the file system
if (clc.downloadRestart) {
clc.downloadRestart = qfalse;
@@ -1418,6 +1438,7 @@ A download completed or failed
void CL_NextDownload(void) {
char *s;
char *remoteName, *localName;
+ qboolean useCURL = qfalse;
// We are looking to start a download here
if (*clc.downloadList) {
@@ -1441,9 +1462,48 @@ void CL_NextDownload(void) {
*s++ = 0;
else
s = localName + strlen(localName); // point at the nul byte
-
- CL_BeginDownload( localName, remoteName );
-
+#if USE_CURL
+ if(!(cl_allowDownload->integer & DLF_NO_REDIRECT)) {
+ if(clc.sv_allowDownload & DLF_NO_REDIRECT) {
+ Com_Printf("WARNING: server does not "
+ "allow download redirection "
+ "(sv_allowDownload is %d)\n",
+ clc.sv_allowDownload);
+ }
+ else if(!*clc.sv_dlURL) {
+ Com_Printf("WARNING: server allows "
+ "download redirection, but does not "
+ "have sv_dlURL set\n");
+ }
+ else if(!CL_cURL_Init()) {
+ Com_Printf("WARNING: could not load "
+ "cURL library\n");
+ }
+ else {
+ CL_cURL_BeginDownload(localName, va("%s/%s",
+ clc.sv_dlURL, remoteName));
+ useCURL = qtrue;
+ }
+ }
+ else if(!(clc.sv_allowDownload & DLF_NO_REDIRECT)) {
+ Com_Printf("WARNING: server allows download "
+ "redirection, but it disabled by client "
+ "configuration (cl_allowDownload is %d)\n",
+ cl_allowDownload->integer);
+ }
+#endif /* USE_CURL */
+ if(!useCURL) {
+ if((cl_allowDownload->integer & DLF_NO_UDP)) {
+ Com_Error(ERR_DROP, "UDP Downloads are "
+ "disabled on your client. "
+ "(cl_allowDownload is %d)",
+ cl_allowDownload->integer);
+ return;
+ }
+ else {
+ CL_BeginDownload( localName, remoteName );
+ }
+ }
clc.downloadRestart = qtrue;
// move over the rest
@@ -1466,7 +1526,7 @@ and determine if we need to download them
void CL_InitDownloads(void) {
char missingfiles[1024];
- if ( !cl_allowDownload->integer )
+ if ( !(cl_allowDownload->integer & DLF_ENABLE) )
{
// autodownload is disabled on the client
// but it's possible that some referenced files on the server are missing
@@ -2028,6 +2088,25 @@ void CL_Frame ( int msec ) {
return;
}
+#if USE_CURL
+ if(clc.downloadCURLM) {
+ CL_cURL_PerformDownload();
+ // we can't process frames normally when in disconnected
+ // download mode since the ui vm expects cls.state to be
+ // CA_CONNECTED
+ if(clc.cURLDisconnected) {
+ cls.realFrametime = msec;
+ cls.frametime = msec;
+ cls.realtime += cls.frametime;
+ SCR_UpdateScreen();
+ S_Update();
+ Con_RunConsole();
+ cls.framecount++;
+ return;
+ }
+ }
+#endif
+
if ( cls.cddialog ) {
// bring up the cd error dialog if needed
cls.cddialog = qfalse;
@@ -2478,6 +2557,9 @@ void CL_Init( void ) {
cl_showMouseRate = Cvar_Get ("cl_showmouserate", "0", 0);
cl_allowDownload = Cvar_Get ("cl_allowDownload", "0", CVAR_ARCHIVE);
+#if USE_CURL
+ cl_cURLLib = Cvar_Get("cl_cURLLib", DEFAULT_CURL_LIB, CVAR_ARCHIVE);
+#endif
cl_conXOffset = Cvar_Get ("cl_conXOffset", "0", 0);
#ifdef MACOS_X
diff --git a/code/client/cl_parse.c b/code/client/cl_parse.c
index d8ad6d7..3039849 100644
--- a/code/client/cl_parse.c
+++ b/code/client/cl_parse.c
@@ -414,6 +414,25 @@ void CL_SystemInfoChanged( void ) {
/*
==================
+CL_ParseServerInfo
+==================
+*/
+static void CL_ParseServerInfo(void)
+{
+ const char *serverInfo;
+
+ serverInfo = cl.gameState.stringData
+ + cl.gameState.stringOffsets[ CS_SERVERINFO ];
+
+ clc.sv_allowDownload = atoi(Info_ValueForKey(serverInfo,
+ "sv_allowDownload"));
+ Q_strncpyz(clc.sv_dlURL,
+ Info_ValueForKey(serverInfo, "sv_dlURL"),
+ sizeof(clc.sv_dlURL));
+}
+
+/*
+==================
CL_ParseGamestate
==================
*/
@@ -479,6 +498,9 @@ void CL_ParseGamestate( msg_t *msg ) {
// read the checksum feed
clc.checksumFeed = MSG_ReadLong( msg );
+ // parse useful values out of CS_SERVERINFO
+ CL_ParseServerInfo();
+
// parse serverId and other cvars
CL_SystemInfoChanged();
diff --git a/code/client/client.h b/code/client/client.h
index 9db786a..89cb477 100644
--- a/code/client/client.h
+++ b/code/client/client.h
@@ -30,6 +30,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "../cgame/cg_public.h"
#include "../game/bg_public.h"
+#if USE_CURL
+#include "cl_curl.h"
+#endif /* USE_CURL */
+
// tjw: file full of random crap that gets used to create cl_guid
#define QKEY_FILE "qkey"
@@ -185,6 +189,16 @@ typedef struct {
fileHandle_t download;
char downloadTempName[MAX_OSPATH];
char downloadName[MAX_OSPATH];
+#ifdef USE_CURL
+ qboolean cURLEnabled;
+ qboolean cURLUsed;
+ qboolean cURLDisconnected;
+ char downloadURL[MAX_OSPATH];
+ CURL *downloadCURL;
+ CURLM *downloadCURLM;
+#endif /* USE_CURL */
+ int sv_allowDownload;
+ char sv_dlURL[MAX_CVAR_VALUE_STRING];
int downloadNumber;
int downloadBlock; // block we are waiting for
int downloadCount; // how many bytes we got
@@ -351,6 +365,7 @@ extern cvar_t *cl_aviMotionJpeg;
extern cvar_t *cl_activeAction;
extern cvar_t *cl_allowDownload;
+extern cvar_t *cl_downloadMethod;
extern cvar_t *cl_conXOffset;
extern cvar_t *cl_inGameVideo;