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