@@ -24,12 +24,17 @@ import (
24
24
"strconv"
25
25
"sync"
26
26
27
- quic "github.com/lucas-clemente/quic-go"
27
+ "github.com/lucas-clemente/quic-go"
28
28
"github.com/lucas-clemente/quic-go/h2quic"
29
29
"github.com/netsec-ethz/scion-apps/lib/scionutil"
30
30
libaddr "github.com/scionproto/scion/go/lib/addr"
31
31
"github.com/scionproto/scion/go/lib/snet"
32
- "github.com/scionproto/scion/go/lib/snet/squic"
32
+ // "github.com/scionproto/scion/go/lib/snet/squic"
33
+ )
34
+
35
+ var (
36
+ // cliTlsCfg is a copy squic.cliTlsCfg
37
+ cliTlsCfg = & tls.Config {InsecureSkipVerify : true }
33
38
)
34
39
35
40
// Transport wraps a h2quic.RoundTripper making it compatible with SCION
@@ -40,7 +45,9 @@ type Transport struct {
40
45
41
46
rt * h2quic.RoundTripper
42
47
43
- dialOnce sync.Once
48
+ dialOnce sync.Once
49
+ connectionsMutex sync.Mutex
50
+ connections []* snet.Conn
44
51
}
45
52
46
53
// RoundTrip does a single round trip; retreiving a response for a given request
@@ -49,6 +56,28 @@ func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) {
49
56
return t .RoundTripOpt (req , h2quic.RoundTripOpt {})
50
57
}
51
58
59
+ // squicDialSCION re-implements squic.DialSCION to get access to the underlying
60
+ // snet.Conn to be able to close the connection later.
61
+ func (t * Transport ) squicDialSCION (network * snet.SCIONNetwork , laddr , raddr * snet.Addr ,
62
+ quicConfig * quic.Config ) (quic.Session , error ) {
63
+
64
+ // squic.sListen (but without the Bind/SVC)
65
+ if network == nil {
66
+ network = snet .DefNetwork
67
+ }
68
+ sconn , err := network .ListenSCION ("udp4" , laddr , 0 )
69
+ if err != nil {
70
+ return nil , err
71
+ }
72
+
73
+ t .connectionsMutex .Lock ()
74
+ defer t .connectionsMutex .Unlock ()
75
+ t .connections = append (t .connections , & sconn )
76
+
77
+ // Use dummy hostname, as it's used for SNI, and we're not doing cert verification.
78
+ return quic .Dial (sconn , raddr , "host:0" , cliTlsCfg , quicConfig )
79
+ }
80
+
52
81
// RoundTripOpt is the same as RoundTrip but takes additional options
53
82
func (t * Transport ) RoundTripOpt (req * http.Request , opt h2quic.RoundTripOpt ) (* http.Response , error ) {
54
83
@@ -90,7 +119,7 @@ func (t *Transport) RoundTripOpt(req *http.Request, opt h2quic.RoundTripOpt) (*h
90
119
}
91
120
l4 := libaddr .NewL4UDPInfo (uint16 (p ))
92
121
raddr := & snet.Addr {IA : ia , Host : & libaddr.AppAddr {L3 : l3 , L4 : l4 }}
93
- return squic . DialSCION (nil , t .LAddr , raddr , cfg )
122
+ return t . squicDialSCION (nil , t .LAddr , raddr , cfg )
94
123
}
95
124
t .rt = & h2quic.RoundTripper {
96
125
Dial : dial ,
@@ -104,5 +133,15 @@ func (t *Transport) RoundTripOpt(req *http.Request, opt h2quic.RoundTripOpt) (*h
104
133
105
134
// Close closes the QUIC connections that this RoundTripper has used
106
135
func (t * Transport ) Close () error {
107
- return t .rt .Close ()
136
+ err := t .rt .Close ()
137
+
138
+ // quic.Session.Close (which is called by RoundTripper.Close()) will NOT
139
+ // close the underlying connections, so we do it manually here.
140
+ t .connectionsMutex .Lock ()
141
+ defer t .connectionsMutex .Unlock ()
142
+ for _ , sconn := range t .connections {
143
+ (* sconn ).Close ()
144
+ }
145
+
146
+ return err
108
147
}
0 commit comments