The C and C++ Include Header Files
/usr/include/nodejs/src/node_http2.h
$ cat -n /usr/include/nodejs/src/node_http2.h 1 #ifndef SRC_NODE_HTTP2_H_ 2 #define SRC_NODE_HTTP2_H_ 3 4 #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 5 6 // clang-format off 7 #include "node.h" // nghttp2.h needs ssize_t 8 // clang-format on 9 #include "nghttp2/nghttp2.h" 10 11 #include "env.h" 12 #include "aliased_struct.h" 13 #include "node_http2_state.h" 14 #include "node_http_common.h" 15 #include "node_mem.h" 16 #include "node_perf.h" 17 #include "stream_base.h" 18 #include "string_bytes.h" 19 20 #include
21 #include
22 23 namespace node { 24 namespace http2 { 25 26 // Constants in all caps are exported as user-facing constants 27 // in JavaScript. Constants using the kName pattern are internal 28 // only. 29 30 // We strictly limit the number of outstanding unacknowledged PINGS a user 31 // may send in order to prevent abuse. The current default cap is 10. The 32 // user may set a different limit using a per Http2Session configuration 33 // option. 34 constexpr size_t kDefaultMaxPings = 10; 35 36 // Also strictly limit the number of outstanding SETTINGS frames a user sends 37 constexpr size_t kDefaultMaxSettings = 10; 38 39 // Default maximum total memory cap for Http2Session. 40 constexpr uint64_t kDefaultMaxSessionMemory = 10000000; 41 42 // These are the standard HTTP/2 defaults as specified by the RFC 43 constexpr uint32_t DEFAULT_SETTINGS_HEADER_TABLE_SIZE = 4096; 44 constexpr uint32_t DEFAULT_SETTINGS_ENABLE_PUSH = 1; 45 constexpr uint32_t DEFAULT_SETTINGS_MAX_CONCURRENT_STREAMS = 0xffffffffu; 46 constexpr uint32_t DEFAULT_SETTINGS_INITIAL_WINDOW_SIZE = 65535; 47 constexpr uint32_t DEFAULT_SETTINGS_MAX_FRAME_SIZE = 16384; 48 constexpr uint32_t DEFAULT_SETTINGS_MAX_HEADER_LIST_SIZE = 65535; 49 constexpr uint32_t DEFAULT_SETTINGS_ENABLE_CONNECT_PROTOCOL = 0; 50 constexpr uint32_t MAX_MAX_FRAME_SIZE = 16777215; 51 constexpr uint32_t MIN_MAX_FRAME_SIZE = DEFAULT_SETTINGS_MAX_FRAME_SIZE; 52 constexpr uint32_t MAX_INITIAL_WINDOW_SIZE = 2147483647; 53 54 // Stream is not going to have any DATA frames 55 constexpr int STREAM_OPTION_EMPTY_PAYLOAD = 0x1; 56 57 // Stream might have trailing headers 58 constexpr int STREAM_OPTION_GET_TRAILERS = 0x2; 59 60 // Http2Stream internal states 61 constexpr int kStreamStateNone = 0x0; 62 constexpr int kStreamStateShut = 0x1; 63 constexpr int kStreamStateReadStart = 0x2; 64 constexpr int kStreamStateReadPaused = 0x4; 65 constexpr int kStreamStateClosed = 0x8; 66 constexpr int kStreamStateDestroyed = 0x10; 67 constexpr int kStreamStateTrailers = 0x20; 68 69 // Http2Session internal states 70 constexpr int kSessionStateNone = 0x0; 71 constexpr int kSessionStateHasScope = 0x1; 72 constexpr int kSessionStateWriteScheduled = 0x2; 73 constexpr int kSessionStateClosed = 0x4; 74 constexpr int kSessionStateClosing = 0x8; 75 constexpr int kSessionStateSending = 0x10; 76 constexpr int kSessionStateWriteInProgress = 0x20; 77 constexpr int kSessionStateReadingStopped = 0x40; 78 constexpr int kSessionStateReceivePaused = 0x80; 79 80 // The Padding Strategy determines the method by which extra padding is 81 // selected for HEADERS and DATA frames. These are configurable via the 82 // options passed in to a Http2Session object. 83 enum PaddingStrategy { 84 // No padding strategy. This is the default. 85 PADDING_STRATEGY_NONE, 86 // Attempts to ensure that the frame is 8-byte aligned 87 PADDING_STRATEGY_ALIGNED, 88 // Padding will ensure all data frames are maxFrameSize 89 PADDING_STRATEGY_MAX, 90 // Removed and turned into an alias because it is unreasonably expensive for 91 // very little benefit. 92 PADDING_STRATEGY_CALLBACK = PADDING_STRATEGY_ALIGNED 93 }; 94 95 enum SessionType { 96 NGHTTP2_SESSION_SERVER, 97 NGHTTP2_SESSION_CLIENT 98 }; 99 100 template
101 struct Nghttp2Deleter { 102 void operator()(T* ptr) const noexcept { fn(ptr); } 103 }; 104 105 using Nghttp2OptionPointer = 106 std::unique_ptr
>; 108 109 using Nghttp2SessionPointer = 110 std::unique_ptr
>; 112 113 using Nghttp2SessionCallbacksPointer = 114 std::unique_ptr
>; 117 118 struct Http2HeadersTraits { 119 typedef nghttp2_nv nv_t; 120 }; 121 122 struct Http2RcBufferPointerTraits { 123 typedef nghttp2_rcbuf rcbuf_t; 124 typedef nghttp2_vec vector_t; 125 126 static void inc(rcbuf_t* buf) { 127 CHECK_NOT_NULL(buf); 128 nghttp2_rcbuf_incref(buf); 129 } 130 static void dec(rcbuf_t* buf) { 131 CHECK_NOT_NULL(buf); 132 nghttp2_rcbuf_decref(buf); 133 } 134 static vector_t get_vec(rcbuf_t* buf) { 135 CHECK_NOT_NULL(buf); 136 return nghttp2_rcbuf_get_buf(buf); 137 } 138 static bool is_static(const rcbuf_t* buf) { 139 CHECK_NOT_NULL(buf); 140 return nghttp2_rcbuf_is_static(buf); 141 } 142 }; 143 144 using Http2Headers = NgHeaders
; 145 using Http2RcBufferPointer = NgRcBufPointer
; 146 147 struct NgHttp2StreamWrite : public MemoryRetainer { 148 BaseObjectPtr
req_wrap; 149 uv_buf_t buf; 150 151 inline explicit NgHttp2StreamWrite(uv_buf_t buf_) : buf(buf_) {} 152 inline NgHttp2StreamWrite(BaseObjectPtr
req_wrap, uv_buf_t buf_) : 153 req_wrap(std::move(req_wrap)), buf(buf_) {} 154 155 void MemoryInfo(MemoryTracker* tracker) const override; 156 SET_MEMORY_INFO_NAME(NgHttp2StreamWrite) 157 SET_SELF_SIZE(NgHttp2StreamWrite) 158 }; 159 160 typedef uint32_t(*get_setting)(nghttp2_session* session, 161 nghttp2_settings_id id); 162 163 class Http2Ping; 164 class Http2Session; 165 class Http2Settings; 166 class Http2Stream; 167 class Origins; 168 169 // This scope should be present when any call into nghttp2 that may schedule 170 // data to be written to the underlying transport is made, and schedules 171 // such a write automatically once the scope is exited. 172 class Http2Scope { 173 public: 174 explicit Http2Scope(Http2Stream* stream); 175 explicit Http2Scope(Http2Session* session); 176 ~Http2Scope(); 177 178 private: 179 BaseObjectPtr
session_; 180 }; 181 182 // The Http2Options class is used to parse the options object passed in to 183 // a Http2Session object and convert those into an appropriate nghttp2_option 184 // struct. This is the primary mechanism by which the Http2Session object is 185 // configured. 186 class Http2Options { 187 public: 188 Http2Options(Http2State* http2_state, 189 SessionType type); 190 191 ~Http2Options() = default; 192 193 nghttp2_option* operator*() const { 194 return options_.get(); 195 } 196 197 void set_max_header_pairs(uint32_t max) { 198 max_header_pairs_ = max; 199 } 200 201 uint32_t max_header_pairs() const { 202 return max_header_pairs_; 203 } 204 205 void set_padding_strategy(PaddingStrategy val) { 206 padding_strategy_ = val; 207 } 208 209 PaddingStrategy padding_strategy() const { 210 return padding_strategy_; 211 } 212 213 void set_max_outstanding_pings(size_t max) { 214 max_outstanding_pings_ = max; 215 } 216 217 size_t max_outstanding_pings() const { 218 return max_outstanding_pings_; 219 } 220 221 void set_max_outstanding_settings(size_t max) { 222 max_outstanding_settings_ = max; 223 } 224 225 size_t max_outstanding_settings() const { 226 return max_outstanding_settings_; 227 } 228 229 void set_max_session_memory(uint64_t max) { 230 max_session_memory_ = max; 231 } 232 233 uint64_t max_session_memory() const { 234 return max_session_memory_; 235 } 236 237 private: 238 Nghttp2OptionPointer options_; 239 uint64_t max_session_memory_ = kDefaultMaxSessionMemory; 240 uint32_t max_header_pairs_ = DEFAULT_MAX_HEADER_LIST_PAIRS; 241 PaddingStrategy padding_strategy_ = PADDING_STRATEGY_NONE; 242 size_t max_outstanding_pings_ = kDefaultMaxPings; 243 size_t max_outstanding_settings_ = kDefaultMaxSettings; 244 }; 245 246 struct Http2Priority : public nghttp2_priority_spec { 247 Http2Priority(Environment* env, 248 v8::Local
parent, 249 v8::Local
weight, 250 v8::Local
exclusive); 251 }; 252 253 class Http2StreamListener : public StreamListener { 254 public: 255 uv_buf_t OnStreamAlloc(size_t suggested_size) override; 256 void OnStreamRead(ssize_t nread, const uv_buf_t& buf) override; 257 }; 258 259 struct Http2HeaderTraits { 260 typedef Http2RcBufferPointer rcbufferpointer_t; 261 typedef Http2Session allocator_t; 262 263 // HTTP/2 does not support identifying header names by token id. 264 // HTTP/3 will, however, so we prepare for that now. 265 static const char* ToHttpHeaderName(int32_t token) { return nullptr; } 266 }; 267 268 using Http2Header = NgHeader
; 269 270 class Http2Stream : public AsyncWrap, 271 public StreamBase { 272 public: 273 static Http2Stream* New( 274 Http2Session* session, 275 int32_t id, 276 nghttp2_headers_category category = NGHTTP2_HCAT_HEADERS, 277 int options = 0); 278 ~Http2Stream() override; 279 280 nghttp2_stream* operator*() const; 281 282 nghttp2_stream* stream() const; 283 284 Http2Session* session() { return session_.get(); } 285 const Http2Session* session() const { return session_.get(); } 286 287 // Required for StreamBase 288 int ReadStart() override; 289 290 // Required for StreamBase 291 int ReadStop() override; 292 293 // Required for StreamBase 294 ShutdownWrap* CreateShutdownWrap(v8::Local
object) override; 295 int DoShutdown(ShutdownWrap* req_wrap) override; 296 297 bool HasWantsWrite() const override { return true; } 298 299 // Initiate a response on this stream. 300 int SubmitResponse(const Http2Headers& headers, int options); 301 302 // Submit informational headers for this stream 303 int SubmitInfo(const Http2Headers& headers); 304 305 // Submit trailing headers for this stream 306 int SubmitTrailers(const Http2Headers& headers); 307 void OnTrailers(); 308 309 // Submit a PRIORITY frame for this stream 310 int SubmitPriority(const Http2Priority& priority, bool silent = false); 311 312 // Submits an RST_STREAM frame using the given code 313 void SubmitRstStream(const uint32_t code); 314 315 void FlushRstStream(); 316 317 // Submits a PUSH_PROMISE frame with this stream as the parent. 318 Http2Stream* SubmitPushPromise( 319 const Http2Headers& headers, 320 int32_t* ret, 321 int options = 0); 322 323 324 void Close(int32_t code); 325 326 // Destroy this stream instance and free all held memory. 327 void Destroy(); 328 329 bool is_destroyed() const { 330 return flags_ & kStreamStateDestroyed; 331 } 332 333 bool is_writable() const { 334 return !(flags_ & kStreamStateShut); 335 } 336 337 bool is_paused() const { 338 return flags_ & kStreamStateReadPaused; 339 } 340 341 bool is_closed() const { 342 return flags_ & kStreamStateClosed; 343 } 344 345 bool has_trailers() const { 346 return flags_ & kStreamStateTrailers; 347 } 348 349 void set_has_trailers(bool on = true) { 350 if (on) 351 flags_ |= kStreamStateTrailers; 352 else 353 flags_ &= ~kStreamStateTrailers; 354 } 355 356 void set_closed() { 357 flags_ |= kStreamStateClosed; 358 } 359 360 void set_destroyed() { 361 flags_ |= kStreamStateDestroyed; 362 } 363 364 void set_not_writable() { 365 flags_ |= kStreamStateShut; 366 } 367 368 void set_reading(bool on = true) { 369 if (on) { 370 flags_ |= kStreamStateReadStart; 371 set_paused(false); 372 } else {} 373 } 374 375 void set_paused(bool on = true) { 376 if (on) 377 flags_ |= kStreamStateReadPaused; 378 else 379 flags_ &= ~kStreamStateReadPaused; 380 } 381 382 // Returns true if this stream is in the reading state, which occurs when 383 // the kStreamStateReadStart flag has been set and the 384 // kStreamStateReadPaused flag is *not* set. 385 bool is_reading() const { 386 return flags_ & kStreamStateReadStart && !is_paused(); 387 } 388 389 // Returns the RST_STREAM code used to close this stream 390 int32_t code() const { return code_; } 391 392 // Returns the stream identifier for this stream 393 int32_t id() const { return id_; } 394 395 void IncrementAvailableOutboundLength(size_t amount); 396 void DecrementAvailableOutboundLength(size_t amount); 397 398 bool AddHeader(nghttp2_rcbuf* name, nghttp2_rcbuf* value, uint8_t flags); 399 400 template
401 void TransferHeaders(Fn&& fn) { 402 size_t i = 0; 403 for (const auto& header : current_headers_ ) 404 fn(header, i++); 405 ClearHeaders(); 406 } 407 408 void ClearHeaders() { 409 current_headers_.clear(); 410 } 411 412 size_t headers_count() const { 413 return current_headers_.size(); 414 } 415 416 nghttp2_headers_category headers_category() const { 417 return current_headers_category_; 418 } 419 420 void StartHeaders(nghttp2_headers_category category); 421 422 // Required for StreamBase 423 bool IsAlive() override { 424 return true; 425 } 426 427 // Required for StreamBase 428 bool IsClosing() override { 429 return false; 430 } 431 432 AsyncWrap* GetAsyncWrap() override { return this; } 433 434 int DoWrite(WriteWrap* w, uv_buf_t* bufs, size_t count, 435 uv_stream_t* send_handle) override; 436 437 void MemoryInfo(MemoryTracker* tracker) const override; 438 SET_MEMORY_INFO_NAME(Http2Stream) 439 SET_SELF_SIZE(Http2Stream) 440 441 std::string diagnostic_name() const override; 442 443 // JavaScript API 444 static void GetID(const v8::FunctionCallbackInfo
& args); 445 static void Destroy(const v8::FunctionCallbackInfo
& args); 446 static void Priority(const v8::FunctionCallbackInfo
& args); 447 static void PushPromise(const v8::FunctionCallbackInfo
& args); 448 static void RefreshState(const v8::FunctionCallbackInfo
& args); 449 static void Info(const v8::FunctionCallbackInfo
& args); 450 static void Trailers(const v8::FunctionCallbackInfo
& args); 451 static void Respond(const v8::FunctionCallbackInfo
& args); 452 static void RstStream(const v8::FunctionCallbackInfo
& args); 453 454 class Provider; 455 456 struct Statistics { 457 uint64_t start_time; 458 uint64_t end_time; 459 uint64_t first_header; // Time first header was received 460 uint64_t first_byte; // Time first DATA frame byte was received 461 uint64_t first_byte_sent; // Time first DATA frame byte was sent 462 uint64_t sent_bytes; 463 uint64_t received_bytes; 464 uint64_t id; 465 }; 466 467 Statistics statistics_ = {}; 468 469 private: 470 Http2Stream(Http2Session* session, 471 v8::Local
obj, 472 int32_t id, 473 nghttp2_headers_category category, 474 int options); 475 476 void EmitStatistics(); 477 478 BaseObjectWeakPtr
session_; // The Parent HTTP/2 Session 479 int32_t id_ = 0; // The Stream Identifier 480 int32_t code_ = NGHTTP2_NO_ERROR; // The RST_STREAM code (if any) 481 int flags_ = kStreamStateNone; // Internal state flags 482 483 uint32_t max_header_pairs_ = DEFAULT_MAX_HEADER_LIST_PAIRS; 484 uint32_t max_header_length_ = DEFAULT_SETTINGS_MAX_HEADER_LIST_SIZE; 485 486 // The Current Headers block... As headers are received for this stream, 487 // they are temporarily stored here until the OnFrameReceived is called 488 // signalling the end of the HEADERS frame 489 nghttp2_headers_category current_headers_category_ = NGHTTP2_HCAT_HEADERS; 490 uint32_t current_headers_length_ = 0; // total number of octets 491 std::vector
current_headers_; 492 493 // This keeps track of the amount of data read from the socket while the 494 // socket was in paused mode. When `ReadStart()` is called (and not before 495 // then), we tell nghttp2 that we consumed that data to get proper 496 // backpressure handling. 497 size_t inbound_consumed_data_while_paused_ = 0; 498 499 // Outbound Data... This is the data written by the JS layer that is 500 // waiting to be written out to the socket. 501 std::queue
queue_; 502 size_t available_outbound_length_ = 0; 503 504 Http2StreamListener stream_listener_; 505 506 friend class Http2Session; 507 }; 508 509 class Http2Stream::Provider { 510 public: 511 Provider(Http2Stream* stream, int options); 512 explicit Provider(int options); 513 virtual ~Provider(); 514 515 nghttp2_data_provider* operator*() { 516 return !empty_ ? &provider_ : nullptr; 517 } 518 519 class FD; 520 class Stream; 521 protected: 522 nghttp2_data_provider provider_; 523 524 private: 525 bool empty_ = false; 526 }; 527 528 class Http2Stream::Provider::Stream : public Http2Stream::Provider { 529 public: 530 Stream(Http2Stream* stream, int options); 531 explicit Stream(int options); 532 533 static ssize_t OnRead(nghttp2_session* session, 534 int32_t id, 535 uint8_t* buf, 536 size_t length, 537 uint32_t* flags, 538 nghttp2_data_source* source, 539 void* user_data); 540 }; 541 542 struct SessionJSFields { 543 uint8_t bitfield; 544 uint8_t priority_listener_count; 545 uint8_t frame_error_listener_count; 546 uint32_t max_invalid_frames = 1000; 547 uint32_t max_rejected_streams = 100; 548 }; 549 550 // Indices for js_fields_, which serves as a way to communicate data with JS 551 // land fast. In particular, we store information about the number/presence 552 // of certain event listeners in JS, and skip calls from C++ into JS if they 553 // are missing. 554 enum SessionUint8Fields { 555 kBitfield = offsetof(SessionJSFields, bitfield), // See below 556 kSessionPriorityListenerCount = 557 offsetof(SessionJSFields, priority_listener_count), 558 kSessionFrameErrorListenerCount = 559 offsetof(SessionJSFields, frame_error_listener_count), 560 kSessionMaxInvalidFrames = offsetof(SessionJSFields, max_invalid_frames), 561 kSessionMaxRejectedStreams = offsetof(SessionJSFields, max_rejected_streams), 562 kSessionUint8FieldCount = sizeof(SessionJSFields) 563 }; 564 565 enum SessionBitfieldFlags { 566 kSessionHasRemoteSettingsListeners, 567 kSessionRemoteSettingsIsUpToDate, 568 kSessionHasPingListeners, 569 kSessionHasAltsvcListeners 570 }; 571 572 class Http2Session : public AsyncWrap, 573 public StreamListener, 574 public mem::NgLibMemoryManager
{ 575 public: 576 Http2Session(Http2State* http2_state, 577 v8::Local
wrap, 578 SessionType type = NGHTTP2_SESSION_SERVER); 579 ~Http2Session() override; 580 581 StreamBase* underlying_stream() { 582 return static_cast
(stream_); 583 } 584 585 void Close(uint32_t code = NGHTTP2_NO_ERROR, 586 bool socket_closed = false); 587 588 void Consume(v8::Local
stream); 589 590 void Goaway(uint32_t code, int32_t lastStreamID, 591 const uint8_t* data, size_t len); 592 593 void AltSvc(int32_t id, 594 uint8_t* origin, 595 size_t origin_len, 596 uint8_t* value, 597 size_t value_len); 598 599 void Origin(const Origins& origins); 600 601 uint8_t SendPendingData(); 602 603 // Submits a new request. If the request is a success, assigned 604 // will be a pointer to the Http2Stream instance assigned. 605 // This only works if the session is a client session. 606 Http2Stream* SubmitRequest( 607 const Http2Priority& priority, 608 const Http2Headers& headers, 609 int32_t* ret, 610 int options = 0); 611 612 SessionType type() const { return session_type_; } 613 614 nghttp2_session* session() const { return session_.get(); } 615 616 nghttp2_session* operator*() { return session_.get(); } 617 618 uint32_t max_header_pairs() const { return max_header_pairs_; } 619 620 const char* TypeName() const; 621 622 bool is_destroyed() { 623 return (flags_ & kSessionStateClosed) || session_ == nullptr; 624 } 625 626 void set_destroyed() { 627 flags_ |= kSessionStateClosed; 628 } 629 630 #define IS_FLAG(name, flag) \ 631 bool is_##name() const { return flags_ & flag; } \ 632 void set_##name(bool on = true) { \ 633 if (on) \ 634 flags_ |= flag; \ 635 else \ 636 flags_ &= ~flag; \ 637 } 638 639 IS_FLAG(in_scope, kSessionStateHasScope) 640 IS_FLAG(write_scheduled, kSessionStateWriteScheduled) 641 IS_FLAG(closing, kSessionStateClosing) 642 IS_FLAG(sending, kSessionStateSending) 643 IS_FLAG(write_in_progress, kSessionStateWriteInProgress) 644 IS_FLAG(reading_stopped, kSessionStateReadingStopped) 645 IS_FLAG(receive_paused, kSessionStateReceivePaused) 646 647 #undef IS_FLAG 648 649 // Schedule a write if nghttp2 indicates it wants to write to the socket. 650 void MaybeScheduleWrite(); 651 652 // Stop reading if nghttp2 doesn't want to anymore. 653 void MaybeStopReading(); 654 655 // Returns pointer to the stream, or nullptr if stream does not exist 656 BaseObjectPtr
FindStream(int32_t id); 657 658 bool CanAddStream(); 659 660 // Adds a stream instance to this session 661 void AddStream(Http2Stream* stream); 662 663 // Removes a stream instance from this session 664 BaseObjectPtr
RemoveStream(int32_t id); 665 666 // Indicates whether there currently exist outgoing buffers for this stream. 667 bool HasWritesOnSocketForStream(Http2Stream* stream); 668 669 // Write data from stream_buf_ to the session. 670 // This will call the error callback if an error occurs. 671 void ConsumeHTTP2Data(); 672 673 void MemoryInfo(MemoryTracker* tracker) const override; 674 SET_MEMORY_INFO_NAME(Http2Session) 675 SET_SELF_SIZE(Http2Session) 676 677 std::string diagnostic_name() const override; 678 679 // Schedule an RstStream for after the current write finishes. 680 void AddPendingRstStream(int32_t stream_id) { 681 pending_rst_streams_.emplace_back(stream_id); 682 } 683 684 bool has_pending_rststream(int32_t stream_id) { 685 return pending_rst_streams_.end() != 686 std::find(pending_rst_streams_.begin(), 687 pending_rst_streams_.end(), 688 stream_id); 689 } 690 691 // Handle reads/writes from the underlying network transport. 692 uv_buf_t OnStreamAlloc(size_t suggested_size) override; 693 void OnStreamRead(ssize_t nread, const uv_buf_t& buf) override; 694 void OnStreamAfterWrite(WriteWrap* w, int status) override; 695 696 // Implementation for mem::NgLibMemoryManager 697 void CheckAllocatedSize(size_t previous_size) const; 698 void IncreaseAllocatedSize(size_t size); 699 void DecreaseAllocatedSize(size_t size); 700 701 // The JavaScript API 702 static void New(const v8::FunctionCallbackInfo
& args); 703 static void Consume(const v8::FunctionCallbackInfo
& args); 704 static void Receive(const v8::FunctionCallbackInfo
& args); 705 static void Destroy(const v8::FunctionCallbackInfo
& args); 706 static void Settings(const v8::FunctionCallbackInfo
& args); 707 static void Request(const v8::FunctionCallbackInfo
& args); 708 static void SetNextStreamID(const v8::FunctionCallbackInfo
& args); 709 static void SetLocalWindowSize( 710 const v8::FunctionCallbackInfo
& args); 711 static void Goaway(const v8::FunctionCallbackInfo
& args); 712 static void UpdateChunksSent(const v8::FunctionCallbackInfo
& args); 713 static void RefreshState(const v8::FunctionCallbackInfo
& args); 714 static void Ping(const v8::FunctionCallbackInfo
& args); 715 static void AltSvc(const v8::FunctionCallbackInfo
& args); 716 static void Origin(const v8::FunctionCallbackInfo
& args); 717 718 template
719 static void RefreshSettings(const v8::FunctionCallbackInfo
& args); 720 721 uv_loop_t* event_loop() const { 722 return env()->event_loop(); 723 } 724 725 Http2State* http2_state() const { return http2_state_.get(); } 726 727 BaseObjectPtr
PopPing(); 728 bool AddPing(const uint8_t* data, v8::Local
callback); 729 730 BaseObjectPtr
PopSettings(); 731 bool AddSettings(v8::Local
callback); 732 733 void IncrementCurrentSessionMemory(uint64_t amount) { 734 current_session_memory_ += amount; 735 } 736 737 void DecrementCurrentSessionMemory(uint64_t amount) { 738 DCHECK_LE(amount, current_session_memory_); 739 current_session_memory_ -= amount; 740 } 741 742 // Tell our custom memory allocator that this rcbuf is independent of 743 // this session now, and may outlive it. 744 void StopTrackingRcbuf(nghttp2_rcbuf* buf); 745 746 // Returns the current session memory including memory allocated by nghttp2, 747 // the current outbound storage queue, and pending writes. 748 uint64_t current_session_memory() const { 749 uint64_t total = current_session_memory_ + sizeof(Http2Session); 750 total += current_nghttp2_memory_; 751 total += outgoing_storage_.size(); 752 return total; 753 } 754 755 // Return true if current_session_memory + amount is less than the max 756 bool has_available_session_memory(uint64_t amount) const { 757 return current_session_memory() + amount <= max_session_memory_; 758 } 759 760 struct Statistics { 761 uint64_t start_time; 762 uint64_t end_time; 763 uint64_t ping_rtt; 764 uint64_t data_sent; 765 uint64_t data_received; 766 uint32_t frame_count; 767 uint32_t frame_sent; 768 int32_t stream_count; 769 size_t max_concurrent_streams; 770 double stream_average_duration; 771 SessionType session_type; 772 }; 773 774 Statistics statistics_ = {}; 775 776 private: 777 void EmitStatistics(); 778 779 // Frame Padding Strategies 780 ssize_t OnDWordAlignedPadding(size_t frameLength, 781 size_t maxPayloadLen); 782 ssize_t OnMaxFrameSizePadding(size_t frameLength, 783 size_t maxPayloadLen); 784 785 // Frame Handler 786 int HandleDataFrame(const nghttp2_frame* frame); 787 void HandleGoawayFrame(const nghttp2_frame* frame); 788 void HandleHeadersFrame(const nghttp2_frame* frame); 789 void HandlePriorityFrame(const nghttp2_frame* frame); 790 void HandleSettingsFrame(const nghttp2_frame* frame); 791 void HandlePingFrame(const nghttp2_frame* frame); 792 void HandleAltSvcFrame(const nghttp2_frame* frame); 793 void HandleOriginFrame(const nghttp2_frame* frame); 794 795 void DecrefHeaders(const nghttp2_frame* frame); 796 797 // nghttp2 callbacks 798 static int OnBeginHeadersCallback( 799 nghttp2_session* session, 800 const nghttp2_frame* frame, 801 void* user_data); 802 static int OnHeaderCallback( 803 nghttp2_session* session, 804 const nghttp2_frame* frame, 805 nghttp2_rcbuf* name, 806 nghttp2_rcbuf* value, 807 uint8_t flags, 808 void* user_data); 809 static int OnFrameReceive( 810 nghttp2_session* session, 811 const nghttp2_frame* frame, 812 void* user_data); 813 static int OnFrameNotSent( 814 nghttp2_session* session, 815 const nghttp2_frame* frame, 816 int error_code, 817 void* user_data); 818 static int OnFrameSent( 819 nghttp2_session* session, 820 const nghttp2_frame* frame, 821 void* user_data); 822 static int OnStreamClose( 823 nghttp2_session* session, 824 int32_t id, 825 uint32_t code, 826 void* user_data); 827 static int OnInvalidHeader( 828 nghttp2_session* session, 829 const nghttp2_frame* frame, 830 nghttp2_rcbuf* name, 831 nghttp2_rcbuf* value, 832 uint8_t flags, 833 void* user_data); 834 static int OnDataChunkReceived( 835 nghttp2_session* session, 836 uint8_t flags, 837 int32_t id, 838 const uint8_t* data, 839 size_t len, 840 void* user_data); 841 static ssize_t OnSelectPadding( 842 nghttp2_session* session, 843 const nghttp2_frame* frame, 844 size_t maxPayloadLen, 845 void* user_data); 846 static int OnNghttpError(nghttp2_session* session, 847 int lib_error_code, 848 const char* message, 849 size_t len, 850 void* user_data); 851 static int OnSendData( 852 nghttp2_session* session, 853 nghttp2_frame* frame, 854 const uint8_t* framehd, 855 size_t length, 856 nghttp2_data_source* source, 857 void* user_data); 858 static int OnInvalidFrame( 859 nghttp2_session* session, 860 const nghttp2_frame* frame, 861 int lib_error_code, 862 void* user_data); 863 864 struct Callbacks { 865 explicit Callbacks(bool kHasGetPaddingCallback); 866 867 Nghttp2SessionCallbacksPointer callbacks; 868 }; 869 870 /* Use callback_struct_saved[kHasGetPaddingCallback ? 1 : 0] */ 871 static const Callbacks callback_struct_saved[2]; 872 873 // The underlying nghttp2_session handle 874 Nghttp2SessionPointer session_; 875 876 // JS-accessible numeric fields, as indexed by SessionUint8Fields. 877 AliasedStruct
js_fields_; 878 879 // The session type: client or server 880 SessionType session_type_; 881 882 // The maximum number of header pairs permitted for streams on this session 883 uint32_t max_header_pairs_ = DEFAULT_MAX_HEADER_LIST_PAIRS; 884 885 // The maximum amount of memory allocated for this session 886 uint64_t max_session_memory_ = kDefaultMaxSessionMemory; 887 uint64_t current_session_memory_ = 0; 888 // The amount of memory allocated by nghttp2 internals 889 uint64_t current_nghttp2_memory_ = 0; 890 891 // The collection of active Http2Streams associated with this session 892 std::unordered_map
> streams_; 893 894 int flags_ = kSessionStateNone; 895 896 // The StreamBase instance being used for i/o 897 PaddingStrategy padding_strategy_ = PADDING_STRATEGY_NONE; 898 899 // use this to allow timeout tracking during long-lasting writes 900 uint32_t chunks_sent_since_last_write_ = 0; 901 902 uv_buf_t stream_buf_ = uv_buf_init(nullptr, 0); 903 // When processing input data, either stream_buf_ab_ or stream_buf_allocation_ 904 // will be set. stream_buf_ab_ is lazily created from stream_buf_allocation_. 905 v8::Global
stream_buf_ab_; 906 std::unique_ptr
stream_buf_allocation_; 907 size_t stream_buf_offset_ = 0; 908 // Custom error code for errors that originated inside one of the callbacks 909 // called by nghttp2_session_mem_recv. 910 const char* custom_recv_error_code_ = nullptr; 911 912 size_t max_outstanding_pings_ = kDefaultMaxPings; 913 std::queue
> outstanding_pings_; 914 915 size_t max_outstanding_settings_ = kDefaultMaxSettings; 916 std::queue
> outstanding_settings_; 917 918 std::vector
outgoing_buffers_; 919 std::vector
outgoing_storage_; 920 size_t outgoing_length_ = 0; 921 std::vector
pending_rst_streams_; 922 // Count streams that have been rejected while being opened. Exceeding a fixed 923 // limit will result in the session being destroyed, as an indication of a 924 // misbehaving peer. This counter is reset once new streams are being 925 // accepted again. 926 uint32_t rejected_stream_count_ = 0; 927 // Also use the invalid frame count as a measure for rejecting input frames. 928 uint32_t invalid_frame_count_ = 0; 929 930 void PushOutgoingBuffer(NgHttp2StreamWrite&& write); 931 932 BaseObjectPtr
http2_state_; 933 934 void CopyDataIntoOutgoing(const uint8_t* src, size_t src_length); 935 void ClearOutgoing(int status); 936 937 friend class Http2Scope; 938 friend class Http2StreamListener; 939 }; 940 941 struct Http2SessionPerformanceEntryTraits { 942 static constexpr performance::PerformanceEntryType kType = 943 performance::NODE_PERFORMANCE_ENTRY_TYPE_HTTP2; 944 945 using Details = Http2Session::Statistics; 946 947 static v8::MaybeLocal
GetDetails( 948 Environment* env, 949 const performance::PerformanceEntry
& 950 entry); 951 }; 952 953 struct Http2StreamPerformanceEntryTraits { 954 static constexpr performance::PerformanceEntryType kType = 955 performance::NODE_PERFORMANCE_ENTRY_TYPE_HTTP2; 956 957 using Details = Http2Stream::Statistics; 958 959 static v8::MaybeLocal
GetDetails( 960 Environment* env, 961 const performance::PerformanceEntry
& 962 entry); 963 }; 964 965 using Http2SessionPerformanceEntry = 966 performance::PerformanceEntry
; 967 using Http2StreamPerformanceEntry = 968 performance::PerformanceEntry
; 969 970 class Http2Ping : public AsyncWrap { 971 public: 972 explicit Http2Ping( 973 Http2Session* session, 974 v8::Local
obj, 975 v8::Local
callback); 976 977 void MemoryInfo(MemoryTracker* tracker) const override; 978 SET_MEMORY_INFO_NAME(Http2Ping) 979 SET_SELF_SIZE(Http2Ping) 980 981 void Send(const uint8_t* payload); 982 void Done(bool ack, const uint8_t* payload = nullptr); 983 void DetachFromSession(); 984 985 v8::Local
callback() const; 986 987 private: 988 BaseObjectWeakPtr
session_; 989 v8::Global
callback_; 990 uint64_t startTime_; 991 }; 992 993 // The Http2Settings class is used to parse the settings passed in for 994 // an Http2Session, converting those into an array of nghttp2_settings_entry 995 // structs. 996 class Http2Settings : public AsyncWrap { 997 public: 998 Http2Settings(Http2Session* session, 999 v8::Local
obj, 1000 v8::Local
callback, 1001 uint64_t start_time = uv_hrtime()); 1002 1003 void MemoryInfo(MemoryTracker* tracker) const override; 1004 SET_MEMORY_INFO_NAME(Http2Settings) 1005 SET_SELF_SIZE(Http2Settings) 1006 1007 void Send(); 1008 void Done(bool ack); 1009 1010 v8::Local
callback() const; 1011 1012 // Returns a Buffer instance with the serialized SETTINGS payload 1013 v8::Local
Pack(); 1014 1015 static v8::Local
Pack(Http2State* state); 1016 1017 // Resets the default values in the settings buffer 1018 static void RefreshDefaults(Http2State* http2_state); 1019 1020 // Update the local or remote settings for the given session 1021 static void Update(Http2Session* session, 1022 get_setting fn); 1023 1024 private: 1025 static size_t Init( 1026 Http2State* http2_state, 1027 nghttp2_settings_entry* entries); 1028 1029 static v8::Local
Pack( 1030 Environment* env, 1031 size_t count, 1032 const nghttp2_settings_entry* entries); 1033 1034 BaseObjectWeakPtr
session_; 1035 v8::Global
callback_; 1036 uint64_t startTime_; 1037 size_t count_ = 0; 1038 nghttp2_settings_entry entries_[IDX_SETTINGS_COUNT]; 1039 }; 1040 1041 class Origins { 1042 public: 1043 Origins(Environment* env, 1044 v8::Local
origin_string, 1045 size_t origin_count); 1046 ~Origins() = default; 1047 1048 const nghttp2_origin_entry* operator*() const { 1049 return static_cast
(bs_->Data()); 1050 } 1051 1052 size_t length() const { 1053 return count_; 1054 } 1055 1056 private: 1057 size_t count_; 1058 std::unique_ptr
bs_; 1059 }; 1060 1061 #define HTTP2_HIDDEN_CONSTANTS(V) \ 1062 V(NGHTTP2_HCAT_REQUEST) \ 1063 V(NGHTTP2_HCAT_RESPONSE) \ 1064 V(NGHTTP2_HCAT_PUSH_RESPONSE) \ 1065 V(NGHTTP2_HCAT_HEADERS) \ 1066 V(NGHTTP2_NV_FLAG_NONE) \ 1067 V(NGHTTP2_NV_FLAG_NO_INDEX) \ 1068 V(NGHTTP2_ERR_DEFERRED) \ 1069 V(NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE) \ 1070 V(NGHTTP2_ERR_INVALID_ARGUMENT) \ 1071 V(NGHTTP2_ERR_STREAM_CLOSED) \ 1072 V(NGHTTP2_ERR_NOMEM) \ 1073 V(STREAM_OPTION_EMPTY_PAYLOAD) \ 1074 V(STREAM_OPTION_GET_TRAILERS) 1075 1076 #define HTTP2_ERROR_CODES(V) \ 1077 V(NGHTTP2_NO_ERROR) \ 1078 V(NGHTTP2_PROTOCOL_ERROR) \ 1079 V(NGHTTP2_INTERNAL_ERROR) \ 1080 V(NGHTTP2_FLOW_CONTROL_ERROR) \ 1081 V(NGHTTP2_SETTINGS_TIMEOUT) \ 1082 V(NGHTTP2_STREAM_CLOSED) \ 1083 V(NGHTTP2_FRAME_SIZE_ERROR) \ 1084 V(NGHTTP2_REFUSED_STREAM) \ 1085 V(NGHTTP2_CANCEL) \ 1086 V(NGHTTP2_COMPRESSION_ERROR) \ 1087 V(NGHTTP2_CONNECT_ERROR) \ 1088 V(NGHTTP2_ENHANCE_YOUR_CALM) \ 1089 V(NGHTTP2_INADEQUATE_SECURITY) \ 1090 V(NGHTTP2_HTTP_1_1_REQUIRED) \ 1091 1092 #define HTTP2_CONSTANTS(V) \ 1093 V(NGHTTP2_ERR_FRAME_SIZE_ERROR) \ 1094 V(NGHTTP2_SESSION_SERVER) \ 1095 V(NGHTTP2_SESSION_CLIENT) \ 1096 V(NGHTTP2_STREAM_STATE_IDLE) \ 1097 V(NGHTTP2_STREAM_STATE_OPEN) \ 1098 V(NGHTTP2_STREAM_STATE_RESERVED_LOCAL) \ 1099 V(NGHTTP2_STREAM_STATE_RESERVED_REMOTE) \ 1100 V(NGHTTP2_STREAM_STATE_HALF_CLOSED_LOCAL) \ 1101 V(NGHTTP2_STREAM_STATE_HALF_CLOSED_REMOTE) \ 1102 V(NGHTTP2_STREAM_STATE_CLOSED) \ 1103 V(NGHTTP2_FLAG_NONE) \ 1104 V(NGHTTP2_FLAG_END_STREAM) \ 1105 V(NGHTTP2_FLAG_END_HEADERS) \ 1106 V(NGHTTP2_FLAG_ACK) \ 1107 V(NGHTTP2_FLAG_PADDED) \ 1108 V(NGHTTP2_FLAG_PRIORITY) \ 1109 V(DEFAULT_SETTINGS_HEADER_TABLE_SIZE) \ 1110 V(DEFAULT_SETTINGS_ENABLE_PUSH) \ 1111 V(DEFAULT_SETTINGS_MAX_CONCURRENT_STREAMS) \ 1112 V(DEFAULT_SETTINGS_INITIAL_WINDOW_SIZE) \ 1113 V(DEFAULT_SETTINGS_MAX_FRAME_SIZE) \ 1114 V(DEFAULT_SETTINGS_MAX_HEADER_LIST_SIZE) \ 1115 V(DEFAULT_SETTINGS_ENABLE_CONNECT_PROTOCOL) \ 1116 V(MAX_MAX_FRAME_SIZE) \ 1117 V(MIN_MAX_FRAME_SIZE) \ 1118 V(MAX_INITIAL_WINDOW_SIZE) \ 1119 V(NGHTTP2_SETTINGS_HEADER_TABLE_SIZE) \ 1120 V(NGHTTP2_SETTINGS_ENABLE_PUSH) \ 1121 V(NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS) \ 1122 V(NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE) \ 1123 V(NGHTTP2_SETTINGS_MAX_FRAME_SIZE) \ 1124 V(NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE) \ 1125 V(NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL) \ 1126 V(PADDING_STRATEGY_NONE) \ 1127 V(PADDING_STRATEGY_ALIGNED) \ 1128 V(PADDING_STRATEGY_MAX) \ 1129 V(PADDING_STRATEGY_CALLBACK) \ 1130 HTTP2_ERROR_CODES(V) 1131 1132 #define HTTP2_SETTINGS(V) \ 1133 V(HEADER_TABLE_SIZE) \ 1134 V(ENABLE_PUSH) \ 1135 V(MAX_CONCURRENT_STREAMS) \ 1136 V(INITIAL_WINDOW_SIZE) \ 1137 V(MAX_FRAME_SIZE) \ 1138 V(MAX_HEADER_LIST_SIZE) \ 1139 V(ENABLE_CONNECT_PROTOCOL) \ 1140 1141 } // namespace http2 1142 } // namespace node 1143 1144 #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 1145 1146 #endif // SRC_NODE_HTTP2_H_
Contact us
|
About us
|
Term of use
|
Copyright © 2000-2024 MyWebUniversity.com ™