Commit 750d5ebc authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

https: simplify HTTP/2 headers parsing

parent cb1f0492
......@@ -113,7 +113,8 @@ static int vlc_h2_stream_fatal(struct vlc_h2_stream *s, uint_fast32_t code)
}
/** Reports received stream headers */
static void vlc_h2_stream_headers(void *ctx, unsigned count, char *hdrs[][2])
static void vlc_h2_stream_headers(void *ctx, unsigned count,
const char *const hdrs[][2])
{
struct vlc_h2_stream *s = ctx;
......
......@@ -522,41 +522,46 @@ static int vlc_h2_parse_headers_end(struct vlc_h2_parser *p)
char *headers[VLC_H2_MAX_HEADERS][2];
/* TODO: limit total decompressed size of the headers list */
int val = hpack_decode(p->headers.decoder, p->headers.buf, p->headers.len,
int n = hpack_decode(p->headers.decoder, p->headers.buf, p->headers.len,
headers, VLC_H2_MAX_HEADERS);
if (val > VLC_H2_MAX_HEADERS)
if (n > VLC_H2_MAX_HEADERS)
{
for (unsigned i = 0; i < VLC_H2_MAX_HEADERS; i++)
{
free(headers[i][0]);
free(headers[i][1]);
}
val = -1;
n = -1;
}
if (val < 0)
if (n < 0)
return vlc_h2_parse_error(p, VLC_H2_COMPRESSION_ERROR);
void *s = vlc_h2_stream_lookup(p, p->headers.sid);
int val = 0;
if (s != NULL)
{
p->cbs->stream_headers(s, val, headers);
val = 0;
const char *ch[n ? n : 1][2];
for (int i = 0; i < n; i++)
ch[i][0] = headers[i][0], ch[i][1] = headers[i][1];
p->cbs->stream_headers(s, n, ch);
if (p->headers.eos)
p->cbs->stream_end(s);
}
else
{
for (int i = 0; i < val; i++)
{
free(headers[i][0]);
free(headers[i][1]);
}
/* NOTE: The specification implies that the error should be sent for
* the first header frame. But we actually want to receive the whole
* fragmented headers block, to preserve the HPACK decoder state.
* So we send the error at the last header frame instead. */
val = vlc_h2_stream_error(p, p->headers.sid, VLC_H2_REFUSED_STREAM);
for (int i = 0; i < n; i++)
{
free(headers[i][0]);
free(headers[i][1]);
}
p->parser = vlc_h2_parse_generic;
......
......@@ -106,7 +106,8 @@ struct vlc_h2_parser_cbs
void *(*stream_lookup)(void *ctx, uint_fast32_t id);
int (*stream_error)(void *ctx, uint_fast32_t id, uint_fast32_t code);
void (*stream_headers)(void *ctx, unsigned count, char *headers[][2]);
void (*stream_headers)(void *ctx, unsigned count,
const char *const headers[][2]);
int (*stream_data)(void *ctx, struct vlc_h2_frame *f);
void (*stream_end)(void *ctx);
int (*stream_reset)(void *ctx, uint_fast32_t code);
......
......@@ -142,7 +142,8 @@ static const unsigned resp_hdrc = sizeof (resp_hdrv) / sizeof (resp_hdrv[0]);
static unsigned stream_header_tables;
static void vlc_h2_stream_headers(void *ctx, unsigned count, char *hdrs[][2])
static void vlc_h2_stream_headers(void *ctx, unsigned count,
const char *const hdrs[][2])
{
assert(ctx == &stream_cookie);
assert(count == resp_hdrc);
......@@ -151,8 +152,6 @@ static void vlc_h2_stream_headers(void *ctx, unsigned count, char *hdrs[][2])
{
assert(!strcmp(hdrs[i][0], resp_hdrv[i][0]));
assert(!strcmp(hdrs[i][1], resp_hdrv[i][1]));
free(hdrs[i][1]);
free(hdrs[i][0]);
}
stream_header_tables++;
......
......@@ -427,7 +427,8 @@ struct vlc_h2_frame *vlc_http_msg_h2_frame(const struct vlc_http_msg *m,
return f;
}
struct vlc_http_msg *vlc_http_msg_h2_headers(unsigned n, char *hdrs[][2])
struct vlc_http_msg *vlc_http_msg_h2_headers(unsigned n,
const char *const hdrs[][2])
{
struct vlc_http_msg *m = vlc_http_resp_create(0);
if (unlikely(m == NULL))
......@@ -507,12 +508,6 @@ error:
vlc_http_msg_destroy(m);
m = NULL;
}
for (unsigned i = 0; i < n; i++)
{
free(hdrs[i][0]);
free(hdrs[i][1]);
}
return m;
}
......
......@@ -257,4 +257,5 @@ struct vlc_h2_frame;
struct vlc_h2_frame *vlc_http_msg_h2_frame(const struct vlc_http_msg *m,
uint_fast32_t stream_id, bool eos);
struct vlc_http_msg *vlc_http_msg_h2_headers(unsigned n, char *hdrs[][2]);
struct vlc_http_msg *vlc_http_msg_h2_headers(unsigned count,
const char *const headers[][2]);
......@@ -255,10 +255,10 @@ int main(void)
vlc_http_msg_destroy(m);
char *bad1[][2] = {
{ strdup(":status"), strdup("200") },
{ strdup(":status"), strdup("200") },
{ strdup("Server"), strdup("BigBad/1.0") },
const char *bad1[][2] = {
{ ":status", "200" },
{ ":status", "200" },
{ "Server", "BigBad/1.0" },
};
m = vlc_http_msg_h2_headers(3, bad1);
......@@ -288,12 +288,12 @@ vlc_h2_frame_headers(uint_fast32_t id, uint_fast32_t mtu, bool eos,
assert(mtu == VLC_H2_DEFAULT_MAX_FRAME);
assert(eos);
char *headers[VLC_H2_MAX_HEADERS][2];
const char *headers[VLC_H2_MAX_HEADERS][2];
for (unsigned i = 0; i < count; i++)
{
headers[i][0] = strdup(tab[i][0]);
headers[i][1] = strdup(tab[i][1]);
headers[i][0] = tab[i][0];
headers[i][1] = tab[i][1];
}
m = vlc_http_msg_h2_headers(count, headers);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment