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