13 static ssize_t read_outgoing_callback(
14 nghttp2_session* session,
19 nghttp2_data_source* ,
22 auto* stream_data = get_stream_data(session, stream_id);
26 "http2::read_outgoing_callback error: unexpected state {}",
27 stream_data->outgoing.state);
28 return NGHTTP2_ERR_CALLBACK_FAILURE;
32 const auto body_remaining = body.
data.size() - body.
consumed;
33 size_t to_read = std::min(body_remaining, length);
41 return NGHTTP2_ERR_DEFERRED;
54 *data_flags |= NGHTTP2_DATA_FLAG_EOF;
57 if (stream_data->outgoing.has_trailers)
59 *data_flags |= NGHTTP2_DATA_FLAG_NO_END_STREAM;
66 static int on_begin_frame_recv_callback(
67 nghttp2_session* ,
const nghttp2_frame_hd* hd,
void* user_data)
69 const auto& stream_id = hd->stream_id;
71 "http2::on_begin_frame_recv_callback, type: {}, stream_id: {}",
83 auto* p = get_parser(user_data);
85 stream_id != DEFAULT_STREAM_ID && p->get_stream(stream_id) ==
nullptr &&
86 hd->type == NGHTTP2_HEADERS)
88 if (stream_id < p->get_last_stream_id())
91 "http2::on_begin_frame_recv_callback: cannot process stream id {} "
92 "< last stream id {}",
94 p->get_last_stream_id());
95 return NGHTTP2_ERR_PROTO;
98 p->create_stream(stream_id);
104 static int on_frame_recv_callback(
105 nghttp2_session* session,
const nghttp2_frame* frame,
void* user_data)
107 LOG_TRACE_FMT(
"http2::on_frame_recv_callback, type: {}", frame->hd.type);
109 const auto stream_id = frame->hd.stream_id;
110 auto* stream_data = get_stream_data(session, stream_id);
112 switch (frame->hd.type)
115 case NGHTTP2_HEADERS:
120 if (stream_data ==
nullptr)
127 if ((frame->hd.flags & NGHTTP2_FLAG_END_STREAM) != 0)
129 auto* p = get_parser(user_data);
130 p->handle_completed(stream_id, stream_data);
143 static int on_begin_headers_callback(
144 nghttp2_session* session,
const nghttp2_frame* frame,
void* user_data)
147 const auto& stream_id = frame->hd.stream_id;
149 auto* p = get_parser(user_data);
151 auto stream_data = p->get_stream(stream_id);
152 if (stream_data ==
nullptr)
155 throw std::logic_error(
156 fmt::format(
"Stream {} should already exist", stream_id));
159 auto rc = nghttp2_session_set_stream_user_data(
160 session, stream_id, stream_data.get());
163 throw std::logic_error(fmt::format(
164 "HTTP/2: Could not set user data for stream {}: {}",
166 nghttp2_strerror(rc)));
172 static int on_header_callback(
173 nghttp2_session* session,
174 const nghttp2_frame* frame,
177 const uint8_t* value,
182 const auto& stream_id = frame->hd.stream_id;
183 auto k = std::string(name, name + namelen);
184 auto v = std::string(value, value + valuelen);
185 LOG_TRACE_FMT(
"http2::on_header_callback: {}, {}:{}", stream_id, k, v);
187 auto* p = get_parser(user_data);
188 const auto& configuration = p->get_configuration();
190 auto const& max_header_size = configuration.max_header_size.value_or(
191 ccf::http::default_max_header_size);
192 if (namelen > max_header_size)
196 "Header key for '{}' is too large (max size allowed: {})",
202 if (valuelen > max_header_size)
206 "Header value for '{}' is too large (max size allowed: {})",
212 auto* stream_data = get_stream_data(session, stream_id);
213 const auto max_headers_count = configuration.max_headers_count.value_or(
214 ccf::http::default_max_headers_count);
215 if (stream_data->incoming.headers.size() >= max_headers_count)
219 "Too many headers (max number allowed: {})", max_headers_count),
223 stream_data->incoming.headers.emplace(k, v);
228 static int on_data_callback(
229 nghttp2_session* session,
236 LOG_TRACE_FMT(
"http2::on_data_callback: {}, {} bytes", stream_id, len);
238 auto* stream_data = get_stream_data(session, stream_id);
239 auto* p = get_parser(user_data);
240 const auto& configuration = p->get_configuration();
242 stream_data->incoming.body.insert(
243 stream_data->incoming.body.end(), data, data + len);
245 auto const& max_body_size =
246 configuration.max_body_size.value_or(ccf::http::default_max_body_size);
247 if (stream_data->incoming.body.size() > max_body_size)
251 "HTTP request body is too large (max size allowed: {})",
259 static int on_stream_close_callback(
266 "http2::on_stream_close_callback: {}, {}", stream_id, error_code);
268 auto* p = get_parser(user_data);
269 p->destroy_stream(stream_id);
274 static ssize_t on_data_source_read_length_callback(
278 int32_t session_remote_window_size,
279 int32_t stream_remote_window_size,
280 uint32_t remote_max_frame_size,
283 auto* p = get_parser(user_data);
284 const auto& configuration = p->get_configuration();
285 const auto& max_frame_size =
286 configuration.max_frame_size.value_or(ccf::http::default_max_frame_size);
289 "http2::on_data_source_read_length_callback: {}, {}, allowed [1, "
293 session_remote_window_size,
294 stream_remote_window_size,
295 remote_max_frame_size);
297 return max_frame_size;
300 static int on_error_callback(
307 LOG_DEBUG_FMT(
"HTTP/2 error: {}", std::string(msg, msg + len));