blob: d957b7bc52dd18fca1dd7995024b2e2034636e5f [file] [log] [blame]
Serge Bazanskicc25bdf2018-10-25 14:02:58 +02001// Copyright 2016 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// +build go1.7
6
7package http2
8
9import (
10 "context"
11 "net"
12 "net/http"
13 "net/http/httptrace"
14 "time"
15)
16
17type contextContext interface {
18 context.Context
19}
20
21var errCanceled = context.Canceled
22
23func serverConnBaseContext(c net.Conn, opts *ServeConnOpts) (ctx contextContext, cancel func()) {
24 ctx, cancel = context.WithCancel(context.Background())
25 ctx = context.WithValue(ctx, http.LocalAddrContextKey, c.LocalAddr())
26 if hs := opts.baseConfig(); hs != nil {
27 ctx = context.WithValue(ctx, http.ServerContextKey, hs)
28 }
29 return
30}
31
32func contextWithCancel(ctx contextContext) (_ contextContext, cancel func()) {
33 return context.WithCancel(ctx)
34}
35
36func requestWithContext(req *http.Request, ctx contextContext) *http.Request {
37 return req.WithContext(ctx)
38}
39
40type clientTrace httptrace.ClientTrace
41
42func reqContext(r *http.Request) context.Context { return r.Context() }
43
44func (t *Transport) idleConnTimeout() time.Duration {
45 if t.t1 != nil {
46 return t.t1.IdleConnTimeout
47 }
48 return 0
49}
50
51func setResponseUncompressed(res *http.Response) { res.Uncompressed = true }
52
53func traceGetConn(req *http.Request, hostPort string) {
54 trace := httptrace.ContextClientTrace(req.Context())
55 if trace == nil || trace.GetConn == nil {
56 return
57 }
58 trace.GetConn(hostPort)
59}
60
61func traceGotConn(req *http.Request, cc *ClientConn) {
62 trace := httptrace.ContextClientTrace(req.Context())
63 if trace == nil || trace.GotConn == nil {
64 return
65 }
66 ci := httptrace.GotConnInfo{Conn: cc.tconn}
67 cc.mu.Lock()
68 ci.Reused = cc.nextStreamID > 1
69 ci.WasIdle = len(cc.streams) == 0 && ci.Reused
70 if ci.WasIdle && !cc.lastActive.IsZero() {
71 ci.IdleTime = time.Now().Sub(cc.lastActive)
72 }
73 cc.mu.Unlock()
74
75 trace.GotConn(ci)
76}
77
78func traceWroteHeaders(trace *clientTrace) {
79 if trace != nil && trace.WroteHeaders != nil {
80 trace.WroteHeaders()
81 }
82}
83
84func traceGot100Continue(trace *clientTrace) {
85 if trace != nil && trace.Got100Continue != nil {
86 trace.Got100Continue()
87 }
88}
89
90func traceWait100Continue(trace *clientTrace) {
91 if trace != nil && trace.Wait100Continue != nil {
92 trace.Wait100Continue()
93 }
94}
95
96func traceWroteRequest(trace *clientTrace, err error) {
97 if trace != nil && trace.WroteRequest != nil {
98 trace.WroteRequest(httptrace.WroteRequestInfo{Err: err})
99 }
100}
101
102func traceFirstResponseByte(trace *clientTrace) {
103 if trace != nil && trace.GotFirstResponseByte != nil {
104 trace.GotFirstResponseByte()
105 }
106}
107
108func requestTrace(req *http.Request) *clientTrace {
109 trace := httptrace.ContextClientTrace(req.Context())
110 return (*clientTrace)(trace)
111}
112
113// Ping sends a PING frame to the server and waits for the ack.
114func (cc *ClientConn) Ping(ctx context.Context) error {
115 return cc.ping(ctx)
116}
117
118// Shutdown gracefully closes the client connection, waiting for running streams to complete.
119func (cc *ClientConn) Shutdown(ctx context.Context) error {
120 return cc.shutdown(ctx)
121}