80 lines2.0 KBC
1/*
2http_common.c: http_fetch, a request whose body is gathered into memory.
3*/
4#include <stdlib.h>
5#include <string.h>
6#include "plat.h"
7
8// no reply we ask for (JSON pages, lyrics, artwork) comes near this; anything
9// bigger is refused rather than allowed to eat the PS3's memory
10#define HTTP_BODY_MAX (24u * 1024 * 1024)
11
12typedef struct {
13 char *buf;
14 size_t len, cap;
15} membuf_t;
16
17static int MemSink(void *ctx, const void *data, int len)
18{
19 membuf_t *m = ctx;
20 if (len < 0 || m->len + (size_t)len + 1 > HTTP_BODY_MAX) {
21 plat_log("http: reply bigger than %u MB, dropped", HTTP_BODY_MAX >> 20);
22 return 0;
23 }
24 if (m->len + len + 1 > m->cap) {
25 size_t cap = m->cap ? m->cap * 2 : 16384;
26 while (cap < m->len + len + 1)
27 cap *= 2;
28 char *nb = realloc(m->buf, cap);
29 if (!nb)
30 return 0;
31 m->buf = nb;
32 m->cap = cap;
33 }
34 memcpy(m->buf + m->len, data, len);
35 m->len += len;
36 return 1;
37}
38
39char *http_fetch(const char *method, const char *url, const char *headers, const char *body,
40 int timeout_s, volatile int *cancel, size_t *len_out, http_res_t *res)
41{
42 return http_fetch_ex(method, url, headers, body, timeout_s, cancel, len_out, res, 0);
43}
44
45char *http_fetch_ex(const char *method, const char *url, const char *headers, const char *body,
46 int timeout_s, volatile int *cancel, size_t *len_out, http_res_t *res, int flags)
47{
48 http_req_t req;
49 http_res_t local;
50 membuf_t m = {0};
51
52 if (!res)
53 res = &local;
54 memset(&req, 0, sizeof(req));
55 req.method = method;
56 req.url = url;
57 req.headers = headers;
58 req.body = body;
59 req.body_len = body ? (int)strlen(body) : 0;
60 req.cancel = cancel;
61 req.timeout_s = timeout_s;
62 req.sink = MemSink;
63 req.ctx = &m;
64 req.no_redirect = flags & HTTP_NO_REDIRECT;
65 req.total_s = (timeout_s > 0 ? timeout_s : 30) * 2 + 10; // a reply that trickles in forever still ends
66
67 if (!http_request(&req, res)) {
68 free(m.buf);
69 return NULL;
70 }
71 if (!m.buf) {
72 m.buf = malloc(1);
73 if (!m.buf)
74 return NULL;
75 }
76 m.buf[m.len] = 0;
77 if (len_out)
78 *len_out = m.len;
79 return m.buf;
80}