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