]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/common/urllib.qc
Fix compilation with gmqcc.
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / urllib.qc
index d23873e74c81eea11a1f877c43a9ce44252a1380..9a5e0e7da274c8b1043f3f52ec838b03590919ad 100644 (file)
 .url_ready_func url_ready;
 .entity url_ready_pass;
 
+// for multi handles
+.float url_attempt;
+.float url_mode;
+
 entity url_fromid[NUM_URL_ID];
 float autocvar__urllib_nextslot;
 
@@ -78,7 +82,7 @@ float url_URI_Get_Callback(float id, float status, string data)
        }
 }
 
-void url_fopen(string url, float mode, url_ready_func rdy, entity pass)
+void url_single_fopen(string url, float mode, url_ready_func rdy, entity pass)
 {
        entity e;
        float i;
@@ -93,13 +97,13 @@ void url_fopen(string url, float mode, url_ready_func rdy, entity pass)
 
                                // create a writing end that does nothing yet
                                e = spawn();
-                               e.classname = "url_fopen_file";
+                               e.classname = "url_single_fopen_file";
                                e.url_url = strzone(url);
                                e.url_fh = URL_FH_CURL;
                                e.url_wbuf = buf_create();
                                if(e.url_wbuf < 0)
                                {
-                                       print("url_fopen: out of memory in buf_create\n");
+                                       print("url_single_fopen: out of memory in buf_create\n");
                                        rdy(e, pass, URL_READY_ERROR);
                                        strunzone(e.url_url);
                                        remove(e);
@@ -107,6 +111,8 @@ void url_fopen(string url, float mode, url_ready_func rdy, entity pass)
                                }
                                e.url_wbufpos = 0;
                                e.url_rbuf = -1;
+                               e.url_ready = rdy;
+                               e.url_ready_pass = pass;
                                rdy(e, pass, URL_READY_CANWRITE);
                                break;
 
@@ -124,7 +130,7 @@ void url_fopen(string url, float mode, url_ready_func rdy, entity pass)
                                                        break;
                                        if(i >= autocvar__urllib_nextslot)
                                        {
-                                               print("url_fopen: too many concurrent requests\n");
+                                               print("url_single_fopen: too many concurrent requests\n");
                                                rdy(world, pass, URL_READY_ERROR);
                                                return;
                                        }
@@ -133,7 +139,7 @@ void url_fopen(string url, float mode, url_ready_func rdy, entity pass)
                                // GET the data
                                if(!crypto_uri_postbuf(url, i + MIN_URL_ID, string_null, string_null, -1, 0))
                                {
-                                       print("url_fopen: failure in crypto_uri_postbuf\n");
+                                       print("url_single_fopen: failure in crypto_uri_postbuf\n");
                                        rdy(world, pass, URL_READY_ERROR);
                                        return;
                                }
@@ -142,7 +148,7 @@ void url_fopen(string url, float mode, url_ready_func rdy, entity pass)
                                // all). Wait for data to come from the
                                // server, then call the callback
                                e = spawn();
-                               e.classname = "url_fopen_file";
+                               e.classname = "url_single_fopen_file";
                                e.url_url = strzone(url);
                                e.url_fh = URL_FH_CURL;
                                e.url_rbuf = -1;
@@ -164,12 +170,14 @@ void url_fopen(string url, float mode, url_ready_func rdy, entity pass)
                        case FILE_WRITE:
                        case FILE_APPEND:
                                e = spawn();
-                               e.classname = "url_fopen_stdout";
+                               e.classname = "url_single_fopen_stdout";
                                e.url_fh = URL_FH_STDOUT;
+                               e.url_ready = rdy;
+                               e.url_ready_pass = pass;
                                rdy(e, pass, URL_READY_CANWRITE);
                                break;
                        case FILE_READ:
-                               print("url_fopen: cannot open '-' for reading\n");
+                               print("url_single_fopen: cannot open '-' for reading\n");
                                rdy(world, pass, URL_READY_ERROR);
                                break;
                }
@@ -186,8 +194,10 @@ void url_fopen(string url, float mode, url_ready_func rdy, entity pass)
                else
                {
                        e = spawn();
-                       e.classname = "url_fopen_file";
+                       e.classname = "url_single_fopen_file";
                        e.url_fh = fh;
+                       e.url_ready = rdy;
+                       e.url_ready_pass = pass;
                        if(mode == FILE_READ)
                                rdy(e, pass, URL_READY_CANREAD);
                        else
@@ -197,7 +207,7 @@ void url_fopen(string url, float mode, url_ready_func rdy, entity pass)
 }
 
 // close a file
-void url_fclose(entity e, url_ready_func rdy, entity pass)
+void url_fclose(entity e)
 {
        float i;
 
@@ -224,7 +234,7 @@ void url_fclose(entity e, url_ready_func rdy, entity pass)
                                if(i >= autocvar__urllib_nextslot)
                                {
                                        print("url_fclose: too many concurrent requests\n");
-                                       rdy(e, pass, URL_READY_ERROR);
+                                       e.url_ready(e,e.url_ready_pass, URL_READY_ERROR);
                                        buf_del(e.url_wbuf);
                                        strunzone(e.url_url);
                                        remove(e);
@@ -236,7 +246,7 @@ void url_fclose(entity e, url_ready_func rdy, entity pass)
                        if(!crypto_uri_postbuf(e.url_url, i + MIN_URL_ID, "text/plain", "", e.url_wbuf, 0))
                        {
                                print("url_fclose: failure in crypto_uri_postbuf\n");
-                               rdy(e, pass, URL_READY_ERROR);
+                               e.url_ready(e, e.url_ready_pass, URL_READY_ERROR);
                                buf_del(e.url_wbuf);
                                strunzone(e.url_url);
                                remove(e);
@@ -248,8 +258,6 @@ void url_fclose(entity e, url_ready_func rdy, entity pass)
                        // call the callback
                        buf_del(e.url_wbuf);
                        e.url_wbuf = -1;
-                       e.url_ready = rdy;
-                       e.url_ready_pass = pass;
                        e.url_id = i;
                        url_fromid[i] = e;
 
@@ -259,7 +267,7 @@ void url_fclose(entity e, url_ready_func rdy, entity pass)
                else
                {
                        // we have READ all data, just close
-                       rdy(e, pass, URL_READY_CLOSED);
+                       e.url_ready(e, e.url_ready_pass, URL_READY_CLOSED);
                        buf_del(e.url_rbuf);
                        strunzone(e.url_url);
                        remove(e);
@@ -267,14 +275,14 @@ void url_fclose(entity e, url_ready_func rdy, entity pass)
        }
        else if(e.url_fh == URL_FH_STDOUT)
        {
-               rdy(e, pass, URL_READY_CLOSED); // closing creates no reading handle
+               e.url_ready(e, e.url_ready_pass, URL_READY_CLOSED); // closing creates no reading handle
                remove(e);
        }
        else
        {
                // file
                fclose(e.url_fh);
-               rdy(e, pass, URL_READY_CLOSED); // closing creates no reading handle
+               e.url_ready(e, e.url_ready_pass, URL_READY_CLOSED); // closing creates no reading handle
                remove(e);
        }
 }
@@ -326,3 +334,53 @@ void url_fputs(entity e, string s)
                fputs(e.url_fh, s);
        }
 }
+
+// multi URL object, tries URLs separated by space in sequence
+void url_multi_ready(entity fh, entity me, float status)
+{
+       float n;
+       if(status == URL_READY_ERROR || status < 0)
+       {
+               if(status == -422) // Unprocessable Entity
+               {
+                       print("uri_multi_ready: got HTTP error 422, data is in unusable format - not continuing\n");
+                       me.url_ready(fh, me.url_ready_pass, status);
+                       strunzone(me.url_url);
+                       remove(me);
+                       return;
+               }
+               me.url_attempt += 1;
+               n = tokenize_console(me.url_url);
+               if(n <= me.url_attempt)
+               {
+                       me.url_ready(fh, me.url_ready_pass, status);
+                       strunzone(me.url_url);
+                       remove(me);
+                       return;
+               }
+               url_single_fopen(argv(me.url_attempt), me.url_mode, url_multi_ready, me);
+               return;
+       }
+       me.url_ready(fh, me.url_ready_pass, status);
+}
+void url_multi_fopen(string url, float mode, url_ready_func rdy, entity pass)
+{
+       float n;
+       n = tokenize_console(url);
+       if(n <= 0)
+       {
+               print("url_multi_fopen: need at least one URL\n");
+               rdy(world, pass, URL_READY_ERROR);
+               return;
+       }
+
+       entity me;
+       me = spawn();
+       me.classname = "url_multi";
+       me.url_url = strzone(url);
+       me.url_attempt = 0;
+       me.url_mode = mode;
+       me.url_ready = rdy;
+       me.url_ready_pass = pass;
+       url_single_fopen(argv(0), mode, url_multi_ready, me);
+}