mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-29 04:55:31 +00:00
derp{,/derphttp},magicsock: tell DERP server when ping acks can be expected
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
parent
f9f3b67f3a
commit
c81814e4f8
@ -21,13 +21,14 @@
|
|||||||
|
|
||||||
// Client is a DERP client.
|
// Client is a DERP client.
|
||||||
type Client struct {
|
type Client struct {
|
||||||
serverKey key.Public // of the DERP server; not a machine or node key
|
serverKey key.Public // of the DERP server; not a machine or node key
|
||||||
privateKey key.Private
|
privateKey key.Private
|
||||||
publicKey key.Public // of privateKey
|
publicKey key.Public // of privateKey
|
||||||
logf logger.Logf
|
logf logger.Logf
|
||||||
nc Conn
|
nc Conn
|
||||||
br *bufio.Reader
|
br *bufio.Reader
|
||||||
meshKey string
|
meshKey string
|
||||||
|
canAckPings bool
|
||||||
|
|
||||||
wmu sync.Mutex // hold while writing to bw
|
wmu sync.Mutex // hold while writing to bw
|
||||||
bw *bufio.Writer
|
bw *bufio.Writer
|
||||||
@ -48,8 +49,9 @@ func (f clientOptFunc) update(o *clientOpt) { f(o) }
|
|||||||
|
|
||||||
// clientOpt are the options passed to newClient.
|
// clientOpt are the options passed to newClient.
|
||||||
type clientOpt struct {
|
type clientOpt struct {
|
||||||
MeshKey string
|
MeshKey string
|
||||||
ServerPub key.Public
|
ServerPub key.Public
|
||||||
|
CanAckPings bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// MeshKey returns a ClientOpt to pass to the DERP server during connect to get
|
// MeshKey returns a ClientOpt to pass to the DERP server during connect to get
|
||||||
@ -64,6 +66,12 @@ func ServerPublicKey(key key.Public) ClientOpt {
|
|||||||
return clientOptFunc(func(o *clientOpt) { o.ServerPub = key })
|
return clientOptFunc(func(o *clientOpt) { o.ServerPub = key })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CanAckPings returns a ClientOpt to set whether it advertises to the
|
||||||
|
// server that it's capable of acknowledging ping requests.
|
||||||
|
func CanAckPings(v bool) ClientOpt {
|
||||||
|
return clientOptFunc(func(o *clientOpt) { o.CanAckPings = v })
|
||||||
|
}
|
||||||
|
|
||||||
func NewClient(privateKey key.Private, nc Conn, brw *bufio.ReadWriter, logf logger.Logf, opts ...ClientOpt) (*Client, error) {
|
func NewClient(privateKey key.Private, nc Conn, brw *bufio.ReadWriter, logf logger.Logf, opts ...ClientOpt) (*Client, error) {
|
||||||
var opt clientOpt
|
var opt clientOpt
|
||||||
for _, o := range opts {
|
for _, o := range opts {
|
||||||
@ -77,13 +85,14 @@ func NewClient(privateKey key.Private, nc Conn, brw *bufio.ReadWriter, logf logg
|
|||||||
|
|
||||||
func newClient(privateKey key.Private, nc Conn, brw *bufio.ReadWriter, logf logger.Logf, opt clientOpt) (*Client, error) {
|
func newClient(privateKey key.Private, nc Conn, brw *bufio.ReadWriter, logf logger.Logf, opt clientOpt) (*Client, error) {
|
||||||
c := &Client{
|
c := &Client{
|
||||||
privateKey: privateKey,
|
privateKey: privateKey,
|
||||||
publicKey: privateKey.Public(),
|
publicKey: privateKey.Public(),
|
||||||
logf: logf,
|
logf: logf,
|
||||||
nc: nc,
|
nc: nc,
|
||||||
br: brw.Reader,
|
br: brw.Reader,
|
||||||
bw: brw.Writer,
|
bw: brw.Writer,
|
||||||
meshKey: opt.MeshKey,
|
meshKey: opt.MeshKey,
|
||||||
|
canAckPings: opt.CanAckPings,
|
||||||
}
|
}
|
||||||
if opt.ServerPub.IsZero() {
|
if opt.ServerPub.IsZero() {
|
||||||
if err := c.recvServerKey(); err != nil {
|
if err := c.recvServerKey(); err != nil {
|
||||||
@ -147,6 +156,10 @@ type clientInfo struct {
|
|||||||
// connection list & forward packets. It's empty for regular
|
// connection list & forward packets. It's empty for regular
|
||||||
// users.
|
// users.
|
||||||
MeshKey string `json:"meshKey,omitempty"`
|
MeshKey string `json:"meshKey,omitempty"`
|
||||||
|
|
||||||
|
// CanAckPings is whether the client declares it's able to ack
|
||||||
|
// pings.
|
||||||
|
CanAckPings bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) sendClientKey() error {
|
func (c *Client) sendClientKey() error {
|
||||||
@ -155,8 +168,9 @@ func (c *Client) sendClientKey() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
msg, err := json.Marshal(clientInfo{
|
msg, err := json.Marshal(clientInfo{
|
||||||
Version: ProtocolVersion,
|
Version: ProtocolVersion,
|
||||||
MeshKey: c.meshKey,
|
MeshKey: c.meshKey,
|
||||||
|
CanAckPings: c.canAckPings,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -63,6 +63,7 @@ type Client struct {
|
|||||||
|
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
preferred bool
|
preferred bool
|
||||||
|
canAckPings bool
|
||||||
closed bool
|
closed bool
|
||||||
netConn io.Closer
|
netConn io.Closer
|
||||||
client *derp.Client
|
client *derp.Client
|
||||||
@ -333,7 +334,11 @@ func (c *Client) connect(ctx context.Context, caller string) (client *derp.Clien
|
|||||||
return nil, 0, fmt.Errorf("GET failed: %v: %s", err, b)
|
return nil, 0, fmt.Errorf("GET failed: %v: %s", err, b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
derpClient, err = derp.NewClient(c.privateKey, httpConn, brw, c.logf, derp.MeshKey(c.MeshKey), derp.ServerPublicKey(serverPub))
|
derpClient, err = derp.NewClient(c.privateKey, httpConn, brw, c.logf,
|
||||||
|
derp.MeshKey(c.MeshKey),
|
||||||
|
derp.ServerPublicKey(serverPub),
|
||||||
|
derp.CanAckPings(c.canAckPings),
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
@ -665,6 +670,15 @@ func (c *Client) SendPong(data [8]byte) error {
|
|||||||
return dc.SendPong(data)
|
return dc.SendPong(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetCanAckPings sets whether this client will reply to ping requests from the server.
|
||||||
|
//
|
||||||
|
// This only affects future connections.
|
||||||
|
func (c *Client) SetCanAckPings(v bool) {
|
||||||
|
c.mu.Lock()
|
||||||
|
defer c.mu.Unlock()
|
||||||
|
c.canAckPings = v
|
||||||
|
}
|
||||||
|
|
||||||
// NotePreferred notes whether this Client is the caller's preferred
|
// NotePreferred notes whether this Client is the caller's preferred
|
||||||
// (home) DERP node. It's only used for stats.
|
// (home) DERP node. It's only used for stats.
|
||||||
func (c *Client) NotePreferred(v bool) {
|
func (c *Client) NotePreferred(v bool) {
|
||||||
|
@ -1308,6 +1308,7 @@ func (c *Conn) derpWriteChanOfAddr(addr netaddr.IPPort, peer key.Public) chan<-
|
|||||||
return c.derpMap.Regions[regionID]
|
return c.derpMap.Regions[regionID]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
dc.SetCanAckPings(true)
|
||||||
dc.NotePreferred(c.myDerp == regionID)
|
dc.NotePreferred(c.myDerp == regionID)
|
||||||
dc.DNSCache = dnscache.Get()
|
dc.DNSCache = dnscache.Get()
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user