Browse Source

http2: handle pings in Transport

Change-Id: I50f7084bca2e5f7adb4cf278a32251f5bb239dbe
Reviewed-on: https://go-review.googlesource.com/16731
Reviewed-by: Blake Mizerany <blake.mizerany@gmail.com>
Brad Fitzpatrick 10 years ago
parent
commit
a179abb31d
3 changed files with 20 additions and 1 deletions
  1. 2 0
      http2/frame.go
  2. 1 1
      http2/server.go
  3. 17 0
      http2/transport.go

+ 2 - 0
http2/frame.go

@@ -574,6 +574,8 @@ type PingFrame struct {
 	Data [8]byte
 }
 
+func (f *PingFrame) IsAck() bool { return f.Flags.Has(FlagPingAck) }
+
 func parsePingFrame(fh FrameHeader, payload []byte) (Frame, error) {
 	if len(payload) != 8 {
 		return nil, ConnectionError(ErrCodeFrameSize)

+ 1 - 1
http2/server.go

@@ -1076,7 +1076,7 @@ func (sc *serverConn) processFrame(f Frame) error {
 
 func (sc *serverConn) processPing(f *PingFrame) error {
 	sc.serveG.check()
-	if f.Flags.Has(FlagSettingsAck) {
+	if f.IsAck() {
 		// 6.7 PING: " An endpoint MUST NOT respond to PING frames
 		// containing this flag."
 		return nil

+ 17 - 0
http2/transport.go

@@ -751,6 +751,8 @@ func (rl *clientConnReadLoop) run() error {
 			err = rl.processPushPromise(f)
 		case *WindowUpdateFrame:
 			err = rl.processWindowUpdate(f)
+		case *PingFrame:
+			err = rl.processPing(f)
 		default:
 			cc.logf("Transport: unhandled response frame type %T", f)
 		}
@@ -983,6 +985,21 @@ func (rl *clientConnReadLoop) processResetStream(f *RSTStreamFrame) error {
 	return nil
 }
 
+func (rl *clientConnReadLoop) processPing(f *PingFrame) error {
+	if f.IsAck() {
+		// 6.7 PING: " An endpoint MUST NOT respond to PING frames
+		// containing this flag."
+		return nil
+	}
+	cc := rl.cc
+	cc.wmu.Lock()
+	defer cc.wmu.Unlock()
+	if err := cc.fr.WritePing(true, f.Data); err != nil {
+		return err
+	}
+	return cc.bw.Flush()
+}
+
 func (rl *clientConnReadLoop) processPushPromise(f *PushPromiseFrame) error {
 	// We told the peer we don't want them.
 	// Spec says: