|
|
|
@ -21,13 +21,14 @@ import (
|
|
|
|
|
|
|
|
|
|
// Client is a DERP client.
|
|
|
|
|
type Client struct {
|
|
|
|
|
serverKey key.Public // of the DERP server; not a machine or node key
|
|
|
|
|
privateKey key.Private
|
|
|
|
|
publicKey key.Public // of privateKey
|
|
|
|
|
logf logger.Logf
|
|
|
|
|
nc Conn
|
|
|
|
|
br *bufio.Reader
|
|
|
|
|
meshKey string
|
|
|
|
|
serverKey key.Public // of the DERP server; not a machine or node key
|
|
|
|
|
privateKey key.Private
|
|
|
|
|
publicKey key.Public // of privateKey
|
|
|
|
|
logf logger.Logf
|
|
|
|
|
nc Conn
|
|
|
|
|
br *bufio.Reader
|
|
|
|
|
meshKey string
|
|
|
|
|
canAckPings bool
|
|
|
|
|
|
|
|
|
|
wmu sync.Mutex // hold while writing to bw
|
|
|
|
|
bw *bufio.Writer
|
|
|
|
@ -48,8 +49,9 @@ func (f clientOptFunc) update(o *clientOpt) { f(o) }
|
|
|
|
|
|
|
|
|
|
// clientOpt are the options passed to newClient.
|
|
|
|
|
type clientOpt struct {
|
|
|
|
|
MeshKey string
|
|
|
|
|
ServerPub key.Public
|
|
|
|
|
MeshKey string
|
|
|
|
|
ServerPub key.Public
|
|
|
|
|
CanAckPings bool
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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 })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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) {
|
|
|
|
|
var opt clientOpt
|
|
|
|
|
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) {
|
|
|
|
|
c := &Client{
|
|
|
|
|
privateKey: privateKey,
|
|
|
|
|
publicKey: privateKey.Public(),
|
|
|
|
|
logf: logf,
|
|
|
|
|
nc: nc,
|
|
|
|
|
br: brw.Reader,
|
|
|
|
|
bw: brw.Writer,
|
|
|
|
|
meshKey: opt.MeshKey,
|
|
|
|
|
privateKey: privateKey,
|
|
|
|
|
publicKey: privateKey.Public(),
|
|
|
|
|
logf: logf,
|
|
|
|
|
nc: nc,
|
|
|
|
|
br: brw.Reader,
|
|
|
|
|
bw: brw.Writer,
|
|
|
|
|
meshKey: opt.MeshKey,
|
|
|
|
|
canAckPings: opt.CanAckPings,
|
|
|
|
|
}
|
|
|
|
|
if opt.ServerPub.IsZero() {
|
|
|
|
|
if err := c.recvServerKey(); err != nil {
|
|
|
|
@ -147,6 +156,10 @@ type clientInfo struct {
|
|
|
|
|
// connection list & forward packets. It's empty for regular
|
|
|
|
|
// users.
|
|
|
|
|
MeshKey string `json:"meshKey,omitempty"`
|
|
|
|
|
|
|
|
|
|
// CanAckPings is whether the client declares it's able to ack
|
|
|
|
|
// pings.
|
|
|
|
|
CanAckPings bool
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *Client) sendClientKey() error {
|
|
|
|
@ -155,8 +168,9 @@ func (c *Client) sendClientKey() error {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
msg, err := json.Marshal(clientInfo{
|
|
|
|
|
Version: ProtocolVersion,
|
|
|
|
|
MeshKey: c.meshKey,
|
|
|
|
|
Version: ProtocolVersion,
|
|
|
|
|
MeshKey: c.meshKey,
|
|
|
|
|
CanAckPings: c.canAckPings,
|
|
|
|
|
})
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|