mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-29 04:55:31 +00:00
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>
This commit is contained in:
parent
b09000ad5d
commit
63d9c7b9b3
@ -12,10 +12,12 @@
|
||||
"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"
|
||||
)
|
||||
@ -37,8 +39,8 @@ type Client struct {
|
||||
rate *rate.Limiter // if non-nil, rate limiter to use
|
||||
|
||||
// Owned by Recv:
|
||||
peeked int // bytes to discard on next Recv
|
||||
readErr error // sticky read error
|
||||
peeked int // bytes to discard on next Recv
|
||||
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 @@
|
||||
"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…
Reference in New Issue
Block a user