/
dial.go
92 lines (83 loc) · 2.58 KB
/
dial.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
package ndt7
import (
"context"
"crypto/tls"
"net/http"
"github.com/gorilla/websocket"
"github.com/ooni/probe-engine/pkg/bytecounter"
"github.com/ooni/probe-engine/pkg/model"
"github.com/ooni/probe-engine/pkg/netxlite"
)
type dialManager struct {
ndt7URL string
logger model.Logger
readBufferSize int
userAgent string
writeBufferSize int
}
func newDialManager(ndt7URL string, logger model.Logger, userAgent string) dialManager {
return dialManager{
ndt7URL: ndt7URL,
logger: logger,
readBufferSize: paramMaxBufferSize,
userAgent: userAgent,
writeBufferSize: paramMaxBufferSize,
}
}
func (mgr dialManager) dialWithTestName(ctx context.Context, testName string) (*websocket.Conn, error) {
reso := netxlite.NewStdlibResolver(mgr.logger)
dlr := netxlite.NewDialerWithResolver(mgr.logger, reso)
dlr = bytecounter.WrapWithContextAwareDialer(dlr)
// Implements shaping if the user builds using `-tags shaping`
// See https://github.com/ooni/probe/issues/2112
dlr = netxlite.NewMaybeShapingDialer(dlr)
// See https://github.com/ooni/probe/issues/2413 to understand
// why we're using nil to force netxlite to use the cached
// default Mozilla cert pool.
tlsConfig := &tls.Config{
RootCAs: nil,
}
dialer := websocket.Dialer{
NetDialContext: dlr.DialContext,
ReadBufferSize: mgr.readBufferSize,
TLSClientConfig: tlsConfig,
WriteBufferSize: mgr.writeBufferSize,
}
headers := http.Header{}
headers.Add("Sec-WebSocket-Protocol", "net.measurementlab.ndt.v7")
headers.Add("User-Agent", mgr.userAgent)
mgr.logrequest(mgr.ndt7URL, headers)
conn, _, err := dialer.DialContext(ctx, mgr.ndt7URL, headers)
if err != nil {
err = netxlite.NewTopLevelGenericErrWrapper(err)
}
mgr.logresponse(err)
return conn, err
}
func (mgr dialManager) logrequest(url string, headers http.Header) {
mgr.logger.Debugf("> GET %s", url)
for key, values := range headers {
for _, v := range values {
mgr.logger.Debugf("> %s: %s", key, v)
}
}
mgr.logger.Debug("> Connection: upgrade")
mgr.logger.Debug("> Upgrade: websocket")
mgr.logger.Debug(">")
}
func (mgr dialManager) logresponse(err error) {
if err != nil {
mgr.logger.Debugf("< %+v", err)
return
}
mgr.logger.Debug("< 101")
mgr.logger.Debug("< Connection: upgrade")
mgr.logger.Debug("< Upgrade: websocket")
mgr.logger.Debug("<")
}
func (mgr dialManager) dialDownload(ctx context.Context) (*websocket.Conn, error) {
return mgr.dialWithTestName(ctx, "download")
}
func (mgr dialManager) dialUpload(ctx context.Context) (*websocket.Conn, error) {
return mgr.dialWithTestName(ctx, "upload")
}