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