diff options
Diffstat (limited to 'vendor/golang.org/x/net/http2/transport.go')
-rw-r--r-- | vendor/golang.org/x/net/http2/transport.go | 66 |
1 files changed, 61 insertions, 5 deletions
diff --git a/vendor/golang.org/x/net/http2/transport.go b/vendor/golang.org/x/net/http2/transport.go index 54acc1e..76a92e0 100644 --- a/vendor/golang.org/x/net/http2/transport.go +++ b/vendor/golang.org/x/net/http2/transport.go | |||
@@ -108,6 +108,19 @@ type Transport struct { | |||
108 | // waiting for their turn. | 108 | // waiting for their turn. |
109 | StrictMaxConcurrentStreams bool | 109 | StrictMaxConcurrentStreams bool |
110 | 110 | ||
111 | // ReadIdleTimeout is the timeout after which a health check using ping | ||
112 | // frame will be carried out if no frame is received on the connection. | ||
113 | // Note that a ping response will is considered a received frame, so if | ||
114 | // there is no other traffic on the connection, the health check will | ||
115 | // be performed every ReadIdleTimeout interval. | ||
116 | // If zero, no health check is performed. | ||
117 | ReadIdleTimeout time.Duration | ||
118 | |||
119 | // PingTimeout is the timeout after which the connection will be closed | ||
120 | // if a response to Ping is not received. | ||
121 | // Defaults to 15s. | ||
122 | PingTimeout time.Duration | ||
123 | |||
111 | // t1, if non-nil, is the standard library Transport using | 124 | // t1, if non-nil, is the standard library Transport using |
112 | // this transport. Its settings are used (but not its | 125 | // this transport. Its settings are used (but not its |
113 | // RoundTrip method, etc). | 126 | // RoundTrip method, etc). |
@@ -131,6 +144,14 @@ func (t *Transport) disableCompression() bool { | |||
131 | return t.DisableCompression || (t.t1 != nil && t.t1.DisableCompression) | 144 | return t.DisableCompression || (t.t1 != nil && t.t1.DisableCompression) |
132 | } | 145 | } |
133 | 146 | ||
147 | func (t *Transport) pingTimeout() time.Duration { | ||
148 | if t.PingTimeout == 0 { | ||
149 | return 15 * time.Second | ||
150 | } | ||
151 | return t.PingTimeout | ||
152 | |||
153 | } | ||
154 | |||
134 | // ConfigureTransport configures a net/http HTTP/1 Transport to use HTTP/2. | 155 | // ConfigureTransport configures a net/http HTTP/1 Transport to use HTTP/2. |
135 | // It returns an error if t1 has already been HTTP/2-enabled. | 156 | // It returns an error if t1 has already been HTTP/2-enabled. |
136 | func ConfigureTransport(t1 *http.Transport) error { | 157 | func ConfigureTransport(t1 *http.Transport) error { |
@@ -675,6 +696,20 @@ func (t *Transport) newClientConn(c net.Conn, singleUse bool) (*ClientConn, erro | |||
675 | return cc, nil | 696 | return cc, nil |
676 | } | 697 | } |
677 | 698 | ||
699 | func (cc *ClientConn) healthCheck() { | ||
700 | pingTimeout := cc.t.pingTimeout() | ||
701 | // We don't need to periodically ping in the health check, because the readLoop of ClientConn will | ||
702 | // trigger the healthCheck again if there is no frame received. | ||
703 | ctx, cancel := context.WithTimeout(context.Background(), pingTimeout) | ||
704 | defer cancel() | ||
705 | err := cc.Ping(ctx) | ||
706 | if err != nil { | ||
707 | cc.closeForLostPing() | ||
708 | cc.t.connPool().MarkDead(cc) | ||
709 | return | ||
710 | } | ||
711 | } | ||
712 | |||
678 | func (cc *ClientConn) setGoAway(f *GoAwayFrame) { | 713 | func (cc *ClientConn) setGoAway(f *GoAwayFrame) { |
679 | cc.mu.Lock() | 714 | cc.mu.Lock() |
680 | defer cc.mu.Unlock() | 715 | defer cc.mu.Unlock() |
@@ -846,14 +881,12 @@ func (cc *ClientConn) sendGoAway() error { | |||
846 | return nil | 881 | return nil |
847 | } | 882 | } |
848 | 883 | ||
849 | // Close closes the client connection immediately. | 884 | // closes the client connection immediately. In-flight requests are interrupted. |
850 | // | 885 | // err is sent to streams. |
851 | // In-flight requests are interrupted. For a graceful shutdown, use Shutdown instead. | 886 | func (cc *ClientConn) closeForError(err error) error { |
852 | func (cc *ClientConn) Close() error { | ||
853 | cc.mu.Lock() | 887 | cc.mu.Lock() |
854 | defer cc.cond.Broadcast() | 888 | defer cc.cond.Broadcast() |
855 | defer cc.mu.Unlock() | 889 | defer cc.mu.Unlock() |
856 | err := errors.New("http2: client connection force closed via ClientConn.Close") | ||
857 | for id, cs := range cc.streams { | 890 | for id, cs := range cc.streams { |
858 | select { | 891 | select { |
859 | case cs.resc <- resAndError{err: err}: | 892 | case cs.resc <- resAndError{err: err}: |
@@ -866,6 +899,20 @@ func (cc *ClientConn) Close() error { | |||
866 | return cc.tconn.Close() | 899 | return cc.tconn.Close() |
867 | } | 900 | } |
868 | 901 | ||
902 | // Close closes the client connection immediately. | ||
903 | // | ||
904 | // In-flight requests are interrupted. For a graceful shutdown, use Shutdown instead. | ||
905 | func (cc *ClientConn) Close() error { | ||
906 | err := errors.New("http2: client connection force closed via ClientConn.Close") | ||
907 | return cc.closeForError(err) | ||
908 | } | ||
909 | |||
910 | // closes the client connection immediately. In-flight requests are interrupted. | ||
911 | func (cc *ClientConn) closeForLostPing() error { | ||
912 | err := errors.New("http2: client connection lost") | ||
913 | return cc.closeForError(err) | ||
914 | } | ||
915 | |||
869 | const maxAllocFrameSize = 512 << 10 | 916 | const maxAllocFrameSize = 512 << 10 |
870 | 917 | ||
871 | // frameBuffer returns a scratch buffer suitable for writing DATA frames. | 918 | // frameBuffer returns a scratch buffer suitable for writing DATA frames. |
@@ -1737,8 +1784,17 @@ func (rl *clientConnReadLoop) run() error { | |||
1737 | rl.closeWhenIdle = cc.t.disableKeepAlives() || cc.singleUse | 1784 | rl.closeWhenIdle = cc.t.disableKeepAlives() || cc.singleUse |
1738 | gotReply := false // ever saw a HEADERS reply | 1785 | gotReply := false // ever saw a HEADERS reply |
1739 | gotSettings := false | 1786 | gotSettings := false |
1787 | readIdleTimeout := cc.t.ReadIdleTimeout | ||
1788 | var t *time.Timer | ||
1789 | if readIdleTimeout != 0 { | ||
1790 | t = time.AfterFunc(readIdleTimeout, cc.healthCheck) | ||
1791 | defer t.Stop() | ||
1792 | } | ||
1740 | for { | 1793 | for { |
1741 | f, err := cc.fr.ReadFrame() | 1794 | f, err := cc.fr.ReadFrame() |
1795 | if t != nil { | ||
1796 | t.Reset(readIdleTimeout) | ||
1797 | } | ||
1742 | if err != nil { | 1798 | if err != nil { |
1743 | cc.vlogf("http2: Transport readFrame error on conn %p: (%T) %v", cc, err, err) | 1799 | cc.vlogf("http2: Transport readFrame error on conn %p: (%T) %v", cc, err, err) |
1744 | } | 1800 | } |