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