1 /* 2 * nghttp2 - HTTP/2 C Library 3 * 4 * Copyright (c) 2012 Tatsuhiro Tsujikawa 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining 7 * a copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sublicense, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be 15 * included in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 */ 25 #ifndef NGHTTP2_FRAME_H 26 #define NGHTTP2_FRAME_H 27 28 #ifdef HAVE_CONFIG_H 29 #include <config.h> 30 #endif /* HAVE_CONFIG_H */ 31 32 #include "nghttp2.h" 33 #include "nghttp2_hd.h" 34 #include "nghttp2_buf.h" 35 36 #define NGHTTP2_STREAM_ID_MASK ((1u << 31) - 1) 37 #define NGHTTP2_PRI_GROUP_ID_MASK ((1u << 31) - 1) 38 #define NGHTTP2_PRIORITY_MASK ((1u << 31) - 1) 39 #define NGHTTP2_WINDOW_SIZE_INCREMENT_MASK ((1u << 31) - 1) 40 #define NGHTTP2_SETTINGS_ID_MASK ((1 << 24) - 1) 41 42 /* The number of bytes of frame header. */ 43 #define NGHTTP2_FRAME_HDLEN 9 44 45 #define NGHTTP2_MAX_FRAME_SIZE_MAX ((1 << 24) - 1) 46 #define NGHTTP2_MAX_FRAME_SIZE_MIN (1 << 14) 47 48 #define NGHTTP2_MAX_PAYLOADLEN 16384 49 /* The one frame buffer length for tranmission. We may use several of 50 them to support CONTINUATION. To account for Pad Length field, we 51 allocate extra 1 byte, which saves extra large memcopying. */ 52 #define NGHTTP2_FRAMEBUF_CHUNKLEN \ 53 (NGHTTP2_FRAME_HDLEN + 1 + NGHTTP2_MAX_PAYLOADLEN) 54 55 /* The default length of DATA frame payload. */ 56 #define NGHTTP2_DATA_PAYLOADLEN NGHTTP2_MAX_FRAME_SIZE_MIN 57 58 /* Maximum headers block size to send, calculated using 59 nghttp2_hd_deflate_bound(). This is the default value, and can be 60 overridden by nghttp2_option_set_max_send_header_block_size(). */ 61 #define NGHTTP2_MAX_HEADERSLEN 65536 62 63 /* The number of bytes for each SETTINGS entry */ 64 #define NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH 6 65 66 /* Length of priority related fields in HEADERS/PRIORITY frames */ 67 #define NGHTTP2_PRIORITY_SPECLEN 5 68 69 /* Maximum length of padding in bytes. */ 70 #define NGHTTP2_MAX_PADLEN 256 71 72 /* Union of extension frame payload */ 73 typedef union { 74 nghttp2_ext_altsvc altsvc; 75 } nghttp2_ext_frame_payload; 76 77 void nghttp2_frame_pack_frame_hd(uint8_t *buf, const nghttp2_frame_hd *hd); 78 79 void nghttp2_frame_unpack_frame_hd(nghttp2_frame_hd *hd, const uint8_t *buf); 80 81 /** 82 * Initializes frame header |hd| with given parameters. Reserved bit 83 * is set to 0. 84 */ 85 void nghttp2_frame_hd_init(nghttp2_frame_hd *hd, size_t length, uint8_t type, 86 uint8_t flags, int32_t stream_id); 87 88 /** 89 * Returns the number of priority field depending on the |flags|. If 90 * |flags| has neither NGHTTP2_FLAG_PRIORITY_GROUP nor 91 * NGHTTP2_FLAG_PRIORITY_DEPENDENCY set, return 0. 92 */ 93 size_t nghttp2_frame_priority_len(uint8_t flags); 94 95 /** 96 * Packs the |pri_spec| in |buf|. This function assumes |buf| has 97 * enough space for serialization. 98 */ 99 void nghttp2_frame_pack_priority_spec(uint8_t *buf, 100 const nghttp2_priority_spec *pri_spec); 101 102 /** 103 * Unpacks the priority specification from payload |payload| of length 104 * |payloadlen| to |pri_spec|. The |flags| is used to determine what 105 * kind of priority specification is in |payload|. This function 106 * assumes the |payload| contains whole priority specification. 107 */ 108 void nghttp2_frame_unpack_priority_spec(nghttp2_priority_spec *pri_spec, 109 const uint8_t *payload); 110 111 /* 112 * Returns the offset from the HEADERS frame payload where the 113 * compressed header block starts. The frame payload does not include 114 * frame header. 115 */ 116 size_t nghttp2_frame_headers_payload_nv_offset(nghttp2_headers *frame); 117 118 /* 119 * Packs HEADERS frame |frame| in wire format and store it in |bufs|. 120 * This function expands |bufs| as necessary to store frame. 121 * 122 * The caller must make sure that nghttp2_bufs_reset(bufs) is called 123 * before calling this function. 124 * 125 * frame->hd.length is assigned after length is determined during 126 * packing process. CONTINUATION frames are also serialized in this 127 * function. This function does not handle padding. 128 * 129 * This function returns 0 if it succeeds, or returns one of the 130 * following negative error codes: 131 * 132 * NGHTTP2_ERR_HEADER_COMP 133 * The deflate operation failed. 134 * NGHTTP2_ERR_NOMEM 135 * Out of memory. 136 */ 137 int nghttp2_frame_pack_headers(nghttp2_bufs *bufs, nghttp2_headers *frame, 138 nghttp2_hd_deflater *deflater); 139 140 /* 141 * Unpacks HEADERS frame byte sequence into |frame|. This function 142 * only unapcks bytes that come before name/value header block and 143 * after possible Pad Length field. 144 * 145 * This function always succeeds and returns 0. 146 */ 147 int nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame, 148 const uint8_t *payload); 149 150 /* 151 * Packs PRIORITY frame |frame| in wire format and store it in 152 * |bufs|. 153 * 154 * The caller must make sure that nghttp2_bufs_reset(bufs) is called 155 * before calling this function. 156 * 157 * This function always succeeds and returns 0. 158 */ 159 int nghttp2_frame_pack_priority(nghttp2_bufs *bufs, nghttp2_priority *frame); 160 161 /* 162 * Unpacks PRIORITY wire format into |frame|. 163 */ 164 void nghttp2_frame_unpack_priority_payload(nghttp2_priority *frame, 165 const uint8_t *payload); 166 167 /* 168 * Packs RST_STREAM frame |frame| in wire frame format and store it in 169 * |bufs|. 170 * 171 * The caller must make sure that nghttp2_bufs_reset(bufs) is called 172 * before calling this function. 173 * 174 * This function always succeeds and returns 0. 175 */ 176 int nghttp2_frame_pack_rst_stream(nghttp2_bufs *bufs, 177 nghttp2_rst_stream *frame); 178 179 /* 180 * Unpacks RST_STREAM frame byte sequence into |frame|. 181 */ 182 void nghttp2_frame_unpack_rst_stream_payload(nghttp2_rst_stream *frame, 183 const uint8_t *payload); 184 185 /* 186 * Packs SETTINGS frame |frame| in wire format and store it in 187 * |bufs|. 188 * 189 * The caller must make sure that nghttp2_bufs_reset(bufs) is called 190 * before calling this function. 191 * 192 * This function returns 0 if it succeeds, or returns one of the 193 * following negative error codes: 194 * 195 * NGHTTP2_ERR_FRAME_SIZE_ERROR 196 * The length of the frame is too large. 197 */ 198 int nghttp2_frame_pack_settings(nghttp2_bufs *bufs, nghttp2_settings *frame); 199 200 /* 201 * Packs the |iv|, which includes |niv| entries, in the |buf|, 202 * assuming the |buf| has at least 8 * |niv| bytes. 203 * 204 * Returns the number of bytes written into the |buf|. 205 */ 206 size_t nghttp2_frame_pack_settings_payload(uint8_t *buf, 207 const nghttp2_settings_entry *iv, 208 size_t niv); 209 210 void nghttp2_frame_unpack_settings_entry(nghttp2_settings_entry *iv, 211 const uint8_t *payload); 212 213 /* 214 * Initializes payload of frame->settings. The |frame| takes 215 * ownership of |iv|. 216 */ 217 void nghttp2_frame_unpack_settings_payload(nghttp2_settings *frame, 218 nghttp2_settings_entry *iv, 219 size_t niv); 220 221 /* 222 * Unpacks SETTINGS payload into |*iv_ptr|. The number of entries are 223 * assigned to the |*niv_ptr|. This function allocates enough memory 224 * to store the result in |*iv_ptr|. The caller is responsible to free 225 * |*iv_ptr| after its use. 226 * 227 * This function returns 0 if it succeeds or one of the following 228 * negative error codes: 229 * 230 * NGHTTP2_ERR_NOMEM 231 * Out of memory. 232 */ 233 int nghttp2_frame_unpack_settings_payload2(nghttp2_settings_entry **iv_ptr, 234 size_t *niv_ptr, 235 const uint8_t *payload, 236 size_t payloadlen, nghttp2_mem *mem); 237 238 /* 239 * Packs PUSH_PROMISE frame |frame| in wire format and store it in 240 * |bufs|. This function expands |bufs| as necessary to store 241 * frame. 242 * 243 * The caller must make sure that nghttp2_bufs_reset(bufs) is called 244 * before calling this function. 245 * 246 * frame->hd.length is assigned after length is determined during 247 * packing process. CONTINUATION frames are also serialized in this 248 * function. This function does not handle padding. 249 * 250 * This function returns 0 if it succeeds, or returns one of the 251 * following negative error codes: 252 * 253 * NGHTTP2_ERR_HEADER_COMP 254 * The deflate operation failed. 255 * NGHTTP2_ERR_NOMEM 256 * Out of memory. 257 */ 258 int nghttp2_frame_pack_push_promise(nghttp2_bufs *bufs, 259 nghttp2_push_promise *frame, 260 nghttp2_hd_deflater *deflater); 261 262 /* 263 * Unpacks PUSH_PROMISE frame byte sequence into |frame|. This 264 * function only unapcks bytes that come before name/value header 265 * block and after possible Pad Length field. 266 * 267 * This function returns 0 if it succeeds or one of the following 268 * negative error codes: 269 * 270 * NGHTTP2_ERR_PROTO 271 * TODO END_HEADERS flag is not set 272 */ 273 int nghttp2_frame_unpack_push_promise_payload(nghttp2_push_promise *frame, 274 const uint8_t *payload); 275 276 /* 277 * Packs PING frame |frame| in wire format and store it in 278 * |bufs|. 279 * 280 * The caller must make sure that nghttp2_bufs_reset(bufs) is called 281 * before calling this function. 282 * 283 * This function always succeeds and returns 0. 284 */ 285 int nghttp2_frame_pack_ping(nghttp2_bufs *bufs, nghttp2_ping *frame); 286 287 /* 288 * Unpacks PING wire format into |frame|. 289 */ 290 void nghttp2_frame_unpack_ping_payload(nghttp2_ping *frame, 291 const uint8_t *payload); 292 293 /* 294 * Packs GOAWAY frame |frame| in wire format and store it in |bufs|. 295 * This function expands |bufs| as necessary to store frame. 296 * 297 * The caller must make sure that nghttp2_bufs_reset(bufs) is called 298 * before calling this function. 299 * 300 * This function returns 0 if it succeeds or one of the following 301 * negative error codes: 302 * 303 * NGHTTP2_ERR_NOMEM 304 * Out of memory. 305 * NGHTTP2_ERR_FRAME_SIZE_ERROR 306 * The length of the frame is too large. 307 */ 308 int nghttp2_frame_pack_goaway(nghttp2_bufs *bufs, nghttp2_goaway *frame); 309 310 /* 311 * Unpacks GOAWAY wire format into |frame|. The |payload| of length 312 * |payloadlen| contains first 8 bytes of payload. The 313 * |var_gift_payload| of length |var_gift_payloadlen| contains 314 * remaining payload and its buffer is gifted to the function and then 315 * |frame|. The |var_gift_payloadlen| must be freed by 316 * nghttp2_frame_goaway_free(). 317 */ 318 void nghttp2_frame_unpack_goaway_payload(nghttp2_goaway *frame, 319 const uint8_t *payload, 320 uint8_t *var_gift_payload, 321 size_t var_gift_payloadlen); 322 323 /* 324 * Unpacks GOAWAY wire format into |frame|. This function only exists 325 * for unit test. After allocating buffer for debug data, this 326 * function internally calls nghttp2_frame_unpack_goaway_payload(). 327 * 328 * This function returns 0 if it succeeds, or one of the following 329 * negative error codes: 330 * 331 * NGHTTP2_ERR_NOMEM 332 * Out of memory. 333 */ 334 int nghttp2_frame_unpack_goaway_payload2(nghttp2_goaway *frame, 335 const uint8_t *payload, 336 size_t payloadlen, nghttp2_mem *mem); 337 338 /* 339 * Packs WINDOW_UPDATE frame |frame| in wire frame format and store it 340 * in |bufs|. 341 * 342 * The caller must make sure that nghttp2_bufs_reset(bufs) is called 343 * before calling this function. 344 * 345 * This function always succeeds and returns 0. 346 */ 347 int nghttp2_frame_pack_window_update(nghttp2_bufs *bufs, 348 nghttp2_window_update *frame); 349 350 /* 351 * Unpacks WINDOW_UPDATE frame byte sequence into |frame|. 352 */ 353 void nghttp2_frame_unpack_window_update_payload(nghttp2_window_update *frame, 354 const uint8_t *payload); 355 356 /* 357 * Packs ALTSVC frame |frame| in wire frame format and store it in 358 * |bufs|. 359 * 360 * The caller must make sure that nghttp2_bufs_reset(bufs) is called 361 * before calling this function. 362 * 363 * This function always succeeds and returns 0. 364 */ 365 int nghttp2_frame_pack_altsvc(nghttp2_bufs *bufs, nghttp2_extension *ext); 366 367 /* 368 * Unpacks ALTSVC wire format into |frame|. The |payload| of 369 * |payloadlen| bytes contains frame payload. This function assumes 370 * that frame->payload points to the nghttp2_ext_altsvc object. 371 * 372 * This function always succeeds and returns 0. 373 */ 374 void nghttp2_frame_unpack_altsvc_payload(nghttp2_extension *frame, 375 size_t origin_len, uint8_t *payload, 376 size_t payloadlen); 377 378 /* 379 * Unpacks ALTSVC wire format into |frame|. This function only exists 380 * for unit test. After allocating buffer for fields, this function 381 * internally calls nghttp2_frame_unpack_altsvc_payload(). 382 * 383 * This function returns 0 if it succeeds, or one of the following 384 * negative error codes: 385 * 386 * NGHTTP2_ERR_NOMEM 387 * Out of memory. 388 * NGHTTP2_ERR_FRAME_SIZE_ERROR 389 * The payload is too small. 390 */ 391 int nghttp2_frame_unpack_altsvc_payload2(nghttp2_extension *frame, 392 const uint8_t *payload, 393 size_t payloadlen, nghttp2_mem *mem); 394 395 /* 396 * Initializes HEADERS frame |frame| with given values. |frame| takes 397 * ownership of |nva|, so caller must not free it. If |stream_id| is 398 * not assigned yet, it must be -1. 399 */ 400 void nghttp2_frame_headers_init(nghttp2_headers *frame, uint8_t flags, 401 int32_t stream_id, nghttp2_headers_category cat, 402 const nghttp2_priority_spec *pri_spec, 403 nghttp2_nv *nva, size_t nvlen); 404 405 void nghttp2_frame_headers_free(nghttp2_headers *frame, nghttp2_mem *mem); 406 407 void nghttp2_frame_priority_init(nghttp2_priority *frame, int32_t stream_id, 408 const nghttp2_priority_spec *pri_spec); 409 410 void nghttp2_frame_priority_free(nghttp2_priority *frame); 411 412 void nghttp2_frame_rst_stream_init(nghttp2_rst_stream *frame, int32_t stream_id, 413 uint32_t error_code); 414 415 void nghttp2_frame_rst_stream_free(nghttp2_rst_stream *frame); 416 417 /* 418 * Initializes PUSH_PROMISE frame |frame| with given values. |frame| 419 * takes ownership of |nva|, so caller must not free it. 420 */ 421 void nghttp2_frame_push_promise_init(nghttp2_push_promise *frame, uint8_t flags, 422 int32_t stream_id, 423 int32_t promised_stream_id, 424 nghttp2_nv *nva, size_t nvlen); 425 426 void nghttp2_frame_push_promise_free(nghttp2_push_promise *frame, 427 nghttp2_mem *mem); 428 429 /* 430 * Initializes SETTINGS frame |frame| with given values. |frame| takes 431 * ownership of |iv|, so caller must not free it. The |flags| are 432 * bitwise-OR of one or more of nghttp2_settings_flag. 433 */ 434 void nghttp2_frame_settings_init(nghttp2_settings *frame, uint8_t flags, 435 nghttp2_settings_entry *iv, size_t niv); 436 437 void nghttp2_frame_settings_free(nghttp2_settings *frame, nghttp2_mem *mem); 438 439 /* 440 * Initializes PING frame |frame| with given values. If the 441 * |opqeue_data| is not NULL, it must point to 8 bytes memory region 442 * of data. The data pointed by |opaque_data| is copied. It can be 443 * NULL. In this case, 8 bytes NULL is used. 444 */ 445 void nghttp2_frame_ping_init(nghttp2_ping *frame, uint8_t flags, 446 const uint8_t *opque_data); 447 448 void nghttp2_frame_ping_free(nghttp2_ping *frame); 449 450 /* 451 * Initializes GOAWAY frame |frame| with given values. On success, 452 * this function takes ownership of |opaque_data|, so caller must not 453 * free it. If the |opaque_data_len| is 0, opaque_data could be NULL. 454 */ 455 void nghttp2_frame_goaway_init(nghttp2_goaway *frame, int32_t last_stream_id, 456 uint32_t error_code, uint8_t *opaque_data, 457 size_t opaque_data_len); 458 459 void nghttp2_frame_goaway_free(nghttp2_goaway *frame, nghttp2_mem *mem); 460 461 void nghttp2_frame_window_update_init(nghttp2_window_update *frame, 462 uint8_t flags, int32_t stream_id, 463 int32_t window_size_increment); 464 465 void nghttp2_frame_window_update_free(nghttp2_window_update *frame); 466 467 void nghttp2_frame_extension_init(nghttp2_extension *frame, uint8_t type, 468 uint8_t flags, int32_t stream_id, 469 void *payload); 470 471 void nghttp2_frame_extension_free(nghttp2_extension *frame); 472 473 /* 474 * Initializes ALTSVC frame |frame| with given values. This function 475 * assumes that frame->payload points to nghttp2_ext_altsvc object. 476 * Also |origin| and |field_value| are allocated in single buffer, 477 * starting |origin|. On success, this function takes ownership of 478 * |origin|, so caller must not free it. 479 */ 480 void nghttp2_frame_altsvc_init(nghttp2_extension *frame, int32_t stream_id, 481 uint8_t *origin, size_t origin_len, 482 uint8_t *field_value, size_t field_value_len); 483 484 /* 485 * Frees up resources under |frame|. This function does not free 486 * nghttp2_ext_altsvc object pointed by frame->payload. This function 487 * only frees origin pointed by nghttp2_ext_altsvc.origin. Therefore, 488 * other fields must be allocated in the same buffer with origin. 489 */ 490 void nghttp2_frame_altsvc_free(nghttp2_extension *frame, nghttp2_mem *mem); 491 492 /* 493 * Returns the number of padding bytes after payload. The total 494 * padding length is given in the |padlen|. The returned value does 495 * not include the Pad Length field. If |padlen| is 0, this function 496 * returns 0, regardless of frame->hd.flags. 497 */ 498 size_t nghttp2_frame_trail_padlen(nghttp2_frame *frame, size_t padlen); 499 500 void nghttp2_frame_data_init(nghttp2_data *frame, uint8_t flags, 501 int32_t stream_id); 502 503 void nghttp2_frame_data_free(nghttp2_data *frame); 504 505 /* 506 * Makes copy of |iv| and return the copy. The |niv| is the number of 507 * entries in |iv|. This function returns the pointer to the copy if 508 * it succeeds, or NULL. 509 */ 510 nghttp2_settings_entry *nghttp2_frame_iv_copy(const nghttp2_settings_entry *iv, 511 size_t niv, nghttp2_mem *mem); 512 513 /* 514 * Sorts the |nva| in ascending order of name and value. If names are 515 * equivalent, sort them by value. 516 */ 517 void nghttp2_nv_array_sort(nghttp2_nv *nva, size_t nvlen); 518 519 /* 520 * Copies name/value pairs from |nva|, which contains |nvlen| pairs, 521 * to |*nva_ptr|, which is dynamically allocated so that all items can 522 * be stored. The resultant name and value in nghttp2_nv are 523 * guaranteed to be NULL-terminated even if the input is not 524 * null-terminated. 525 * 526 * The |*nva_ptr| must be freed using nghttp2_nv_array_del(). 527 * 528 * This function returns 0 if it succeeds or one of the following 529 * negative error codes: 530 * 531 * NGHTTP2_ERR_NOMEM 532 * Out of memory. 533 */ 534 int nghttp2_nv_array_copy(nghttp2_nv **nva_ptr, const nghttp2_nv *nva, 535 size_t nvlen, nghttp2_mem *mem); 536 537 /* 538 * Returns nonzero if the name/value pair |a| equals to |b|. The name 539 * is compared in case-sensitive, because we ensure that this function 540 * is called after the name is lower-cased. 541 */ 542 int nghttp2_nv_equal(const nghttp2_nv *a, const nghttp2_nv *b); 543 544 /* 545 * Frees |nva|. 546 */ 547 void nghttp2_nv_array_del(nghttp2_nv *nva, nghttp2_mem *mem); 548 549 /* 550 * Checks that the |iv|, which includes |niv| entries, does not have 551 * invalid values. 552 * 553 * This function returns nonzero if it succeeds, or 0. 554 */ 555 int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv); 556 557 /* 558 * Sets Pad Length field and flags and adjusts frame header position 559 * of each buffers in |bufs|. The number of padding is given in the 560 * |padlen| including Pad Length field. The |hd| is the frame header 561 * for the serialized data. This function fills zeros padding region 562 * unless framehd_only is nonzero. 563 * 564 * This function returns 0 if it succeeds, or one of the following 565 * negative error codes: 566 * 567 * NGHTTP2_ERR_NOMEM 568 * Out of memory. 569 * NGHTTP2_ERR_FRAME_SIZE_ERROR 570 * The length of the resulting frame is too large. 571 */ 572 int nghttp2_frame_add_pad(nghttp2_bufs *bufs, nghttp2_frame_hd *hd, 573 size_t padlen, int framehd_only); 574 575 #endif /* NGHTTP2_FRAME_H */ 576