|
|
|
@ -70,7 +70,7 @@ func Parse(p []byte) (Message, error) {
|
|
|
|
|
case TypePong:
|
|
|
|
|
return parsePong(ver, p)
|
|
|
|
|
case TypeCallMeMaybe:
|
|
|
|
|
return CallMeMaybe{}, nil
|
|
|
|
|
return parseCallMeMaybe(ver, p)
|
|
|
|
|
default:
|
|
|
|
|
return nil, fmt.Errorf("unknown message type 0x%02x", byte(t))
|
|
|
|
|
}
|
|
|
|
@ -122,13 +122,49 @@ func parsePing(ver uint8, p []byte) (m *Ping, err error) {
|
|
|
|
|
//
|
|
|
|
|
// The recipient may choose to not open a path back, if it's already
|
|
|
|
|
// happy with its path. But usually it will.
|
|
|
|
|
type CallMeMaybe struct{}
|
|
|
|
|
|
|
|
|
|
func (CallMeMaybe) AppendMarshal(b []byte) []byte {
|
|
|
|
|
ret, _ := appendMsgHeader(b, TypeCallMeMaybe, v0, 0)
|
|
|
|
|
type CallMeMaybe struct {
|
|
|
|
|
// MyNumber is what the peer believes its endpoints are.
|
|
|
|
|
// Tailscale clients before 1.4 did not populate this
|
|
|
|
|
// so these values should merely augment whetever the control
|
|
|
|
|
// server sends. But because the client could've been idle
|
|
|
|
|
// before it reached out to us, the control plane might
|
|
|
|
|
// have stale info and these endpoints in CallMeMaybe
|
|
|
|
|
// might contain the just-obtained-milliseconds-ago
|
|
|
|
|
// STUN endpoint.
|
|
|
|
|
MyNumber []netaddr.IPPort
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const epLength = 16 + 2 // 16 byte IP address + 2 byte port
|
|
|
|
|
|
|
|
|
|
func (m *CallMeMaybe) AppendMarshal(b []byte) []byte {
|
|
|
|
|
ret, p := appendMsgHeader(b, TypeCallMeMaybe, v0, epLength*len(m.MyNumber))
|
|
|
|
|
for _, ipp := range m.MyNumber {
|
|
|
|
|
a := ipp.IP.As16()
|
|
|
|
|
copy(p[:], a[:])
|
|
|
|
|
binary.BigEndian.PutUint16(p[16:], ipp.Port)
|
|
|
|
|
p = p[epLength:]
|
|
|
|
|
}
|
|
|
|
|
return ret
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func parseCallMeMaybe(ver uint8, p []byte) (m *CallMeMaybe, err error) {
|
|
|
|
|
m = new(CallMeMaybe)
|
|
|
|
|
if len(p)%epLength != 0 || ver != 0 || len(p) == 0 {
|
|
|
|
|
return m, nil
|
|
|
|
|
}
|
|
|
|
|
m.MyNumber = make([]netaddr.IPPort, 0, len(p)/epLength)
|
|
|
|
|
for len(p) > 0 {
|
|
|
|
|
var a [16]byte
|
|
|
|
|
copy(a[:], p)
|
|
|
|
|
m.MyNumber = append(m.MyNumber, netaddr.IPPort{
|
|
|
|
|
IP: netaddr.IPFrom16(a),
|
|
|
|
|
Port: binary.BigEndian.Uint16(p[16:18]),
|
|
|
|
|
})
|
|
|
|
|
p = p[epLength:]
|
|
|
|
|
}
|
|
|
|
|
return m, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Pong is a response a Ping.
|
|
|
|
|
//
|
|
|
|
|
// It includes the sender's source IP + port, so it's effectively a
|
|
|
|
@ -171,7 +207,7 @@ func MessageSummary(m Message) string {
|
|
|
|
|
return fmt.Sprintf("ping tx=%x", m.TxID[:6])
|
|
|
|
|
case *Pong:
|
|
|
|
|
return fmt.Sprintf("pong tx=%x", m.TxID[:6])
|
|
|
|
|
case CallMeMaybe:
|
|
|
|
|
case *CallMeMaybe:
|
|
|
|
|
return "call-me-maybe"
|
|
|
|
|
default:
|
|
|
|
|
return fmt.Sprintf("%#v", m)
|
|
|
|
|