]> git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - libcurl.c
Improve client/listen curl transfer speed at low FPS
[xonotic/darkplaces.git] / libcurl.c
index 26cb7a4914de0cc915f19fa813d73fe056d80422..53674299a8a603388088bb15e635a2dc164f636f 100644 (file)
--- a/libcurl.c
+++ b/libcurl.c
@@ -15,6 +15,7 @@ static cvar_t sv_curl_maxspeed = {CF_SERVER | CF_ARCHIVE, "sv_curl_maxspeed","0"
 static cvar_t cl_curl_enabled = {CF_CLIENT | CF_ARCHIVE, "cl_curl_enabled","1", "whether client's download support is enabled"};
 static cvar_t cl_curl_useragent = {CF_CLIENT, "cl_curl_useragent","1", "send the User-Agent string (note: turning this off may break stuff)"};
 static cvar_t cl_curl_useragent_append = {CF_CLIENT, "cl_curl_useragent_append","", "a string to append to the User-Agent string (useful for name and version number of your mod)"};
+static cvar_t developer_curl = {CF_CLIENT | CF_SERVER, "developer_curl","0", "whether verbose curl output should be printed to stderr"};
 
 /*
 =================================================================
@@ -62,6 +63,7 @@ typedef enum
        CINIT(LOW_SPEED_TIME, LONG, 20),
        CINIT(RESUME_FROM, LONG, 21),
        CINIT(HTTPHEADER, OBJECTPOINT, 23),
+       CINIT(VERBOSE, LONG, 41),
        CINIT(POST, LONG, 47),         /* HTTP POST method */
        CINIT(FOLLOWLOCATION, LONG, 52),  /* use Location: Luke! */
        CINIT(POSTFIELDSIZE, LONG, 60),
@@ -156,6 +158,7 @@ static const char * (*qcurl_easy_strerror) (CURLcode);
 
 static CURLM * (*qcurl_multi_init) (void);
 static CURLMcode (*qcurl_multi_perform) (CURLM *multi_handle, int *running_handles);
+static CURLMcode (*qcurl_multi_poll) (CURLM *multi_handle, void*, unsigned int extra_nfds, int timeout_ms, int *ret);
 static CURLMcode (*qcurl_multi_add_handle) (CURLM *multi_handle, CURL *easy_handle);
 static CURLMcode (*qcurl_multi_remove_handle) (CURLM *multi_handle, CURL *easy_handle);
 static CURLMsg * (*qcurl_multi_info_read) (CURLM *multi_handle, int *msgs_in_queue);
@@ -175,6 +178,7 @@ static dllfunction_t curlfuncs[] =
        {"curl_easy_getinfo",           (void **) &qcurl_easy_getinfo},
        {"curl_multi_init",                     (void **) &qcurl_multi_init},
        {"curl_multi_perform",          (void **) &qcurl_multi_perform},
+       {"curl_multi_poll",             (void **) &qcurl_multi_poll},
        {"curl_multi_add_handle",       (void **) &qcurl_multi_add_handle},
        {"curl_multi_remove_handle",(void **) &qcurl_multi_remove_handle},
        {"curl_multi_info_read",        (void **) &qcurl_multi_info_read},
@@ -430,6 +434,8 @@ static size_t CURL_fwrite(void *data, size_t size, size_t nmemb, void *vdi)
 
        di->bytes_received += bytes;
 
+       //Con_Printf("CURL_fwrite callback timestamp: %f bytes: %ld\n", host.realtime, ret);
+
        return ret;
        // Why not ret / nmemb?
        // Because CURLOPT_WRITEFUNCTION docs say to return the number of bytes.
@@ -581,7 +587,7 @@ static void Curl_EndDownload(downloadinfo *di, CurlStatus status, CURLcode error
 
        if(ok && di->loadtype == LOADTYPE_PAK)
        {
-               ok = FS_AddPack(di->filename, NULL, true);
+               ok = FS_AddPack(di->filename, NULL, true, true);
                if(!ok)
                        CLEAR_AND_RETRY();
        }
@@ -734,6 +740,8 @@ static void CheckPendingDownloads(void)
                                }
                                else
                                        qcurl_easy_setopt(di->curle, CURLOPT_USERAGENT, "");
+                               if(developer_curl.integer) 
+                                       qcurl_easy_setopt(di->curle, CURLOPT_VERBOSE, (long) 1);
                                qcurl_easy_setopt(di->curle, CURLOPT_REFERER, di->referer);
                                qcurl_easy_setopt(di->curle, CURLOPT_RESUME_FROM, (long) di->startpos);
                                qcurl_easy_setopt(di->curle, CURLOPT_FOLLOWLOCATION, 1);
@@ -803,7 +811,7 @@ void Curl_Init(void)
        if(!curl_dll)
                return;
        if (Thread_HasThreads()) curl_mutex = Thread_CreateMutex();
-       qcurl_global_init(CURL_GLOBAL_NOTHING);
+       qcurl_global_init(CURL_GLOBAL_SSL);
        curlm = qcurl_multi_init();
 }
 
@@ -982,7 +990,7 @@ static qbool Curl_Begin(const char *URL, const char *extraheaders, double maxspe
                                if(loadtype == LOADTYPE_PAK)
                                {
                                        qbool already_loaded;
-                                       if(FS_AddPack(fn, &already_loaded, true))
+                                       if(FS_AddPack(fn, &already_loaded, true, true))
                                        {
                                                Con_DPrintf("%s already exists, not downloading!\n", fn);
                                                if(already_loaded)
@@ -1231,6 +1239,25 @@ void Curl_Frame(void)
        if (curl_mutex) Thread_UnlockMutex(curl_mutex);
 }
 
+/*
+====================
+Curl_Select
+
+Sleeps until there's some transfer progress or a timeout is reached,
+unfortunately the timeout is only in milliseconds.
+This allows good throughput even at very low FPS.
+====================
+*/
+void Curl_Select(double *microseconds)
+{
+       if (List_Is_Empty(&downloads))
+               return;
+       if (qcurl_multi_poll(curlm, NULL, 0, *microseconds / 1000, NULL) == CURLM_OK)
+               *microseconds = 0; // either we finished waiting or a transfer progressed
+       else
+               Con_Print("There's an emergency going on!\nIt's still going on!\nMaybe you need to upgrade libcurl?\n");
+}
+
 /*
 ====================
 Curl_CancelAll
@@ -1542,6 +1569,7 @@ void Curl_Init_Commands(void)
        Cvar_RegisterVariable (&sv_curl_maxspeed);
        Cvar_RegisterVariable (&cl_curl_useragent);
        Cvar_RegisterVariable (&cl_curl_useragent_append);
+       Cvar_RegisterVariable (&developer_curl);
        Cmd_AddCommand(CF_CLIENT | CF_CLIENT_FROM_SERVER, "curl", Curl_Curl_f, "download data from an URL and add to search path");
        //Cmd_AddCommand(cmd_local, "curlcat", Curl_CurlCat_f, "display data from an URL (debugging command)");
 }