New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add a ConnContext to the quic.Config, remove it from the http3.Server #4422
Comments
I'm actually not sure how we'd implement this. Currently, we use the stream context: Lines 546 to 555 in da410a7
This seems to be the right thing to do, because the request is inherently bound to the stream. If we want to implement this change, we'd need a context that derives from both the stream and the connection, which is not possible. Any ideas @mattrobenolt? |
Yeah, I'd suspect that's correct. You'd want one originating at the Connection itself, each Stream derives from that. Not speaking about logistic for the implementation, but conceptually that's my expectation. Connection -> Stream -> Request Context is "forked" at each of those. Each Stream inherits from the Connection, and each Request inherits from the Stream. Am I right in that each Stream is 1 HTTP3 request? Or can one Stream handle multiple HTTP3 requests? |
The problem here is that we're dealing with the HTTP/3 layer, but streams are opened on the QUIC layer. Maybe that's the solution: We should add a Unfortunately, this is a much bigger change, and we might want to implement #3862 first (but maybe not strictly necessary?). |
I would agree, it would naturally be a better hook on the quic layer. I'm curious how this will translate over to |
Thinking about this more, I don't think this is even necessary. The API will be more useful, but it's pretty much orthogonal to this issue.
Oh well, nothing we have to worry about here :) |
A simple way to implement the original idea would be to use
Then in
Arguably, the other values could also be set in handleConn. |
Nevermind. My suggestion won't work. The only way this can work is if the stream ctx is tied to the conn ctx. |
I opened two PRs, #4507 and #4510. #4507 adds a @mattrobenolt @rthellend Could you take a look at these PRs, and maybe even try them out? |
The problem with #4510 is that the context in the The solution needs to satisfy these requirements:
The current implementation satisfies these requirements. What we're adding is a new requirement that says To me, that means that:
Part 2 can be done at the quic level or at the http3 level, depending on how part 1 is implemented. It's possible that #4507 is doing the implementation at the quic level, but I'll need more time to understand what it is doing. |
I think #4507 would be an improvement, but it wouldn't help my use-case. The ctx is buried too deep in the quic implementation. I have an alternative suggestion. It looks like the connection's context is used as base context for the streams. So, if we added a diff --git a/http3/server.go b/http3/server.go
index 4042da33..8372955a 100644
--- a/http3/server.go
+++ b/http3/server.go
@@ -422,6 +422,15 @@ func (s *Server) removeListener(l *QUICEarlyListener) {
}
func (s *Server) handleConn(conn quic.Connection) error {
+ ctx := context.WithValue(conn.Context(), ServerContextKey, s)
+ if s.ConnContext != nil {
+ ctx = s.ConnContext(ctx, conn)
+ if ctx == nil {
+ panic("http3: ConnContext returned nil")
+ }
+ }
+ conn = conn.WithContext(ctx)
+
// send a SETTINGS frame
str, err := conn.OpenUniStream()
if err != nil {
@@ -534,15 +543,8 @@ func (s *Server) handleRequest(conn *connection, str quic.Stream, datagrams *dat
}
ctx := str.Context()
- ctx = context.WithValue(ctx, ServerContextKey, s)
ctx = context.WithValue(ctx, http.LocalAddrContextKey, conn.LocalAddr())
ctx = context.WithValue(ctx, RemoteAddrContextKey, conn.RemoteAddr())
- if s.ConnContext != nil {
- ctx = s.ConnContext(ctx, conn.Connection)
- if ctx == nil {
- panic("http3: ConnContext returned nil")
- }
- }
req = req.WithContext(ctx)
r := newResponseWriter(hstr, conn, req.Method == http.MethodHead, s.Logger)
handler := s.Handler Edit: it might be easier to implement a |
This never properly worked. The context was derived from the send side of the stream, but you really want it to be derived from the receive side of the stream (which doesn't have a context though). #4510 removes the incorrect behavior, and the proper fix is tracked in #4508.
This doesn't work. The connections I don't understand where the requirement comes from that the request context is derived from the stream's context. Yes, we need to get cancellation right (see #4508), but we can do this at the HTTP/3 layer. In fact, there's no way around that, since the request needs to be cancelled when |
I wasn't aware that it wasn't working correctly. The point remains though. The Request context must be canceled when the stream is closed (i.e. when we can't send the response to the client anymore). That's usually done by making the request context a descendant of the stream context, but you're right, there are other ways to make it work.
Which part doesn't work? If we want to call
The |
For sure, and we won't release anything that would break this. That's why #4508 is included in the next milestone. I'll also make sure to add an extra integration test for this. Just trying to disentangle things a bit to keep PRs to a manageable size, sorry for the confusion created.
The QUIC layer would call
Ok, let me prepare a fix for #4508, building on top of the other two PRs. Then we can see if all the parts work together as I imagine it right now. Would be great if you could test it again then! :) |
As pointed out by @mattrobenolt in #4230 (comment),
ConnContext
should only be called once after the QUIC connection has been accepted.Currently blocked on the http3 refactor for #3522.
The text was updated successfully, but these errors were encountered: