derp: add Client.LocalAddr method

So magicsock can later ask a DERP connection whether its source IP
would've changed if it reconnected.

Updates #3619

Change-Id: Ibc8810340c511d6786b60c78c1a61c09f5800e40
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
pull/3634/head
Brad Fitzpatrick 3 years ago committed by Brad Fitzpatrick
parent b09000ad5d
commit 63d9c7b9b3

@ -12,10 +12,12 @@ import (
"fmt"
"io"
"sync"
"sync/atomic"
"time"
"go4.org/mem"
"golang.org/x/time/rate"
"inet.af/netaddr"
"tailscale.com/types/key"
"tailscale.com/types/logger"
)
@ -38,7 +40,7 @@ type Client struct {
// Owned by Recv:
peeked int // bytes to discard on next Recv
readErr error // sticky read error
readErr atomic.Value // of error; sticky (set by Recv)
}
// ClientOpt is an option passed to NewClient.
@ -441,13 +443,14 @@ func (c *Client) Recv() (m ReceivedMessage, err error) {
}
func (c *Client) recvTimeout(timeout time.Duration) (m ReceivedMessage, err error) {
if c.readErr != nil {
return nil, c.readErr
readErr, _ := c.readErr.Load().(error)
if readErr != nil {
return nil, readErr
}
defer func() {
if err != nil {
err = fmt.Errorf("derp.Recv: %w", err)
c.readErr = err
c.readErr.Store(err)
}
}()
@ -587,3 +590,22 @@ func (c *Client) setSendRateLimiter(sm ServerInfoMessage) {
sm.TokenBucketBytesBurst)
}
}
// LocalAddr returns the TCP connection's local address.
//
// If the client is broken in some previously detectable way, it
// returns an error.
func (c *Client) LocalAddr() (netaddr.IPPort, error) {
readErr, _ := c.readErr.Load().(error)
if readErr != nil {
return netaddr.IPPort{}, readErr
}
if c.nc == nil {
return netaddr.IPPort{}, errors.New("nil conn")
}
a := c.nc.LocalAddr()
if a == nil {
return netaddr.IPPort{}, errors.New("nil addr")
}
return netaddr.ParseIPPort(a.String())
}

@ -23,6 +23,7 @@ import (
"math"
"math/big"
"math/rand"
"net"
"net/http"
"os"
"os/exec"
@ -283,9 +284,8 @@ type PacketForwarder interface {
// It is a defined type so that non-net connections can be used.
type Conn interface {
io.WriteCloser
LocalAddr() net.Addr
// The *Deadline methods follow the semantics of net.Conn.
SetDeadline(time.Time) error
SetReadDeadline(time.Time) error
SetWriteDeadline(time.Time) error

Loading…
Cancel
Save