mirror of
https://github.com/ioquake/ioq3.git
synced 2024-11-10 07:11:46 +00:00
* add cURL support for HTTP/FTP downloading (bug 2661)
This commit is contained in:
parent
fa904ff235
commit
2af23e813d
18 changed files with 2829 additions and 6 deletions
51
Makefile
51
Makefile
|
@ -100,6 +100,18 @@ ifndef USE_OPENAL_DLOPEN
|
|||
USE_OPENAL_DLOPEN=0
|
||||
endif
|
||||
|
||||
ifndef USE_CURL
|
||||
USE_CURL=1
|
||||
endif
|
||||
|
||||
ifndef USE_CURL_DLOPEN
|
||||
ifeq ($(PLATFORM),mingw32)
|
||||
USE_CURL_DLOPEN=0
|
||||
else
|
||||
USE_CURL_DLOPEN=1
|
||||
endif
|
||||
endif
|
||||
|
||||
ifndef USE_CODEC_VORBIS
|
||||
USE_CODEC_VORBIS=0
|
||||
endif
|
||||
|
@ -187,6 +199,13 @@ ifeq ($(PLATFORM),linux)
|
|||
BASE_CFLAGS += -DUSE_OPENAL_DLOPEN=1
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(USE_CURL),1)
|
||||
BASE_CFLAGS += -DUSE_CURL=1
|
||||
ifeq ($(USE_CURL_DLOPEN),1)
|
||||
BASE_CFLAGS += -DUSE_CURL_DLOPEN=1
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(USE_CODEC_VORBIS),1)
|
||||
BASE_CFLAGS += -DUSE_CODEC_VORBIS=1
|
||||
|
@ -249,6 +268,12 @@ ifeq ($(PLATFORM),linux)
|
|||
CLIENT_LDFLAGS += -lopenal
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(USE_CURL),1)
|
||||
ifneq ($(USE_CURL_DLOPEN),1)
|
||||
CLIENT_LDFLAGS += -lcurl
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(USE_CODEC_VORBIS),1)
|
||||
CLIENT_LDFLAGS += -lvorbisfile -lvorbis -logg
|
||||
|
@ -348,6 +373,15 @@ ifeq ($(PLATFORM),darwin)
|
|||
BASE_CFLAGS += -DUSE_OPENAL_DLOPEN=1
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(USE_CURL),1)
|
||||
BASE_CFLAGS += -DUSE_CURL=1
|
||||
ifneq ($(USE_CURL_DLOPEN),1)
|
||||
CLIENT_LDFLAGS += -lcurl
|
||||
else
|
||||
BASE_CFLAGS += -DUSE_CURL_DLOPEN=1
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(USE_CODEC_VORBIS),1)
|
||||
BASE_CFLAGS += -DUSE_CODEC_VORBIS=1
|
||||
|
@ -404,6 +438,13 @@ ifeq ($(PLATFORM),mingw32)
|
|||
ifeq ($(USE_OPENAL),1)
|
||||
BASE_CFLAGS += -DUSE_OPENAL=1 -DUSE_OPENAL_DLOPEN=1
|
||||
endif
|
||||
|
||||
ifeq ($(USE_CURL),1)
|
||||
BASE_CFLAGS += -DUSE_CURL=1
|
||||
ifneq ($(USE_CURL_DLOPEN),1)
|
||||
BASE_CFLAGS += -DCURL_STATICLIB
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(USE_CODEC_VORBIS),1)
|
||||
BASE_CFLAGS += -DUSE_CODEC_VORBIS=1
|
||||
|
@ -430,6 +471,12 @@ ifeq ($(PLATFORM),mingw32)
|
|||
LDFLAGS= -mwindows -lshfolder -lwsock32 -lgdi32 -lwinmm -lole32
|
||||
CLIENT_LDFLAGS=
|
||||
|
||||
ifeq ($(USE_CURL),1)
|
||||
ifneq ($(USE_CURL_DLOPEN),1)
|
||||
CLIENT_LDFLAGS += $(LIBSDIR)/win32/libcurl.a
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(USE_CODEC_VORBIS),1)
|
||||
CLIENT_LDFLAGS += -lvorbisfile -lvorbis -logg
|
||||
endif
|
||||
|
@ -847,6 +894,8 @@ Q3OBJ = \
|
|||
$(B)/client/qal.o \
|
||||
$(B)/client/snd_openal.o \
|
||||
\
|
||||
$(B)/client/cl_curl.o \
|
||||
\
|
||||
$(B)/client/sv_bot.o \
|
||||
$(B)/client/sv_ccmds.o \
|
||||
$(B)/client/sv_client.o \
|
||||
|
@ -1067,6 +1116,8 @@ $(B)/client/snd_codec_ogg.o : $(CDIR)/snd_codec_ogg.c; $(DO_CC)
|
|||
$(B)/client/qal.o : $(CDIR)/qal.c; $(DO_CC)
|
||||
$(B)/client/snd_openal.o : $(CDIR)/snd_openal.c; $(DO_CC)
|
||||
|
||||
$(B)/client/cl_curl.o : $(CDIR)/cl_curl.c; $(DO_CC)
|
||||
|
||||
$(B)/client/sv_bot.o : $(SDIR)/sv_bot.c; $(DO_CC)
|
||||
$(B)/client/sv_client.o : $(SDIR)/sv_client.c; $(DO_CC)
|
||||
$(B)/client/sv_ccmds.o : $(SDIR)/sv_ccmds.c; $(DO_CC)
|
||||
|
|
41
README
41
README
|
@ -23,6 +23,7 @@ for further development. Some of the major features currently implemented are:
|
|||
* Much improved QVM tools
|
||||
* Support for various esoteric operating systems (see
|
||||
http://icculus.org/quake3/?page=status)
|
||||
* HTTP/FTP download redirection (using cURL)
|
||||
* Many, many bug fixes
|
||||
|
||||
The map editor and associated compiling tools are not included. We suggest you
|
||||
|
@ -140,6 +141,9 @@ New cvars
|
|||
cl_platformSensitivity - read only, indicates the mouse input
|
||||
scaling
|
||||
r_ext_texture_filter_anisotropic - anisotropic texture filtering
|
||||
cl_cURLLib - filename of cURL library to load
|
||||
sv_dlURL - the base of the HTTP or FTP site that
|
||||
holds custom pk3 files for your server
|
||||
|
||||
New commands
|
||||
video [filename] - start video capture (use with demo command)
|
||||
|
@ -192,6 +196,43 @@ Creating mods compatible with Q3 1.32b
|
|||
compiler. See http://www.quakesrc.org/forums/viewtopic.php?t=5665 (if it
|
||||
still exists when you read this) for more details.
|
||||
|
||||
Using HTTP/FTP Download Support (Server)
|
||||
You can enable redirected downloads on your server even if it's not
|
||||
an ioquake3 server. You simply need to use the 'sets' command to put
|
||||
the sv_dlURL cvar into your SERVERINFO string and ensure sv_allowDownloads
|
||||
is set to 1
|
||||
|
||||
sv_dlURL is the base of the URL that contains your custom .pk3 files
|
||||
the client will append both fs_game and the filename to the end of
|
||||
this value. For example, if you have sv_dlURL set to
|
||||
"http://icculus.org/quake3", fs_game is "baseq3", and the client is
|
||||
missing "test.pk3", it will attempt to download from the URL
|
||||
"http://icculus.org/quake3/baseq3/test.pk3"
|
||||
|
||||
sv_allowDownload's value is now a bitmask made up of the following
|
||||
flags:
|
||||
1 - ENABLE
|
||||
2 - do not use HTTP/FTP downloads
|
||||
4 - do not use UDP downloads
|
||||
8 - do not ask the client to disconnect when using HTTP/FTP
|
||||
|
||||
Server operators who are concerned about potential "leeching" from their
|
||||
HTTP servers from other ioquake3 servers can make use of the HTTP_REFERER
|
||||
that ioquake3 sets which is "ioQ3://{SERVER_IP}:{SERVER_PORT}". For,
|
||||
example, Apache's mod_rewrite can restrict access based on HTTP_REFERER.
|
||||
|
||||
Using HTTP/FTP Download Support (Client)
|
||||
Simply setting cl_allowDownload to 1 will enable HTTP/FTP downloads
|
||||
assuming ioquake3 was compiled with USE_CURL=1 (the default).
|
||||
like sv_allowDownload, cl_allowDownload also uses a bitmask value
|
||||
supporting the following flags:
|
||||
1 - ENABLE
|
||||
2 - do not use HTTP/FTP downloads
|
||||
4 - do not use UDP downloads
|
||||
|
||||
When ioquake3 is built with USE_CURL_DLOPEN=1 (default on some platforms),
|
||||
it will use the value of the cvar cl_cURLLib as the filename of the cURL
|
||||
library to dynamically load.
|
||||
|
||||
------------------------------------------------------------- Contributing -----
|
||||
|
||||
|
|
358
code/client/cl_curl.c
Normal file
358
code/client/cl_curl.c
Normal file
|
@ -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 */
|
101
code/client/cl_curl.h
Normal file
101
code/client/cl_curl.h
Normal file
|
@ -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__
|
|
@ -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
|
||||
|
|
|
@ -412,6 +412,25 @@ void CL_SystemInfoChanged( void ) {
|
|||
cl_connectedToPureServer = Cvar_VariableValue( "sv_pure" );
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
1563
code/libcurl/curl/curl.h
Normal file
1563
code/libcurl/curl/curl.h
Normal file
File diff suppressed because it is too large
Load diff
56
code/libcurl/curl/curlver.h
Normal file
56
code/libcurl/curl/curlver.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
#ifndef __CURL_CURLVER_H
|
||||
#define __CURL_CURLVER_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at http://curl.haxx.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* $Id: curlver.h,v 1.21 2006-06-12 07:24:14 bagder Exp $
|
||||
***************************************************************************/
|
||||
|
||||
/* This header file contains nothing but libcurl version info, generated by
|
||||
a script at release-time. This was made its own header file in 7.11.2 */
|
||||
|
||||
/* This is the version number of the libcurl package from which this header
|
||||
file origins: */
|
||||
#define LIBCURL_VERSION "7.15.5"
|
||||
|
||||
/* The numeric version number is also available "in parts" by using these
|
||||
defines: */
|
||||
#define LIBCURL_VERSION_MAJOR 7
|
||||
#define LIBCURL_VERSION_MINOR 15
|
||||
#define LIBCURL_VERSION_PATCH 5
|
||||
|
||||
/* This is the numeric version of the libcurl version number, meant for easier
|
||||
parsing and comparions by programs. The LIBCURL_VERSION_NUM define will
|
||||
always follow this syntax:
|
||||
|
||||
0xXXYYZZ
|
||||
|
||||
Where XX, YY and ZZ are the main version, release and patch numbers in
|
||||
hexadecimal (using 8 bits each). All three numbers are always represented
|
||||
using two digits. 1.2 would appear as "0x010200" while version 9.11.7
|
||||
appears as "0x090b07".
|
||||
|
||||
This 6-digit (24 bits) hexadecimal number does not show pre-release number,
|
||||
and it is always a greater number in a more recent release. It makes
|
||||
comparisons with greater than and less than work.
|
||||
*/
|
||||
#define LIBCURL_VERSION_NUM 0x070f05
|
||||
|
||||
#endif /* __CURL_CURLVER_H */
|
81
code/libcurl/curl/easy.h
Normal file
81
code/libcurl/curl/easy.h
Normal file
|
@ -0,0 +1,81 @@
|
|||
#ifndef __CURL_EASY_H
|
||||
#define __CURL_EASY_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at http://curl.haxx.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* $Id: easy.h,v 1.13 2004/11/09 14:02:58 giva Exp $
|
||||
***************************************************************************/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
CURL_EXTERN CURL *curl_easy_init(void);
|
||||
CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...);
|
||||
CURL_EXTERN CURLcode curl_easy_perform(CURL *curl);
|
||||
CURL_EXTERN void curl_easy_cleanup(CURL *curl);
|
||||
|
||||
/*
|
||||
* NAME curl_easy_getinfo()
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Request internal information from the curl session with this function. The
|
||||
* third argument MUST be a pointer to a long, a pointer to a char * or a
|
||||
* pointer to a double (as the documentation describes elsewhere). The data
|
||||
* pointed to will be filled in accordingly and can be relied upon only if the
|
||||
* function returns CURLE_OK. This function is intended to get used *AFTER* a
|
||||
* performed transfer, all results from this function are undefined until the
|
||||
* transfer is completed.
|
||||
*/
|
||||
CURL_EXTERN CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...);
|
||||
|
||||
|
||||
/*
|
||||
* NAME curl_easy_duphandle()
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Creates a new curl session handle with the same options set for the handle
|
||||
* passed in. Duplicating a handle could only be a matter of cloning data and
|
||||
* options, internal state info and things like persistant connections cannot
|
||||
* be transfered. It is useful in multithreaded applications when you can run
|
||||
* curl_easy_duphandle() for each new thread to avoid a series of identical
|
||||
* curl_easy_setopt() invokes in every thread.
|
||||
*/
|
||||
CURL_EXTERN CURL* curl_easy_duphandle(CURL *curl);
|
||||
|
||||
/*
|
||||
* NAME curl_easy_reset()
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Re-initializes a CURL handle to the default values. This puts back the
|
||||
* handle to the same state as it was in when it was just created.
|
||||
*
|
||||
* It does keep: live connections, the Session ID cache, the DNS cache and the
|
||||
* cookies.
|
||||
*/
|
||||
CURL_EXTERN void curl_easy_reset(CURL *curl);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
62
code/libcurl/curl/mprintf.h
Normal file
62
code/libcurl/curl/mprintf.h
Normal file
|
@ -0,0 +1,62 @@
|
|||
#ifndef __CURL_MPRINTF_H
|
||||
#define __CURL_MPRINTF_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at http://curl.haxx.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* $Id: mprintf.h,v 1.13 2006-03-28 10:08:54 bagder Exp $
|
||||
***************************************************************************/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h> /* needed for FILE */
|
||||
|
||||
#include "curl.h"
|
||||
|
||||
CURL_EXTERN int curl_mprintf(const char *format, ...);
|
||||
CURL_EXTERN int curl_mfprintf(FILE *fd, const char *format, ...);
|
||||
CURL_EXTERN int curl_msprintf(char *buffer, const char *format, ...);
|
||||
CURL_EXTERN int curl_msnprintf(char *buffer, size_t maxlength, const char *format, ...);
|
||||
CURL_EXTERN int curl_mvprintf(const char *format, va_list args);
|
||||
CURL_EXTERN int curl_mvfprintf(FILE *fd, const char *format, va_list args);
|
||||
CURL_EXTERN int curl_mvsprintf(char *buffer, const char *format, va_list args);
|
||||
CURL_EXTERN int curl_mvsnprintf(char *buffer, size_t maxlength, const char *format, va_list args);
|
||||
CURL_EXTERN char *curl_maprintf(const char *format, ...);
|
||||
CURL_EXTERN char *curl_mvaprintf(const char *format, va_list args);
|
||||
|
||||
#ifdef _MPRINTF_REPLACE
|
||||
# define printf curl_mprintf
|
||||
# define fprintf curl_mfprintf
|
||||
#ifdef CURLDEBUG
|
||||
/* When built with CURLDEBUG we define away the sprintf() functions since we
|
||||
don't want internal code to be using them */
|
||||
# define sprintf sprintf_was_used
|
||||
# define vsprintf vsprintf_was_used
|
||||
#else
|
||||
# define sprintf curl_msprintf
|
||||
# define vsprintf curl_mvsprintf
|
||||
#endif
|
||||
# define snprintf curl_msnprintf
|
||||
# define vprintf curl_mvprintf
|
||||
# define vfprintf curl_mvfprintf
|
||||
# define vsnprintf curl_mvsnprintf
|
||||
# define aprintf curl_maprintf
|
||||
# define vaprintf curl_mvaprintf
|
||||
#endif
|
||||
|
||||
#endif /* __CURL_MPRINTF_H */
|
344
code/libcurl/curl/multi.h
Normal file
344
code/libcurl/curl/multi.h
Normal file
|
@ -0,0 +1,344 @@
|
|||
#ifndef __CURL_MULTI_H
|
||||
#define __CURL_MULTI_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at http://curl.haxx.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* $Id: multi.h,v 1.38 2006-08-04 18:53:48 danf Exp $
|
||||
***************************************************************************/
|
||||
/*
|
||||
This is an "external" header file. Don't give away any internals here!
|
||||
|
||||
GOALS
|
||||
|
||||
o Enable a "pull" interface. The application that uses libcurl decides where
|
||||
and when to ask libcurl to get/send data.
|
||||
|
||||
o Enable multiple simultaneous transfers in the same thread without making it
|
||||
complicated for the application.
|
||||
|
||||
o Enable the application to select() on its own file descriptors and curl's
|
||||
file descriptors simultaneous easily.
|
||||
|
||||
*/
|
||||
#if defined(_WIN32) && !defined(WIN32)
|
||||
/* Chris Lewis mentioned that he doesn't get WIN32 defined, only _WIN32 so we
|
||||
make this adjustment to catch this. */
|
||||
#define WIN32 1
|
||||
#endif
|
||||
|
||||
#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__GNUC__) && \
|
||||
!defined(__CYGWIN__) || defined(__MINGW32__)
|
||||
#if !(defined(_WINSOCKAPI_) || defined(_WINSOCK_H))
|
||||
/* The check above prevents the winsock2 inclusion if winsock.h already was
|
||||
included, since they can't co-exist without problems */
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
#else
|
||||
|
||||
/* HP-UX systems version 9, 10 and 11 lack sys/select.h and so does oldish
|
||||
libc5-based Linux systems. Only include it on system that are known to
|
||||
require it! */
|
||||
#if defined(_AIX) || defined(NETWARE) || defined(__NetBSD__) || defined(_MINIX)
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32_WCE
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This header file should not really need to include "curl.h" since curl.h
|
||||
* itself includes this file and we expect user applications to do #include
|
||||
* <curl/curl.h> without the need for especially including multi.h.
|
||||
*
|
||||
* For some reason we added this include here at one point, and rather than to
|
||||
* break existing (wrongly written) libcurl applications, we leave it as-is
|
||||
* but with this warning attached.
|
||||
*/
|
||||
#include "curl.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void CURLM;
|
||||
|
||||
#ifndef curl_socket_typedef
|
||||
/* Public socket typedef */
|
||||
#ifdef WIN32
|
||||
typedef SOCKET curl_socket_t;
|
||||
#define CURL_SOCKET_BAD INVALID_SOCKET
|
||||
#else
|
||||
typedef int curl_socket_t;
|
||||
#define CURL_SOCKET_BAD -1
|
||||
#endif
|
||||
#define curl_socket_typedef
|
||||
#endif /* curl_socket_typedef */
|
||||
|
||||
typedef enum {
|
||||
CURLM_CALL_MULTI_PERFORM = -1, /* please call curl_multi_perform() or
|
||||
curl_multi_socket*() soon */
|
||||
CURLM_OK,
|
||||
CURLM_BAD_HANDLE, /* the passed-in handle is not a valid CURLM handle */
|
||||
CURLM_BAD_EASY_HANDLE, /* an easy handle was not good/valid */
|
||||
CURLM_OUT_OF_MEMORY, /* if you ever get this, you're in deep sh*t */
|
||||
CURLM_INTERNAL_ERROR, /* this is a libcurl bug */
|
||||
CURLM_BAD_SOCKET, /* the passed in socket argument did not match */
|
||||
CURLM_UNKNOWN_OPTION, /* curl_multi_setopt() with unsupported option */
|
||||
CURLM_LAST
|
||||
} CURLMcode;
|
||||
|
||||
/* just to make code nicer when using curl_multi_socket() you can now check
|
||||
for CURLM_CALL_MULTI_SOCKET too in the same style it works for
|
||||
curl_multi_perform() and CURLM_CALL_MULTI_PERFORM */
|
||||
#define CURLM_CALL_MULTI_SOCKET CURLM_CALL_MULTI_PERFORM
|
||||
|
||||
typedef enum {
|
||||
CURLMSG_NONE, /* first, not used */
|
||||
CURLMSG_DONE, /* This easy handle has completed. 'result' contains
|
||||
the CURLcode of the transfer */
|
||||
CURLMSG_LAST /* last, not used */
|
||||
} CURLMSG;
|
||||
|
||||
struct CURLMsg {
|
||||
CURLMSG msg; /* what this message means */
|
||||
CURL *easy_handle; /* the handle it concerns */
|
||||
union {
|
||||
void *whatever; /* message-specific data */
|
||||
CURLcode result; /* return code for transfer */
|
||||
} data;
|
||||
};
|
||||
typedef struct CURLMsg CURLMsg;
|
||||
|
||||
/*
|
||||
* Name: curl_multi_init()
|
||||
*
|
||||
* Desc: inititalize multi-style curl usage
|
||||
*
|
||||
* Returns: a new CURLM handle to use in all 'curl_multi' functions.
|
||||
*/
|
||||
CURL_EXTERN CURLM *curl_multi_init(void);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_add_handle()
|
||||
*
|
||||
* Desc: add a standard curl handle to the multi stack
|
||||
*
|
||||
* Returns: CURLMcode type, general multi error code.
|
||||
*/
|
||||
CURL_EXTERN CURLMcode curl_multi_add_handle(CURLM *multi_handle,
|
||||
CURL *curl_handle);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_remove_handle()
|
||||
*
|
||||
* Desc: removes a curl handle from the multi stack again
|
||||
*
|
||||
* Returns: CURLMcode type, general multi error code.
|
||||
*/
|
||||
CURL_EXTERN CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
|
||||
CURL *curl_handle);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_fdset()
|
||||
*
|
||||
* Desc: Ask curl for its fd_set sets. The app can use these to select() or
|
||||
* poll() on. We want curl_multi_perform() called as soon as one of
|
||||
* them are ready.
|
||||
*
|
||||
* Returns: CURLMcode type, general multi error code.
|
||||
*/
|
||||
CURL_EXTERN CURLMcode curl_multi_fdset(CURLM *multi_handle,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
fd_set *exc_fd_set,
|
||||
int *max_fd);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_perform()
|
||||
*
|
||||
* Desc: When the app thinks there's data available for curl it calls this
|
||||
* function to read/write whatever there is right now. This returns
|
||||
* as soon as the reads and writes are done. This function does not
|
||||
* require that there actually is data available for reading or that
|
||||
* data can be written, it can be called just in case. It returns
|
||||
* the number of handles that still transfer data in the second
|
||||
* argument's integer-pointer.
|
||||
*
|
||||
* Returns: CURLMcode type, general multi error code. *NOTE* that this only
|
||||
* returns errors etc regarding the whole multi stack. There might
|
||||
* still have occurred problems on invidual transfers even when this
|
||||
* returns OK.
|
||||
*/
|
||||
CURL_EXTERN CURLMcode curl_multi_perform(CURLM *multi_handle,
|
||||
int *running_handles);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_cleanup()
|
||||
*
|
||||
* Desc: Cleans up and removes a whole multi stack. It does not free or
|
||||
* touch any individual easy handles in any way. We need to define
|
||||
* in what state those handles will be if this function is called
|
||||
* in the middle of a transfer.
|
||||
*
|
||||
* Returns: CURLMcode type, general multi error code.
|
||||
*/
|
||||
CURL_EXTERN CURLMcode curl_multi_cleanup(CURLM *multi_handle);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_info_read()
|
||||
*
|
||||
* Desc: Ask the multi handle if there's any messages/informationals from
|
||||
* the individual transfers. Messages include informationals such as
|
||||
* error code from the transfer or just the fact that a transfer is
|
||||
* completed. More details on these should be written down as well.
|
||||
*
|
||||
* Repeated calls to this function will return a new struct each
|
||||
* time, until a special "end of msgs" struct is returned as a signal
|
||||
* that there is no more to get at this point.
|
||||
*
|
||||
* The data the returned pointer points to will not survive calling
|
||||
* curl_multi_cleanup().
|
||||
*
|
||||
* The 'CURLMsg' struct is meant to be very simple and only contain
|
||||
* very basic informations. If more involved information is wanted,
|
||||
* we will provide the particular "transfer handle" in that struct
|
||||
* and that should/could/would be used in subsequent
|
||||
* curl_easy_getinfo() calls (or similar). The point being that we
|
||||
* must never expose complex structs to applications, as then we'll
|
||||
* undoubtably get backwards compatibility problems in the future.
|
||||
*
|
||||
* Returns: A pointer to a filled-in struct, or NULL if it failed or ran out
|
||||
* of structs. It also writes the number of messages left in the
|
||||
* queue (after this read) in the integer the second argument points
|
||||
* to.
|
||||
*/
|
||||
CURL_EXTERN CURLMsg *curl_multi_info_read(CURLM *multi_handle,
|
||||
int *msgs_in_queue);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_strerror()
|
||||
*
|
||||
* Desc: The curl_multi_strerror function may be used to turn a CURLMcode
|
||||
* value into the equivalent human readable error string. This is
|
||||
* useful for printing meaningful error messages.
|
||||
*
|
||||
* Returns: A pointer to a zero-terminated error message.
|
||||
*/
|
||||
CURL_EXTERN const char *curl_multi_strerror(CURLMcode);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_socket() and
|
||||
* curl_multi_socket_all()
|
||||
*
|
||||
* Desc: An alternative version of curl_multi_perform() that allows the
|
||||
* application to pass in one of the file descriptors that have been
|
||||
* detected to have "action" on them and let libcurl perform.
|
||||
* See man page for details.
|
||||
*/
|
||||
#define CURL_POLL_NONE 0
|
||||
#define CURL_POLL_IN 1
|
||||
#define CURL_POLL_OUT 2
|
||||
#define CURL_POLL_INOUT 3
|
||||
#define CURL_POLL_REMOVE 4
|
||||
|
||||
#define CURL_SOCKET_TIMEOUT CURL_SOCKET_BAD
|
||||
|
||||
typedef int (*curl_socket_callback)(CURL *easy, /* easy handle */
|
||||
curl_socket_t s, /* socket */
|
||||
int what, /* see above */
|
||||
void *userp, /* private callback
|
||||
pointer */
|
||||
void *socketp); /* private socket
|
||||
pointer */
|
||||
|
||||
CURL_EXTERN CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s,
|
||||
int *running_handles);
|
||||
|
||||
CURL_EXTERN CURLMcode curl_multi_socket_all(CURLM *multi_handle,
|
||||
int *running_handles);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_timeout()
|
||||
*
|
||||
* Desc: Returns the maximum number of milliseconds the app is allowed to
|
||||
* wait before curl_multi_socket() or curl_multi_perform() must be
|
||||
* called (to allow libcurl's timed events to take place).
|
||||
*
|
||||
* Returns: CURLM error code.
|
||||
*/
|
||||
CURL_EXTERN CURLMcode curl_multi_timeout(CURLM *multi_handle,
|
||||
long *milliseconds);
|
||||
|
||||
#undef CINIT /* re-using the same name as in curl.h */
|
||||
|
||||
#ifdef CURL_ISOCPP
|
||||
#define CINIT(name,type,number) CURLMOPT_ ## name = CURLOPTTYPE_ ## type + number
|
||||
#else
|
||||
/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */
|
||||
#define LONG CURLOPTTYPE_LONG
|
||||
#define OBJECTPOINT CURLOPTTYPE_OBJECTPOINT
|
||||
#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT
|
||||
#define OFF_T CURLOPTTYPE_OFF_T
|
||||
#define CINIT(name,type,number) CURLMOPT_/**/name = type + number
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
/* This is the socket callback function pointer */
|
||||
CINIT(SOCKETFUNCTION, FUNCTIONPOINT, 1),
|
||||
|
||||
/* This is the argument passed to the socket callback */
|
||||
CINIT(SOCKETDATA, OBJECTPOINT, 2),
|
||||
|
||||
CURLMOPT_LASTENTRY /* the last unused */
|
||||
} CURLMoption;
|
||||
|
||||
|
||||
/*
|
||||
* Name: curl_multi_setopt()
|
||||
*
|
||||
* Desc: Sets options for the multi handle.
|
||||
*
|
||||
* Returns: CURLM error code.
|
||||
*/
|
||||
CURL_EXTERN CURLMcode curl_multi_setopt(CURLM *multi_handle,
|
||||
CURLMoption option, ...);
|
||||
|
||||
|
||||
/*
|
||||
* Name: curl_multi_assign()
|
||||
*
|
||||
* Desc: This function sets an association in the multi handle between the
|
||||
* given socket and a private pointer of the application. This is
|
||||
* (only) useful for curl_multi_socket uses.
|
||||
*
|
||||
* Returns: CURLM error code.
|
||||
*/
|
||||
CURL_EXTERN CURLMcode curl_multi_assign(CURLM *multi_handle,
|
||||
curl_socket_t sockfd, void *sockp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
34
code/libcurl/curl/stdcheaders.h
Normal file
34
code/libcurl/curl/stdcheaders.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
#ifndef __STDC_HEADERS_H
|
||||
#define __STDC_HEADERS_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at http://curl.haxx.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* $Id: stdcheaders.h,v 1.8 2004/01/07 09:19:34 bagder Exp $
|
||||
***************************************************************************/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
size_t fread (void *, size_t, size_t, FILE *);
|
||||
size_t fwrite (const void *, size_t, size_t, FILE *);
|
||||
|
||||
int strcasecmp(const char *, const char *);
|
||||
int strncasecmp(const char *, const char *, size_t);
|
||||
|
||||
#endif
|
1
code/libcurl/curl/types.h
Normal file
1
code/libcurl/curl/types.h
Normal file
|
@ -0,0 +1 @@
|
|||
/* not used */
|
BIN
code/libs/win32/libcurl.a
Normal file
BIN
code/libs/win32/libcurl.a
Normal file
Binary file not shown.
|
@ -1100,4 +1100,10 @@ extern huffman_t clientHuffTables;
|
|||
#define CL_ENCODE_START 12
|
||||
#define CL_DECODE_START 4
|
||||
|
||||
// flags for sv_allowDownload and cl_allowDownload
|
||||
#define DLF_ENABLE 1
|
||||
#define DLF_NO_REDIRECT 2
|
||||
#define DLF_NO_UDP 4
|
||||
#define DLF_NO_DISCONNECT 8
|
||||
|
||||
#endif // _QCOMMON_H_
|
||||
|
|
|
@ -801,7 +801,9 @@ void SV_WriteDownloadToClient( client_t *cl , msg_t *msg )
|
|||
}
|
||||
|
||||
// We open the file here
|
||||
if ( !sv_allowDownload->integer || idPack || unreferenced ||
|
||||
if ( !(sv_allowDownload->integer & DLF_ENABLE) ||
|
||||
(sv_allowDownload->integer & DLF_NO_UDP) ||
|
||||
idPack || unreferenced ||
|
||||
( cl->downloadSize = FS_SV_FOpenFileRead( cl->downloadName, &cl->download ) ) <= 0 ) {
|
||||
// cannot auto-download file
|
||||
if(unreferenced)
|
||||
|
@ -818,7 +820,10 @@ void SV_WriteDownloadToClient( client_t *cl , msg_t *msg )
|
|||
else {
|
||||
Com_sprintf(errorMessage, sizeof(errorMessage), "Cannot autodownload id pk3 file \"%s\"", cl->downloadName);
|
||||
}
|
||||
} else if ( !sv_allowDownload->integer ) {
|
||||
}
|
||||
else if ( !(sv_allowDownload->integer & DLF_ENABLE) ||
|
||||
(sv_allowDownload->integer & DLF_NO_UDP) ) {
|
||||
|
||||
Com_Printf("clientDownload: %d : \"%s\" download disabled", cl - svs.clients, cl->downloadName);
|
||||
if (sv_pure->integer) {
|
||||
Com_sprintf(errorMessage, sizeof(errorMessage), "Could not download \"%s\" because autodownloading is disabled on the server.\n\n"
|
||||
|
|
|
@ -606,6 +606,7 @@ void SV_Init (void) {
|
|||
Cvar_Get ("nextmap", "", CVAR_TEMP );
|
||||
|
||||
sv_allowDownload = Cvar_Get ("sv_allowDownload", "0", CVAR_SERVERINFO);
|
||||
Cvar_Get ("sv_dlURL", "", CVAR_SERVERINFO | CVAR_ARCHIVE);
|
||||
sv_master[0] = Cvar_Get ("sv_master1", MASTER_SERVER_NAME, 0 );
|
||||
sv_master[1] = Cvar_Get ("sv_master2", "", CVAR_ARCHIVE );
|
||||
sv_master[2] = Cvar_Get ("sv_master3", "", CVAR_ARCHIVE );
|
||||
|
|
Loading…
Reference in a new issue