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