libretro: adjust psxclock description
[pcsx_rearmed.git] / deps / libretro-common / net / net_http.c
1 /* Copyright  (C) 2010-2020 The RetroArch team
2  *
3  * ---------------------------------------------------------------------------------------
4  * The following license statement only applies to this file (net_http.c).
5  * ---------------------------------------------------------------------------------------
6  *
7  * Permission is hereby granted, free of charge,
8  * to any person obtaining a copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation the rights to
10  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
11  * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
16  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <ctype.h>
26
27 #include <net/net_http.h>
28 #include <net/net_compat.h>
29 #include <net/net_socket.h>
30 #ifdef HAVE_SSL
31 #include <net/net_socket_ssl.h>
32 #endif
33 #include <compat/strl.h>
34 #include <string/stdstring.h>
35 #include <string.h>
36 #include <retro_common_api.h>
37 #include <retro_miscellaneous.h>
38
39 enum
40 {
41    P_HEADER_TOP = 0,
42    P_HEADER,
43    P_BODY,
44    P_BODY_CHUNKLEN,
45    P_DONE,
46    P_ERROR
47 };
48
49 enum
50 {
51    T_FULL = 0,
52    T_LEN,
53    T_CHUNK
54 };
55
56 struct http_socket_state_t
57 {
58    void *ssl_ctx;
59    int fd;
60    bool ssl;
61 };
62
63 struct http_t
64 {
65    char *data;
66    struct http_socket_state_t sock_state; /* ptr alignment */
67    size_t pos;
68    size_t len;
69    size_t buflen;
70    int status;
71    char part;
72    char bodytype;
73    bool error;
74 };
75
76 struct http_connection_t
77 {
78    char *domain;
79    char *location;
80    char *urlcopy;
81    char *scan;
82    char *methodcopy;
83    char *contenttypecopy;
84    char *postdatacopy;
85    char *useragentcopy;
86    char *headerscopy;
87    struct http_socket_state_t sock_state; /* ptr alignment */
88    int port;
89 };
90
91 /**
92  * net_http_urlencode:
93  *
94  * URL Encode a string
95  * caller is responsible for deleting the destination buffer
96  **/
97 void net_http_urlencode(char **dest, const char *source)
98 {
99    static const char urlencode_lut[256] = 
100    {
101       0,       /* 0   */
102       0,       /* 1   */
103       0,       /* 2   */
104       0,       /* 3   */
105       0,       /* 4   */
106       0,       /* 5   */
107       0,       /* 6   */
108       0,       /* 7   */
109       0,       /* 8   */
110       0,       /* 9   */
111       0,       /* 10  */
112       0,       /* 11  */
113       0,       /* 12  */
114       0,       /* 13  */
115       0,       /* 14  */
116       0,       /* 15  */
117       0,       /* 16  */
118       0,       /* 17  */
119       0,       /* 18  */
120       0,       /* 19  */
121       0,       /* 20  */
122       0,       /* 21  */
123       0,       /* 22  */
124       0,       /* 23  */
125       0,       /* 24  */
126       0,       /* 25  */
127       0,       /* 26  */
128       0,       /* 27  */
129       0,       /* 28  */
130       0,       /* 29  */
131       0,       /* 30  */
132       0,       /* 31  */
133       0,       /* 32  */
134       0,       /* 33  */
135       0,       /* 34  */
136       0,       /* 35  */
137       0,       /* 36  */
138       0,       /* 37  */
139       0,       /* 38  */
140       0,       /* 39  */
141       0,       /* 40  */
142       0,       /* 41  */
143       '*',     /* 42  */
144       0,       /* 43  */
145       0,       /* 44  */
146       '-',     /* 45  */
147       '.',     /* 46  */
148       '/',     /* 47  */
149       '0',     /* 48  */
150       '1',     /* 49  */
151       '2',     /* 50  */
152       '3',     /* 51  */
153       '4',     /* 52  */
154       '5',     /* 53  */
155       '6',     /* 54  */
156       '7',     /* 55  */
157       '8',     /* 56  */
158       '9',     /* 57  */
159       0,       /* 58  */
160       0,       /* 59  */
161       0,       /* 60  */
162       0,       /* 61  */
163       0,       /* 62  */
164       0,       /* 63  */
165       0,       /* 64  */
166       'A',     /* 65  */
167       'B',     /* 66  */
168       'C',     /* 67  */
169       'D',     /* 68  */
170       'E',     /* 69  */
171       'F',     /* 70  */
172       'G',     /* 71  */
173       'H',     /* 72  */
174       'I',     /* 73  */
175       'J',     /* 74  */
176       'K',     /* 75  */
177       'L',     /* 76  */
178       'M',     /* 77  */
179       'N',     /* 78  */
180       'O',     /* 79  */
181       'P',     /* 80  */
182       'Q',     /* 81  */
183       'R',     /* 82  */
184       'S',     /* 83  */
185       'T',     /* 84  */
186       'U',     /* 85  */
187       'V',     /* 86  */
188       'W',     /* 87  */
189       'X',     /* 88  */
190       'Y',     /* 89  */
191       'Z',     /* 90  */
192       0,       /* 91  */
193       0,       /* 92  */
194       0,       /* 93  */
195       0,       /* 94  */
196       '_',     /* 95  */
197       0,       /* 96  */
198       'a',     /* 97  */
199       'b',     /* 98  */
200       'c',     /* 99  */
201       'd',     /* 100 */
202       'e',     /* 101 */
203       'f',     /* 102 */
204       'g',     /* 103 */
205       'h',     /* 104 */
206       'i',     /* 105 */
207       'j',     /* 106 */
208       'k',     /* 107 */
209       'l',     /* 108 */
210       'm',     /* 109 */
211       'n',     /* 110 */
212       'o',     /* 111 */
213       'p',     /* 112 */
214       'q',     /* 113 */
215       'r',     /* 114 */
216       's',     /* 115 */
217       't',     /* 116 */
218       'u',     /* 117 */
219       'v',     /* 118 */
220       'w',     /* 119 */
221       'x',     /* 120 */
222       'y',     /* 121 */
223       'z',     /* 122 */
224       0,       /* 123 */
225       0,       /* 124 */
226       0,       /* 125 */
227       0,       /* 126 */
228       0,       /* 127 */
229       0,       /* 128 */
230       0,       /* 129 */
231       0,       /* 130 */
232       0,       /* 131 */
233       0,       /* 132 */
234       0,       /* 133 */
235       0,       /* 134 */
236       0,       /* 135 */
237       0,       /* 136 */
238       0,       /* 137 */
239       0,       /* 138 */
240       0,       /* 139 */
241       0,       /* 140 */
242       0,       /* 141 */
243       0,       /* 142 */
244       0,       /* 143 */
245       0,       /* 144 */
246       0,       /* 145 */
247       0,       /* 146 */
248       0,       /* 147 */
249       0,       /* 148 */
250       0,       /* 149 */
251       0,       /* 150 */
252       0,       /* 151 */
253       0,       /* 152 */
254       0,       /* 153 */
255       0,       /* 154 */
256       0,       /* 155 */
257       0,       /* 156 */
258       0,       /* 157 */
259       0,       /* 158 */
260       0,       /* 159 */
261       0,       /* 160 */
262       0,       /* 161 */
263       0,       /* 162 */
264       0,       /* 163 */
265       0,       /* 164 */
266       0,       /* 165 */
267       0,       /* 166 */
268       0,       /* 167 */
269       0,       /* 168 */
270       0,       /* 169 */
271       0,       /* 170 */
272       0,       /* 171 */
273       0,       /* 172 */
274       0,       /* 173 */
275       0,       /* 174 */
276       0,       /* 175 */
277       0,       /* 176 */
278       0,       /* 177 */
279       0,       /* 178 */
280       0,       /* 179 */
281       0,       /* 180 */
282       0,       /* 181 */
283       0,       /* 182 */
284       0,       /* 183 */
285       0,       /* 184 */
286       0,       /* 185 */
287       0,       /* 186 */
288       0,       /* 187 */
289       0,       /* 188 */
290       0,       /* 189 */
291       0,       /* 190 */
292       0,       /* 191 */
293       0,       /* 192 */
294       0,       /* 193 */
295       0,       /* 194 */
296       0,       /* 195 */
297       0,       /* 196 */
298       0,       /* 197 */
299       0,       /* 198 */
300       0,       /* 199 */
301       0,       /* 200 */
302       0,       /* 201 */
303       0,       /* 202 */
304       0,       /* 203 */
305       0,       /* 204 */
306       0,       /* 205 */
307       0,       /* 206 */
308       0,       /* 207 */
309       0,       /* 208 */
310       0,       /* 209 */
311       0,       /* 210 */
312       0,       /* 211 */
313       0,       /* 212 */
314       0,       /* 213 */
315       0,       /* 214 */
316       0,       /* 215 */
317       0,       /* 216 */
318       0,       /* 217 */
319       0,       /* 218 */
320       0,       /* 219 */
321       0,       /* 220 */
322       0,       /* 221 */
323       0,       /* 222 */
324       0,       /* 223 */
325       0,       /* 224 */
326       0,       /* 225 */
327       0,       /* 226 */
328       0,       /* 227 */
329       0,       /* 228 */
330       0,       /* 229 */
331       0,       /* 230 */
332       0,       /* 231 */
333       0,       /* 232 */
334       0,       /* 233 */
335       0,       /* 234 */
336       0,       /* 235 */
337       0,       /* 236 */
338       0,       /* 237 */
339       0,       /* 238 */
340       0,       /* 239 */
341       0,       /* 240 */
342       0,       /* 241 */
343       0,       /* 242 */
344       0,       /* 243 */
345       0,       /* 244 */
346       0,       /* 245 */
347       0,       /* 246 */
348       0,       /* 247 */
349       0,       /* 248 */
350       0,       /* 249 */
351       0,       /* 250 */
352       0,       /* 251 */
353       0,       /* 252 */
354       0,       /* 253 */
355       0,       /* 254 */
356       0        /* 255 */
357    };
358
359    /* Assume every character will be encoded, so we need 3 times the space. */
360    size_t len                       = strlen(source) * 3 + 1;
361    size_t count                     = len;
362    char *enc                        = (char*)calloc(1, len);
363    *dest                            = enc;
364
365    for (; *source; source++)
366    {
367       int written = 0;
368
369       /* any non-ASCII character will just be encoded without question */
370       if ((unsigned)*source < sizeof(urlencode_lut) && urlencode_lut[(unsigned)*source])
371          written = snprintf(enc, count, "%c", urlencode_lut[(unsigned)*source]);
372       else
373          written = snprintf(enc, count, "%%%02X", *source & 0xFF);
374
375       if (written > 0)
376          count -= written;
377
378       while (*++enc);
379    }
380
381    (*dest)[len - 1] = '\0';
382 }
383
384 /**
385  * net_http_urlencode_full:
386  *
387  * Re-encode a full URL
388  **/
389 void net_http_urlencode_full(char *dest,
390       const char *source, size_t size)
391 {
392    size_t tmp_len;
393    size_t url_domain_len;
394    char url_domain[256];
395    char url_path[PATH_MAX_LENGTH];
396    size_t buf_pos                    = 0;
397    char *tmp                         = NULL;
398    int count                         = 0;
399
400    strlcpy(url_path, source, sizeof(url_path));
401    tmp = url_path;
402
403    while (count < 3 && tmp[0] != '\0')
404    {
405       tmp = strchr(tmp, '/');
406       count++;
407       tmp++;
408    }
409
410    tmp_len        = strlen(tmp);
411    url_domain_len = ((strlcpy(url_domain, source, tmp - url_path)) - tmp_len) - 1;
412    strlcpy(url_path,
413          source + url_domain_len + 1,
414          tmp_len + 1
415          );
416
417    tmp             = NULL;
418    net_http_urlencode(&tmp, url_path);
419    buf_pos         = strlcpy(dest, url_domain, size);
420    dest[buf_pos]   = '/';
421    dest[buf_pos+1] = '\0';
422    strlcat(dest, tmp, size);
423    free (tmp);
424 }
425
426 static int net_http_new_socket(struct http_connection_t *conn)
427 {
428    struct addrinfo *addr = NULL, *next_addr = NULL;
429    int fd                = socket_init(
430          (void**)&addr, conn->port, conn->domain, SOCKET_TYPE_STREAM, 0);
431 #ifdef HAVE_SSL
432    if (conn->sock_state.ssl)
433    {
434       if (fd < 0)
435          goto done;
436
437       if (!(conn->sock_state.ssl_ctx = ssl_socket_init(fd, conn->domain)))
438       {
439          socket_close(fd);
440          fd = -1;
441          goto done;
442       }
443
444       /* TODO: Properly figure out what's going wrong when the newer 
445          timeout/poll code interacts with mbed and winsock
446          https://github.com/libretro/RetroArch/issues/14742 */
447
448       /* Temp fix, don't use new timeout/poll code for cheevos http requests */
449          bool timeout = true;
450 #ifdef __WIN32
451       if (!strcmp(conn->domain, "retroachievements.org"))
452          timeout = false;
453 #endif
454
455       if (ssl_socket_connect(conn->sock_state.ssl_ctx, addr, timeout, true)
456             < 0)
457       {
458          fd = -1;
459          goto done;
460       }
461    }
462    else
463 #endif
464    for (next_addr = addr; fd >= 0; fd = socket_next((void**)&next_addr))
465    {
466       if (socket_connect_with_timeout(fd, next_addr, 5000))
467          break;
468
469       socket_close(fd);
470    }
471
472 #ifdef HAVE_SSL
473 done:
474 #endif
475    if (addr)
476       freeaddrinfo_retro(addr);
477
478    conn->sock_state.fd = fd;
479
480    return fd;
481 }
482
483 static void net_http_send_str(
484       struct http_socket_state_t *sock_state, bool *error,
485       const char *text, size_t text_size)
486 {
487    if (*error)
488       return;
489 #ifdef HAVE_SSL
490    if (sock_state->ssl)
491    {
492       if (!ssl_socket_send_all_blocking(
493                sock_state->ssl_ctx, text, text_size, true))
494          *error = true;
495    }
496    else
497 #endif
498    {
499       if (!socket_send_all_blocking(
500                sock_state->fd, text, text_size, true))
501          *error = true;
502    }
503 }
504
505 struct http_connection_t *net_http_connection_new(const char *url,
506       const char *method, const char *data)
507 {
508    struct http_connection_t *conn = NULL;
509
510    if (!url)
511       return NULL;
512    if (!(conn = (struct http_connection_t*)malloc(
513          sizeof(*conn))))
514       return NULL;
515
516    conn->domain            = NULL;
517    conn->location          = NULL;
518    conn->urlcopy           = NULL;
519    conn->scan              = NULL;
520    conn->methodcopy        = NULL;
521    conn->contenttypecopy   = NULL;
522    conn->postdatacopy      = NULL;
523    conn->useragentcopy     = NULL;
524    conn->headerscopy       = NULL;
525    conn->port              = 0;
526    conn->sock_state.fd     = 0;
527    conn->sock_state.ssl    = false;
528    conn->sock_state.ssl_ctx= NULL;
529
530    if (method)
531       conn->methodcopy     = strdup(method);
532
533    if (data)
534       conn->postdatacopy   = strdup(data);
535
536    if (!(conn->urlcopy = strdup(url)))
537       goto error;
538
539    if (!strncmp(url, "http://", STRLEN_CONST("http://")))
540       conn->scan           = conn->urlcopy + STRLEN_CONST("http://");
541    else if (!strncmp(url, "https://", STRLEN_CONST("https://")))
542    {
543       conn->scan           = conn->urlcopy + STRLEN_CONST("https://");
544       conn->sock_state.ssl = true;
545    }
546    else
547       goto error;
548
549    if (string_is_empty(conn->scan))
550       goto error;
551
552    conn->domain = conn->scan;
553
554    return conn;
555
556 error:
557    if (conn->urlcopy)
558       free(conn->urlcopy);
559    if (conn->methodcopy)
560       free(conn->methodcopy);
561    if (conn->postdatacopy)
562       free(conn->postdatacopy);
563    conn->urlcopy      = NULL;
564    conn->methodcopy   = NULL;
565    conn->postdatacopy = NULL;
566    free(conn);
567    return NULL;
568 }
569
570 /**
571  * net_http_connection_iterate:
572  *
573  * Leaf function.
574  **/
575 bool net_http_connection_iterate(struct http_connection_t *conn)
576 {
577    if (!conn)
578       return false;
579
580    while (*conn->scan != '/' && *conn->scan != ':' && *conn->scan != '\0')
581       conn->scan++;
582
583    return true;
584 }
585
586 bool net_http_connection_done(struct http_connection_t *conn)
587 {
588    int has_port = 0;
589
590    if (!conn || !conn->domain || !*conn->domain)
591       return false;
592
593    if (*conn->scan == ':')
594    {
595       /* domain followed by port, split off the port */
596       *conn->scan++ = '\0';
597
598       if (!isdigit((int)(*conn->scan)))
599          return false;
600
601       conn->port = (int)strtoul(conn->scan, &conn->scan, 10);
602       has_port   = 1;
603    }
604    else if (conn->port == 0)
605    {
606       /* port not specified, default to standard HTTP or HTTPS port */
607       if (conn->sock_state.ssl)
608          conn->port = 443;
609       else
610          conn->port = 80;
611    }
612
613    if (*conn->scan == '/')
614    {
615       /* domain followed by location - split off the location */
616       /*   site.com/path.html   or   site.com:80/path.html   */
617       *conn->scan    = '\0';
618       conn->location = conn->scan + 1;
619       return true;
620    }
621    else if (!*conn->scan)
622    {
623       /* domain with no location - point location at empty string */
624       /*   site.com   or   site.com:80   */
625       conn->location = conn->scan;
626       return true;
627    }
628    else if (*conn->scan == '?')
629    {
630       /* domain with no location, but still has query parms - point location at the query parms */
631       /*   site.com?param=3   or  site.com:80?param=3   */
632       if (!has_port)
633       {
634          /* if there wasn't a port, we have to expand the urlcopy so we can separate the two parts */
635          size_t domain_len   = strlen(conn->domain);
636          size_t location_len = strlen(conn->scan);
637          char* urlcopy       = (char*)malloc(domain_len + location_len + 2);
638          memcpy(urlcopy, conn->domain, domain_len);
639          urlcopy[domain_len] = '\0';
640          memcpy(urlcopy + domain_len + 1, conn->scan, location_len + 1);
641
642          free(conn->urlcopy);
643          conn->domain        = conn->urlcopy = urlcopy;
644          conn->location      = conn->scan    = urlcopy + domain_len + 1;
645       }
646       else /* There was a port, so overwriting the : will terminate the domain and we can just point at the ? */
647          conn->location      = conn->scan;
648
649       return true;
650    }
651
652    /* invalid character after domain/port */
653    return false;
654 }
655
656 void net_http_connection_free(struct http_connection_t *conn)
657 {
658    if (!conn)
659       return;
660
661    if (conn->urlcopy)
662       free(conn->urlcopy);
663
664    if (conn->methodcopy)
665       free(conn->methodcopy);
666
667    if (conn->contenttypecopy)
668       free(conn->contenttypecopy);
669
670    if (conn->postdatacopy)
671       free(conn->postdatacopy);
672
673    if (conn->useragentcopy)
674       free(conn->useragentcopy);
675
676    if (conn->headerscopy)
677       free(conn->headerscopy);
678
679    conn->urlcopy         = NULL;
680    conn->methodcopy      = NULL;
681    conn->contenttypecopy = NULL;
682    conn->postdatacopy    = NULL;
683    conn->useragentcopy   = NULL;
684    conn->headerscopy     = NULL;
685
686    free(conn);
687 }
688
689 void net_http_connection_set_user_agent(
690       struct http_connection_t *conn, const char *user_agent)
691 {
692    if (conn->useragentcopy)
693       free(conn->useragentcopy);
694
695    conn->useragentcopy = user_agent ? strdup(user_agent) : NULL;
696 }
697
698 void net_http_connection_set_headers(
699       struct http_connection_t *conn, const char *headers)
700 {
701    if (conn->headerscopy)
702       free(conn->headerscopy);
703
704    conn->headerscopy = headers ? strdup(headers) : NULL;
705 }
706
707 const char *net_http_connection_url(struct http_connection_t *conn)
708 {
709    return conn->urlcopy;
710 }
711
712 const char* net_http_connection_method(struct http_connection_t* conn)
713 {
714    return conn->methodcopy;
715 }
716
717 struct http_t *net_http_new(struct http_connection_t *conn)
718 {
719    bool error            = false;
720    int fd                = -1;
721    struct http_t *state  = NULL;
722
723    if (!conn)
724       goto error;
725
726    if ((fd = net_http_new_socket(conn)) < 0)
727       goto error;
728
729    error = false;
730
731    /* This is a bit lazy, but it works. */
732    if (conn->methodcopy)
733    {
734       net_http_send_str(&conn->sock_state, &error, conn->methodcopy,
735             strlen(conn->methodcopy));
736       net_http_send_str(&conn->sock_state, &error, " /",
737             STRLEN_CONST(" /"));
738    }
739    else
740    {
741       net_http_send_str(&conn->sock_state, &error, "GET /",
742             STRLEN_CONST("GET /"));
743    }
744
745    net_http_send_str(&conn->sock_state, &error, conn->location,
746          strlen(conn->location));
747    net_http_send_str(&conn->sock_state, &error, " HTTP/1.1\r\n",
748          STRLEN_CONST(" HTTP/1.1\r\n"));
749
750    net_http_send_str(&conn->sock_state, &error, "Host: ",
751          STRLEN_CONST("Host: "));
752    net_http_send_str(&conn->sock_state, &error, conn->domain,
753          strlen(conn->domain));
754
755    if (conn->port)
756    {
757       char portstr[16];
758
759       portstr[0] = '\0';
760
761       snprintf(portstr, sizeof(portstr), ":%i", conn->port);
762       net_http_send_str(&conn->sock_state, &error, portstr,
763             strlen(portstr));
764    }
765
766    net_http_send_str(&conn->sock_state, &error, "\r\n",
767          STRLEN_CONST("\r\n"));
768
769    /* Pre-formatted headers */
770    if (conn->headerscopy)
771       net_http_send_str(&conn->sock_state, &error, conn->headerscopy,
772             strlen(conn->headerscopy));
773    /* This is not being set anywhere yet */
774    else if (conn->contenttypecopy)
775    {
776       net_http_send_str(&conn->sock_state, &error, "Content-Type: ",
777             STRLEN_CONST("Content-Type: "));
778       net_http_send_str(&conn->sock_state, &error,
779             conn->contenttypecopy, strlen(conn->contenttypecopy));
780       net_http_send_str(&conn->sock_state, &error, "\r\n",
781             STRLEN_CONST("\r\n"));
782    }
783
784    if (conn->methodcopy && (string_is_equal(conn->methodcopy, "POST")))
785    {
786       size_t post_len, len;
787       char *len_str        = NULL;
788
789       if (!conn->postdatacopy)
790          goto error;
791
792       if (!conn->headerscopy)
793       {
794          if (!conn->contenttypecopy)
795             net_http_send_str(&conn->sock_state, &error,
796                   "Content-Type: application/x-www-form-urlencoded\r\n",
797                   STRLEN_CONST(
798                      "Content-Type: application/x-www-form-urlencoded\r\n"
799                      ));
800       }
801
802       net_http_send_str(&conn->sock_state, &error, "Content-Length: ",
803             STRLEN_CONST("Content-Length: "));
804
805       post_len = strlen(conn->postdatacopy);
806 #ifdef _WIN32
807       len     = snprintf(NULL, 0, "%" PRIuPTR, post_len);
808       len_str = (char*)malloc(len + 1);
809       snprintf(len_str, len + 1, "%" PRIuPTR, post_len);
810 #else
811       len     = snprintf(NULL, 0, "%llu", (long long unsigned)post_len);
812       len_str = (char*)malloc(len + 1);
813       snprintf(len_str, len + 1, "%llu", (long long unsigned)post_len);
814 #endif
815
816       len_str[len] = '\0';
817
818       net_http_send_str(&conn->sock_state, &error, len_str,
819             strlen(len_str));
820       net_http_send_str(&conn->sock_state, &error, "\r\n",
821             STRLEN_CONST("\r\n"));
822
823       free(len_str);
824    }
825
826    net_http_send_str(&conn->sock_state, &error, "User-Agent: ",
827          STRLEN_CONST("User-Agent: "));
828    if (conn->useragentcopy)
829       net_http_send_str(&conn->sock_state, &error,
830             conn->useragentcopy, strlen(conn->useragentcopy));
831    else
832       net_http_send_str(&conn->sock_state, &error, "libretro",
833             STRLEN_CONST("libretro"));
834    net_http_send_str(&conn->sock_state, &error, "\r\n",
835          STRLEN_CONST("\r\n"));
836
837    net_http_send_str(&conn->sock_state, &error,
838          "Connection: close\r\n", STRLEN_CONST("Connection: close\r\n"));
839    net_http_send_str(&conn->sock_state, &error, "\r\n",
840          STRLEN_CONST("\r\n"));
841
842    if (conn->methodcopy && (string_is_equal(conn->methodcopy, "POST")))
843       net_http_send_str(&conn->sock_state, &error, conn->postdatacopy,
844             strlen(conn->postdatacopy));
845
846    if (error)
847       goto error;
848
849    state             = (struct http_t*)malloc(sizeof(struct http_t));
850    state->sock_state = conn->sock_state;
851    state->status     = -1;
852    state->data       = NULL;
853    state->part       = P_HEADER_TOP;
854    state->bodytype   = T_FULL;
855    state->error      = false;
856    state->pos        = 0;
857    state->len        = 0;
858    state->buflen     = 512;
859
860    if (!(state->data = (char*)malloc(state->buflen)))
861       goto error;
862
863    return state;
864
865 error:
866    if (conn)
867    {
868       if (conn->methodcopy)
869          free(conn->methodcopy);
870       if (conn->contenttypecopy)
871          free(conn->contenttypecopy);
872       conn->methodcopy      = NULL;
873       conn->contenttypecopy = NULL;
874       conn->postdatacopy    = NULL;
875    }
876 #ifdef HAVE_SSL
877    if (conn && conn->sock_state.ssl_ctx)
878    {
879       ssl_socket_close(conn->sock_state.ssl_ctx);
880       ssl_socket_free(conn->sock_state.ssl_ctx);
881       conn->sock_state.ssl_ctx = NULL;
882    }
883 #else
884    if (fd >= 0)
885       socket_close(fd);
886 #endif
887    if (state)
888       free(state);
889    return NULL;
890 }
891
892 /**
893  * net_http_fd:
894  *
895  * Leaf function.
896  *
897  * You can use this to call net_http_update
898  * only when something will happen; select() it for reading.
899  **/
900 int net_http_fd(struct http_t *state)
901 {
902    if (!state)
903       return -1;
904    return state->sock_state.fd;
905 }
906
907 /**
908  * net_http_update:
909  *
910  * @return true if it's done, or if something broke.
911  * @total will be 0 if it's not known.
912  **/
913 bool net_http_update(struct http_t *state, size_t* progress, size_t* total)
914 {
915    ssize_t newlen = 0;
916
917    if (!state)
918       return true;
919    if (state->error)
920    {
921       state->part   = P_ERROR;
922       state->status = -1;
923       return true;
924    }
925
926    if (state->part < P_BODY)
927    {
928       if (state->error)
929       {
930          state->part   = P_ERROR;
931          state->status = -1;
932          return true;
933       }
934
935 #ifdef HAVE_SSL
936       if (state->sock_state.ssl && state->sock_state.ssl_ctx)
937          newlen = ssl_socket_receive_all_nonblocking(state->sock_state.ssl_ctx, &state->error,
938                (uint8_t*)state->data + state->pos,
939                state->buflen - state->pos);
940       else
941 #endif
942          newlen = socket_receive_all_nonblocking(state->sock_state.fd, &state->error,
943                (uint8_t*)state->data + state->pos,
944                state->buflen - state->pos);
945
946       if (newlen < 0)
947       {
948          state->error  = true;
949          state->part   = P_ERROR;
950          state->status = -1;
951          return true;
952       }
953
954       if (state->pos + newlen >= state->buflen - 64)
955       {
956          state->buflen *= 2;
957          state->data    = (char*)realloc(state->data, state->buflen);
958       }
959       state->pos += newlen;
960
961       while (state->part < P_BODY)
962       {
963          char *dataend = state->data + state->pos;
964          char *lineend = (char*)memchr(state->data, '\n', state->pos);
965
966          if (!lineend)
967             break;
968
969          *lineend='\0';
970
971          if (lineend != state->data && lineend[-1]=='\r')
972             lineend[-1]='\0';
973
974          if (state->part == P_HEADER_TOP)
975          {
976             if (strncmp(state->data, "HTTP/1.", STRLEN_CONST("HTTP/1."))!=0)
977             {
978                state->error  = true;
979                state->part   = P_ERROR;
980                state->status = -1;
981                return true;
982             }
983             state->status    = (int)strtoul(state->data 
984                   + STRLEN_CONST("HTTP/1.1 "), NULL, 10);
985             state->part      = P_HEADER;
986          }
987          else
988          {
989             if (string_starts_with_case_insensitive(state->data, "Content-Length:"))
990             {
991                char* ptr = state->data + STRLEN_CONST("Content-Length:");
992                while (ISSPACE(*ptr))
993                   ++ptr;
994
995                state->bodytype = T_LEN;
996                state->len = strtol(ptr, NULL, 10);
997             }
998             if (string_is_equal_case_insensitive(state->data, "Transfer-Encoding: chunked"))
999                state->bodytype = T_CHUNK;
1000
1001             /* TODO: save headers somewhere */
1002             if (state->data[0]=='\0')
1003             {
1004                state->part = P_BODY;
1005                if (state->bodytype == T_CHUNK)
1006                   state->part = P_BODY_CHUNKLEN;
1007             }
1008          }
1009
1010          memmove(state->data, lineend + 1, dataend-(lineend+1));
1011          state->pos = (dataend-(lineend + 1));
1012       }
1013
1014       if (state->part >= P_BODY)
1015       {
1016          newlen     = state->pos;
1017          state->pos = 0;
1018       }
1019    }
1020
1021    if (state->part >= P_BODY && state->part < P_DONE)
1022    {
1023       if (!newlen)
1024       {
1025          if (state->error)
1026             newlen = -1;
1027          else
1028          {
1029 #ifdef HAVE_SSL
1030             if (state->sock_state.ssl && state->sock_state.ssl_ctx)
1031                newlen = ssl_socket_receive_all_nonblocking(
1032                   state->sock_state.ssl_ctx,
1033                   &state->error,
1034                   (uint8_t*)state->data + state->pos,
1035                   state->buflen - state->pos);
1036             else
1037 #endif
1038                newlen = socket_receive_all_nonblocking(
1039                   state->sock_state.fd,
1040                   &state->error,
1041                   (uint8_t*)state->data + state->pos,
1042                   state->buflen - state->pos);
1043          }
1044
1045          if (newlen < 0)
1046          {
1047             if (state->bodytype != T_FULL)
1048             {
1049                state->error  = true;
1050                state->part   = P_ERROR;
1051                state->status = -1;
1052                return true;
1053             }
1054             state->part      = P_DONE;
1055             state->data      = (char*)realloc(state->data, state->len);
1056             newlen           = 0;
1057          }
1058
1059          if (state->pos + newlen >= state->buflen - 64)
1060          {
1061             state->buflen   *= 2;
1062             state->data      = (char*)realloc(state->data, state->buflen);
1063          }
1064       }
1065
1066 parse_again:
1067       if (state->bodytype == T_CHUNK)
1068       {
1069          if (state->part == P_BODY_CHUNKLEN)
1070          {
1071             state->pos      += newlen;
1072
1073             if (state->pos - state->len >= 2)
1074             {
1075                /*
1076                 * len=start of chunk including \r\n
1077                 * pos=end of data
1078                 */
1079
1080                char *fullend = state->data + state->pos;
1081                char *end     = (char*)memchr(state->data + state->len + 2, '\n',
1082                      state->pos - state->len - 2);
1083
1084                if (end)
1085                {
1086                   size_t chunklen = strtoul(state->data+state->len, NULL, 16);
1087                   state->pos      = state->len;
1088                   end++;
1089
1090                   memmove(state->data+state->len, end, fullend-end);
1091
1092                   state->len      = chunklen;
1093                   newlen          = (fullend - end);
1094
1095                   /*
1096                      len=num bytes
1097                      newlen=unparsed bytes after \n
1098                      pos=start of chunk including \r\n
1099                      */
1100
1101                   state->part = P_BODY;
1102                   if (state->len == 0)
1103                   {
1104                      state->part = P_DONE;
1105                      state->len  = state->pos;
1106                      state->data = (char*)realloc(state->data, state->len);
1107                   }
1108                   goto parse_again;
1109                }
1110             }
1111          }
1112          else if (state->part == P_BODY)
1113          {
1114             if ((size_t)newlen >= state->len)
1115             {
1116                state->pos += state->len;
1117                newlen     -= state->len;
1118                state->len  = state->pos;
1119                state->part = P_BODY_CHUNKLEN;
1120                goto parse_again;
1121             }
1122             state->pos += newlen;
1123             state->len -= newlen;
1124          }
1125       }
1126       else
1127       {
1128          state->pos += newlen;
1129
1130          if (state->pos > state->len)
1131          {
1132             state->error  = true;
1133             state->part   = P_ERROR;
1134             state->status = -1;
1135             return true;
1136          }
1137          else if (state->pos == state->len)
1138          {
1139             state->part   = P_DONE;
1140             state->data   = (char*)realloc(state->data, state->len);
1141          }
1142       }
1143    }
1144
1145    if (progress)
1146       *progress = state->pos;
1147
1148    if (total)
1149    {
1150       if (state->bodytype == T_LEN)
1151          *total = state->len;
1152       else
1153          *total = 0;
1154    }
1155
1156    return (state->part == P_DONE);
1157 }
1158
1159 /**
1160  * net_http_status:
1161  *
1162  * Report HTTP status. 200, 404, or whatever.
1163  *
1164  * Leaf function.
1165  * 
1166  * @return HTTP status code.
1167  **/
1168 int net_http_status(struct http_t *state)
1169 {
1170    if (!state)
1171       return -1;
1172    return state->status;
1173 }
1174
1175 /**
1176  * net_http_data:
1177  *
1178  * Leaf function.
1179  *
1180  * @return the downloaded data. The returned buffer is owned by the
1181  * HTTP handler; it's freed by net_http_delete().
1182  * If the status is not 20x and accept_error is false, it returns NULL.
1183  **/
1184 uint8_t* net_http_data(struct http_t *state, size_t* len, bool accept_error)
1185 {
1186    if (!state)
1187       return NULL;
1188
1189    if (!accept_error && (state->error || state->status < 200 || state->status > 299))
1190    {
1191       if (len)
1192          *len = 0;
1193       return NULL;
1194    }
1195
1196    if (len)
1197       *len    = state->len;
1198
1199    return (uint8_t*)state->data;
1200 }
1201
1202 /**
1203  * net_http_delete:
1204  *
1205  * Cleans up all memory.
1206  **/
1207 void net_http_delete(struct http_t *state)
1208 {
1209    if (!state)
1210       return;
1211
1212    if (state->sock_state.fd >= 0)
1213    {
1214 #ifdef HAVE_SSL
1215       if (state->sock_state.ssl && state->sock_state.ssl_ctx)
1216       {
1217          ssl_socket_close(state->sock_state.ssl_ctx);
1218          ssl_socket_free(state->sock_state.ssl_ctx);
1219          state->sock_state.ssl_ctx = NULL;
1220       }
1221       else
1222 #endif
1223       socket_close(state->sock_state.fd);
1224    }
1225    free(state);
1226 }
1227
1228 /**
1229  * net_http_error:
1230  *
1231  * Leaf function
1232  **/
1233 bool net_http_error(struct http_t *state)
1234 {
1235    return (state->error || state->status < 200 || state->status > 299);
1236 }