pub struct Connection { /* private fields */ }Expand description
One HTTP/2 connection, either end.
Implementations§
Source§impl Connection
impl Connection
Sourcepub fn server(cfg: Config) -> Connection
pub fn server(cfg: Config) -> Connection
A server connection. It expects the client preface; its own SETTINGS are already in
Connection::output.
Examples found in repository?
24fn pair() -> (Connection, Connection, Vec<u8>) {
25 let cfg = Config { window_autotune: false, ..Config::default() };
26 let mut c = Connection::client(cfg.clone());
27 let mut s = Connection::server(cfg);
28 let mut buf = Vec::with_capacity(64 * 1024);
29 for _ in 0..3 {
30 transfer(&mut c, &mut buf);
31 s.recv(&buf, 0, &mut |_| {});
32 transfer(&mut s, &mut buf);
33 c.recv(&buf, 0, &mut |_| {});
34 }
35 (c, s, buf)
36}Sourcepub fn client(cfg: Config) -> Connection
pub fn client(cfg: Config) -> Connection
A client connection (h2c prior knowledge, or h2 after ALPN). The preface and SETTINGS are
already in Connection::output, and requests can be sent at once.
Examples found in repository?
24fn pair() -> (Connection, Connection, Vec<u8>) {
25 let cfg = Config { window_autotune: false, ..Config::default() };
26 let mut c = Connection::client(cfg.clone());
27 let mut s = Connection::server(cfg);
28 let mut buf = Vec::with_capacity(64 * 1024);
29 for _ in 0..3 {
30 transfer(&mut c, &mut buf);
31 s.recv(&buf, 0, &mut |_| {});
32 transfer(&mut s, &mut buf);
33 c.recv(&buf, 0, &mut |_| {});
34 }
35 (c, s, buf)
36}Sourcepub fn server_upgrade(
cfg: Config,
http2_settings: &[u8],
) -> Result<Connection, Error>
pub fn server_upgrade( cfg: Config, http2_settings: &[u8], ) -> Result<Connection, Error>
A server connection after an HTTP/1.1 Upgrade: h2c request (RFC 7540 §3.2) was
answered with 101 Switching Protocols. http2_settings is the request’s
HTTP2-Settings value. The request itself becomes stream 1, half-closed (remote) with
its handler running: answer it with Connection::send_response on stream 1.
Sourcepub fn client_upgrade(cfg: Config, head: bool) -> Connection
pub fn client_upgrade(cfg: Config, head: bool) -> Connection
A client connection after the server answered our HTTP/1.1 Upgrade: h2c request with
101. The upgrade request is stream 1, half-closed (local); its response arrives as
events for stream 1. head says whether that request was HEAD.
Sourcepub fn take_output(&mut self, empty: Vec<u8>) -> Vec<u8> ⓘ
pub fn take_output(&mut self, empty: Vec<u8>) -> Vec<u8> ⓘ
Takes every byte of Connection::output as an owned buffer (no copy), leaving
empty (cleared) to collect the next output. Same as reading output() and calling
advance_output with its length.
Sourcepub fn advance_output(&mut self, n: usize)
pub fn advance_output(&mut self, n: usize)
Marks n bytes of Connection::output as written.
Sourcepub fn wants_close(&self) -> bool
pub fn wants_close(&self) -> bool
True when the transport should be closed once Connection::output is flushed: after a
connection error, or after a GOAWAY (sent or received) once every stream is done.
Sourcepub fn close_code(&self) -> Option<ErrorCode>
pub fn close_code(&self) -> Option<ErrorCode>
The error code of the GOAWAY we closed the connection with.
Sourcepub fn active_handlers(&self) -> u32
pub fn active_handlers(&self) -> u32
Streams whose handler work is still running (server).
Sourcepub fn open_streams(&self) -> u32
pub fn open_streams(&self) -> u32
Streams open or half-closed.
Sourcepub fn tracked_streams(&self) -> usize
pub fn tracked_streams(&self) -> usize
Streams the engine still tracks (open, or closed with work running).
Examples found in repository?
66fn bench_requests(streams: usize, total: usize) -> f64 {
67 let (mut c, mut s, mut buf) = pair();
68 let mut ids = Vec::with_capacity(streams);
69 // warm up (tables, buffers)
70 for _ in 0..100 {
71 batch(&mut c, &mut s, &mut buf, &mut ids, streams);
72 }
73 let rounds = total / streams;
74 let t = Instant::now();
75 let mut got = 0;
76 for _ in 0..rounds {
77 got += batch(&mut c, &mut s, &mut buf, &mut ids, streams);
78 }
79 let ns = t.elapsed().as_nanos() as f64 / (rounds * streams) as f64;
80 assert_eq!(got, rounds * streams * BODY.len());
81 assert_eq!(s.tracked_streams(), 0);
82 ns
83}Sourcepub fn peer_max_concurrent_streams(&self) -> u32
pub fn peer_max_concurrent_streams(&self) -> u32
The peer’s SETTINGS_MAX_CONCURRENT_STREAMS.
Sourcepub fn can_open_stream(&self) -> bool
pub fn can_open_stream(&self) -> bool
True when a client may open another stream now.
Sourcepub fn send_capacity(&self, stream: u32) -> usize
pub fn send_capacity(&self, stream: u32) -> usize
Bytes stream may send now: the smaller of its window, the connection window and the
room in the output buffer.
Sourcepub fn receive_windows(&self) -> (u32, u32)
pub fn receive_windows(&self) -> (u32, u32)
The connection’s current receive targets (connection, per stream), after auto-tuning.
Sourcepub fn poll_timeout(&self) -> Option<u64>
pub fn poll_timeout(&self) -> Option<u64>
The next deadline (settings acknowledgement, graceful shutdown) for
Connection::handle_timeout.
Sourcepub fn handle_timeout(&mut self, now: u64, sink: &mut dyn FnMut(Event<'_>))
pub fn handle_timeout(&mut self, now: u64, sink: &mut dyn FnMut(Event<'_>))
Fires due timers.
Sourcepub fn recv(
&mut self,
input: &[u8],
now: u64,
sink: &mut dyn FnMut(Event<'_>),
) -> usize
pub fn recv( &mut self, input: &[u8], now: u64, sink: &mut dyn FnMut(Event<'_>), ) -> usize
Processes received bytes at time now (monotonic milliseconds from any origin).
Returns how many bytes were consumed; the caller keeps the rest and passes it again with
more data. A buffer of max_frame_size + 9 bytes always makes progress. Input processing
pauses (returns early) while more than twice max_send_buffer of output is waiting, so a
peer that does not read cannot make us queue unbounded replies. After the connection is
closed all input is consumed and ignored.
Examples found in repository?
24fn pair() -> (Connection, Connection, Vec<u8>) {
25 let cfg = Config { window_autotune: false, ..Config::default() };
26 let mut c = Connection::client(cfg.clone());
27 let mut s = Connection::server(cfg);
28 let mut buf = Vec::with_capacity(64 * 1024);
29 for _ in 0..3 {
30 transfer(&mut c, &mut buf);
31 s.recv(&buf, 0, &mut |_| {});
32 transfer(&mut s, &mut buf);
33 c.recv(&buf, 0, &mut |_| {});
34 }
35 (c, s, buf)
36}
37
38/// One batch: `streams` requests out, responses back. Returns body bytes received.
39fn batch(c: &mut Connection, s: &mut Connection, buf: &mut Vec<u8>, ids: &mut Vec<u32>, streams: usize) -> usize {
40 for _ in 0..streams {
41 c.send_request(b"GET", b"https", b"example.com", b"/hello", &[(b"user-agent", b"simoom-bench"), (b"accept", b"*/*")], true).unwrap();
42 }
43 transfer(c, buf);
44 ids.clear();
45 let n = s.recv(buf, 0, &mut |e| {
46 if let Event::Headers { stream, .. } = e {
47 ids.push(stream);
48 }
49 });
50 debug_assert_eq!(n, buf.len());
51 for &id in ids.iter() {
52 s.send_response(id, 200, &[(b"content-type", b"text/plain")], false).unwrap();
53 s.send_data(id, BODY, true).unwrap();
54 s.stream_finished(id);
55 }
56 transfer(s, buf);
57 let mut got = 0;
58 c.recv(buf, 0, &mut |e| {
59 if let Event::Data { data, .. } = e {
60 got += data.len();
61 }
62 });
63 got
64}Sourcepub fn release(&mut self, stream: u32, n: usize)
pub fn release(&mut self, stream: u32, n: usize)
Tells the engine the application consumed n bytes of DATA on stream, so the peer may
send more. Releasing more than was delivered is ignored.
Sourcepub fn peer_max_header_list_size(&self) -> u32
pub fn peer_max_header_list_size(&self) -> u32
The peer’s SETTINGS_MAX_HEADER_LIST_SIZE (u32::MAX until it announces one).
Sourcepub fn peer_connect_protocol(&self) -> bool
pub fn peer_connect_protocol(&self) -> bool
The peer (a server) allows extended CONNECT: it sent SETTINGS_ENABLE_CONNECT_PROTOCOL
= 1 (RFC 8441 §3). Known once its SETTINGS arrived (Event::Settings).
Sourcepub fn send_extended_connect(
&mut self,
protocol: &[u8],
scheme: &[u8],
authority: &[u8],
path: &[u8],
fields: &[(&[u8], &[u8])],
) -> Result<u32, Error>
pub fn send_extended_connect( &mut self, protocol: &[u8], scheme: &[u8], authority: &[u8], path: &[u8], fields: &[(&[u8], &[u8])], ) -> Result<u32, Error>
Client: opens an extended CONNECT stream (RFC 8441 §4), for example with
protocol = b"websocket" for WebSocket over HTTP/2 (RFC 8441 §5). The stream stays open
both ways; a 2xx response accepts the tunnel, whose bytes then travel as DATA. Fails with
Error::ConnectProtocolDisabled unless the server enabled extended CONNECT.
Sourcepub fn send_response(
&mut self,
stream: u32,
status: u16,
fields: &[(&[u8], &[u8])],
end_stream: bool,
) -> Result<(), Error>
pub fn send_response( &mut self, stream: u32, status: u16, fields: &[(&[u8], &[u8])], end_stream: bool, ) -> Result<(), Error>
Server: sends response headers on stream. A status below 200 sends an informational
response (101 is not allowed in HTTP/2); then the final one follows.
Examples found in repository?
39fn batch(c: &mut Connection, s: &mut Connection, buf: &mut Vec<u8>, ids: &mut Vec<u32>, streams: usize) -> usize {
40 for _ in 0..streams {
41 c.send_request(b"GET", b"https", b"example.com", b"/hello", &[(b"user-agent", b"simoom-bench"), (b"accept", b"*/*")], true).unwrap();
42 }
43 transfer(c, buf);
44 ids.clear();
45 let n = s.recv(buf, 0, &mut |e| {
46 if let Event::Headers { stream, .. } = e {
47 ids.push(stream);
48 }
49 });
50 debug_assert_eq!(n, buf.len());
51 for &id in ids.iter() {
52 s.send_response(id, 200, &[(b"content-type", b"text/plain")], false).unwrap();
53 s.send_data(id, BODY, true).unwrap();
54 s.stream_finished(id);
55 }
56 transfer(s, buf);
57 let mut got = 0;
58 c.recv(buf, 0, &mut |e| {
59 if let Event::Data { data, .. } = e {
60 got += data.len();
61 }
62 });
63 got
64}Sourcepub fn send_request(
&mut self,
method: &[u8],
scheme: &[u8],
authority: &[u8],
path: &[u8],
fields: &[(&[u8], &[u8])],
end_stream: bool,
) -> Result<u32, Error>
pub fn send_request( &mut self, method: &[u8], scheme: &[u8], authority: &[u8], path: &[u8], fields: &[(&[u8], &[u8])], end_stream: bool, ) -> Result<u32, Error>
Client: opens a stream with a request. authority may be empty; path is ignored for
CONNECT. Returns the new stream id.
Examples found in repository?
39fn batch(c: &mut Connection, s: &mut Connection, buf: &mut Vec<u8>, ids: &mut Vec<u32>, streams: usize) -> usize {
40 for _ in 0..streams {
41 c.send_request(b"GET", b"https", b"example.com", b"/hello", &[(b"user-agent", b"simoom-bench"), (b"accept", b"*/*")], true).unwrap();
42 }
43 transfer(c, buf);
44 ids.clear();
45 let n = s.recv(buf, 0, &mut |e| {
46 if let Event::Headers { stream, .. } = e {
47 ids.push(stream);
48 }
49 });
50 debug_assert_eq!(n, buf.len());
51 for &id in ids.iter() {
52 s.send_response(id, 200, &[(b"content-type", b"text/plain")], false).unwrap();
53 s.send_data(id, BODY, true).unwrap();
54 s.stream_finished(id);
55 }
56 transfer(s, buf);
57 let mut got = 0;
58 c.recv(buf, 0, &mut |e| {
59 if let Event::Data { data, .. } = e {
60 got += data.len();
61 }
62 });
63 got
64}Sourcepub fn send_trailers(
&mut self,
stream: u32,
fields: &[(&[u8], &[u8])],
) -> Result<(), Error>
pub fn send_trailers( &mut self, stream: u32, fields: &[(&[u8], &[u8])], ) -> Result<(), Error>
Sends trailers, ending the stream.
Sourcepub fn send_data(
&mut self,
stream: u32,
data: &[u8],
end_stream: bool,
) -> Result<usize, Error>
pub fn send_data( &mut self, stream: u32, data: &[u8], end_stream: bool, ) -> Result<usize, Error>
Sends body bytes on stream, as much as the stream window, the connection window and
the output buffer cap allow. Returns how many bytes were accepted; end_stream applies
only when all of data was accepted. When fewer were accepted the stream is remembered,
and Connection::poll_writable reports it once it can send again.
Examples found in repository?
39fn batch(c: &mut Connection, s: &mut Connection, buf: &mut Vec<u8>, ids: &mut Vec<u32>, streams: usize) -> usize {
40 for _ in 0..streams {
41 c.send_request(b"GET", b"https", b"example.com", b"/hello", &[(b"user-agent", b"simoom-bench"), (b"accept", b"*/*")], true).unwrap();
42 }
43 transfer(c, buf);
44 ids.clear();
45 let n = s.recv(buf, 0, &mut |e| {
46 if let Event::Headers { stream, .. } = e {
47 ids.push(stream);
48 }
49 });
50 debug_assert_eq!(n, buf.len());
51 for &id in ids.iter() {
52 s.send_response(id, 200, &[(b"content-type", b"text/plain")], false).unwrap();
53 s.send_data(id, BODY, true).unwrap();
54 s.stream_finished(id);
55 }
56 transfer(s, buf);
57 let mut got = 0;
58 c.recv(buf, 0, &mut |e| {
59 if let Event::Data { data, .. } = e {
60 got += data.len();
61 }
62 });
63 got
64}Sourcepub fn poll_writable(&mut self) -> Option<u32>
pub fn poll_writable(&mut self) -> Option<u32>
A stream that was short of capacity in Connection::send_data and can send again.
Call it after Connection::recv and Connection::advance_output until it returns
None.
Sourcepub fn reset(&mut self, stream: u32, code: ErrorCode)
pub fn reset(&mut self, stream: u32, code: ErrorCode)
Resets stream with code at the application’s request.
Sourcepub fn stream_finished(&mut self, stream: u32)
pub fn stream_finished(&mut self, stream: u32)
The application’s work for stream is finished: it no longer counts against the
concurrency limit. A stream we have not ended is reset with CANCEL; a request body that
was not read to the end is cut off with RST_STREAM(NO_ERROR) (RFC 9113 §8.1).
Examples found in repository?
39fn batch(c: &mut Connection, s: &mut Connection, buf: &mut Vec<u8>, ids: &mut Vec<u32>, streams: usize) -> usize {
40 for _ in 0..streams {
41 c.send_request(b"GET", b"https", b"example.com", b"/hello", &[(b"user-agent", b"simoom-bench"), (b"accept", b"*/*")], true).unwrap();
42 }
43 transfer(c, buf);
44 ids.clear();
45 let n = s.recv(buf, 0, &mut |e| {
46 if let Event::Headers { stream, .. } = e {
47 ids.push(stream);
48 }
49 });
50 debug_assert_eq!(n, buf.len());
51 for &id in ids.iter() {
52 s.send_response(id, 200, &[(b"content-type", b"text/plain")], false).unwrap();
53 s.send_data(id, BODY, true).unwrap();
54 s.stream_finished(id);
55 }
56 transfer(s, buf);
57 let mut got = 0;
58 c.recv(buf, 0, &mut |e| {
59 if let Event::Data { data, .. } = e {
60 got += data.len();
61 }
62 });
63 got
64}Sourcepub fn ping(&mut self, data: [u8; 8])
pub fn ping(&mut self, data: [u8; 8])
Sends a PING; the answer arrives as Event::Pong.
Sourcepub fn shutdown(&mut self, now: u64)
pub fn shutdown(&mut self, now: u64)
Starts a graceful shutdown (RFC 9113 §6.8). A server sends GOAWAY with the largest
stream id and a PING, then, after the PING round trip (or graceful_timeout_ms), the
final GOAWAY with the last stream it accepted. Streams already accepted run to the end;
Connection::wants_close turns true when they are done.