Skip to content

Commit c7a9fed

Browse files
authored
Merge pull request #54 from matzf/shttp-close-conn
shttp: Close connections, scionutil: use "sciondFromIA" logic if no default.sock
2 parents bcfb86d + 3ea0e44 commit c7a9fed

File tree

3 files changed

+68
-16
lines changed

3 files changed

+68
-16
lines changed

lib/scionutil/initialization.go

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,16 @@
1515
package scionutil
1616

1717
import (
18+
"github.com/scionproto/scion/go/lib/addr"
1819
"github.com/scionproto/scion/go/lib/sciond"
1920
"github.com/scionproto/scion/go/lib/snet"
21+
"os"
2022
)
2123

2224
// InitSCION initializes the default SCION networking context with the provided SCION address
2325
// and the default SCIOND/SCION dispatcher
2426
func InitSCION(localAddr *snet.Addr) error {
25-
err := snet.Init(localAddr.IA, GetDefaultSCIOND(), GetDefaultDispatcher())
27+
err := snet.Init(localAddr.IA, GetSCIONDPath(&localAddr.IA), GetDefaultDispatcher())
2628
if err != nil {
2729
return err
2830
}
@@ -37,17 +39,23 @@ func InitSCIONString(localAddr string) (*snet.Addr, error) {
3739
return nil, err
3840
}
3941

40-
err = snet.Init(addr.IA, GetDefaultSCIOND(), GetDefaultDispatcher())
42+
err = snet.Init(addr.IA, GetSCIONDPath(&addr.IA), GetDefaultDispatcher())
4143
if err != nil {
4244
return nil, err
4345
}
4446

4547
return addr, nil
4648
}
4749

48-
// GetDefaultSCIOND returns the path to the default SCION socket
49-
func GetDefaultSCIOND() string {
50-
return sciond.GetDefaultSCIONDPath(nil)
50+
// GetSCIONDPath returns the path to the SCION socket.
51+
func GetSCIONDPath(ia *addr.IA) string {
52+
53+
// Use default.sock if exists:
54+
if _, err := os.Stat(sciond.DefaultSCIONDPath); err == nil {
55+
return sciond.DefaultSCIONDPath
56+
}
57+
// otherwise, use socket with ia name:
58+
return sciond.GetDefaultSCIONDPath(ia)
5159
}
5260

5361
// GetDefaultDispatcher returns the path to the default SCION dispatcher

lib/shttp/examples/minimal/README.md

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,23 @@ This example application makes two requests from the client to the server.
22

33
First, it issues a GET request and downloads an HTML file. Afterwards it sends data to the server via POST.
44

5-
To run the example, first start the server like this
6-
```Go
7-
go run server.go -local 17-ffaa:1:c2,[127.0.0.1]:40002 -cert tls.pem -key tls.key
5+
To run the example, generate a certificate for the server first, e.g
6+
```sh
7+
openssl req -x509 -newkey rsa:1024 -keyout key.pem -nodes -out cert.pem -days 365 -subj '/CN=minimal-server'
8+
```
9+
10+
Start the server like this
11+
```sh
12+
go run server.go -local 17-ffaa:1:c2,[127.0.0.1]:40002 -cert cert.pem -key key.pem
813
```
914

1015
Then, start the client:
11-
```Go
16+
```sh
1217
go run client.go -local 17-ffaa:1:c2,[127.0.0.1]:0
1318
```
1419

1520
For an interactive mode that lets the user choose a path from all available paths add the `-i` flag:
16-
```Go
21+
```sh
1722
go run client.go -local 17-ffaa:1:c2,[127.0.0.1]:0 -i
1823
```
1924

@@ -22,4 +27,4 @@ Make sure to replace the addresses with your own AS addresses and to set the TLS
2227
Also, `minimal-server` must resolve to the SCION address on which you run the server. You can add `minimal-server` to your known hosts by adding the following line to `/etc/hosts`. (replace `ISD-AS` and `IP` with your actual address):
2328
```
2429
ISD-AS,[IP] minimal-server
25-
```
30+
```

lib/shttp/transport.go

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,17 @@ import (
2424
"strconv"
2525
"sync"
2626

27-
quic "github.com/lucas-clemente/quic-go"
27+
"github.com/lucas-clemente/quic-go"
2828
"github.com/lucas-clemente/quic-go/h2quic"
2929
"github.com/netsec-ethz/scion-apps/lib/scionutil"
3030
libaddr "github.com/scionproto/scion/go/lib/addr"
3131
"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}
3338
)
3439

3540
// Transport wraps a h2quic.RoundTripper making it compatible with SCION
@@ -40,7 +45,9 @@ type Transport struct {
4045

4146
rt *h2quic.RoundTripper
4247

43-
dialOnce sync.Once
48+
dialOnce sync.Once
49+
connectionsMutex sync.Mutex
50+
connections []*snet.Conn
4451
}
4552

4653
// 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) {
4956
return t.RoundTripOpt(req, h2quic.RoundTripOpt{})
5057
}
5158

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+
5281
// RoundTripOpt is the same as RoundTrip but takes additional options
5382
func (t *Transport) RoundTripOpt(req *http.Request, opt h2quic.RoundTripOpt) (*http.Response, error) {
5483

@@ -90,7 +119,7 @@ func (t *Transport) RoundTripOpt(req *http.Request, opt h2quic.RoundTripOpt) (*h
90119
}
91120
l4 := libaddr.NewL4UDPInfo(uint16(p))
92121
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)
94123
}
95124
t.rt = &h2quic.RoundTripper{
96125
Dial: dial,
@@ -104,5 +133,15 @@ func (t *Transport) RoundTripOpt(req *http.Request, opt h2quic.RoundTripOpt) (*h
104133

105134
// Close closes the QUIC connections that this RoundTripper has used
106135
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
108147
}

0 commit comments

Comments
 (0)