|
@@ -213,6 +213,13 @@ func ConfigureServer(s *http.Server, conf *Server) error {
|
|
|
return nil
|
|
return nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// h1ServerShutdownChan if non-nil provides a func to return a channel
|
|
|
|
|
+// that will be closed when the provided *http.Server wants to shut
|
|
|
|
|
+// down. This is initialized via an init func in net/http (via its
|
|
|
|
|
+// mangled name from x/tools/cmd/bundle). This is only used when http2
|
|
|
|
|
+// is bundled into std for now.
|
|
|
|
|
+var h1ServerShutdownChan func(*http.Server) <-chan struct{}
|
|
|
|
|
+
|
|
|
// ServeConnOpts are options for the Server.ServeConn method.
|
|
// ServeConnOpts are options for the Server.ServeConn method.
|
|
|
type ServeConnOpts struct {
|
|
type ServeConnOpts struct {
|
|
|
// BaseConfig optionally sets the base configuration
|
|
// BaseConfig optionally sets the base configuration
|
|
@@ -710,6 +717,11 @@ func (sc *serverConn) serve() {
|
|
|
sc.idleTimerCh = sc.idleTimer.C
|
|
sc.idleTimerCh = sc.idleTimer.C
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ var gracefulShutdownCh <-chan struct{}
|
|
|
|
|
+ if sc.hs != nil && h1ServerShutdownChan != nil {
|
|
|
|
|
+ gracefulShutdownCh = h1ServerShutdownChan(sc.hs)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
go sc.readFrames() // closed by defer sc.conn.Close above
|
|
go sc.readFrames() // closed by defer sc.conn.Close above
|
|
|
|
|
|
|
|
settingsTimer := time.NewTimer(firstSettingsTimeout)
|
|
settingsTimer := time.NewTimer(firstSettingsTimeout)
|
|
@@ -737,6 +749,9 @@ func (sc *serverConn) serve() {
|
|
|
case <-settingsTimer.C:
|
|
case <-settingsTimer.C:
|
|
|
sc.logf("timeout waiting for SETTINGS frames from %v", sc.conn.RemoteAddr())
|
|
sc.logf("timeout waiting for SETTINGS frames from %v", sc.conn.RemoteAddr())
|
|
|
return
|
|
return
|
|
|
|
|
+ case <-gracefulShutdownCh:
|
|
|
|
|
+ gracefulShutdownCh = nil
|
|
|
|
|
+ sc.goAwayIn(ErrCodeNo, 0)
|
|
|
case <-sc.shutdownTimerCh:
|
|
case <-sc.shutdownTimerCh:
|
|
|
sc.vlogf("GOAWAY close timer fired; closing conn from %v", sc.conn.RemoteAddr())
|
|
sc.vlogf("GOAWAY close timer fired; closing conn from %v", sc.conn.RemoteAddr())
|
|
|
return
|
|
return
|
|
@@ -746,6 +761,10 @@ func (sc *serverConn) serve() {
|
|
|
case fn := <-sc.testHookCh:
|
|
case fn := <-sc.testHookCh:
|
|
|
fn(loopNum)
|
|
fn(loopNum)
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ if sc.inGoAway && sc.curClientStreams == 0 && !sc.needToSendGoAway && !sc.writingFrame {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -1018,7 +1037,7 @@ func (sc *serverConn) scheduleFrameWrite() {
|
|
|
sc.startFrameWrite(FrameWriteRequest{write: writeSettingsAck{}})
|
|
sc.startFrameWrite(FrameWriteRequest{write: writeSettingsAck{}})
|
|
|
continue
|
|
continue
|
|
|
}
|
|
}
|
|
|
- if !sc.inGoAway {
|
|
|
|
|
|
|
+ if !sc.inGoAway || sc.goAwayCode == ErrCodeNo {
|
|
|
if wr, ok := sc.writeSched.Pop(); ok {
|
|
if wr, ok := sc.writeSched.Pop(); ok {
|
|
|
sc.startFrameWrite(wr)
|
|
sc.startFrameWrite(wr)
|
|
|
continue
|
|
continue
|
|
@@ -1036,14 +1055,23 @@ func (sc *serverConn) scheduleFrameWrite() {
|
|
|
|
|
|
|
|
func (sc *serverConn) goAway(code ErrCode) {
|
|
func (sc *serverConn) goAway(code ErrCode) {
|
|
|
sc.serveG.check()
|
|
sc.serveG.check()
|
|
|
- if sc.inGoAway {
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ var forceCloseIn time.Duration
|
|
|
if code != ErrCodeNo {
|
|
if code != ErrCodeNo {
|
|
|
- sc.shutDownIn(250 * time.Millisecond)
|
|
|
|
|
|
|
+ forceCloseIn = 250 * time.Millisecond
|
|
|
} else {
|
|
} else {
|
|
|
// TODO: configurable
|
|
// TODO: configurable
|
|
|
- sc.shutDownIn(1 * time.Second)
|
|
|
|
|
|
|
+ forceCloseIn = 1 * time.Second
|
|
|
|
|
+ }
|
|
|
|
|
+ sc.goAwayIn(code, forceCloseIn)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func (sc *serverConn) goAwayIn(code ErrCode, forceCloseIn time.Duration) {
|
|
|
|
|
+ sc.serveG.check()
|
|
|
|
|
+ if sc.inGoAway {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ if forceCloseIn != 0 {
|
|
|
|
|
+ sc.shutDownIn(forceCloseIn)
|
|
|
}
|
|
}
|
|
|
sc.inGoAway = true
|
|
sc.inGoAway = true
|
|
|
sc.needToSendGoAway = true
|
|
sc.needToSendGoAway = true
|