Skip to content

Commit

Permalink
Concurrently dial and listen dtls (#260)
Browse files Browse the repository at this point in the history
  • Loading branch information
mingyech authored Nov 13, 2023
1 parent 4026944 commit c4f2d96
Showing 1 changed file with 33 additions and 17 deletions.
50 changes: 33 additions & 17 deletions pkg/transports/connecting/dtls/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ type ClientTransport struct {
psk []byte
stunServer string
disableIRWorkaround bool
listenTimeout *time.Duration
}

type ClientConfig struct {
Expand Down Expand Up @@ -132,7 +131,6 @@ func (t *ClientTransport) SetParams(p any) error {
case *ClientConfig:
t.stunServer = params.STUNServer
t.disableIRWorkaround = params.DisableIRWorkaround
t.listenTimeout = params.ListenTimeout
}

return nil
Expand Down Expand Up @@ -205,27 +203,45 @@ func (t *ClientTransport) GetDstPort(seed []byte) (uint16, error) {

func (t *ClientTransport) WrapDial(dialer dialFunc) (dialFunc, error) {
dtlsDialer := func(ctx context.Context, network, localAddr, address string) (net.Conn, error) {
// Create a context that will automatically cancel after 5 seconds or when the existing context is cancelled, whichever comes first.
timeout := t.listenTimeout
if timeout == nil {
time := defaultListenTime
timeout = &time
}
ctxtimeout, cancel := context.WithTimeout(ctx, *timeout)

dialCtx, cancel := context.WithCancel(ctx)
defer cancel()

conn, errListen := t.listen(ctxtimeout, dialer, address)
if errListen != nil {
// fallback to dial
conn, errDial := t.dial(ctx, dialer, address)
if errDial != nil {
return nil, fmt.Errorf("error listening: %v, error dialing: %v", errListen, errDial)
type result struct {
conn net.Conn
err error
}

results := make(chan result, 2)

go func() {
conn, err := t.listen(dialCtx, dialer, address)
results <- result{conn, err}
}()

go func() {
conn, err := t.dial(dialCtx, dialer, address)
results <- result{conn, err}
}()

first := <-results
if first.err == nil {
// Interrupt the other dial
cancel()
second := <-results
if second.conn != nil {
_ = second.conn.Close()
}
return first.conn, nil
}

return conn, nil
second := <-results
if second.err == nil {
return second.conn, nil
}

return conn, nil
// TODO: once our minimum golang version is >= 1.20 change this to "%w; %w"
return nil, fmt.Errorf("%w; %s", first.err, second.err)
}

return dtlsDialer, nil
Expand Down

0 comments on commit c4f2d96

Please sign in to comment.