Skip to content

Commit d3ae69e

Browse files
committed
pan: isolate Rains resolver context handling
The rains.Query function takes a timeout value instead of a context, use a default timeout if the context has no deadline.
1 parent 7e75102 commit d3ae69e

File tree

3 files changed

+37
-30
lines changed

3 files changed

+37
-30
lines changed

pkg/pan/hosts.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,9 @@ func (resolvers resolverList) Resolve(ctx context.Context, name string) (scionAd
9393
continue
9494
}
9595
// check ctx to avoid unnecessary calls with already expired context
96-
select {
97-
case <-ctx.Done():
96+
if err := ctx.Err(); err != nil {
97+
rerr = err
9898
break
99-
default:
10099
}
101100
addr, err := resolver.Resolve(ctx, name)
102101
if err == nil {

pkg/pan/pan.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,6 @@ import (
110110
// ResolveUDPAddr parses the address and resolves the hostname.
111111
// The address can be of the form of a SCION address (i.e. of the form "ISD-AS,[IP]:port")
112112
// or in the form of "hostname:port".
113-
// Default timeout is 1 second, use ResolveUDPAddrContext to provide an explicit context.
114113
// If the address is in the form of a hostname, the the following sources will
115114
// be used to resolve a name, in the given order of precedence.
116115
//

pkg/pan/rains.go

Lines changed: 35 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"context"
2222
"fmt"
2323
"io/ioutil"
24+
"net"
2425
"os"
2526
"strings"
2627
"time"
@@ -64,7 +65,7 @@ func readRainsConfig() (UDPAddr, error) {
6465
return address, nil
6566
}
6667

67-
func rainsQuery(ctx context.Context, server UDPAddr, hostname string) (addr scionAddr, err error) {
68+
func rainsQuery(ctx context.Context, server UDPAddr, hostname string) (scionAddr, error) {
6869
const (
6970
rainsCtx = "." // use global context
7071
qType = rains.OTScionAddr // request SCION addresses
@@ -73,40 +74,48 @@ func rainsQuery(ctx context.Context, server UDPAddr, hostname string) (addr scio
7374
)
7475
qOpts := []rains.Option{} // no options
7576

76-
// TODO(matzf): check that this actually works
77-
// - return error on timeout, network problems, invalid format, ...
78-
// - return HostNotFoundError error if all went well, but host not found
7977
// TODO(chaehni): This call can sometimes cause a timeout even though the server is reachable (see issue #221)
80-
// The timeout value has been decreased to counter this behavior until the problem is resolved.
78+
// The (default) timeout value has been decreased to counter this behavior until the problem is resolved.
8179
srv := server.snetUDPAddr()
8280

81+
reply, err := rainsQueryChecked(ctx, hostname, rainsCtx, []rains.Type{qType}, qOpts, expire, timeout, srv)
82+
if err != nil {
83+
return scionAddr{}, err
84+
}
85+
addrStr, ok := reply[qType]
86+
if !ok {
87+
return scionAddr{}, &HostNotFoundError{hostname}
88+
}
89+
addr, err := parseSCIONAddr(addrStr)
90+
if err != nil {
91+
return scionAddr{}, fmt.Errorf("address for host %q invalid: %w", hostname, err)
92+
}
93+
return addr, nil
94+
}
95+
96+
func rainsQueryChecked(ctx context.Context, name, rainsCtx string, types []rains.Type, opts []rains.Option,
97+
expire, timeout time.Duration, addr net.Addr) (res map[rains.Type]string, err error) {
98+
99+
var contextTimeout time.Duration
100+
deadline, finite := ctx.Deadline()
101+
if finite {
102+
contextTimeout = time.Until(deadline)
103+
if contextTimeout < 0 {
104+
return res, context.DeadlineExceeded
105+
}
106+
} else {
107+
contextTimeout = timeout
108+
}
109+
83110
done := make(chan struct{})
84111
go func() {
85112
defer close(done)
86-
var reply map[rains.Type]string
87-
reply, err = rains.Query(hostname, rainsCtx, []rains.Type{qType}, qOpts, expire, timeout, srv)
88-
if err != nil {
89-
err = fmt.Errorf("address for host %q not found: %w", hostname, err)
90-
return
91-
}
92-
addrStr, ok := reply[qType]
93-
if !ok {
94-
err = &HostNotFoundError{hostname}
95-
return
96-
}
97-
addr, err = parseSCIONAddr(addrStr)
98-
if err != nil {
99-
err = fmt.Errorf("address for host %q invalid: %w", hostname, err)
100-
addr = scionAddr{}
101-
}
113+
res, err = rains.Query(name, rainsCtx, types, opts, expire, contextTimeout, addr)
102114
}()
103115
select {
104116
case <-ctx.Done():
105-
return scionAddr{}, context.DeadlineExceeded
117+
return res, ctx.Err()
106118
case <-done:
107119
}
108-
if err != nil {
109-
return scionAddr{}, err
110-
}
111-
return addr, nil
120+
return
112121
}

0 commit comments

Comments
 (0)