From 5b45b44b766e3a88b3590893b84a7f516c71a2e2 Mon Sep 17 00:00:00 2001 From: divverent Date: Fri, 12 Sep 2008 08:14:24 +0000 Subject: [PATCH] add extension DP_QC_URI_GET (downloads HTTP/whatever URLs to QC strings using a callback) git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@8502 d7cf8633-e32d-0410-b094-e92efae38249 --- clvm_cmds.c | 2 +- mvm_cmds.c | 3 ++- progsvm.h | 1 + prvm_cmds.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++ prvm_cmds.h | 1 + prvm_edict.c | 1 + svvm_cmds.c | 3 ++- 7 files changed, 77 insertions(+), 3 deletions(-) diff --git a/clvm_cmds.c b/clvm_cmds.c index 16c9ce81..f1d3b4ac 100644 --- a/clvm_cmds.c +++ b/clvm_cmds.c @@ -3487,7 +3487,7 @@ NULL, // #509 VM_uri_escape, // #510 string(string in) uri_escape = #510; VM_uri_unescape, // #511 string(string in) uri_unescape = #511; VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT) -NULL, // #513 +VM_uri_get, // #513 float(string uril, float id) uri_get = #512; (DP_QC_URI_GET) NULL, // #514 NULL, // #515 NULL, // #516 diff --git a/mvm_cmds.c b/mvm_cmds.c index 0581a1c8..5b507dd3 100644 --- a/mvm_cmds.c +++ b/mvm_cmds.c @@ -26,6 +26,7 @@ char *vm_m_extensions = "DP_QC_TOKENIZEBYSEPARATOR " "DP_QC_UNLIMITEDTEMPSTRINGS " "DP_QC_URI_ESCAPE " +"DP_QC_URI_GET " "DP_QC_WHICHPACK " "FTE_STRINGS " ; @@ -1356,7 +1357,7 @@ NULL, // #509 VM_uri_escape, // #510 string(string in) uri_escape = #510; VM_uri_unescape, // #511 string(string in) uri_unescape = #511; VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT) -NULL, // #513 +VM_uri_get, // #513 float(string uril, float id) uri_get = #513; (DP_QC_URI_GET) NULL, // #514 NULL, // #515 NULL, // #516 diff --git a/progsvm.h b/progsvm.h index 41640fc4..cabd7b40 100644 --- a/progsvm.h +++ b/progsvm.h @@ -286,6 +286,7 @@ typedef struct prvm_prog_funcoffsets_s func_t SV_OnEntityNoSpawnFunction; // ssqc func_t GameCommand; // any func_t SV_Shutdown; // ssqc + func_t URI_Get_Callback; // any // menu qc only uses some functions, nothing else func_t m_draw; // mqc diff --git a/prvm_cmds.c b/prvm_cmds.c index 82cbb3fe..2a4ebc87 100644 --- a/prvm_cmds.c +++ b/prvm_cmds.c @@ -7,6 +7,7 @@ #include "quakedef.h" #include "prvm_cmds.h" +#include "libcurl.h" #include extern cvar_t prvm_backtraceforwarnings; @@ -4846,3 +4847,71 @@ void VM_whichpack (void) PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(pack ? pack : ""); } +typedef struct +{ + int prognr; + double starttime; + float id; + char buffer[MAX_INPUTLINE]; +} +uri_to_prog_t; + +static void uri_to_string_callback(int status, size_t length_received, unsigned char *buffer, void *cbdata) +{ + uri_to_prog_t *handle = cbdata; + + if(!PRVM_ProgLoaded(handle->prognr)) + { + // curl reply came too late... so just drop it + Z_Free(handle); + return; + } + + PRVM_SetProg(handle->prognr); + PRVM_Begin; + if((prog->starttime == handle->starttime) && (prog->funcoffsets.URI_Get_Callback)) + { + if(length_received >= sizeof(handle->buffer)) + length_received = sizeof(handle->buffer) - 1; + handle->buffer[length_received] = 0; + + PRVM_G_FLOAT(OFS_PARM0) = handle->id; + PRVM_G_FLOAT(OFS_PARM1) = status; + PRVM_G_INT(OFS_PARM2) = PRVM_SetTempString(handle->buffer); + PRVM_ExecuteProgram(prog->funcoffsets.URI_Get_Callback, "QC function URI_Get_Callback is missing"); + } + PRVM_End; + + Z_Free(handle); +} + +// uri_get() gets content from an URL and calls a callback "uri_get_callback" with it set as string; an unique ID of the transfer is returned +// returns 1 on success, and then calls the callback with the ID, 0 or the HTTP status code, and the received data in a string +void VM_uri_get (void) +{ + const char *url; + float id; + qboolean ret; + uri_to_prog_t *handle; + + if(!prog->funcoffsets.URI_Get_Callback) + PRVM_ERROR("uri_get called by %s without URI_Get_Callback defined", PRVM_NAME); + + url = PRVM_G_STRING(OFS_PARM0); + id = PRVM_G_FLOAT(OFS_PARM1); + handle = Z_Malloc(sizeof(*handle)); // this can't be the prog's mem pool, as curl may call the callback later! + + handle->prognr = PRVM_GetProgNr(); + handle->starttime = prog->starttime; + handle->id = id; + ret = Curl_Begin_ToMemory(url, (unsigned char *) handle->buffer, sizeof(handle->buffer), uri_to_string_callback, handle); + if(ret) + { + PRVM_G_INT(OFS_RETURN) = 1; + } + else + { + Z_Free(handle); + PRVM_G_INT(OFS_RETURN) = 0; + } +} diff --git a/prvm_cmds.h b/prvm_cmds.h index d6ab8277..54c8d7db 100644 --- a/prvm_cmds.h +++ b/prvm_cmds.h @@ -429,3 +429,4 @@ void VM_uri_unescape (void); void VM_whichpack (void); void VM_etof (void); +void VM_uri_get (void); diff --git a/prvm_edict.c b/prvm_edict.c index 65ba909d..7c6e16ce 100644 --- a/prvm_edict.c +++ b/prvm_edict.c @@ -1482,6 +1482,7 @@ void PRVM_FindOffsets(void) prog->funcoffsets.SV_OnEntityNoSpawnFunction = PRVM_ED_FindFunctionOffset("SV_OnEntityNoSpawnFunction"); prog->funcoffsets.GameCommand = PRVM_ED_FindFunctionOffset("GameCommand"); prog->funcoffsets.SV_Shutdown = PRVM_ED_FindFunctionOffset("SV_Shutdown"); + prog->funcoffsets.URI_Get_Callback = PRVM_ED_FindFunctionOffset("URI_Get_Callback"); prog->globaloffsets.SV_InitCmd = PRVM_ED_FindGlobalOffset("SV_InitCmd"); prog->globaloffsets.self = PRVM_ED_FindGlobalOffset("self"); prog->globaloffsets.time = PRVM_ED_FindGlobalOffset("time"); diff --git a/svvm_cmds.c b/svvm_cmds.c index d7fe26dc..a042dee4 100644 --- a/svvm_cmds.c +++ b/svvm_cmds.c @@ -92,6 +92,7 @@ char *vm_sv_extensions = "DP_QC_TRACE_MOVETYPE_WORLDONLY " "DP_QC_UNLIMITEDTEMPSTRINGS " "DP_QC_URI_ESCAPE " +"DP_QC_URI_GET " "DP_QC_VECTOANGLES_WITH_ROLL " "DP_QC_VECTORVECTORS " "DP_QC_WHICHPACK " @@ -3411,7 +3412,7 @@ NULL, // #509 VM_uri_escape, // #510 string(string in) uri_escape = #510; VM_uri_unescape, // #511 string(string in) uri_unescape = #511; VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT) -NULL, // #513 +VM_uri_get, // #513 float(string uril, float id) uri_get = #513; (DP_QC_URI_GET) NULL, // #514 NULL, // #515 NULL, // #516 -- 2.39.2