Commit cd8c2701 authored by Brad Fitzpatrick's avatar Brad Fitzpatrick

http2: add support for net/http.Server.ConnState tracking

This is required to work with the upcoming rewrite of the
httptest.Server's connection tracking in
https://go-review.googlesource.com/#/c/15151/
which (at least as of patchset 7) doesn't forcefully tear
down a StateNew connection during Server.Wait. That might
change.

In any case, this adds support for ConnState, which users would
expect regardless of protocol in a mixed HTTP/1 and HTTP/2
environment.

Change-Id: I124aafec29dda123a018935fa306f465ae99cd97
Reviewed-on: https://go-review.googlesource.com/15913Reviewed-by: 's avatarAndrew Gerrand <adg@golang.org>
parent 21c3935a
......@@ -443,6 +443,15 @@ func (sc *serverConn) state(streamID uint32) (streamState, *stream) {
return stateIdle, nil
}
// setConnState calls the net/http ConnState hook for this connection, if configured.
// Note that the net/http package does StateNew and StateClosed for us.
// There is currently no plan for StateHijacked or hijacking HTTP/2 connections.
func (sc *serverConn) setConnState(state http.ConnState) {
if sc.hs.ConnState != nil {
sc.hs.ConnState(sc.conn, state)
}
}
func (sc *serverConn) vlogf(format string, args ...interface{}) {
if VerboseLogs {
sc.logf(format, args...)
......@@ -640,6 +649,12 @@ func (sc *serverConn) serve() {
sc.condlogf(err, "error reading preface from client %v: %v", sc.conn.RemoteAddr(), err)
return
}
// Now that we've got the preface, get us out of the
// "StateNew" state. We can't go directly to idle, though.
// Active means we read some data and anticipate a request. We'll
// do another Active when we get a HEADERS frame.
sc.setConnState(http.StateActive)
sc.setConnState(http.StateIdle)
go sc.readFrames() // closed by defer sc.conn.Close above
......@@ -1087,6 +1102,9 @@ func (sc *serverConn) closeStream(st *stream, err error) {
}
st.state = stateClosed
sc.curOpenStreams--
if sc.curOpenStreams == 0 {
sc.setConnState(http.StateIdle)
}
delete(sc.streams, st.id)
if p := st.body; p != nil {
p.Close(err)
......@@ -1263,6 +1281,9 @@ func (sc *serverConn) processHeaders(f *HeadersFrame) error {
adjustStreamPriority(sc.streams, st.id, f.Priority)
}
sc.curOpenStreams++
if sc.curOpenStreams == 1 {
sc.setConnState(http.StateActive)
}
sc.req = requestParam{
stream: st,
header: make(http.Header),
......
......@@ -41,7 +41,7 @@ func TestTransport(t *testing.T) {
const body = "sup"
st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, body)
})
}, optOnlyServer)
defer st.Close()
tr := &Transport{InsecureTLSDial: true}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment