h2 icon indicating copy to clipboard operation
h2 copied to clipboard

expose information about negotiated connection settings

Open hawkw opened this issue 4 years ago • 5 comments

h2 currently permits configuring most of the HTTP/2 protocol settings that are negotiated with the remote peer; for example, the client builder can configure settings like maximum frame size, maximum concurrent streams, etc.

However, once a connection is established, there's no way to access information about the settings that were negotiated with a remote peer, besides information about stream flow control. For example, in my particular use case, we would like to be able to record the max concurrent streams limit set by the server after initiating a client connection. It would be great to add some kind of API for querying connection-level settings that were received from a remote peer.

hawkw avatar Feb 03 '21 19:02 hawkw

I'd be happy to work on this, but I'd love to get input on API design --- cc @seanmonstar.

hawkw avatar Feb 03 '21 19:02 hawkw

Seems reasonable. My first instinct is to add getters to Connection.

seanmonstar avatar Feb 03 '21 22:02 seanmonstar

Seems reasonable. My first instinct is to add getters to Connection.

Hmm, that was my initial thought as well. I suppose the downside is that the Connection type is usually spawned immediately, so users need to access that information immediately. Probably not a huge issue.

hawkw avatar Feb 04 '21 19:02 hawkw

current implementation still does not return the remote max_send_streams. I am not a maintainer but see two ways to solve it:

  • provide state machine API for Connection when the negotiated settings are received, example:
let (h2, connection) = client::Builder::new().initial_max_send_streams(1000000).handshake(tcp).await?;
let settings_negotiated = connection.await.unwrap();
tokio::spawn(async move {
   settings_negotiated.await.unwrap();
});
  • or somehow include such functionality in h2.ready(), example:
let (h2, connection) = client::Builder::new().initial_max_send_streams(1000000).handshake(tcp).await?;
tokio::spawn(async move {
   connection.await.unwrap();
});
let mut h2 = h2.ready().await?;
// in current implementation, max_send_streams may not be populated at this particular line
// adding tokio::time::sleep() helps, but it is ugly
h2.max_send_streams();

Yneth avatar Oct 14 '22 19:10 Yneth

@Yneth maybe it makes sense to use ready as a signal that the data is ready then use global getters that return an Option<&ConfigItem>. Could maybe use something like a oncecell?

LucioFranco avatar Oct 17 '22 18:10 LucioFranco