lsquic_frame_reader.c revision 8cba36d8
1/* Copyright (c) 2017 - 2019 LiteSpeed Technologies Inc.  See LICENSE. */
2/*
3 * lsquic_frame_reader.c -- Read HTTP frames from stream
4 */
5
6#ifndef WIN32
7#include <arpa/inet.h>
8#endif
9#include <assert.h>
10#include <ctype.h>
11#include <errno.h>
12#include <inttypes.h>
13#include <stdlib.h>
14#include <string.h>
15#include <sys/queue.h>
16
17#include "lshpack.h"
18#include "lsquic.h"
19#include "lsquic_mm.h"
20#include "lsquic_frame_common.h"
21#include "lsquic_frame_reader.h"
22#include "lsquic_http1x_if.h"
23#include "lsquic_headers.h"
24#include "lsquic_ev_log.h"
25#include "lsquic_conn.h"
26
27#define LSQUIC_LOGGER_MODULE LSQLM_FRAME_READER
28#define LSQUIC_LOG_CONN_ID lsquic_conn_id(lsquic_stream_conn(fr->fr_stream))
29#include "lsquic_logger.h"
30
31
32/* headers_state is used by HEADERS, PUSH_PROMISE, and CONTINUATION frames */
33struct headers_state
34{
35    enum http_frame_type
36                    frame_type;
37    unsigned        nread;  /* Not counting pesw, only payload and padding */
38
39    /* Values parsed out from pesw buffer: */
40    uint32_t        oth_stream_id;  /* For HEADERS: ID of stream we depend on;
41                                     * for PUSH_PROMISE: promised stream ID.
42                                     */
43    unsigned short  weight;         /* HEADERS only */
44    signed char     exclusive;      /* HEADERS only */
45    unsigned char   pad_length;
46
47    unsigned char   pseh;
48
49    /* PESW: Pad length, Exclusive, Stream Dependency, Weight.  This is at
50     * most six bytes for HEADERS frame (RFC 7540, page 33) and five bytes
51     * for PUSH_PROMISE frame (Ibid, p. 40).
52     */
53    unsigned char   pesw_size;
54    unsigned char   pesw_nread;
55    unsigned char   pesw[6];
56};
57
58
59struct settings_state
60{   /* RFC 7540, Section 6.5.1 */
61    unsigned char   nread;
62    unsigned char   set_buf[2 + 4]; /* We'll read one setting at a time */
63};
64
65
66struct priority_state
67{   /* RFC 7540, Section 6.3 */
68    unsigned char   nread;
69    union {
70        unsigned char           prio_buf[sizeof(struct http_prio_frame)];
71        struct http_prio_frame  prio_frame;
72    }               u;
73};
74
75
76struct skip_state
77{
78    uint32_t    n_skipped;
79};
80
81
82struct reader_state
83{
84    unsigned                    nh_read;    /* Number of bytes of header read */
85    struct http_frame_header    header;
86    enum {
87        READER_SKIP,
88        READER_HEADERS,
89        READER_PUSH_PROMISE,
90        READER_CONTIN,
91        READER_SETTINGS,
92        READER_PRIORITY,
93    }                           reader_type;
94    unsigned                    payload_length;
95    union {
96        struct headers_state    headers_state;
97        struct skip_state       skip_state;
98        struct settings_state   settings_state;
99        struct priority_state   priority_state;
100    }                           by_type;
101};
102
103
104struct lsquic_frame_reader
105{
106    struct lsquic_mm                *fr_mm;
107    struct lshpack_dec              *fr_hdec;
108    struct lsquic_stream            *fr_stream;
109    fr_stream_read_f                 fr_read;
110    const struct frame_reader_callbacks
111                                    *fr_callbacks;
112    void                            *fr_cb_ctx;
113    const struct lsquic_hset_if     *fr_hsi_if;
114    void                            *fr_hsi_ctx;
115    struct http1x_ctor_ctx           fr_h1x_ctor_ctx;
116    /* The the header block is shared between HEADERS, PUSH_PROMISE, and
117     * CONTINUATION frames.  It gets added to as block fragments come in.
118     */
119    unsigned char                   *fr_header_block;
120#if LSQUIC_CONN_STATS
121    struct conn_stats               *fr_conn_stats;
122#endif
123    unsigned                         fr_header_block_sz;
124    unsigned                         fr_max_headers_sz; /* 0 means no limit */
125    enum frame_reader_flags          fr_flags;
126    /* Keep some information about previous frame to catch framing errors.
127     */
128    uint32_t                         fr_prev_stream_id;
129    enum http_frame_header_flags     fr_prev_hfh_flags:8;
130    enum http_frame_type             fr_prev_frame_type:8;
131    struct reader_state              fr_state;
132};
133
134
135#define reset_state(fr) do {                                                \
136    LSQ_DEBUG("reset state");                                                \
137    (fr)->fr_state.nh_read = 0;                                             \
138} while (0)
139
140
141static uint32_t
142fr_get_stream_id (const struct lsquic_frame_reader *fr)
143{
144    uint32_t stream_id;
145    assert(fr->fr_state.nh_read >= sizeof(fr->fr_state.header));
146    memcpy(&stream_id, fr->fr_state.header.hfh_stream_id, sizeof(stream_id));
147    stream_id = ntohl(stream_id);
148    return stream_id;
149}
150
151
152static const char *
153hft_to_string (enum http_frame_type hft)
154{
155    static const char *const map[] = {
156        [HTTP_FRAME_DATA]           =  "HTTP_FRAME_DATA",
157        [HTTP_FRAME_HEADERS]        =  "HTTP_FRAME_HEADERS",
158        [HTTP_FRAME_PRIORITY]       =  "HTTP_FRAME_PRIORITY",
159        [HTTP_FRAME_RST_STREAM]     =  "HTTP_FRAME_RST_STREAM",
160        [HTTP_FRAME_SETTINGS]       =  "HTTP_FRAME_SETTINGS",
161        [HTTP_FRAME_PUSH_PROMISE]   =  "HTTP_FRAME_PUSH_PROMISE",
162        [HTTP_FRAME_PING]           =  "HTTP_FRAME_PING",
163        [HTTP_FRAME_GOAWAY]         =  "HTTP_FRAME_GOAWAY",
164        [HTTP_FRAME_WINDOW_UPDATE]  =  "HTTP_FRAME_WINDOW_UPDATE",
165        [HTTP_FRAME_CONTINUATION]   =  "HTTP_FRAME_CONTINUATION",
166    };
167    if (hft < N_HTTP_FRAME_TYPES)
168        return map[hft];
169    else
170        return "<unknown>";
171}
172
173
174struct lsquic_frame_reader *
175lsquic_frame_reader_new (enum frame_reader_flags flags,
176                    unsigned max_headers_sz,
177                    struct lsquic_mm *mm,
178                    struct lsquic_stream *stream, fr_stream_read_f read,
179                    struct lshpack_dec *hdec,
180                    const struct frame_reader_callbacks *cb,
181                    void *frame_reader_cb_ctx,
182#if LSQUIC_CONN_STATS
183                    struct conn_stats *conn_stats,
184#endif
185                    const struct lsquic_hset_if *hsi_if, void *hsi_ctx)
186{
187    struct lsquic_frame_reader *fr = malloc(sizeof(*fr));
188    if (!fr)
189        return NULL;
190    fr->fr_mm             = mm;
191    fr->fr_hdec           = hdec;
192    fr->fr_flags          = flags;
193    fr->fr_stream         = stream;
194    fr->fr_read           = read;
195    fr->fr_callbacks      = cb;
196    fr->fr_cb_ctx         = frame_reader_cb_ctx;
197    fr->fr_header_block   = NULL;
198    fr->fr_max_headers_sz = max_headers_sz;
199    fr->fr_hsi_if         = hsi_if;
200    if (hsi_if == lsquic_http1x_if)
201    {
202        fr->fr_h1x_ctor_ctx = (struct http1x_ctor_ctx) {
203            .cid            = LSQUIC_LOG_CONN_ID,
204            .max_headers_sz = fr->fr_max_headers_sz,
205            .is_server      = fr->fr_flags & FRF_SERVER,
206        };
207        fr->fr_hsi_ctx = &fr->fr_h1x_ctor_ctx;
208    }
209    else
210        fr->fr_hsi_ctx = hsi_ctx;
211    reset_state(fr);
212#if LSQUIC_CONN_STATS
213    fr->fr_conn_stats = conn_stats;
214#endif
215    return fr;
216}
217
218
219void
220lsquic_frame_reader_destroy (struct lsquic_frame_reader *fr)
221{
222    free(fr->fr_header_block);
223    free(fr);
224}
225
226
227#define RETURN_ERROR(nread) do {                                        \
228    assert(nread <= 0);                                                 \
229    if (0 == nread)                                                     \
230    {                                                                   \
231        LSQ_INFO("%s: unexpected EOF", __func__);                        \
232        return -1;                                                      \
233    }                                                                   \
234    else                                                                \
235    {                                                                   \
236        LSQ_WARN("%s: error reading from stream: %s", __func__,          \
237            strerror(errno));                                           \
238        return -1;                                                      \
239    }                                                                   \
240} while (0)
241
242
243static int
244prepare_for_payload (struct lsquic_frame_reader *fr)
245{
246    uint32_t stream_id;
247    unsigned char *header_block;
248
249    /* RFC 7540, Section 4.1: Ignore R bit: */
250    fr->fr_state.header.hfh_stream_id[0] &= ~0x80;
251
252    fr->fr_state.payload_length = hfh_get_length(&fr->fr_state.header);
253
254    stream_id = fr_get_stream_id(fr);
255
256    if (fr->fr_state.header.hfh_type != HTTP_FRAME_CONTINUATION &&
257        (fr->fr_flags & FRF_HAVE_PREV) &&
258        (fr->fr_prev_frame_type == HTTP_FRAME_HEADERS      ||
259         fr->fr_prev_frame_type == HTTP_FRAME_PUSH_PROMISE ||
260         fr->fr_prev_frame_type == HTTP_FRAME_CONTINUATION    ) &&
261        0 == (fr->fr_prev_hfh_flags & HFHF_END_HEADERS))
262    {
263        LSQ_INFO("Framing error: expected CONTINUATION frame, got %u",
264                                            fr->fr_state.header.hfh_type);
265        fr->fr_callbacks->frc_on_error(fr->fr_cb_ctx, stream_id,
266                                                FR_ERR_EXPECTED_CONTIN);
267        return -1;
268    }
269
270    switch (fr->fr_state.header.hfh_type)
271    {
272    case HTTP_FRAME_HEADERS:
273        if (fr->fr_max_headers_sz &&
274            fr->fr_state.payload_length > fr->fr_max_headers_sz)
275            goto headers_too_large;
276        fr->fr_state.by_type.headers_state.frame_type = HTTP_FRAME_HEADERS;
277        fr->fr_state.by_type.headers_state.nread = 0;
278        fr->fr_state.by_type.headers_state.pesw_nread = 0;
279        fr->fr_state.by_type.headers_state.pseh = 0;
280        if (fr->fr_state.header.hfh_flags & HFHF_PADDED)
281            fr->fr_state.by_type.headers_state.pesw_size = 1;
282        else
283        {
284            fr->fr_state.by_type.headers_state.pad_length = 0;
285            fr->fr_state.by_type.headers_state.pesw_size = 0;
286        }
287        if (fr->fr_state.header.hfh_flags & HFHF_PRIORITY)
288            fr->fr_state.by_type.headers_state.pesw_size += 5;
289        else
290        {
291            fr->fr_state.by_type.headers_state.exclusive     = -1;
292            fr->fr_state.by_type.headers_state.oth_stream_id = 0;
293            fr->fr_state.by_type.headers_state.weight        = 0;
294        }
295        LSQ_DEBUG("pesw size: %u; payload length: %u; flags: 0x%X",
296            fr->fr_state.by_type.headers_state.pesw_size,
297            fr->fr_state.payload_length, fr->fr_state.header.hfh_flags);
298        if (fr->fr_state.by_type.headers_state.pesw_size >
299                                        fr->fr_state.payload_length)
300        {
301            LSQ_INFO("Invalid headers frame: payload length too small");
302            errno = EBADMSG;
303            return -1;
304        }
305        fr->fr_state.reader_type = READER_HEADERS;
306        break;
307    case HTTP_FRAME_PUSH_PROMISE:
308        if (fr->fr_flags & FRF_SERVER)
309        {
310            LSQ_INFO("clients should not push promised");
311            fr->fr_callbacks->frc_on_error(fr->fr_cb_ctx, stream_id,
312                                                    FR_ERR_UNEXPECTED_PUSH);
313            return -1;
314        }
315        if (fr->fr_max_headers_sz &&
316            fr->fr_state.payload_length > fr->fr_max_headers_sz)
317            goto headers_too_large;
318        fr->fr_state.by_type.headers_state.frame_type = HTTP_FRAME_PUSH_PROMISE;
319        fr->fr_state.by_type.headers_state.nread = 0;
320        fr->fr_state.by_type.headers_state.pesw_nread = 0;
321        fr->fr_state.by_type.headers_state.pseh = 0;
322        if (fr->fr_state.header.hfh_flags & HFHF_PADDED)
323            fr->fr_state.by_type.headers_state.pesw_size = 5;
324        else
325        {
326            fr->fr_state.by_type.headers_state.pad_length = 0;
327            fr->fr_state.by_type.headers_state.pesw_size = 4;
328        }
329        LSQ_DEBUG("pesw size: %u; payload length: %u; flags: 0x%X",
330            fr->fr_state.by_type.headers_state.pesw_size,
331            fr->fr_state.payload_length, fr->fr_state.header.hfh_flags);
332        if (fr->fr_state.by_type.headers_state.pesw_size >
333                                        fr->fr_state.payload_length)
334        {
335            LSQ_INFO("Invalid headers frame: payload length too small");
336            errno = EBADMSG;
337            return -1;
338        }
339        fr->fr_state.reader_type = READER_PUSH_PROMISE;
340        break;
341    case HTTP_FRAME_CONTINUATION:
342        if (0 == (fr->fr_flags & FRF_HAVE_PREV))
343        {
344            LSQ_INFO("Framing error: unexpected CONTINUATION");
345            return -1;
346        }
347        if (!(fr->fr_prev_frame_type == HTTP_FRAME_HEADERS      ||
348              fr->fr_prev_frame_type == HTTP_FRAME_PUSH_PROMISE ||
349              fr->fr_prev_frame_type == HTTP_FRAME_CONTINUATION))
350        {
351            LSQ_INFO("Framing error: unexpected CONTINUATION");
352            return -1;
353        }
354        if (fr->fr_prev_hfh_flags & HFHF_END_HEADERS)
355        {
356            LSQ_INFO("Framing error: unexpected CONTINUATION");
357            return -1;
358        }
359        if (stream_id != fr->fr_prev_stream_id)
360        {
361            LSQ_INFO("Framing error: CONTINUATION does not have matching "
362                "stream ID");
363            return -1;
364        }
365        if (fr->fr_state.reader_type == READER_SKIP)
366            goto continue_skipping;
367        fr->fr_header_block_sz += fr->fr_state.payload_length;
368        if (fr->fr_max_headers_sz &&
369            fr->fr_header_block_sz > fr->fr_max_headers_sz)
370        {
371            free(fr->fr_header_block);
372            fr->fr_header_block = NULL;
373            goto headers_too_large;
374        }
375        header_block = realloc(fr->fr_header_block, fr->fr_header_block_sz);
376        if (!header_block)
377        {
378            LSQ_WARN("cannot allocate %u bytes for header block",
379                                                    fr->fr_header_block_sz);
380            fr->fr_callbacks->frc_on_error(fr->fr_cb_ctx, stream_id,
381                                                                FR_ERR_NOMEM);
382            return -1;
383        }
384        fr->fr_header_block = header_block;
385        fr->fr_state.by_type.headers_state.nread = 0;
386        fr->fr_state.reader_type = READER_CONTIN;
387        break;
388    case HTTP_FRAME_SETTINGS:
389        if (0 == fr->fr_state.payload_length ||
390            0 != fr->fr_state.payload_length % 6)
391        {
392            LSQ_INFO("Framing error: %u is not a valid SETTINGS length",
393                fr->fr_state.payload_length);
394            fr->fr_callbacks->frc_on_error(fr->fr_cb_ctx, stream_id,
395                                                    FR_ERR_INVALID_FRAME_SIZE);
396            return -1;
397        }
398        if (stream_id)
399        {   /* RFC 7540, Section 6.5 */
400            LSQ_INFO("Error: SETTINGS frame should not have stream ID set");
401            fr->fr_callbacks->frc_on_error(fr->fr_cb_ctx, stream_id,
402                                                    FR_ERR_NONZERO_STREAM_ID);
403            return -1;
404        }
405        fr->fr_state.by_type.settings_state.nread = 0;
406        fr->fr_state.reader_type = READER_SETTINGS;
407        break;
408    case HTTP_FRAME_PRIORITY:
409        if (fr->fr_state.payload_length != sizeof(struct http_prio_frame))
410        {
411            LSQ_INFO("Framing error: %u is not a valid PRIORITY length",
412                fr->fr_state.payload_length);
413            fr->fr_callbacks->frc_on_error(fr->fr_cb_ctx, stream_id,
414                                                    FR_ERR_INVALID_FRAME_SIZE);
415            return -1;
416        }
417        if (!stream_id)
418        {   /* RFC 7540, Section 6.3 */
419            LSQ_INFO("Error: PRIORITY frame must have stream ID set");
420            fr->fr_callbacks->frc_on_error(fr->fr_cb_ctx, stream_id,
421                                                    FR_ERR_ZERO_STREAM_ID);
422            return -1;
423        }
424        fr->fr_state.by_type.settings_state.nread = 0;
425        fr->fr_state.reader_type = READER_PRIORITY;
426        break;
427    headers_too_large:
428        LSQ_INFO("headers are too large (%u bytes), skipping",
429            fr->fr_state.payload_length);
430        fr->fr_callbacks->frc_on_error(fr->fr_cb_ctx, stream_id,
431                                                FR_ERR_HEADERS_TOO_LARGE);
432        /* fallthru */
433    continue_skipping:
434    default:
435        fr->fr_state.by_type.skip_state.n_skipped = 0;
436        fr->fr_state.reader_type = READER_SKIP;
437        break;
438    }
439
440    fr->fr_flags |= FRF_HAVE_PREV;
441    fr->fr_prev_frame_type = fr->fr_state.header.hfh_type;
442    fr->fr_prev_hfh_flags  = fr->fr_state.header.hfh_flags;
443    fr->fr_prev_stream_id  = stream_id;
444
445    return 0;
446}
447
448
449static int
450read_http_frame_header (struct lsquic_frame_reader *fr)
451{
452    ssize_t nr;
453    size_t ntoread;
454    unsigned char *dst;
455
456    ntoread = sizeof(fr->fr_state.header) - fr->fr_state.nh_read;
457    dst = (unsigned char *) &fr->fr_state.header + fr->fr_state.nh_read;
458    nr = fr->fr_read(fr->fr_stream, dst, ntoread);
459    if (nr <= 0)
460        RETURN_ERROR(nr);
461    fr->fr_state.nh_read += nr;
462    if (fr->fr_state.nh_read == sizeof(fr->fr_state.header))
463    {
464        LSQ_DEBUG("read in frame %s", hft_to_string(fr->fr_state.header.hfh_type));
465        return prepare_for_payload(fr);
466    }
467    else
468        return 0;
469}
470
471
472static int
473skip_payload (struct lsquic_frame_reader *fr)
474{
475    struct skip_state *ss = &fr->fr_state.by_type.skip_state;
476    size_t ntoread = fr->fr_state.payload_length - ss->n_skipped;
477    unsigned char buf[0x100];
478    if (ntoread > sizeof(buf))
479        ntoread = sizeof(buf);
480    ssize_t nr = fr->fr_read(fr->fr_stream, buf, ntoread);
481    if (nr <= 0)
482        RETURN_ERROR(nr);
483    ss->n_skipped += nr;
484    if (ss->n_skipped == fr->fr_state.payload_length)
485        reset_state(fr);
486    return 0;
487}
488
489
490static int
491skip_headers_padding (struct lsquic_frame_reader *fr)
492{
493    unsigned char buf[0x100];
494    struct headers_state *hs = &fr->fr_state.by_type.headers_state;
495    unsigned pay_and_pad_length = fr->fr_state.payload_length - hs->pesw_size;
496    unsigned ntoread = pay_and_pad_length - hs->nread;
497    assert(ntoread <= sizeof(buf));
498    if (ntoread > sizeof(buf))
499        ntoread = sizeof(buf);
500    ssize_t nr = fr->fr_read(fr->fr_stream, buf, ntoread);
501    if (nr <= 0)
502        RETURN_ERROR(nr);
503    hs->nread += nr;
504    if (hs->nread == pay_and_pad_length)
505        reset_state(fr);
506    return 0;
507}
508
509
510static int
511decode_and_pass_payload (struct lsquic_frame_reader *fr)
512{
513    struct headers_state *hs = &fr->fr_state.by_type.headers_state;
514    const unsigned char *comp, *end;
515    enum frame_reader_error err;
516    int s;
517    uint32_t name_idx;
518    unsigned name_len, val_len;
519    char *buf;
520    struct uncompressed_headers *uh = NULL;
521    void *hset = NULL;
522
523    buf = lsquic_mm_get_16k(fr->fr_mm);
524    if (!buf)
525    {
526        err = FR_ERR_NOMEM;
527        goto stream_error;
528    }
529
530    hset = fr->fr_hsi_if->hsi_create_header_set(fr->fr_hsi_ctx,
531                            READER_PUSH_PROMISE == fr->fr_state.reader_type);
532    if (!hset)
533    {
534        err = FR_ERR_NOMEM;
535        goto stream_error;
536    }
537
538    comp = fr->fr_header_block;
539    end = comp + fr->fr_header_block_sz;
540
541    while (comp < end)
542    {
543        s = lshpack_dec_decode(fr->fr_hdec, &comp, end,
544                    buf, buf + 16 * 1024, &name_len, &val_len, &name_idx);
545        if (s == 0)
546        {
547            err = (enum frame_reader_error)
548                fr->fr_hsi_if->hsi_process_header(hset, name_idx, buf,
549                                        name_len, buf + name_len, val_len);
550            if (err == 0)
551            {
552#if LSQUIC_CONN_STATS
553                fr->fr_conn_stats->in.headers_uncomp += name_len + val_len;
554#endif
555                continue;
556            }
557        }
558        else
559            err = FR_ERR_DECOMPRESS;
560        goto stream_error;
561    }
562    assert(comp == end);
563    lsquic_mm_put_16k(fr->fr_mm, buf);
564    buf = NULL;
565
566    err = (enum frame_reader_error)
567        fr->fr_hsi_if->hsi_process_header(hset, 0, 0, 0, 0, 0);
568    if (err)
569        goto stream_error;
570
571    uh = calloc(1, sizeof(*uh));
572    if (!uh)
573    {
574        err = FR_ERR_NOMEM;
575        goto stream_error;
576    }
577
578    memcpy(&uh->uh_stream_id, fr->fr_state.header.hfh_stream_id,
579                                                sizeof(uh->uh_stream_id));
580    uh->uh_stream_id     = ntohl(uh->uh_stream_id);
581    uh->uh_oth_stream_id = hs->oth_stream_id;
582    if (HTTP_FRAME_HEADERS == fr->fr_state.by_type.headers_state.frame_type)
583    {
584        uh->uh_weight    = hs->weight;
585        uh->uh_exclusive = hs->exclusive;
586        uh->uh_flags     = 0;
587    }
588    else
589    {
590        assert(HTTP_FRAME_PUSH_PROMISE ==
591                                fr->fr_state.by_type.headers_state.frame_type);
592        uh->uh_weight    = 0;   /* Zero unused value */
593        uh->uh_exclusive = 0;   /* Zero unused value */
594        uh->uh_flags     = UH_PP;
595    }
596    if (fr->fr_state.header.hfh_flags & HFHF_END_STREAM)
597        uh->uh_flags    |= UH_FIN;
598    if (fr->fr_hsi_if == lsquic_http1x_if)
599        uh->uh_flags    |= UH_H1H;
600    uh->uh_hset = hset;
601
602    EV_LOG_HTTP_HEADERS_IN(LSQUIC_LOG_CONN_ID, fr->fr_flags & FRF_SERVER, uh);
603    if (HTTP_FRAME_HEADERS == fr->fr_state.by_type.headers_state.frame_type)
604        fr->fr_callbacks->frc_on_headers(fr->fr_cb_ctx, uh);
605    else
606        fr->fr_callbacks->frc_on_push_promise(fr->fr_cb_ctx, uh);
607#if LSQUIC_CONN_STATS
608    fr->fr_conn_stats->in.headers_comp += fr->fr_header_block_sz;
609#endif
610
611    return 0;
612
613  stream_error:
614    LSQ_INFO("%s: stream error %u", __func__, err);
615    if (hset)
616        fr->fr_hsi_if->hsi_discard_header_set(hset);
617    if (uh)
618        free(uh);
619    if (buf)
620        lsquic_mm_put_16k(fr->fr_mm, buf);
621    fr->fr_callbacks->frc_on_error(fr->fr_cb_ctx, fr_get_stream_id(fr), err);
622    return 0;
623}
624
625
626static int
627read_headers_block_fragment (struct lsquic_frame_reader *fr)
628{
629    struct headers_state *hs = &fr->fr_state.by_type.headers_state;
630    ssize_t nr;
631    unsigned payload_length = fr->fr_state.payload_length - hs->pesw_size -
632                                                                hs->pad_length;
633    if (!fr->fr_header_block)
634    {
635        fr->fr_header_block_sz = payload_length;
636        fr->fr_header_block = malloc(payload_length);
637        if (!fr->fr_header_block)
638            return -1;
639    }
640    nr = fr->fr_read(fr->fr_stream, fr->fr_header_block + hs->nread,
641                                            fr->fr_header_block_sz - hs->nread);
642    if (nr <= 0)
643    {
644        free(fr->fr_header_block);
645        fr->fr_header_block = NULL;
646        RETURN_ERROR(nr);
647    }
648    hs->nread += nr;
649    if (hs->nread == payload_length &&
650                (fr->fr_state.header.hfh_flags & HFHF_END_HEADERS))
651    {
652        int rv = decode_and_pass_payload(fr);
653        free(fr->fr_header_block);
654        fr->fr_header_block = NULL;
655        return rv;
656    }
657    else
658        return 0;
659}
660
661
662static int
663read_headers_block_fragment_and_padding (struct lsquic_frame_reader *fr)
664{
665    struct headers_state *hs = &fr->fr_state.by_type.headers_state;
666    unsigned payload_length = fr->fr_state.payload_length - hs->pesw_size;
667    int rv;
668    if (hs->nread < payload_length - hs->pad_length)
669        rv = read_headers_block_fragment(fr);
670    else if (payload_length)
671        rv = skip_headers_padding(fr);
672    else
673    {   /* Edge case where PESW takes up the whole frame */
674        fr->fr_header_block_sz = 0;
675        fr->fr_header_block    = NULL;
676        rv = 0;
677    }
678    if (0 == rv && hs->nread == payload_length)
679        reset_state(fr);
680    return rv;
681}
682
683
684static int
685read_headers_pesw (struct lsquic_frame_reader *fr)
686{
687    struct headers_state *hs = &fr->fr_state.by_type.headers_state;
688    ssize_t nr = fr->fr_read(fr->fr_stream, hs->pesw + hs->pesw_nread,
689                                            hs->pesw_size - hs->pesw_nread);
690    if (nr <= 0)
691        RETURN_ERROR(nr);
692    hs->pesw_nread += nr;
693    if (hs->pesw_nread == hs->pesw_size)
694    {
695        unsigned char *p = hs->pesw;
696        if (fr->fr_state.header.hfh_flags & HFHF_PADDED)
697            hs->pad_length = *p++;
698        if (fr->fr_state.header.hfh_flags & HFHF_PRIORITY)
699        {
700            hs->exclusive = p[0] >> 7;
701            p[0] &= ~0x80;  /* Note that we are modifying pesw buffer. */
702            memcpy(&hs->oth_stream_id, p, sizeof(hs->oth_stream_id));
703            hs->oth_stream_id = ntohl(hs->oth_stream_id);
704            p += 4;
705            hs->weight = 1 + *p++;
706        }
707        assert(p - hs->pesw == hs->pesw_size);
708
709        if (hs->pesw_size + hs->pad_length > fr->fr_state.payload_length)
710        {
711            LSQ_INFO("Invalid headers frame: pesw length and padding length "
712                    "are larger than the payload length");
713            errno = EBADMSG;
714            return -1;
715        }
716    }
717    return 0;
718}
719
720
721static int
722read_headers (struct lsquic_frame_reader *fr)
723{
724    struct headers_state *hs = &fr->fr_state.by_type.headers_state;
725    if (hs->pesw_nread < hs->pesw_size)
726        return read_headers_pesw(fr);
727    else
728        return read_headers_block_fragment_and_padding(fr);
729}
730
731
732static int
733read_push_promise_pesw (struct lsquic_frame_reader *fr)
734{
735    struct headers_state *hs = &fr->fr_state.by_type.headers_state;
736    ssize_t nr = fr->fr_read(fr->fr_stream, hs->pesw + hs->pesw_nread,
737                                            hs->pesw_size - hs->pesw_nread);
738    if (nr <= 0)
739        RETURN_ERROR(nr);
740    hs->pesw_nread += nr;
741    if (hs->pesw_nread == hs->pesw_size)
742    {
743        unsigned char *p = hs->pesw;
744        if (fr->fr_state.header.hfh_flags & HFHF_PADDED)
745            hs->pad_length = *p++;
746        p[0] &= ~0x80;  /* Clear reserved bit.  Note: modifying pesw buffer. */
747        memcpy(&hs->oth_stream_id, p, sizeof(hs->oth_stream_id));
748        hs->oth_stream_id = ntohl(hs->oth_stream_id);
749        p += 4;
750        assert(p - hs->pesw == hs->pesw_size);
751        if (hs->pesw_size + hs->pad_length > fr->fr_state.payload_length)
752        {
753            LSQ_INFO("Invalid PUSH_PROMISE frame: pesw length and padding length "
754                    "are larger than the payload length");
755            errno = EBADMSG;
756            return -1;
757        }
758    }
759    return 0;
760}
761
762
763static int
764read_push_promise (struct lsquic_frame_reader *fr)
765{
766    struct headers_state *hs = &fr->fr_state.by_type.headers_state;
767    if (hs->pesw_nread < hs->pesw_size)
768        return read_push_promise_pesw(fr);
769    else
770        return read_headers_block_fragment_and_padding(fr);
771}
772
773
774static int
775read_contin (struct lsquic_frame_reader *fr)
776{
777    struct headers_state *hs = &fr->fr_state.by_type.headers_state;
778    unsigned ntoread;
779    ssize_t nr;
780
781    ntoread = fr->fr_state.payload_length - hs->nread;
782    nr = fr->fr_read(fr->fr_stream,
783                     fr->fr_header_block + fr->fr_header_block_sz - ntoread,
784                     ntoread);
785    if (nr <= 0)
786        RETURN_ERROR(nr);
787    hs->nread += nr;
788    if (hs->nread == fr->fr_state.payload_length)
789    {
790        if (fr->fr_state.header.hfh_flags & HFHF_END_HEADERS)
791        {
792            int rv = decode_and_pass_payload(fr);
793            free(fr->fr_header_block);
794            fr->fr_header_block = NULL;
795            reset_state(fr);
796            return rv;
797        }
798        else
799        {
800            reset_state(fr);
801            return 0;
802        }
803    }
804    else
805        return 0;
806}
807
808
809static int
810read_settings (struct lsquic_frame_reader *fr)
811{
812    struct settings_state *ss = &fr->fr_state.by_type.settings_state;
813    unsigned ntoread;
814    ssize_t nr;
815    uint32_t setting_value;
816    uint16_t setting_id;
817
818    ntoread = sizeof(ss->set_buf) - ss->nread;
819    nr = fr->fr_read(fr->fr_stream, ss->set_buf + ss->nread, ntoread);
820    if (nr <= 0)
821        RETURN_ERROR(nr);
822    ss->nread += nr;
823    if (ss->nread == sizeof(ss->set_buf))
824    {
825        memcpy(&setting_id,    ss->set_buf, 2);
826        memcpy(&setting_value, ss->set_buf + 2, 4);
827        setting_id    = ntohs(setting_id);
828        setting_value = ntohl(setting_value);
829        EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID, "read HTTP SETTING %s=%"PRIu32,
830                        lsquic_http_setting_id2str(setting_id), setting_value);
831        fr->fr_callbacks->frc_on_settings(fr->fr_cb_ctx, setting_id,
832                                                        setting_value);
833
834        fr->fr_state.payload_length -= sizeof(ss->set_buf);
835        if (0 == fr->fr_state.payload_length)
836            reset_state(fr);
837        else
838            ss->nread = 0;
839    }
840    return 0;
841}
842
843
844static int
845read_priority (struct lsquic_frame_reader *fr)
846{
847    struct priority_state *ps = &fr->fr_state.by_type.priority_state;
848    unsigned ntoread;
849    ssize_t nr;
850    uint32_t stream_id, dep_stream_id;
851    int exclusive;
852
853    ntoread = sizeof(ps->u.prio_buf) - ps->nread;
854    nr = fr->fr_read(fr->fr_stream, ps->u.prio_buf + ps->nread, ntoread);
855    if (nr <= 0)
856        RETURN_ERROR(nr);
857    ps->nread += nr;
858    if (ps->nread == sizeof(ps->u.prio_buf))
859    {
860        memcpy(&dep_stream_id, ps->u.prio_frame.hpf_stream_id, 4);
861        dep_stream_id = ntohl(dep_stream_id);
862        exclusive = dep_stream_id >> 31;
863        dep_stream_id &= ~(1UL << 31);
864        stream_id = fr_get_stream_id(fr);
865        if (stream_id == dep_stream_id)
866            fr->fr_callbacks->frc_on_error(fr->fr_cb_ctx, stream_id,
867                                                    FR_ERR_SELF_DEP_STREAM);
868        else
869        {
870            EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID, "read PRIORITY frame; "
871                "stream: %"PRIu32", dep stream %"PRIu32", exclusive: %d, "
872                "weight: %u", stream_id, dep_stream_id, exclusive,
873                ps->u.prio_frame.hpf_weight + 1);
874            fr->fr_callbacks->frc_on_priority(fr->fr_cb_ctx, stream_id,
875                    exclusive, dep_stream_id, ps->u.prio_frame.hpf_weight + 1);
876        }
877        reset_state(fr);
878    }
879    return 0;
880}
881
882
883static int
884read_payload (struct lsquic_frame_reader *fr)
885{
886    switch (fr->fr_state.reader_type)
887    {
888    case READER_HEADERS:
889        return read_headers(fr);
890    case READER_PUSH_PROMISE:
891        return read_push_promise(fr);
892    case READER_CONTIN:
893        return read_contin(fr);
894    case READER_SETTINGS:
895        return read_settings(fr);
896    case READER_PRIORITY:
897        return read_priority(fr);
898    default:
899        assert(READER_SKIP == fr->fr_state.reader_type);
900        return skip_payload(fr);
901    }
902}
903
904
905int
906lsquic_frame_reader_read (struct lsquic_frame_reader *fr)
907{
908    if (fr->fr_state.nh_read < sizeof(fr->fr_state.header))
909        return read_http_frame_header(fr);
910    else
911        return read_payload(fr);
912}
913
914
915size_t
916lsquic_frame_reader_mem_used (const struct lsquic_frame_reader *fr)
917{
918    size_t size;
919    size = sizeof(*fr);
920    if (fr->fr_header_block)
921        size += fr->fr_header_block_sz;
922    return size;
923}
924