Skip to content

Commit

Permalink
h3: add support for additional HEADERS
Browse files Browse the repository at this point in the history
HTTP/3 request and response message exchanges allow multiple HEADERS
frames to be sent, which allows for trailer sections or non-final
responses. Previously, quiche has only supported generating a single
HEADERS frame per request or response, and didn't support receiving
them.

This change adds support for sending and receiving multiple HEADERS
frames on a request stream. It enforces the sequencing rules defined in
https://www.rfc-editor.org/rfc/rfc9114.html#section-4.1.
Sending additional HEADERS is done using the new
`send_additional_headers()` method. On the receive side, rather than add
a new Event enum variant for these additional uses of HEADERS, this
change reuses Event::Headers. Previosuly, this event included a
`has_body` boolean, which has been renamed to `more_frames` to better
align with how HTTP/3 streams work.
  • Loading branch information
LPardue authored Sep 27, 2024
1 parent 523c045 commit 2514d58
Show file tree
Hide file tree
Showing 6 changed files with 629 additions and 118 deletions.
2 changes: 1 addition & 1 deletion nginx/nginx-1.16.patch
Original file line number Diff line number Diff line change
Expand Up @@ -2569,7 +2569,7 @@ index 000000000..d7c4fbf1d
+ return;
+ }
+
+ stream->in_closed = !quiche_h3_event_headers_has_body(ev);
+ stream->in_closed = !quiche_h3_event_headers_has_more_frames(ev);
+
+ ngx_http_v3_run_request(stream->request);
+}
Expand Down
10 changes: 8 additions & 2 deletions quiche/include/quiche.h
Original file line number Diff line number Diff line change
Expand Up @@ -1060,8 +1060,8 @@ int quiche_h3_for_each_setting(quiche_h3_conn *conn,
uint64_t value, void *argp),
void *argp);

// Check whether data will follow the headers on the stream.
bool quiche_h3_event_headers_has_body(quiche_h3_event *ev);
// Check whether more frames will follow the headers on the stream.
bool quiche_h3_event_headers_has_more_frames(quiche_h3_event *ev);

// Check whether or not extended connection is enabled by the peer
bool quiche_h3_extended_connect_enabled_by_peer(quiche_h3_conn *conn);
Expand Down Expand Up @@ -1099,6 +1099,12 @@ int quiche_h3_send_response_with_priority(quiche_h3_conn *conn,
const quiche_h3_header *headers, size_t headers_len,
quiche_h3_priority *priority, bool fin);

// Sends additional HTTP/3 headers on the specified stream.
int quiche_h3_send_additional_headers(quiche_h3_conn *conn,
quiche_conn *quic_conn, uint64_t stream_id,
quiche_h3_header *headers, size_t headers_len,
bool is_trailer_section, bool fin);

// Sends an HTTP/3 body chunk on the given stream.
ssize_t quiche_h3_send_body(quiche_h3_conn *conn, quiche_conn *quic_conn,
uint64_t stream_id, const uint8_t *body, size_t body_len,
Expand Down
25 changes: 23 additions & 2 deletions quiche/src/h3/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,9 +188,9 @@ pub extern fn quiche_h3_event_for_each_header(
}

#[no_mangle]
pub extern fn quiche_h3_event_headers_has_body(ev: &h3::Event) -> bool {
pub extern fn quiche_h3_event_headers_has_more_frames(ev: &h3::Event) -> bool {
match ev {
h3::Event::Headers { has_body, .. } => *has_body,
h3::Event::Headers { more_frames, .. } => *more_frames,

_ => unreachable!(),
}
Expand Down Expand Up @@ -265,6 +265,27 @@ pub extern fn quiche_h3_send_response_with_priority(
}
}

#[no_mangle]
pub extern fn quiche_h3_send_additional_headers(
conn: &mut h3::Connection, quic_conn: &mut Connection, stream_id: u64,
headers: *const Header, headers_len: size_t, is_trailer_section: bool,
fin: bool,
) -> c_int {
let headers = headers_from_ptr(headers, headers_len);

match conn.send_additional_headers(
quic_conn,
stream_id,
&headers,
is_trailer_section,
fin,
) {
Ok(_) => 0,

Err(e) => e.to_c() as c_int,
}
}

#[no_mangle]
pub extern fn quiche_h3_send_body(
conn: &mut h3::Connection, quic_conn: &mut Connection, stream_id: u64,
Expand Down
Loading

0 comments on commit 2514d58

Please sign in to comment.