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