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