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 committed Sep 6, 2022
1 parent 3131c0d commit 897e019
Show file tree
Hide file tree
Showing 6 changed files with 610 additions and 107 deletions.
2 changes: 1 addition & 1 deletion nginx/nginx-1.16.patch
Original file line number Diff line number Diff line change
Expand Up @@ -1921,7 +1921,7 @@ index 000000000..1a05d4e01
+ 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 @@ -824,8 +824,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);

// Frees the HTTP/3 event object.
void quiche_h3_event_free(quiche_h3_event *ev);
Expand Down Expand Up @@ -860,6 +860,12 @@ int quiche_h3_send_response_with_priority(quiche_h3_conn *conn,
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 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, uint8_t *body, size_t body_len,
Expand Down
18 changes: 16 additions & 2 deletions quiche/src/h3/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,9 +183,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 @@ -253,6 +253,20 @@ 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, fin: bool,
) -> c_int {
let headers = headers_from_ptr(headers, headers_len);

match conn.send_additional_headers(quic_conn, stream_id, &headers, 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 897e019

Please sign in to comment.