This commit is contained in:
2026-02-19 10:07:43 +00:00
parent 007438e372
commit 6e637ecf77
1763 changed files with 60820 additions and 279516 deletions

View File

@@ -30,7 +30,7 @@ type Client struct {
logf logger.Logf
nc Conn
br *bufio.Reader
meshKey string
meshKey key.DERPMesh
canAckPings bool
isProber bool
@@ -56,7 +56,7 @@ func (f clientOptFunc) update(o *clientOpt) { f(o) }
// clientOpt are the options passed to newClient.
type clientOpt struct {
MeshKey string
MeshKey key.DERPMesh
ServerPub key.NodePublic
CanAckPings bool
IsProber bool
@@ -66,7 +66,7 @@ type clientOpt struct {
// access to join the mesh.
//
// An empty key means to not use a mesh key.
func MeshKey(key string) ClientOpt { return clientOptFunc(func(o *clientOpt) { o.MeshKey = key }) }
func MeshKey(k key.DERPMesh) ClientOpt { return clientOptFunc(func(o *clientOpt) { o.MeshKey = k }) }
// IsProber returns a ClientOpt to pass to the DERP server during connect to
// declare that this client is a a prober.
@@ -133,17 +133,17 @@ func (c *Client) recvServerKey() error {
if err != nil {
return err
}
if flen < uint32(len(buf)) || t != frameServerKey || string(buf[:len(magic)]) != magic {
if flen < uint32(len(buf)) || t != FrameServerKey || string(buf[:len(Magic)]) != Magic {
return errors.New("invalid server greeting")
}
c.serverKey = key.NodePublicFromRaw32(mem.B(buf[len(magic):]))
c.serverKey = key.NodePublicFromRaw32(mem.B(buf[len(Magic):]))
return nil
}
func (c *Client) parseServerInfo(b []byte) (*serverInfo, error) {
const maxLength = nonceLen + maxInfoLen
func (c *Client) parseServerInfo(b []byte) (*ServerInfo, error) {
const maxLength = NonceLen + MaxInfoLen
fl := len(b)
if fl < nonceLen {
if fl < NonceLen {
return nil, fmt.Errorf("short serverInfo frame")
}
if fl > maxLength {
@@ -153,19 +153,21 @@ func (c *Client) parseServerInfo(b []byte) (*serverInfo, error) {
if !ok {
return nil, fmt.Errorf("failed to open naclbox from server key %s", c.serverKey)
}
info := new(serverInfo)
info := new(ServerInfo)
if err := json.Unmarshal(msg, info); err != nil {
return nil, fmt.Errorf("invalid JSON: %v", err)
}
return info, nil
}
type clientInfo struct {
// ClientInfo is the information a DERP client sends to the server
// about itself when it connects.
type ClientInfo struct {
// MeshKey optionally specifies a pre-shared key used by
// trusted clients. It's required to subscribe to the
// connection list & forward packets. It's empty for regular
// users.
MeshKey string `json:"meshKey,omitempty"`
MeshKey key.DERPMesh `json:"meshKey,omitempty,omitzero"`
// Version is the DERP protocol version that the client was built with.
// See the ProtocolVersion const.
@@ -179,8 +181,19 @@ type clientInfo struct {
IsProber bool `json:",omitempty"`
}
// Equal reports if two clientInfo values are equal.
func (c *ClientInfo) Equal(other *ClientInfo) bool {
if c == nil || other == nil {
return c == other
}
if c.Version != other.Version || c.CanAckPings != other.CanAckPings || c.IsProber != other.IsProber {
return false
}
return c.MeshKey.Equal(other.MeshKey)
}
func (c *Client) sendClientKey() error {
msg, err := json.Marshal(clientInfo{
msg, err := json.Marshal(ClientInfo{
Version: ProtocolVersion,
MeshKey: c.meshKey,
CanAckPings: c.canAckPings,
@@ -191,10 +204,10 @@ func (c *Client) sendClientKey() error {
}
msgbox := c.privateKey.SealTo(c.serverKey, msg)
buf := make([]byte, 0, keyLen+len(msgbox))
buf := make([]byte, 0, KeyLen+len(msgbox))
buf = c.publicKey.AppendTo(buf)
buf = append(buf, msgbox...)
return writeFrame(c.bw, frameClientInfo, buf)
return WriteFrame(c.bw, FrameClientInfo, buf)
}
// ServerPublicKey returns the server's public key.
@@ -219,12 +232,12 @@ func (c *Client) send(dstKey key.NodePublic, pkt []byte) (ret error) {
c.wmu.Lock()
defer c.wmu.Unlock()
if c.rate != nil {
pktLen := frameHeaderLen + key.NodePublicRawLen + len(pkt)
pktLen := FrameHeaderLen + key.NodePublicRawLen + len(pkt)
if !c.rate.AllowN(c.clock.Now(), pktLen) {
return nil // drop
}
}
if err := writeFrameHeader(c.bw, frameSendPacket, uint32(key.NodePublicRawLen+len(pkt))); err != nil {
if err := WriteFrameHeader(c.bw, FrameSendPacket, uint32(key.NodePublicRawLen+len(pkt))); err != nil {
return err
}
if _, err := c.bw.Write(dstKey.AppendTo(nil)); err != nil {
@@ -253,7 +266,7 @@ func (c *Client) ForwardPacket(srcKey, dstKey key.NodePublic, pkt []byte) (err e
timer := c.clock.AfterFunc(5*time.Second, c.writeTimeoutFired)
defer timer.Stop()
if err := writeFrameHeader(c.bw, frameForwardPacket, uint32(keyLen*2+len(pkt))); err != nil {
if err := WriteFrameHeader(c.bw, FrameForwardPacket, uint32(KeyLen*2+len(pkt))); err != nil {
return err
}
if _, err := c.bw.Write(srcKey.AppendTo(nil)); err != nil {
@@ -271,17 +284,17 @@ func (c *Client) ForwardPacket(srcKey, dstKey key.NodePublic, pkt []byte) (err e
func (c *Client) writeTimeoutFired() { c.nc.Close() }
func (c *Client) SendPing(data [8]byte) error {
return c.sendPingOrPong(framePing, data)
return c.sendPingOrPong(FramePing, data)
}
func (c *Client) SendPong(data [8]byte) error {
return c.sendPingOrPong(framePong, data)
return c.sendPingOrPong(FramePong, data)
}
func (c *Client) sendPingOrPong(typ frameType, data [8]byte) error {
func (c *Client) sendPingOrPong(typ FrameType, data [8]byte) error {
c.wmu.Lock()
defer c.wmu.Unlock()
if err := writeFrameHeader(c.bw, typ, 8); err != nil {
if err := WriteFrameHeader(c.bw, typ, 8); err != nil {
return err
}
if _, err := c.bw.Write(data[:]); err != nil {
@@ -303,7 +316,7 @@ func (c *Client) NotePreferred(preferred bool) (err error) {
c.wmu.Lock()
defer c.wmu.Unlock()
if err := writeFrameHeader(c.bw, frameNotePreferred, 1); err != nil {
if err := WriteFrameHeader(c.bw, FrameNotePreferred, 1); err != nil {
return err
}
var b byte = 0x00
@@ -321,7 +334,7 @@ func (c *Client) NotePreferred(preferred bool) (err error) {
func (c *Client) WatchConnectionChanges() error {
c.wmu.Lock()
defer c.wmu.Unlock()
if err := writeFrameHeader(c.bw, frameWatchConns, 0); err != nil {
if err := WriteFrameHeader(c.bw, FrameWatchConns, 0); err != nil {
return err
}
return c.bw.Flush()
@@ -332,7 +345,7 @@ func (c *Client) WatchConnectionChanges() error {
func (c *Client) ClosePeer(target key.NodePublic) error {
c.wmu.Lock()
defer c.wmu.Unlock()
return writeFrame(c.bw, frameClosePeer, target.AppendTo(nil))
return WriteFrame(c.bw, FrameClosePeer, target.AppendTo(nil))
}
// ReceivedMessage represents a type returned by Client.Recv. Unless
@@ -491,7 +504,7 @@ func (c *Client) recvTimeout(timeout time.Duration) (m ReceivedMessage, err erro
c.peeked = 0
}
t, n, err := readFrameHeader(c.br)
t, n, err := ReadFrameHeader(c.br)
if err != nil {
return nil, err
}
@@ -522,7 +535,7 @@ func (c *Client) recvTimeout(timeout time.Duration) (m ReceivedMessage, err erro
switch t {
default:
continue
case frameServerInfo:
case FrameServerInfo:
// Server sends this at start-up. Currently unused.
// Just has a JSON message saying "version: 2",
// but the protocol seems extensible enough as-is without
@@ -539,29 +552,29 @@ func (c *Client) recvTimeout(timeout time.Duration) (m ReceivedMessage, err erro
}
c.setSendRateLimiter(sm)
return sm, nil
case frameKeepAlive:
case FrameKeepAlive:
// A one-way keep-alive message that doesn't require an acknowledgement.
// This predated framePing/framePong.
return KeepAliveMessage{}, nil
case framePeerGone:
if n < keyLen {
case FramePeerGone:
if n < KeyLen {
c.logf("[unexpected] dropping short peerGone frame from DERP server")
continue
}
// Backward compatibility for the older peerGone without reason byte
reason := PeerGoneReasonDisconnected
if n > keyLen {
reason = PeerGoneReasonType(b[keyLen])
if n > KeyLen {
reason = PeerGoneReasonType(b[KeyLen])
}
pg := PeerGoneMessage{
Peer: key.NodePublicFromRaw32(mem.B(b[:keyLen])),
Peer: key.NodePublicFromRaw32(mem.B(b[:KeyLen])),
Reason: reason,
}
return pg, nil
case framePeerPresent:
case FramePeerPresent:
remain := b
chunk, remain, ok := cutLeadingN(remain, keyLen)
chunk, remain, ok := cutLeadingN(remain, KeyLen)
if !ok {
c.logf("[unexpected] dropping short peerPresent frame from DERP server")
continue
@@ -589,17 +602,17 @@ func (c *Client) recvTimeout(timeout time.Duration) (m ReceivedMessage, err erro
msg.Flags = PeerPresentFlags(chunk[0])
return msg, nil
case frameRecvPacket:
case FrameRecvPacket:
var rp ReceivedPacket
if n < keyLen {
if n < KeyLen {
c.logf("[unexpected] dropping short packet from DERP server")
continue
}
rp.Source = key.NodePublicFromRaw32(mem.B(b[:keyLen]))
rp.Data = b[keyLen:n]
rp.Source = key.NodePublicFromRaw32(mem.B(b[:KeyLen]))
rp.Data = b[KeyLen:n]
return rp, nil
case framePing:
case FramePing:
var pm PingMessage
if n < 8 {
c.logf("[unexpected] dropping short ping frame")
@@ -608,7 +621,7 @@ func (c *Client) recvTimeout(timeout time.Duration) (m ReceivedMessage, err erro
copy(pm[:], b[:])
return pm, nil
case framePong:
case FramePong:
var pm PongMessage
if n < 8 {
c.logf("[unexpected] dropping short ping frame")
@@ -617,10 +630,10 @@ func (c *Client) recvTimeout(timeout time.Duration) (m ReceivedMessage, err erro
copy(pm[:], b[:])
return pm, nil
case frameHealth:
case FrameHealth:
return HealthMessage{Problem: string(b[:])}, nil
case frameRestarting:
case FrameRestarting:
var m ServerRestartingMessage
if n < 8 {
c.logf("[unexpected] dropping short server restarting frame")