1 #ifndef SRC_NODE_HTTP2_CORE_H_ 2 #define SRC_NODE_HTTP2_CORE_H_ 4 #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 9 #include "nghttp2/nghttp2.h" 12 #include <unordered_map> 17 #ifdef NODE_DEBUG_HTTP2 20 static inline void _debug_vfprintf(
const char *fmt, va_list args) {
21 vfprintf(stderr, fmt, args);
24 void inline debug_vfprintf(
const char *format, ...) {
26 va_start(args, format);
27 _debug_vfprintf(format, args);
31 #define DEBUG_HTTP2(...) debug_vfprintf(__VA_ARGS__); 33 #define DEBUG_HTTP2(...) \ 41 struct nghttp2_stream_write_t;
42 struct nghttp2_data_chunk_t;
43 struct nghttp2_data_chunks_t;
45 #define MAX_BUFFER_COUNT 10 46 #define SEND_BUFFER_RECOMMENDED_SIZE 4096 48 enum nghttp2_session_type {
49 NGHTTP2_SESSION_SERVER,
50 NGHTTP2_SESSION_CLIENT
53 enum nghttp2_shutdown_flags {
54 NGHTTP2_SHUTDOWN_FLAG_GRACEFUL
57 enum nghttp2_stream_flags {
58 NGHTTP2_STREAM_FLAG_NONE = 0x0,
60 NGHTTP2_STREAM_FLAG_SHUT = 0x1,
62 NGHTTP2_STREAM_FLAG_READ_START = 0x2,
64 NGHTTP2_STREAM_FLAG_READ_PAUSED = 0x4,
66 NGHTTP2_STREAM_FLAG_CLOSED = 0x8,
68 NGHTTP2_STREAM_FLAG_DESTROYED = 0x10
73 typedef void (*nghttp2_stream_write_cb)(
74 nghttp2_stream_write_t*
req,
77 struct nghttp2_stream_write_queue {
78 unsigned int nbufs = 0;
79 nghttp2_stream_write_t* req =
nullptr;
80 nghttp2_stream_write_cb cb =
nullptr;
81 nghttp2_stream_write_queue* next =
nullptr;
82 MaybeStackBuffer<uv_buf_t, MAX_BUFFER_COUNT> bufs;
85 struct nghttp2_header_list {
86 nghttp2_rcbuf* name =
nullptr;
87 nghttp2_rcbuf* value =
nullptr;
88 nghttp2_header_list* next =
nullptr;
92 class Nghttp2Session {
97 const nghttp2_session_type type = NGHTTP2_SESSION_SERVER,
98 nghttp2_option* options =
nullptr,
99 nghttp2_mem* mem =
nullptr);
103 inline void MarkDestroying();
104 bool IsDestroying() {
108 inline const char* TypeName(nghttp2_session_type type) {
110 case NGHTTP2_SESSION_SERVER:
return "server";
111 case NGHTTP2_SESSION_CLIENT:
return "client";
120 inline Nghttp2Stream* FindStream(int32_t
id);
125 inline int32_t SubmitRequest(
126 nghttp2_priority_spec* prispec,
129 Nghttp2Stream** assigned =
nullptr,
130 bool emptyPayload =
true,
131 bool getTrailers =
false);
135 inline void SubmitShutdownNotice();
138 inline int SubmitSettings(
const nghttp2_settings_entry iv[],
size_t niv);
141 inline ssize_t Write(
const uv_buf_t* bufs,
unsigned int nbufs);
144 inline nghttp2_session* session() {
return session_; }
146 nghttp2_session_type type() {
147 return session_type_;
152 inline void AddStream(Nghttp2Stream* stream);
155 inline void RemoveStream(int32_t
id);
157 virtual void Send(uv_buf_t*
buf,
size_t length) {}
158 virtual void OnHeaders(Nghttp2Stream* stream,
159 nghttp2_header_list* headers,
160 nghttp2_headers_category cat,
162 virtual void OnStreamClose(int32_t
id, uint32_t code) {}
163 virtual void OnDataChunk(Nghttp2Stream* stream,
164 nghttp2_data_chunk_t* chunk) {}
165 virtual void OnSettings(
bool ack) {}
166 virtual void OnPriority(int32_t
id,
170 virtual void OnGoAway(int32_t lastStreamID,
174 virtual void OnFrameError(int32_t
id,
177 virtual ssize_t GetPadding(
size_t frameLength,
178 size_t maxFrameLength) {
return 0; }
179 virtual void OnFreeSession() {}
180 virtual void AllocateSend(
size_t suggested_size, uv_buf_t*
buf) = 0;
182 virtual bool HasGetPaddingCallback() {
return false; }
184 class SubmitTrailers {
186 inline void Submit(nghttp2_nv* trailers,
size_t length)
const;
189 inline SubmitTrailers(Nghttp2Session* handle,
190 Nghttp2Stream* stream,
193 Nghttp2Session*
const handle_;
194 Nghttp2Stream*
const stream_;
195 uint32_t*
const flags_;
197 friend class Nghttp2Session;
200 virtual void OnTrailers(Nghttp2Stream* stream,
201 const SubmitTrailers& submit_trailers) {}
204 inline void SendPendingData();
205 inline void HandleHeadersFrame(
const nghttp2_frame* frame);
206 inline void HandlePriorityFrame(
const nghttp2_frame* frame);
207 inline void HandleDataFrame(
const nghttp2_frame* frame);
208 inline void HandleGoawayFrame(
const nghttp2_frame* frame);
210 static inline void GetTrailers(nghttp2_session* session,
211 Nghttp2Session* handle,
212 Nghttp2Stream* stream,
216 #ifdef NODE_DEBUG_HTTP2 217 static inline int OnNghttpError(nghttp2_session* session,
223 static inline int OnBeginHeadersCallback(nghttp2_session* session,
224 const nghttp2_frame* frame,
226 static inline int OnHeaderCallback(nghttp2_session* session,
227 const nghttp2_frame* frame,
229 nghttp2_rcbuf* value,
232 static inline int OnFrameReceive(nghttp2_session* session,
233 const nghttp2_frame* frame,
235 static inline int OnFrameNotSent(nghttp2_session* session,
236 const nghttp2_frame* frame,
239 static inline int OnStreamClose(nghttp2_session* session,
243 static inline int OnInvalidHeader(nghttp2_session* session,
244 const nghttp2_frame* frame,
246 nghttp2_rcbuf* value,
249 static inline int OnDataChunkReceived(nghttp2_session* session,
255 static inline ssize_t OnStreamReadFD(nghttp2_session* session,
260 nghttp2_data_source*
source,
262 static inline ssize_t OnStreamRead(nghttp2_session* session,
267 nghttp2_data_source*
source,
269 static inline ssize_t OnSelectPadding(nghttp2_session* session,
270 const nghttp2_frame* frame,
271 size_t maxPayloadLen,
275 inline explicit Callbacks(
bool kHasGetPaddingCallback);
278 nghttp2_session_callbacks* callbacks;
282 static Callbacks callback_struct_saved[2];
284 nghttp2_session* session_;
287 nghttp2_session_type session_type_;
288 std::unordered_map<int32_t, Nghttp2Stream*> streams_;
289 bool destroying_ =
false;
291 friend class Nghttp2Stream;
296 class Nghttp2Stream {
298 static inline Nghttp2Stream*
Init(
300 Nghttp2Session* session,
301 nghttp2_headers_category category = NGHTTP2_HCAT_HEADERS,
302 bool getTrailers =
false);
304 inline ~Nghttp2Stream() {
305 CHECK_EQ(session_,
nullptr);
306 CHECK_EQ(queue_head_,
nullptr);
307 CHECK_EQ(queue_tail_,
nullptr);
308 CHECK_EQ(data_chunks_head_,
nullptr);
309 CHECK_EQ(data_chunks_tail_,
nullptr);
310 CHECK_EQ(current_headers_head_,
nullptr);
311 CHECK_EQ(current_headers_tail_,
nullptr);
312 DEBUG_HTTP2(
"Nghttp2Stream %d: freed\n", id_);
315 inline void FlushDataChunks(
bool done =
false);
318 inline void ResetState(
320 Nghttp2Session* session,
321 nghttp2_headers_category category = NGHTTP2_HCAT_HEADERS,
322 bool getTrailers =
false);
333 inline void Destroy();
336 inline bool IsDestroyed()
const {
337 return flags_ & NGHTTP2_STREAM_FLAG_DESTROYED;
342 nghttp2_stream_write_t* req,
343 const uv_buf_t bufs[],
345 nghttp2_stream_write_cb cb);
348 inline int SubmitResponse(nghttp2_nv* nva,
350 bool emptyPayload =
false,
351 bool getTrailers =
false);
354 inline int SubmitFile(
int fd,
355 nghttp2_nv* nva,
size_t len,
358 bool getTrailers =
false);
361 inline int SubmitInfo(nghttp2_nv* nva,
size_t len);
364 inline int SubmitPriority(nghttp2_priority_spec* prispec,
365 bool silent =
false);
368 inline int SubmitRstStream(
const uint32_t code);
371 inline int SubmitPushPromise(
374 Nghttp2Stream** assigned =
nullptr,
375 bool writable =
true);
378 inline void Shutdown() {
379 flags_ |= NGHTTP2_STREAM_FLAG_SHUT;
380 nghttp2_session_resume_data(session_->session(), id_);
384 inline bool IsWritable()
const {
385 return !(flags_ & NGHTTP2_STREAM_FLAG_SHUT);
390 inline void ReadStart();
393 inline void ReadStop();
396 inline bool IsPaused()
const {
397 return flags_ & NGHTTP2_STREAM_FLAG_READ_PAUSED;
400 inline bool GetTrailers()
const {
407 inline bool IsReading()
const {
408 return flags_ & NGHTTP2_STREAM_FLAG_READ_START &&
409 !(flags_ & NGHTTP2_STREAM_FLAG_READ_PAUSED);
412 inline void Close(int32_t code) {
413 DEBUG_HTTP2(
"Nghttp2Stream %d: closing with code %d\n", id_, code);
414 flags_ |= NGHTTP2_STREAM_FLAG_CLOSED;
416 session_->OnStreamClose(id_, code);
417 DEBUG_HTTP2(
"Nghttp2Stream %d: closed\n", id_);
422 inline bool IsClosed()
const {
423 return flags_ & NGHTTP2_STREAM_FLAG_CLOSED;
427 inline int32_t code()
const {
432 inline int32_t id()
const {
436 inline nghttp2_header_list* headers()
const {
437 return current_headers_head_;
440 inline nghttp2_headers_category headers_category()
const {
441 return current_headers_category_;
444 inline void FreeHeaders();
446 void StartHeaders(nghttp2_headers_category category) {
447 DEBUG_HTTP2(
"Nghttp2Stream %d: starting headers, category: %d\n",
451 CHECK_EQ(current_headers_head_,
nullptr);
452 CHECK_EQ(current_headers_tail_,
nullptr);
453 current_headers_category_ = category;
458 Nghttp2Session* session_ =
nullptr;
468 nghttp2_stream_write_queue* queue_head_ =
nullptr;
469 nghttp2_stream_write_queue* queue_tail_ =
nullptr;
470 unsigned int queue_head_index_ = 0;
471 size_t queue_head_offset_ = 0;
472 int64_t fd_offset_ = 0;
473 int64_t fd_length_ = -1;
478 nghttp2_header_list* current_headers_head_ =
nullptr;
479 nghttp2_header_list* current_headers_tail_ =
nullptr;
480 nghttp2_headers_category current_headers_category_ = NGHTTP2_HCAT_HEADERS;
483 nghttp2_data_chunk_t* data_chunks_head_ =
nullptr;
484 nghttp2_data_chunk_t* data_chunks_tail_ =
nullptr;
487 int32_t code_ = NGHTTP2_NO_ERROR;
489 int32_t prev_local_window_size_ = 65535;
492 bool getTrailers_ =
false;
494 friend class Nghttp2Session;
497 struct nghttp2_stream_write_t {
500 Nghttp2Stream* handle;
501 nghttp2_stream_write_queue* item;
504 struct nghttp2_data_chunk_t {
506 nghttp2_data_chunk_t* next =
nullptr;
509 struct nghttp2_data_chunks_t {
510 unsigned int nbufs = 0;
511 uv_buf_t
buf[MAX_BUFFER_COUNT];
513 inline ~nghttp2_data_chunks_t();
519 #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 521 #endif // SRC_NODE_HTTP2_CORE_H_
union node::cares_wrap::@8::CaresAsyncData::@0 data
void Init(int *argc, const char **argv, int *exec_argc, const char ***exec_argv)