13 static ssize_t read_outgoing_callback(
14 nghttp2_session* session,
19 nghttp2_data_source* 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;
31 auto& body = stream_data->outgoing.body.ro_data();
32 size_t to_read = std::min(body.size(), length);
40 return NGHTTP2_ERR_DEFERRED;
45 memcpy(buf, body.data(), to_read);
46 body = body.subspan(to_read);
53 *data_flags |= NGHTTP2_DATA_FLAG_EOF;
56 if (stream_data->outgoing.has_trailers)
58 *data_flags |= NGHTTP2_DATA_FLAG_NO_END_STREAM;
65 static int on_begin_frame_recv_callback(
66 nghttp2_session* session,
const nghttp2_frame_hd* hd,
void* user_data)
68 const auto& stream_id = hd->stream_id;
70 "http2::on_begin_frame_recv_callback, type: {}, stream_id: {}",
82 auto* p = get_parser(user_data);
84 stream_id != DEFAULT_STREAM_ID && p->get_stream(stream_id) ==
nullptr &&
85 hd->type == NGHTTP2_HEADERS)
87 if (stream_id < p->get_last_stream_id())
90 "http2::on_begin_frame_recv_callback: cannot process stream id {} "
91 "< last stream id {}",
93 p->get_last_stream_id());
94 return NGHTTP2_ERR_PROTO;
97 p->create_stream(stream_id);
103 static int on_frame_recv_callback(
104 nghttp2_session* session,
const nghttp2_frame* frame,
void* user_data)
106 LOG_TRACE_FMT(
"http2::on_frame_recv_callback, type: {}", frame->hd.type);
108 const auto stream_id = frame->hd.stream_id;
109 auto* stream_data = get_stream_data(session, stream_id);
111 switch (frame->hd.type)
114 case NGHTTP2_HEADERS:
119 if (stream_data ==
nullptr)
126 if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM)
128 auto* p = get_parser(user_data);
129 p->handle_completed(stream_id, stream_data);
142 static int on_begin_headers_callback(
143 nghttp2_session* session,
const nghttp2_frame* frame,
void* user_data)
146 const auto& stream_id = frame->hd.stream_id;
148 auto* p = get_parser(user_data);
150 auto stream_data = p->get_stream(stream_id);
151 if (stream_data ==
nullptr)
154 throw std::logic_error(
155 fmt::format(
"Stream {} should already exist", stream_id));
158 auto rc = nghttp2_session_set_stream_user_data(
159 session, stream_id, stream_data.get());
162 throw std::logic_error(fmt::format(
163 "HTTP/2: Could not set user data for stream {}: {}",
165 nghttp2_strerror(rc)));
171 static int on_header_callback(
172 nghttp2_session* session,
173 const nghttp2_frame* frame,
176 const uint8_t* value,
181 const auto& stream_id = frame->hd.stream_id;
182 auto k = std::string(name, name + namelen);
183 auto v = std::string(value, value + valuelen);
184 LOG_TRACE_FMT(
"http2::on_header_callback: {}, {}:{}", stream_id, k, v);
186 auto* p = get_parser(user_data);
187 const auto& configuration = p->get_configuration();
189 auto const& max_header_size = configuration.max_header_size.value_or(
190 ccf::http::default_max_header_size);
191 if (namelen > max_header_size)
195 "Header key for '{}' is too large (max size allowed: {})",
201 if (valuelen > max_header_size)
205 "Header value for '{}' is too large (max size allowed: {})",
211 auto* stream_data = get_stream_data(session, stream_id);
212 const auto max_headers_count = configuration.max_headers_count.value_or(
213 ccf::http::default_max_headers_count);
214 if (stream_data->incoming.headers.size() >= max_headers_count)
218 "Too many headers (max number allowed: {})", max_headers_count),
222 stream_data->incoming.headers.emplace(k, v);
227 static int on_data_callback(
228 nghttp2_session* session,
235 LOG_TRACE_FMT(
"http2::on_data_callback: {}, {} bytes", stream_id, len);
237 auto* stream_data = get_stream_data(session, stream_id);
238 auto* p = get_parser(user_data);
239 const auto& configuration = p->get_configuration();
241 stream_data->incoming.body.insert(
242 stream_data->incoming.body.end(), data, data + len);
244 auto const& max_body_size =
245 configuration.max_body_size.value_or(ccf::http::default_max_body_size);
246 if (stream_data->incoming.body.size() > max_body_size)
250 "HTTP request body is too large (max size allowed: {})",
258 static int on_stream_close_callback(
259 nghttp2_session* session,
265 "http2::on_stream_close_callback: {}, {}", stream_id, error_code);
267 auto* p = get_parser(user_data);
268 p->destroy_stream(stream_id);
273 static ssize_t on_data_source_read_length_callback(
274 nghttp2_session* session,
277 int32_t session_remote_window_size,
278 int32_t stream_remote_window_size,
279 uint32_t remote_max_frame_size,
282 auto* p = get_parser(user_data);
283 const auto& configuration = p->get_configuration();
284 const auto& max_frame_size =
285 configuration.max_frame_size.value_or(ccf::http::default_max_frame_size);
288 "http2::on_data_source_read_length_callback: {}, {}, allowed [1, "
292 session_remote_window_size,
293 stream_remote_window_size,
294 remote_max_frame_size);
296 return max_frame_size;
299 static int on_error_callback(
300 nghttp2_session* session,
306 LOG_DEBUG_FMT(
"HTTP/2 error: {}", std::string(msg, msg + len));