@@ -292,7 +292,7 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
292
292
streams : make (map [uint32 ]* stream ),
293
293
readFrameCh : make (chan readFrameResult ),
294
294
wantWriteFrameCh : make (chan FrameWriteRequest , 8 ),
295
- wantStartPushCh : make (chan startPushRequest , 8 ),
295
+ serveMsgCh : make (chan interface {} , 8 ),
296
296
wroteFrameCh : make (chan frameWriteResult , 1 ), // buffered; one send in writeFrameAsync
297
297
bodyReadCh : make (chan bodyReadMsg ), // buffering doesn't matter either way
298
298
doneServing : make (chan struct {}),
@@ -405,10 +405,9 @@ type serverConn struct {
405
405
doneServing chan struct {} // closed when serverConn.serve ends
406
406
readFrameCh chan readFrameResult // written by serverConn.readFrames
407
407
wantWriteFrameCh chan FrameWriteRequest // from handlers -> serve
408
- wantStartPushCh chan startPushRequest // from handlers -> serve
409
408
wroteFrameCh chan frameWriteResult // from writeFrameAsync -> serve, tickles more frame writes
410
409
bodyReadCh chan bodyReadMsg // from handlers -> serve
411
- testHookCh chan func ( int ) // code to run on the serve loop
410
+ serveMsgCh chan interface {} // misc messages & code to send to / run on the serve loop
412
411
flow flow // conn-wide (not stream-specific) outbound flow control
413
412
inflow flow // conn-wide inbound flow control
414
413
tlsState * tls.ConnectionState // shared by all handlers, like net/http
@@ -440,10 +439,8 @@ type serverConn struct {
440
439
inFrameScheduleLoop bool // whether we're in the scheduleFrameWrite loop
441
440
needToSendGoAway bool // we need to schedule a GOAWAY frame write
442
441
goAwayCode ErrCode
443
- shutdownTimerCh <- chan time.Time // nil until used
444
- shutdownTimer * time.Timer // nil until used
445
- idleTimer * time.Timer // nil if unused
446
- idleTimerCh <- chan time.Time // nil if unused
442
+ shutdownTimer * time.Timer // nil until used
443
+ idleTimer * time.Timer // nil if unused
447
444
448
445
// Owned by the writeFrameAsync goroutine:
449
446
headerWriteBuf bytes.Buffer
@@ -748,9 +745,8 @@ func (sc *serverConn) serve() {
748
745
sc .setConnState (http .StateIdle )
749
746
750
747
if sc .srv .IdleTimeout != 0 {
751
- sc .idleTimer = time .NewTimer (sc .srv .IdleTimeout )
748
+ sc .idleTimer = time .AfterFunc (sc .srv .IdleTimeout , sc . onIdleTimer )
752
749
defer sc .idleTimer .Stop ()
753
- sc .idleTimerCh = sc .idleTimer .C
754
750
}
755
751
756
752
var gracefulShutdownCh chan struct {}
@@ -764,7 +760,9 @@ func (sc *serverConn) serve() {
764
760
765
761
go sc .readFrames () // closed by defer sc.conn.Close above
766
762
767
- settingsTimer := time .NewTimer (firstSettingsTimeout )
763
+ settingsTimer := time .AfterFunc (firstSettingsTimeout , sc .onSettingsTimer )
764
+ defer settingsTimer .Stop ()
765
+
768
766
loopNum := 0
769
767
for {
770
768
loopNum ++
@@ -775,35 +773,45 @@ func (sc *serverConn) serve() {
775
773
break
776
774
}
777
775
sc .writeFrame (wr )
778
- case spr := <- sc .wantStartPushCh :
779
- sc .startPush (spr )
780
776
case res := <- sc .wroteFrameCh :
781
777
sc .wroteFrame (res )
782
778
case res := <- sc .readFrameCh :
783
779
if ! sc .processFrameFromReader (res ) {
784
780
return
785
781
}
786
782
res .readMore ()
787
- if settingsTimer . C != nil {
783
+ if settingsTimer != nil {
788
784
settingsTimer .Stop ()
789
- settingsTimer . C = nil
785
+ settingsTimer = nil
790
786
}
791
787
case m := <- sc .bodyReadCh :
792
788
sc .noteBodyRead (m .st , m .n )
793
- case <- settingsTimer .C :
794
- sc .logf ("timeout waiting for SETTINGS frames from %v" , sc .conn .RemoteAddr ())
795
- return
796
789
case <- gracefulShutdownCh :
797
790
gracefulShutdownCh = nil
798
791
sc .startGracefulShutdown ()
799
- case <- sc .shutdownTimerCh :
800
- sc .vlogf ("GOAWAY close timer fired; closing conn from %v" , sc .conn .RemoteAddr ())
801
- return
802
- case <- sc .idleTimerCh :
803
- sc .vlogf ("connection is idle" )
804
- sc .goAway (ErrCodeNo )
805
- case fn := <- sc .testHookCh :
806
- fn (loopNum )
792
+ case msg := <- sc .serveMsgCh :
793
+ switch v := msg .(type ) {
794
+ case func (int ):
795
+ v (loopNum ) // for testing
796
+ case * timerMessage :
797
+ switch v {
798
+ case settingsTimerMsg :
799
+ sc .logf ("timeout waiting for SETTINGS frames from %v" , sc .conn .RemoteAddr ())
800
+ return
801
+ case idleTimerMsg :
802
+ sc .vlogf ("connection is idle" )
803
+ sc .goAway (ErrCodeNo )
804
+ case shutdownTimerMsg :
805
+ sc .vlogf ("GOAWAY close timer fired; closing conn from %v" , sc .conn .RemoteAddr ())
806
+ return
807
+ default :
808
+ panic ("unknown timer" )
809
+ }
810
+ case * startPushRequest :
811
+ sc .startPush (v )
812
+ default :
813
+ panic (fmt .Sprintf ("unexpected type %T" , v ))
814
+ }
807
815
}
808
816
809
817
if sc .inGoAway && sc .curOpenStreams () == 0 && ! sc .needToSendGoAway && ! sc .writingFrame {
@@ -820,6 +828,27 @@ func (sc *serverConn) awaitGracefulShutdown(sharedCh <-chan struct{}, privateCh
820
828
}
821
829
}
822
830
831
+ type timerMessage int
832
+
833
+ // Timeout message values sent to serveMsgCh.
834
+ var (
835
+ settingsTimerMsg = new (timerMessage )
836
+ idleTimerMsg = new (timerMessage )
837
+ shutdownTimerMsg = new (timerMessage )
838
+ )
839
+
840
+ func (sc * serverConn ) onSettingsTimer () { sc .sendServeMsg (settingsTimerMsg ) }
841
+ func (sc * serverConn ) onIdleTimer () { sc .sendServeMsg (idleTimerMsg ) }
842
+ func (sc * serverConn ) onShutdownTimer () { sc .sendServeMsg (shutdownTimerMsg ) }
843
+
844
+ func (sc * serverConn ) sendServeMsg (msg interface {}) {
845
+ sc .serveG .checkNotOn () // NOT
846
+ select {
847
+ case sc .serveMsgCh <- msg :
848
+ case <- sc .doneServing :
849
+ }
850
+ }
851
+
823
852
// readPreface reads the ClientPreface greeting from the peer
824
853
// or returns an error on timeout or an invalid greeting.
825
854
func (sc * serverConn ) readPreface () error {
@@ -1172,8 +1201,7 @@ func (sc *serverConn) goAwayIn(code ErrCode, forceCloseIn time.Duration) {
1172
1201
1173
1202
func (sc * serverConn ) shutDownIn (d time.Duration ) {
1174
1203
sc .serveG .check ()
1175
- sc .shutdownTimer = time .NewTimer (d )
1176
- sc .shutdownTimerCh = sc .shutdownTimer .C
1204
+ sc .shutdownTimer = time .AfterFunc (d , sc .onShutdownTimer )
1177
1205
}
1178
1206
1179
1207
func (sc * serverConn ) resetStream (se StreamError ) {
@@ -2551,7 +2579,7 @@ func (w *responseWriter) push(target string, opts pushOptions) error {
2551
2579
return fmt .Errorf ("method %q must be GET or HEAD" , opts .Method )
2552
2580
}
2553
2581
2554
- msg := startPushRequest {
2582
+ msg := & startPushRequest {
2555
2583
parent : st ,
2556
2584
method : opts .Method ,
2557
2585
url : u ,
@@ -2564,7 +2592,7 @@ func (w *responseWriter) push(target string, opts pushOptions) error {
2564
2592
return errClientDisconnected
2565
2593
case <- st .cw :
2566
2594
return errStreamClosed
2567
- case sc .wantStartPushCh <- msg :
2595
+ case sc .serveMsgCh <- msg :
2568
2596
}
2569
2597
2570
2598
select {
@@ -2586,7 +2614,7 @@ type startPushRequest struct {
2586
2614
done chan error
2587
2615
}
2588
2616
2589
- func (sc * serverConn ) startPush (msg startPushRequest ) {
2617
+ func (sc * serverConn ) startPush (msg * startPushRequest ) {
2590
2618
sc .serveG .check ()
2591
2619
2592
2620
// http://tools.ietf.org/html/rfc7540#section-6.6.
0 commit comments