-
Notifications
You must be signed in to change notification settings - Fork 163
/
Copy pathdiscovery.go
141 lines (127 loc) · 4.14 KB
/
discovery.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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// Copyright 2020 Anapaya Systems
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package hiddenpath
import (
"context"
"net"
"github.com/scionproto/scion/pkg/addr"
"github.com/scionproto/scion/pkg/grpc"
"github.com/scionproto/scion/pkg/private/serrors"
"github.com/scionproto/scion/pkg/snet"
"github.com/scionproto/scion/pkg/snet/path"
)
// Servers is a list of discovered remote hidden segment server.
type Servers struct {
// Lookup is the list of lookup addresses.
Lookup []*net.UDPAddr
// Registration is the list of registration addresses.
Registration []*net.UDPAddr
}
// Discoverer can be used to find remote discovery services.
type Discoverer interface {
Discover(ctx context.Context, dsAddr net.Addr) (Servers, error)
}
// AddressResolver helps to resolve addresses in a remote AS.
type AddressResolver interface {
// Resolve creates an address with a path to the remote ISD-AS that is
// specified.
Resolve(context.Context, addr.IA) (net.Addr, error)
}
// RegistrationResolver resolves the address of a hidden segment registration
// server in an IA.
type RegistrationResolver struct {
Router snet.Router
Discoverer Discoverer
}
// Resolve resolves a hidden segment registration server in the remote IA.
func (r RegistrationResolver) Resolve(ctx context.Context, ia addr.IA) (net.Addr, error) {
return resolve(ctx, ia, r.Discoverer, r.Router, func(s Servers) (*net.UDPAddr, error) {
if len(s.Registration) == 0 {
return nil, serrors.New("no registration server found")
}
return s.Registration[0], nil
})
}
// CSResolver resolves the address of a Control Service
// server in an IA. This is needed to get the needed
// certificates from the Register to verify the segments.
type CSResolver struct {
Router snet.Router
Rewriter grpc.AddressRewriter
}
// Resolve resolves the CS server in the remote IA.
func (r CSResolver) Resolve(ctx context.Context, ia addr.IA) (net.Addr, error) {
// TODO(JordiSubira): Put path failover mechanism in-place
path, err := r.Router.Route(ctx, ia)
if err != nil {
return nil, serrors.WrapStr("looking up path", err)
}
if path == nil {
return nil, serrors.WrapStr("no path found to remote", err)
}
return &snet.SVCAddr{
IA: ia,
NextHop: path.UnderlayNextHop(),
Path: path.Dataplane(),
SVC: addr.SvcCS,
}, nil
}
// LookupResolver resolves the address of a hidden segment lookup
// server in an IA.
type LookupResolver struct {
Router snet.Router
Discoverer Discoverer
}
// Resolve resolves a hidden segment lookup server in the remote IA.
func (r LookupResolver) Resolve(ctx context.Context, ia addr.IA) (net.Addr, error) {
return resolve(ctx, ia, r.Discoverer, r.Router, func(s Servers) (*net.UDPAddr, error) {
if len(s.Lookup) == 0 {
return nil, serrors.New("no lookup server found")
}
return s.Lookup[0], nil
})
}
func resolve(ctx context.Context, ia addr.IA, discoverer Discoverer, router snet.Router,
extractAddr func(Servers) (*net.UDPAddr, error)) (net.Addr, error) {
p, err := router.Route(ctx, ia)
if err != nil {
return nil, serrors.WrapStr("looking up path", err)
}
if p == nil {
return nil, serrors.WrapStr("no path found to remote", err)
}
dsAddr := &snet.SVCAddr{
IA: ia,
NextHop: p.UnderlayNextHop(),
Path: p.Dataplane(),
SVC: addr.SvcDS,
}
if dsAddr.Path == nil {
dsAddr.Path = path.Empty{}
}
hps, err := discoverer.Discover(ctx, dsAddr)
if err != nil {
return nil, serrors.WrapStr("discovering hidden path server", err)
}
a, err := extractAddr(hps)
if err != nil {
return nil, serrors.WithCtx(err, "isd_as", ia)
}
return &snet.UDPAddr{
IA: ia,
Host: a,
NextHop: dsAddr.NextHop,
Path: dsAddr.Path,
}, nil
}