lsquic_frame_reader.c revision 10c492f0
1/* Copyright (c) 2017 - 2018 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 "lsquic_arr.h"
18#include "lsquic_hpack_dec.h"
19#include "lsquic.h"
20#include "lsquic_mm.h"
21#include "lsquic_frame_common.h"
22#include "lsquic_frame_reader.h"
23#include "lsquic_ev_log.h"
24
25#define LSQUIC_LOGGER_MODULE LSQLM_FRAME_READER
26#define LSQUIC_LOG_CONN_ID lsquic_conn_id(lsquic_stream_conn(fr->fr_stream))
27#include "lsquic_logger.h"
28
29
30enum pseudo_header
31{
32    PSEH_METHOD,
33    PSEH_SCHEME,
34    PSEH_AUTHORITY,
35    PSEH_PATH,
36    PSEH_STATUS,
37    N_PSEH
38};
39
40#define BIT(x) (1 << (x))
41
42#define ALL_REQUEST_PSEH (BIT(PSEH_METHOD)|BIT(PSEH_SCHEME)|BIT(PSEH_AUTHORITY)|BIT(PSEH_PATH))
43#define REQUIRED_REQUEST_PSEH (BIT(PSEH_METHOD)|BIT(PSEH_SCHEME)|BIT(PSEH_PATH))
44
45#define ALL_SERVER_PSEH BIT(PSEH_STATUS)
46#define REQUIRED_SERVER_PSEH ALL_SERVER_PSEH
47
48#define PSEH_LEN(h) (sizeof(#h) - 5)
49
50
51/* headers_state is used by HEADERS, PUSH_PROMISE, and CONTINUATION frames */
52struct headers_state
53{
54    enum http_frame_type
55                    frame_type;
56    unsigned        nread;  /* Not counting pesw, only payload and padding */
57
58    /* Values parsed out from pesw buffer: */
59    uint32_t        oth_stream_id;  /* For HEADERS: ID of stream we depend on;
60                                     * for PUSH_PROMISE: promised stream ID.
61                                     */
62    unsigned short  weight;         /* HEADERS only */
63    signed char     exclusive;      /* HEADERS only */
64    unsigned char   pad_length;
65
66    unsigned char   pseh;
67
68    /* PESW: Pad length, Exclusive, Stream Dependency, Weight.  This is at
69     * most six bytes for HEADERS frame (RFC 7540, page 33) and five bytes
70     * for PUSH_PROMISE frame (Ibid, p. 40).
71     */
72    unsigned char   pesw_size;
73    unsigned char   pesw_nread;
74    unsigned char   pesw[6];
75};
76
77
78struct settings_state
79{   /* RFC 7540, Section 6.5.1 */
80    unsigned char   nread;
81    unsigned char   set_buf[2 + 4]; /* We'll read one setting at a time */
82};
83
84
85struct priority_state
86{   /* RFC 7540, Section 6.3 */
87    unsigned char   nread;
88    union {
89        unsigned char           prio_buf[sizeof(struct http_prio_frame)];
90        struct http_prio_frame  prio_frame;
91    }               u;
92};
93
94
95struct skip_state
96{
97    uint32_t    n_skipped;
98};
99
100
101struct reader_state
102{
103    unsigned                    nh_read;    /* Number of bytes of header read */
104    struct http_frame_header    header;
105    enum {
106        READER_SKIP,
107        READER_HEADERS,
108        READER_PUSH_PROMISE,
109        READER_CONTIN,
110        READER_SETTINGS,
111        READER_PRIORITY,
112    }                           reader_type;
113    unsigned                    payload_length;
114    union {
115        struct headers_state    headers_state;
116        struct skip_state       skip_state;
117        struct settings_state   settings_state;
118        struct priority_state   priority_state;
119    }                           by_type;
120};
121
122
123struct lsquic_frame_reader
124{
125    struct lsquic_mm                *fr_mm;
126    struct lsquic_hdec              *fr_hdec;
127    struct lsquic_stream            *fr_stream;
128    fr_stream_read_f                 fr_read;
129    const struct frame_reader_callbacks
130                                    *fr_callbacks;
131    void                            *fr_cb_ctx;
132    /* The the header block is shared between HEADERS, PUSH_PROMISE, and
133     * CONTINUATION frames.  It gets added to as block fragments come in.
134     */
135    unsigned char                   *fr_header_block;
136    unsigned                         fr_header_block_sz;
137    unsigned                         fr_max_headers_sz; /* 0 means no limit */
138    enum frame_reader_flags          fr_flags;
139    /* Keep some information about previous frame to catch framing errors.
140     */
141    uint32_t                         fr_prev_stream_id;
142    enum http_frame_header_flags     fr_prev_hfh_flags:8;
143    enum http_frame_type             fr_prev_frame_type:8;
144    struct reader_state              fr_state;
145};
146
147
148#define reset_state(fr) do {                                                \
149    LSQ_DEBUG("reset state");                                                \
150    (fr)->fr_state.nh_read = 0;                                             \
151} while (0)
152
153
154static uint32_t
155fr_get_stream_id (const struct lsquic_frame_reader *fr)
156{
157    uint32_t stream_id;
158    assert(fr->fr_state.nh_read >= sizeof(fr->fr_state.header));
159    memcpy(&stream_id, fr->fr_state.header.hfh_stream_id, sizeof(stream_id));
160    stream_id = ntohl(stream_id);
161    return stream_id;
162}
163
164
165static const char *
166hft_to_string (enum http_frame_type hft)
167{
168    static const char *const map[] = {
169        [HTTP_FRAME_DATA]           =  "HTTP_FRAME_DATA",
170        [HTTP_FRAME_HEADERS]        =  "HTTP_FRAME_HEADERS",
171        [HTTP_FRAME_PRIORITY]       =  "HTTP_FRAME_PRIORITY",
172        [HTTP_FRAME_RST_STREAM]     =  "HTTP_FRAME_RST_STREAM",
173        [HTTP_FRAME_SETTINGS]       =  "HTTP_FRAME_SETTINGS",
174        [HTTP_FRAME_PUSH_PROMISE]   =  "HTTP_FRAME_PUSH_PROMISE",
175        [HTTP_FRAME_PING]           =  "HTTP_FRAME_PING",
176        [HTTP_FRAME_GOAWAY]         =  "HTTP_FRAME_GOAWAY",
177        [HTTP_FRAME_WINDOW_UPDATE]  =  "HTTP_FRAME_WINDOW_UPDATE",
178        [HTTP_FRAME_CONTINUATION]   =  "HTTP_FRAME_CONTINUATION",
179    };
180    if (hft < N_HTTP_FRAME_TYPES)
181        return map[hft];
182    else
183        return "<unknown>";
184}
185
186
187struct lsquic_frame_reader *
188lsquic_frame_reader_new (enum frame_reader_flags flags,
189                    unsigned max_headers_sz,
190                    struct lsquic_mm *mm,
191                    struct lsquic_stream *stream, fr_stream_read_f read,
192                    struct lsquic_hdec *hdec,
193                    const struct frame_reader_callbacks *cb,
194                    void *frame_reader_cb_ctx)
195{
196    struct lsquic_frame_reader *fr = malloc(sizeof(*fr));
197    if (!fr)
198        return NULL;
199    fr->fr_mm             = mm;
200    fr->fr_hdec           = hdec;
201    fr->fr_flags          = flags;
202    fr->fr_stream         = stream;
203    fr->fr_read           = read;
204    fr->fr_callbacks      = cb;
205    fr->fr_cb_ctx         = frame_reader_cb_ctx;
206    fr->fr_header_block   = NULL;
207    fr->fr_max_headers_sz = max_headers_sz;
208    reset_state(fr);
209    return fr;
210}
211
212
213void
214lsquic_frame_reader_destroy (struct lsquic_frame_reader *fr)
215{
216    free(fr->fr_header_block);
217    free(fr);
218}
219
220
221#define RETURN_ERROR(nread) do {                                        \
222    assert(nread <= 0);                                                 \
223    if (0 == nread)                                                     \
224    {                                                                   \
225        LSQ_INFO("%s: unexpected EOF", __func__);                        \
226        return -1;                                                      \
227    }                                                                   \
228    else                                                                \
229    {                                                                   \
230        LSQ_WARN("%s: error reading from stream: %s", __func__,          \
231            strerror(errno));                                           \
232        return -1;                                                      \
233    }                                                                   \
234} while (0)
235
236
237static int
238prepare_for_payload (struct lsquic_frame_reader *fr)
239{
240    uint32_t stream_id;
241    unsigned char *header_block;
242
243    /* RFC 7540, Section 4.1: Ignore R bit: */
244    fr->fr_state.header.hfh_stream_id[0] &= ~0x80;
245
246    fr->fr_state.payload_length = hfh_get_length(&fr->fr_state.header);
247
248    stream_id = fr_get_stream_id(fr);
249
250    if (fr->fr_state.header.hfh_type != HTTP_FRAME_CONTINUATION &&
251        (fr->fr_flags & FRF_HAVE_PREV) &&
252        (fr->fr_prev_frame_type == HTTP_FRAME_HEADERS      ||
253         fr->fr_prev_frame_type == HTTP_FRAME_PUSH_PROMISE ||
254         fr->fr_prev_frame_type == HTTP_FRAME_CONTINUATION    ) &&
255        0 == (fr->fr_prev_hfh_flags & HFHF_END_HEADERS))
256    {
257        LSQ_INFO("Framing error: expected CONTINUATION frame, got %u",
258                                            fr->fr_state.header.hfh_type);
259        fr->fr_callbacks->frc_on_error(fr->fr_cb_ctx, stream_id,
260                                                FR_ERR_EXPECTED_CONTIN);
261        return -1;
262    }
263
264    switch (fr->fr_state.header.hfh_type)
265    {
266    case HTTP_FRAME_HEADERS:
267        if (fr->fr_max_headers_sz &&
268            fr->fr_state.payload_length > fr->fr_max_headers_sz)
269            goto headers_too_large;
270        fr->fr_state.by_type.headers_state.frame_type = HTTP_FRAME_HEADERS;
271        fr->fr_state.by_type.headers_state.nread = 0;
272        fr->fr_state.by_type.headers_state.pesw_nread = 0;
273        fr->fr_state.by_type.headers_state.pseh = 0;
274        if (fr->fr_state.header.hfh_flags & HFHF_PADDED)
275            fr->fr_state.by_type.headers_state.pesw_size = 1;
276        else
277        {
278            fr->fr_state.by_type.headers_state.pad_length = 0;
279            fr->fr_state.by_type.headers_state.pesw_size = 0;
280        }
281        if (fr->fr_state.header.hfh_flags & HFHF_PRIORITY)
282            fr->fr_state.by_type.headers_state.pesw_size += 5;
283        else
284        {
285            fr->fr_state.by_type.headers_state.exclusive     = -1;
286            fr->fr_state.by_type.headers_state.oth_stream_id = 0;
287            fr->fr_state.by_type.headers_state.weight        = 0;
288        }
289        LSQ_DEBUG("pesw size: %u; payload length: %u; flags: 0x%X",
290            fr->fr_state.by_type.headers_state.pesw_size,
291            fr->fr_state.payload_length, fr->fr_state.header.hfh_flags);
292        if (fr->fr_state.by_type.headers_state.pesw_size >
293                                        fr->fr_state.payload_length)
294        {
295            LSQ_INFO("Invalid headers frame: payload length too small");
296            errno = EBADMSG;
297            return -1;
298        }
299        fr->fr_state.reader_type = READER_HEADERS;
300        break;
301    case HTTP_FRAME_PUSH_PROMISE:
302        if (fr->fr_flags & FRF_SERVER)
303        {
304            LSQ_INFO("clients should not push promised");
305            fr->fr_callbacks->frc_on_error(fr->fr_cb_ctx, stream_id,
306                                                    FR_ERR_UNEXPECTED_PUSH);
307            return -1;
308        }
309        if (fr->fr_max_headers_sz &&
310            fr->fr_state.payload_length > fr->fr_max_headers_sz)
311            goto headers_too_large;
312        fr->fr_state.by_type.headers_state.frame_type = HTTP_FRAME_PUSH_PROMISE;
313        fr->fr_state.by_type.headers_state.nread = 0;
314        fr->fr_state.by_type.headers_state.pesw_nread = 0;
315        fr->fr_state.by_type.headers_state.pseh = 0;
316        if (fr->fr_state.header.hfh_flags & HFHF_PADDED)
317            fr->fr_state.by_type.headers_state.pesw_size = 5;
318        else
319        {
320            fr->fr_state.by_type.headers_state.pad_length = 0;
321            fr->fr_state.by_type.headers_state.pesw_size = 4;
322        }
323        LSQ_DEBUG("pesw size: %u; payload length: %u; flags: 0x%X",
324            fr->fr_state.by_type.headers_state.pesw_size,
325            fr->fr_state.payload_length, fr->fr_state.header.hfh_flags);
326        if (fr->fr_state.by_type.headers_state.pesw_size >
327                                        fr->fr_state.payload_length)
328        {
329            LSQ_INFO("Invalid headers frame: payload length too small");
330            errno = EBADMSG;
331            return -1;
332        }
333        fr->fr_state.reader_type = READER_PUSH_PROMISE;
334        break;
335    case HTTP_FRAME_CONTINUATION:
336        if (0 == (fr->fr_flags & FRF_HAVE_PREV))
337        {
338            LSQ_INFO("Framing error: unexpected CONTINUATION");
339            return -1;
340        }
341        if (!(fr->fr_prev_frame_type == HTTP_FRAME_HEADERS      ||
342              fr->fr_prev_frame_type == HTTP_FRAME_PUSH_PROMISE ||
343              fr->fr_prev_frame_type == HTTP_FRAME_CONTINUATION))
344        {
345            LSQ_INFO("Framing error: unexpected CONTINUATION");
346            return -1;
347        }
348        if (fr->fr_prev_hfh_flags & HFHF_END_HEADERS)
349        {
350            LSQ_INFO("Framing error: unexpected CONTINUATION");
351            return -1;
352        }
353        if (stream_id != fr->fr_prev_stream_id)
354        {
355            LSQ_INFO("Framing error: CONTINUATION does not have matching "
356                "stream ID");
357            return -1;
358        }
359        if (fr->fr_state.reader_type == READER_SKIP)
360            goto continue_skipping;
361        fr->fr_header_block_sz += fr->fr_state.payload_length;
362        if (fr->fr_max_headers_sz &&
363            fr->fr_header_block_sz > fr->fr_max_headers_sz)
364        {
365            free(fr->fr_header_block);
366            fr->fr_header_block = NULL;
367            goto headers_too_large;
368        }
369        header_block = realloc(fr->fr_header_block, fr->fr_header_block_sz);
370        if (!header_block)
371        {
372            LSQ_WARN("cannot allocate %u bytes for header block",
373                                                    fr->fr_header_block_sz);
374            fr->fr_callbacks->frc_on_error(fr->fr_cb_ctx, stream_id,
375                                                                FR_ERR_NOMEM);
376            return -1;
377        }
378        fr->fr_header_block = header_block;
379        fr->fr_state.by_type.headers_state.nread = 0;
380        fr->fr_state.reader_type = READER_CONTIN;
381        break;
382    case HTTP_FRAME_SETTINGS:
383        if (0 == fr->fr_state.payload_length ||
384            0 != fr->fr_state.payload_length % 6)
385        {
386            LSQ_INFO("Framing error: %u is not a valid SETTINGS length",
387                fr->fr_state.payload_length);
388            fr->fr_callbacks->frc_on_error(fr->fr_cb_ctx, stream_id,
389                                                    FR_ERR_INVALID_FRAME_SIZE);
390            return -1;
391        }
392        if (stream_id)
393        {   /* RFC 7540, Section 6.5 */
394            LSQ_INFO("Error: SETTINGS frame should not have stream ID set");
395            fr->fr_callbacks->frc_on_error(fr->fr_cb_ctx, stream_id,
396                                                    FR_ERR_NONZERO_STREAM_ID);
397            return -1;
398        }
399        fr->fr_state.by_type.settings_state.nread = 0;
400        fr->fr_state.reader_type = READER_SETTINGS;
401        break;
402    case HTTP_FRAME_PRIORITY:
403        if (fr->fr_state.payload_length != sizeof(struct http_prio_frame))
404        {
405            LSQ_INFO("Framing error: %u is not a valid PRIORITY length",
406                fr->fr_state.payload_length);
407            fr->fr_callbacks->frc_on_error(fr->fr_cb_ctx, stream_id,
408                                                    FR_ERR_INVALID_FRAME_SIZE);
409            return -1;
410        }
411        if (!stream_id)
412        {   /* RFC 7540, Section 6.3 */
413            LSQ_INFO("Error: PRIORITY frame must have stream ID set");
414            fr->fr_callbacks->frc_on_error(fr->fr_cb_ctx, stream_id,
415                                                    FR_ERR_ZERO_STREAM_ID);
416            return -1;
417        }
418        fr->fr_state.by_type.settings_state.nread = 0;
419        fr->fr_state.reader_type = READER_PRIORITY;
420        break;
421    headers_too_large:
422        LSQ_INFO("headers are too large (%u bytes), skipping",
423            fr->fr_state.payload_length);
424        fr->fr_callbacks->frc_on_error(fr->fr_cb_ctx, stream_id,
425                                                FR_ERR_HEADERS_TOO_LARGE);
426    continue_skipping:
427    default:
428        fr->fr_state.by_type.skip_state.n_skipped = 0;
429        fr->fr_state.reader_type = READER_SKIP;
430        break;
431    }
432
433    fr->fr_flags |= FRF_HAVE_PREV;
434    fr->fr_prev_frame_type = fr->fr_state.header.hfh_type;
435    fr->fr_prev_hfh_flags  = fr->fr_state.header.hfh_flags;
436    fr->fr_prev_stream_id  = stream_id;
437
438    return 0;
439}
440
441
442static int
443read_http_frame_header (struct lsquic_frame_reader *fr)
444{
445    ssize_t nr;
446    size_t ntoread;
447    unsigned char *dst;
448
449    ntoread = sizeof(fr->fr_state.header) - fr->fr_state.nh_read;
450    dst = (unsigned char *) &fr->fr_state.header + fr->fr_state.nh_read;
451    nr = fr->fr_read(fr->fr_stream, dst, ntoread);
452    if (nr <= 0)
453        RETURN_ERROR(nr);
454    fr->fr_state.nh_read += nr;
455    if (fr->fr_state.nh_read == sizeof(fr->fr_state.header))
456    {
457        LSQ_DEBUG("read in frame %s", hft_to_string(fr->fr_state.header.hfh_type));
458        return prepare_for_payload(fr);
459    }
460    else
461        return 0;
462}
463
464
465static int
466skip_payload (struct lsquic_frame_reader *fr)
467{
468    struct skip_state *ss = &fr->fr_state.by_type.skip_state;
469    size_t ntoread = fr->fr_state.payload_length - ss->n_skipped;
470    unsigned char buf[0x100];
471    if (ntoread > sizeof(buf))
472        ntoread = sizeof(buf);
473    ssize_t nr = fr->fr_read(fr->fr_stream, buf, ntoread);
474    if (nr <= 0)
475        RETURN_ERROR(nr);
476    ss->n_skipped += nr;
477    if (ss->n_skipped == fr->fr_state.payload_length)
478        reset_state(fr);
479    return 0;
480}
481
482
483static int
484skip_headers_padding (struct lsquic_frame_reader *fr)
485{
486    unsigned char buf[0x100];
487    struct headers_state *hs = &fr->fr_state.by_type.headers_state;
488    unsigned pay_and_pad_length = fr->fr_state.payload_length - hs->pesw_size;
489    unsigned ntoread = pay_and_pad_length - hs->nread;
490    assert(ntoread <= sizeof(buf));
491    if (ntoread > sizeof(buf))
492        ntoread = sizeof(buf);
493    ssize_t nr = fr->fr_read(fr->fr_stream, buf, ntoread);
494    if (nr <= 0)
495        RETURN_ERROR(nr);
496    hs->nread += nr;
497    if (hs->nread == pay_and_pad_length)
498        reset_state(fr);
499    return 0;
500}
501
502
503struct header_writer_ctx
504{
505    struct uncompressed_headers *uh;
506    struct lsquic_mm            *mm;
507    char                        *buf;
508    char                        *cookie_val;
509    unsigned                     cookie_sz, cookie_nalloc;
510    unsigned                     max_headers_sz,
511                                 headers_sz,
512                                 w_off;
513    enum {
514        HWC_EXPECT_COLON = (1 << 0),
515        HWC_SEEN_HOST    = (1 << 1),
516    }                            hwc_flags;
517    enum pseudo_header           pseh_mask;
518    char                        *pseh_bufs[N_PSEH];
519    hpack_strlen_t               name_len,
520                                 val_len;
521};
522
523
524#define HWC_PSEH_LEN(hwc, ph) ((int) strlen((hwc)->pseh_bufs[ph]))
525
526#define HWC_PSEH_VAL(hwc, ph) ((hwc)->pseh_bufs[ph])
527
528static int
529hwc_uh_write (struct header_writer_ctx *hwc, const void *buf, size_t sz)
530{
531    struct uncompressed_headers *uh;
532
533    if (hwc->w_off + sz > hwc->headers_sz)
534    {
535        if (hwc->headers_sz * 2 >= hwc->w_off + sz)
536            hwc->headers_sz *= 2;
537        else
538            hwc->headers_sz = hwc->w_off + sz;
539        uh = realloc(hwc->uh, sizeof(*hwc->uh) + hwc->headers_sz);
540        if (!uh)
541            return -1;
542        hwc->uh = uh;
543    }
544    memcpy(hwc->uh->uh_headers + hwc->w_off, buf, sz);
545    hwc->w_off += sz;
546    return 0;
547}
548
549
550static enum frame_reader_error
551init_hwc (struct header_writer_ctx *hwc, struct lsquic_mm *mm,
552          unsigned max_headers_sz, unsigned headers_block_sz)
553{
554    memset(hwc, 0, sizeof(*hwc));
555    hwc->hwc_flags = HWC_EXPECT_COLON;
556    hwc->max_headers_sz = max_headers_sz;
557    hwc->headers_sz = headers_block_sz * 4;     /* A guess */
558    hwc->uh = malloc(sizeof(*hwc->uh) + hwc->headers_sz);
559    if (!hwc->uh)
560        return FR_ERR_NOMEM;
561    hwc->mm = mm;
562    hwc->buf = lsquic_mm_get_16k(mm);
563    if (!hwc->buf)
564        return FR_ERR_NOMEM;
565    return 0;
566}
567
568
569static void
570deinit_hwc (struct header_writer_ctx *hwc)
571{
572    unsigned i;
573    for (i = 0; i < sizeof(hwc->pseh_bufs) / sizeof(hwc->pseh_bufs[0]); ++i)
574        if (hwc->pseh_bufs[i])
575            free(hwc->pseh_bufs[i]);
576    if (hwc->cookie_val)
577        free(hwc->cookie_val);
578    free(hwc->uh);
579    if (hwc->buf)
580        lsquic_mm_put_16k(hwc->mm, hwc->buf);
581}
582
583
584static enum frame_reader_error
585save_pseudo_header (const struct lsquic_frame_reader *fr,
586                        struct header_writer_ctx *hwc, enum pseudo_header ph)
587{
588    if (0 == (hwc->pseh_mask & BIT(ph)))
589    {
590        assert(!hwc->pseh_bufs[ph]);
591        hwc->pseh_bufs[ph] = malloc(hwc->val_len + 1);
592        if (!hwc->pseh_bufs[ph])
593            return FR_ERR_NOMEM;
594        hwc->pseh_mask |= BIT(ph);
595        memcpy(hwc->pseh_bufs[ph], hwc->buf + hwc->name_len, hwc->val_len);
596        hwc->pseh_bufs[ph][hwc->val_len] = '\0';
597        return 0;
598    }
599    else
600    {
601        LSQ_INFO("header %u is already present", ph);
602        return FR_ERR_DUPLICATE_PSEH;
603    }
604}
605
606
607static enum frame_reader_error
608add_pseudo_header_to_uh (const struct lsquic_frame_reader *fr,
609                                                struct header_writer_ctx *hwc)
610{
611    if (!(hwc->hwc_flags & HWC_EXPECT_COLON))
612    {
613        LSQ_INFO("unexpected colon");
614        return FR_ERR_MISPLACED_PSEH;
615    }
616
617    switch (hwc->name_len)
618    {
619    case 5:
620        if (0 == memcmp(hwc->buf,     ":path", 5))
621            return save_pseudo_header(fr, hwc, PSEH_PATH);
622        break;
623    case 7:
624        switch (hwc->buf[2])
625        {
626        case 'c':
627            if (0 == memcmp(hwc->buf, ":scheme", 7))
628                return save_pseudo_header(fr, hwc, PSEH_SCHEME);
629            break;
630        case 'e':
631            if (0 == memcmp(hwc->buf, ":method", 7))
632                return save_pseudo_header(fr, hwc, PSEH_METHOD);
633            break;
634        case 't':
635            if (0 == memcmp(hwc->buf, ":status", 7))
636                return save_pseudo_header(fr, hwc, PSEH_STATUS);
637            break;
638        }
639        break;
640    case 10:
641        if (0 == memcmp(hwc->buf,     ":authority", 10))
642            return save_pseudo_header(fr, hwc, PSEH_AUTHORITY);
643        break;
644    }
645
646    LSQ_INFO("unknown pseudo-header `%.*s'", hwc->name_len, hwc->buf);
647    return FR_ERR_UNKNOWN_PSEH;
648}
649
650
651#define HTTP_CODE_LEN 3
652
653static const char *
654code_str_to_reason (const char code_str[HTTP_CODE_LEN])
655{
656    /* RFC 7231, Section 6: */
657    static const char *const http_reason_phrases[] =
658    {
659    #define HTTP_REASON_CODE(code, reason) [code - 100] = reason
660        HTTP_REASON_CODE(100, "Continue"),
661        HTTP_REASON_CODE(101, "Switching Protocols"),
662        HTTP_REASON_CODE(200, "OK"),
663        HTTP_REASON_CODE(201, "Created"),
664        HTTP_REASON_CODE(202, "Accepted"),
665        HTTP_REASON_CODE(203, "Non-Authoritative Information"),
666        HTTP_REASON_CODE(204, "No Content"),
667        HTTP_REASON_CODE(205, "Reset Content"),
668        HTTP_REASON_CODE(206, "Partial Content"),
669        HTTP_REASON_CODE(300, "Multiple Choices"),
670        HTTP_REASON_CODE(301, "Moved Permanently"),
671        HTTP_REASON_CODE(302, "Found"),
672        HTTP_REASON_CODE(303, "See Other"),
673        HTTP_REASON_CODE(304, "Not Modified"),
674        HTTP_REASON_CODE(305, "Use Proxy"),
675        HTTP_REASON_CODE(307, "Temporary Redirect"),
676        HTTP_REASON_CODE(400, "Bad Request"),
677        HTTP_REASON_CODE(401, "Unauthorized"),
678        HTTP_REASON_CODE(402, "Payment Required"),
679        HTTP_REASON_CODE(403, "Forbidden"),
680        HTTP_REASON_CODE(404, "Not Found"),
681        HTTP_REASON_CODE(405, "Method Not Allowed"),
682        HTTP_REASON_CODE(406, "Not Acceptable"),
683        HTTP_REASON_CODE(407, "Proxy Authentication Required"),
684        HTTP_REASON_CODE(408, "Request Timeout"),
685        HTTP_REASON_CODE(409, "Conflict"),
686        HTTP_REASON_CODE(410, "Gone"),
687        HTTP_REASON_CODE(411, "Length Required"),
688        HTTP_REASON_CODE(412, "Precondition Failed"),
689        HTTP_REASON_CODE(413, "Payload Too Large"),
690        HTTP_REASON_CODE(414, "URI Too Long"),
691        HTTP_REASON_CODE(415, "Unsupported Media Type"),
692        HTTP_REASON_CODE(416, "Range Not Satisfiable"),
693        HTTP_REASON_CODE(417, "Expectation Failed"),
694        HTTP_REASON_CODE(426, "Upgrade Required"),
695        HTTP_REASON_CODE(500, "Internal Server Error"),
696        HTTP_REASON_CODE(501, "Not Implemented"),
697        HTTP_REASON_CODE(502, "Bad Gateway"),
698        HTTP_REASON_CODE(503, "Service Unavailable"),
699        HTTP_REASON_CODE(504, "Gateway Timeout"),
700        HTTP_REASON_CODE(505, "HTTP Version Not Supported"),
701    #undef HTTP_REASON_CODE
702    };
703
704    long code;
705    char code_buf[HTTP_CODE_LEN + 1];
706
707    memcpy(code_buf, code_str, HTTP_CODE_LEN);
708    code_buf[HTTP_CODE_LEN] = '\0';
709    code = strtol(code_buf, NULL, 10) - 100;
710    if (code > 0 && code < (long) (sizeof(http_reason_phrases) /
711                                        sizeof(http_reason_phrases[0])))
712        return http_reason_phrases[code];
713    else
714        return NULL;
715}
716
717
718static enum frame_reader_error
719convert_response_pseudo_headers (const struct lsquic_frame_reader *fr,
720                                                struct header_writer_ctx *hwc)
721{
722    if ((hwc->pseh_mask & REQUIRED_SERVER_PSEH) != REQUIRED_SERVER_PSEH)
723    {
724        LSQ_INFO("not all response pseudo-headers are specified");
725        return FR_ERR_INCOMPL_RESP_PSEH;
726    }
727    if (hwc->pseh_mask & ALL_REQUEST_PSEH)
728    {
729        LSQ_INFO("response pseudo-headers contain request-only headers");
730        return FR_ERR_UNNEC_REQ_PSEH;
731    }
732
733    const char *code_str, *reason;
734    int code_len;
735
736    code_str = HWC_PSEH_VAL(hwc, PSEH_STATUS);
737    code_len = HWC_PSEH_LEN(hwc, PSEH_STATUS);
738
739#define HWC_UH_WRITE(h, buf, sz) do {                                   \
740    if (0 != hwc_uh_write(h, buf, sz))                                  \
741        return FR_ERR_NOMEM;                                            \
742} while (0)
743
744    HWC_UH_WRITE(hwc, "HTTP/1.1 ", 9);
745    HWC_UH_WRITE(hwc, code_str, code_len);
746    if (HTTP_CODE_LEN == code_len && (reason = code_str_to_reason(code_str)))
747    {
748        HWC_UH_WRITE(hwc, " ", 1);
749        HWC_UH_WRITE(hwc, reason, strlen(reason));
750        HWC_UH_WRITE(hwc, "\r\n", 2);
751    }
752    else
753        HWC_UH_WRITE(hwc, " \r\n", 3);
754    if (hwc->max_headers_sz && hwc->w_off > hwc->max_headers_sz)
755    {
756        LSQ_INFO("headers too large");
757        return FR_ERR_HEADERS_TOO_LARGE;
758    }
759    return 0;
760
761#undef HWC_UH_WRITE
762}
763
764
765static enum frame_reader_error
766convert_request_pseudo_headers (const struct lsquic_frame_reader *fr,
767                                                struct header_writer_ctx *hwc)
768{
769    if ((hwc->pseh_mask & REQUIRED_REQUEST_PSEH) != REQUIRED_REQUEST_PSEH)
770    {
771        LSQ_INFO("not all request pseudo-headers are specified");
772        return FR_ERR_INCOMPL_REQ_PSEH;
773    }
774    if (hwc->pseh_mask & ALL_SERVER_PSEH)
775    {
776        LSQ_INFO("request pseudo-headers contain response-only headers");
777        return FR_ERR_UNNEC_RESP_PSEH;
778    }
779
780#define HWC_UH_WRITE(h, buf, sz) do {                                   \
781    if (0 != hwc_uh_write(h, buf, sz))                                  \
782        return FR_ERR_NOMEM;                                            \
783} while (0)
784
785    HWC_UH_WRITE(hwc, HWC_PSEH_VAL(hwc, PSEH_METHOD), HWC_PSEH_LEN(hwc, PSEH_METHOD));
786    HWC_UH_WRITE(hwc, " ", 1);
787    HWC_UH_WRITE(hwc, HWC_PSEH_VAL(hwc, PSEH_PATH), HWC_PSEH_LEN(hwc, PSEH_PATH));
788    HWC_UH_WRITE(hwc, " HTTP/1.1\r\n", 11);
789
790    if (hwc->max_headers_sz && hwc->w_off > hwc->max_headers_sz)
791    {
792        LSQ_INFO("headers too large");
793        return FR_ERR_HEADERS_TOO_LARGE;
794    }
795
796    return 0;
797
798#undef HWC_UH_WRITE
799}
800
801
802static enum frame_reader_error
803convert_pseudo_headers (const struct lsquic_frame_reader *fr,
804                                                struct header_writer_ctx *hwc)
805{
806    /* We are *reading* the message.  Thus, a server expects a request, and a
807     * client expects a response.  Unless we receive a push promise from the
808     * server, in which case this should also be a request.
809     */
810    if ((fr->fr_flags & FRF_SERVER) ||
811                            READER_PUSH_PROMISE == fr->fr_state.reader_type)
812        return convert_request_pseudo_headers(fr, hwc);
813    else
814        return convert_response_pseudo_headers(fr, hwc);
815}
816
817
818static enum frame_reader_error
819save_cookie (struct header_writer_ctx *hwc)
820{
821    char *cookie_val;
822
823    if (0 == hwc->cookie_sz)
824    {
825        hwc->cookie_nalloc = hwc->cookie_sz = hwc->val_len;
826        cookie_val = malloc(hwc->cookie_nalloc);
827        if (!cookie_val)
828            return FR_ERR_NOMEM;
829        hwc->cookie_val = cookie_val;
830        memcpy(hwc->cookie_val, hwc->buf + hwc->name_len, hwc->val_len);
831    }
832    else
833    {
834        hwc->cookie_sz += hwc->val_len + 2 /* "; " */;
835        if (hwc->cookie_sz > hwc->cookie_nalloc)
836        {
837            hwc->cookie_nalloc = hwc->cookie_nalloc * 2 + hwc->val_len + 2;
838            cookie_val = realloc(hwc->cookie_val, hwc->cookie_nalloc);
839            if (!cookie_val)
840                return FR_ERR_NOMEM;
841            hwc->cookie_val = cookie_val;
842        }
843        memcpy(hwc->cookie_val + hwc->cookie_sz - hwc->val_len - 2, "; ", 2);
844        memcpy(hwc->cookie_val + hwc->cookie_sz - hwc->val_len,
845               hwc->buf + hwc->name_len, hwc->val_len);
846    }
847
848    return 0;
849}
850
851
852static enum frame_reader_error
853add_real_header_to_uh (const struct lsquic_frame_reader *fr,
854                                                struct header_writer_ctx *hwc)
855{
856    enum frame_reader_error err;
857    unsigned i;
858    int n_upper;
859
860    if (hwc->hwc_flags & HWC_EXPECT_COLON)
861    {
862        if (0 != (err = convert_pseudo_headers(fr, hwc)))
863            return err;
864        hwc->hwc_flags &= ~HWC_EXPECT_COLON;
865    }
866
867    if (4 == hwc->name_len && 0 == memcmp(hwc->buf, "host", 4))
868        hwc->hwc_flags |= HWC_SEEN_HOST;
869
870    n_upper = 0;
871    for (i = 0; i < hwc->name_len; ++i)
872        n_upper += isupper(hwc->buf[i]);
873    if (n_upper > 0)
874    {
875        LSQ_INFO("Header name `%.*s' contains uppercase letters",
876            hwc->name_len, hwc->buf);
877        return FR_ERR_UPPERCASE_HEADER;
878    }
879
880    if (6 == hwc->name_len && memcmp(hwc->buf, "cookie", 6) == 0)
881    {
882        return save_cookie(hwc);
883    }
884
885#define HWC_UH_WRITE(h, buf, sz) do {                                   \
886    if (0 != hwc_uh_write(h, buf, sz))                                  \
887        return FR_ERR_NOMEM;                                            \
888} while (0)
889
890    HWC_UH_WRITE(hwc, hwc->buf, hwc->name_len);
891    HWC_UH_WRITE(hwc, ": ", 2);
892    HWC_UH_WRITE(hwc, hwc->buf + hwc->name_len, hwc->val_len);
893    HWC_UH_WRITE(hwc, "\r\n", 2);
894
895    if (hwc->max_headers_sz && hwc->w_off > hwc->max_headers_sz)
896    {
897        LSQ_INFO("headers too large");
898        return FR_ERR_HEADERS_TOO_LARGE;
899    }
900
901    return 0;
902
903#undef HWC_UH_WRITE
904}
905
906
907static enum frame_reader_error
908add_header_to_uh (const struct lsquic_frame_reader *fr,
909                                                struct header_writer_ctx *hwc)
910{
911    LSQ_DEBUG("Got header '%.*s': '%.*s'", hwc->name_len, hwc->buf,
912        hwc->val_len, hwc->buf + hwc->name_len);
913    if (':' == hwc->buf[0])
914        return add_pseudo_header_to_uh(fr, hwc);
915    else
916        return add_real_header_to_uh(fr, hwc);
917}
918
919
920static int
921decode_and_pass_payload (struct lsquic_frame_reader *fr)
922{
923    struct headers_state *hs = &fr->fr_state.by_type.headers_state;
924    const unsigned char *comp, *end;
925    enum frame_reader_error err;
926    int s;
927    struct header_writer_ctx hwc;
928
929    err = init_hwc(&hwc, fr->fr_mm, fr->fr_max_headers_sz, fr->fr_header_block_sz);
930    if (0 != err)
931        goto stream_error;
932
933    comp = fr->fr_header_block;
934    end = comp + fr->fr_header_block_sz;
935
936    while (comp < end)
937    {
938        s = lsquic_hdec_decode(fr->fr_hdec, &comp, end,
939                                hwc.buf, hwc.buf + 16 * 1024,
940                                &hwc.name_len, &hwc.val_len);
941        if (s > 0)
942        {
943            err = add_header_to_uh(fr, &hwc);
944            if (0 != err)
945                goto stream_error;
946        }
947        else if (s < 0)
948        {
949            err = FR_ERR_DECOMPRESS;
950            goto stream_error;
951        }
952        else
953            break;
954    }
955    assert(comp == end);
956
957    if (hwc.hwc_flags & HWC_EXPECT_COLON)
958    {
959        err = convert_pseudo_headers(fr, &hwc);
960        if (0 != err)
961            goto stream_error;
962        hwc.hwc_flags &= ~HWC_EXPECT_COLON;
963    }
964
965
966#define HWC_UH_WRITE(h, buf, sz) do {                                   \
967    err = hwc_uh_write(h, buf, sz);                                     \
968    if (0 != err)                                                       \
969        goto stream_error;                                              \
970} while (0)
971
972    if ((hwc.pseh_mask & BIT(PSEH_AUTHORITY)) &&
973                                0 == (hwc.hwc_flags & HWC_SEEN_HOST))
974    {
975        LSQ_DEBUG("Setting 'Host: %.*s'", HWC_PSEH_LEN(&hwc, PSEH_AUTHORITY),
976                                            HWC_PSEH_VAL(&hwc, PSEH_AUTHORITY));
977        HWC_UH_WRITE(&hwc, "Host: ", 6);
978        HWC_UH_WRITE(&hwc, HWC_PSEH_VAL(&hwc, PSEH_AUTHORITY), HWC_PSEH_LEN(&hwc, PSEH_AUTHORITY));
979        HWC_UH_WRITE(&hwc, "\r\n", 2);
980    }
981
982    if (hwc.cookie_val)
983    {
984        LSQ_DEBUG("Setting 'Cookie: %.*s'", hwc.cookie_sz, hwc.cookie_val);
985        HWC_UH_WRITE(&hwc, "Cookie: ", 8);
986        HWC_UH_WRITE(&hwc, hwc.cookie_val, hwc.cookie_sz);
987        HWC_UH_WRITE(&hwc, "\r\n", 2);
988    }
989
990    HWC_UH_WRITE(&hwc, "\r\n", 2 + 1 /* NUL byte */);
991    hwc.w_off -= 1;     /* Do not count NUL byte */
992
993    if (hwc.max_headers_sz && hwc.w_off > hwc.max_headers_sz)
994    {
995        LSQ_INFO("headers too large");
996        err = FR_ERR_HEADERS_TOO_LARGE;
997        goto stream_error;
998    }
999
1000    memcpy(&hwc.uh->uh_stream_id, fr->fr_state.header.hfh_stream_id,
1001                                                sizeof(hwc.uh->uh_stream_id));
1002    hwc.uh->uh_stream_id     = ntohl(hwc.uh->uh_stream_id);
1003    hwc.uh->uh_size          = hwc.w_off;
1004    hwc.uh->uh_oth_stream_id = hs->oth_stream_id;
1005    hwc.uh->uh_off           = 0;
1006    if (HTTP_FRAME_HEADERS == fr->fr_state.by_type.headers_state.frame_type)
1007    {
1008        hwc.uh->uh_weight    = hs->weight;
1009        hwc.uh->uh_exclusive = hs->exclusive;
1010        hwc.uh->uh_flags     = 0;
1011    }
1012    else
1013    {
1014        assert(HTTP_FRAME_PUSH_PROMISE ==
1015                                fr->fr_state.by_type.headers_state.frame_type);
1016        hwc.uh->uh_weight    = 0;   /* Zero unused value */
1017        hwc.uh->uh_exclusive = 0;   /* Zero unused value */
1018        hwc.uh->uh_flags     = UH_PP;
1019    }
1020    if (fr->fr_state.header.hfh_flags & HFHF_END_STREAM)
1021        hwc.uh->uh_flags    |= UH_FIN;
1022
1023    EV_LOG_HTTP_HEADERS_IN(LSQUIC_LOG_CONN_ID, fr->fr_flags & FRF_SERVER,
1024                                                                    hwc.uh);
1025    if (HTTP_FRAME_HEADERS == fr->fr_state.by_type.headers_state.frame_type)
1026        fr->fr_callbacks->frc_on_headers(fr->fr_cb_ctx, hwc.uh);
1027    else
1028        fr->fr_callbacks->frc_on_push_promise(fr->fr_cb_ctx, hwc.uh);
1029
1030    hwc.uh = NULL;
1031
1032    deinit_hwc(&hwc);
1033
1034    return 0;
1035
1036  stream_error:
1037    LSQ_INFO("%s: stream error %u", __func__, err);
1038    deinit_hwc(&hwc);
1039    fr->fr_callbacks->frc_on_error(fr->fr_cb_ctx, fr_get_stream_id(fr), err);
1040    return 0;
1041
1042#undef HWC_UH_WRITE
1043}
1044
1045
1046static int
1047read_headers_block_fragment (struct lsquic_frame_reader *fr)
1048{
1049    struct headers_state *hs = &fr->fr_state.by_type.headers_state;
1050    ssize_t nr;
1051    unsigned payload_length = fr->fr_state.payload_length - hs->pesw_size -
1052                                                                hs->pad_length;
1053    if (!fr->fr_header_block)
1054    {
1055        fr->fr_header_block_sz = payload_length;
1056        fr->fr_header_block = malloc(payload_length);
1057        if (!fr->fr_header_block)
1058            return -1;
1059    }
1060    nr = fr->fr_read(fr->fr_stream, fr->fr_header_block + hs->nread,
1061                                            fr->fr_header_block_sz - hs->nread);
1062    if (nr <= 0)
1063    {
1064        free(fr->fr_header_block);
1065        fr->fr_header_block = NULL;
1066        RETURN_ERROR(nr);
1067    }
1068    hs->nread += nr;
1069    if (hs->nread == payload_length &&
1070                (fr->fr_state.header.hfh_flags & HFHF_END_HEADERS))
1071    {
1072        int rv = decode_and_pass_payload(fr);
1073        free(fr->fr_header_block);
1074        fr->fr_header_block = NULL;
1075        return rv;
1076    }
1077    else
1078        return 0;
1079}
1080
1081
1082static int
1083read_headers_block_fragment_and_padding (struct lsquic_frame_reader *fr)
1084{
1085    struct headers_state *hs = &fr->fr_state.by_type.headers_state;
1086    unsigned payload_length = fr->fr_state.payload_length - hs->pesw_size;
1087    int rv;
1088    if (hs->nread < payload_length - hs->pad_length)
1089        rv = read_headers_block_fragment(fr);
1090    else if (payload_length)
1091        rv = skip_headers_padding(fr);
1092    else
1093    {   /* Edge case where PESW takes up the whole frame */
1094        fr->fr_header_block_sz = 0;
1095        fr->fr_header_block    = NULL;
1096        rv = 0;
1097    }
1098    if (0 == rv && hs->nread == payload_length)
1099        reset_state(fr);
1100    return rv;
1101}
1102
1103
1104static int
1105read_headers_pesw (struct lsquic_frame_reader *fr)
1106{
1107    struct headers_state *hs = &fr->fr_state.by_type.headers_state;
1108    ssize_t nr = fr->fr_read(fr->fr_stream, hs->pesw + hs->pesw_nread,
1109                                            hs->pesw_size - hs->pesw_nread);
1110    if (nr <= 0)
1111        RETURN_ERROR(nr);
1112    hs->pesw_nread += nr;
1113    if (hs->pesw_nread == hs->pesw_size)
1114    {
1115        unsigned char *p = hs->pesw;
1116        if (fr->fr_state.header.hfh_flags & HFHF_PADDED)
1117            hs->pad_length = *p++;
1118        if (fr->fr_state.header.hfh_flags & HFHF_PRIORITY)
1119        {
1120            hs->exclusive = p[0] >> 7;
1121            p[0] &= ~0x80;  /* Note that we are modifying pesw buffer. */
1122            memcpy(&hs->oth_stream_id, p, sizeof(hs->oth_stream_id));
1123            hs->oth_stream_id = ntohl(hs->oth_stream_id);
1124            p += 4;
1125            hs->weight = 1 + *p++;
1126        }
1127        assert(p - hs->pesw == hs->pesw_size);
1128
1129        if (hs->pesw_size + hs->pad_length > fr->fr_state.payload_length)
1130        {
1131            LSQ_INFO("Invalid headers frame: pesw length and padding length "
1132                    "are larger than the payload length");
1133            errno = EBADMSG;
1134            return -1;
1135        }
1136    }
1137    return 0;
1138}
1139
1140
1141static int
1142read_headers (struct lsquic_frame_reader *fr)
1143{
1144    struct headers_state *hs = &fr->fr_state.by_type.headers_state;
1145    if (hs->pesw_nread < hs->pesw_size)
1146        return read_headers_pesw(fr);
1147    else
1148        return read_headers_block_fragment_and_padding(fr);
1149}
1150
1151
1152static int
1153read_push_promise_pesw (struct lsquic_frame_reader *fr)
1154{
1155    struct headers_state *hs = &fr->fr_state.by_type.headers_state;
1156    ssize_t nr = fr->fr_read(fr->fr_stream, hs->pesw + hs->pesw_nread,
1157                                            hs->pesw_size - hs->pesw_nread);
1158    if (nr <= 0)
1159        RETURN_ERROR(nr);
1160    hs->pesw_nread += nr;
1161    if (hs->pesw_nread == hs->pesw_size)
1162    {
1163        unsigned char *p = hs->pesw;
1164        if (fr->fr_state.header.hfh_flags & HFHF_PADDED)
1165            hs->pad_length = *p++;
1166        p[0] &= ~0x80;  /* Clear reserved bit.  Note: modifying pesw buffer. */
1167        memcpy(&hs->oth_stream_id, p, sizeof(hs->oth_stream_id));
1168        hs->oth_stream_id = ntohl(hs->oth_stream_id);
1169        p += 4;
1170        assert(p - hs->pesw == hs->pesw_size);
1171        if (hs->pesw_size + hs->pad_length > fr->fr_state.payload_length)
1172        {
1173            LSQ_INFO("Invalid PUSH_PROMISE frame: pesw length and padding length "
1174                    "are larger than the payload length");
1175            errno = EBADMSG;
1176            return -1;
1177        }
1178    }
1179    return 0;
1180}
1181
1182
1183static int
1184read_push_promise (struct lsquic_frame_reader *fr)
1185{
1186    struct headers_state *hs = &fr->fr_state.by_type.headers_state;
1187    if (hs->pesw_nread < hs->pesw_size)
1188        return read_push_promise_pesw(fr);
1189    else
1190        return read_headers_block_fragment_and_padding(fr);
1191}
1192
1193
1194static int
1195read_contin (struct lsquic_frame_reader *fr)
1196{
1197    struct headers_state *hs = &fr->fr_state.by_type.headers_state;
1198    unsigned ntoread;
1199    ssize_t nr;
1200
1201    ntoread = fr->fr_state.payload_length - hs->nread;
1202    nr = fr->fr_read(fr->fr_stream,
1203                     fr->fr_header_block + fr->fr_header_block_sz - ntoread,
1204                     ntoread);
1205    if (nr <= 0)
1206        RETURN_ERROR(nr);
1207    hs->nread += nr;
1208    if (hs->nread == fr->fr_state.payload_length)
1209    {
1210        if (fr->fr_state.header.hfh_flags & HFHF_END_HEADERS)
1211        {
1212            int rv = decode_and_pass_payload(fr);
1213            free(fr->fr_header_block);
1214            fr->fr_header_block = NULL;
1215            reset_state(fr);
1216            return rv;
1217        }
1218        else
1219        {
1220            reset_state(fr);
1221            return 0;
1222        }
1223    }
1224    else
1225        return 0;
1226}
1227
1228
1229static int
1230read_settings (struct lsquic_frame_reader *fr)
1231{
1232    struct settings_state *ss = &fr->fr_state.by_type.settings_state;
1233    unsigned ntoread;
1234    ssize_t nr;
1235    uint32_t setting_value;
1236    uint16_t setting_id;
1237
1238    ntoread = sizeof(ss->set_buf) - ss->nread;
1239    nr = fr->fr_read(fr->fr_stream, ss->set_buf + ss->nread, ntoread);
1240    if (nr <= 0)
1241        RETURN_ERROR(nr);
1242    ss->nread += nr;
1243    if (ss->nread == sizeof(ss->set_buf))
1244    {
1245        memcpy(&setting_id,    ss->set_buf, 2);
1246        memcpy(&setting_value, ss->set_buf + 2, 4);
1247        setting_id    = ntohs(setting_id);
1248        setting_value = ntohl(setting_value);
1249        EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID, "read HTTP SETTING %s=%"PRIu32,
1250                        lsquic_http_setting_id2str(setting_id), setting_value);
1251        fr->fr_callbacks->frc_on_settings(fr->fr_cb_ctx, setting_id,
1252                                                        setting_value);
1253
1254        fr->fr_state.payload_length -= sizeof(ss->set_buf);
1255        if (0 == fr->fr_state.payload_length)
1256            reset_state(fr);
1257        else
1258            ss->nread = 0;
1259    }
1260    return 0;
1261}
1262
1263
1264static int
1265read_priority (struct lsquic_frame_reader *fr)
1266{
1267    struct priority_state *ps = &fr->fr_state.by_type.priority_state;
1268    unsigned ntoread;
1269    ssize_t nr;
1270    uint32_t stream_id, dep_stream_id;
1271    int exclusive;
1272
1273    ntoread = sizeof(ps->u.prio_buf) - ps->nread;
1274    nr = fr->fr_read(fr->fr_stream, ps->u.prio_buf + ps->nread, ntoread);
1275    if (nr <= 0)
1276        RETURN_ERROR(nr);
1277    ps->nread += nr;
1278    if (ps->nread == sizeof(ps->u.prio_buf))
1279    {
1280        memcpy(&dep_stream_id, ps->u.prio_frame.hpf_stream_id, 4);
1281        dep_stream_id = ntohl(dep_stream_id);
1282        exclusive = dep_stream_id >> 31;
1283        dep_stream_id &= ~(1UL << 31);
1284        stream_id = fr_get_stream_id(fr);
1285        if (stream_id == dep_stream_id)
1286            fr->fr_callbacks->frc_on_error(fr->fr_cb_ctx, stream_id,
1287                                                    FR_ERR_SELF_DEP_STREAM);
1288        else
1289        {
1290            EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID, "read PRIORITY frame; "
1291                "stream: %"PRIu32", dep stream %"PRIu32", exclusive: %d, "
1292                "weight: %u", stream_id, dep_stream_id, exclusive,
1293                ps->u.prio_frame.hpf_weight + 1);
1294            fr->fr_callbacks->frc_on_priority(fr->fr_cb_ctx, stream_id,
1295                    exclusive, dep_stream_id, ps->u.prio_frame.hpf_weight + 1);
1296        }
1297        reset_state(fr);
1298    }
1299    return 0;
1300}
1301
1302
1303static int
1304read_payload (struct lsquic_frame_reader *fr)
1305{
1306    switch (fr->fr_state.reader_type)
1307    {
1308    case READER_HEADERS:
1309        return read_headers(fr);
1310    case READER_PUSH_PROMISE:
1311        return read_push_promise(fr);
1312    case READER_CONTIN:
1313        return read_contin(fr);
1314    case READER_SETTINGS:
1315        return read_settings(fr);
1316    case READER_PRIORITY:
1317        return read_priority(fr);
1318    default:
1319        assert(READER_SKIP == fr->fr_state.reader_type);
1320        return skip_payload(fr);
1321    }
1322}
1323
1324
1325int
1326lsquic_frame_reader_read (struct lsquic_frame_reader *fr)
1327{
1328    if (fr->fr_state.nh_read < sizeof(fr->fr_state.header))
1329        return read_http_frame_header(fr);
1330    else
1331        return read_payload(fr);
1332}
1333
1334
1335size_t
1336lsquic_frame_reader_mem_used (const struct lsquic_frame_reader *fr)
1337{
1338    size_t size;
1339    size = sizeof(*fr);
1340    if (fr->fr_header_block)
1341        size += fr->fr_header_block_sz;
1342    return size;
1343}
1344