mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-07-22 18:32:51 +02:00
115 lines
2.2 KiB
Go
115 lines
2.2 KiB
Go
package zerotier
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"errors"
|
|
)
|
|
|
|
// Endpoint types are the same as the enum values in Endpoint.hpp in the core.
|
|
const (
|
|
EndpointTypeNil = 0
|
|
EndpointTypeInetAddr = 1
|
|
EndpointTypeDnsName = 2
|
|
EndpointTypeZeroTier = 3
|
|
EndpointTypeUrl = 4
|
|
EndpointTypeEthernet = 5
|
|
EndpointTypeUnrecognized = 255
|
|
)
|
|
|
|
type Endpoint struct {
|
|
Type int
|
|
value, value2 interface{}
|
|
}
|
|
|
|
var (
|
|
ErrInvalidEndpoint = errors.New("invalid marshaled endpoint object")
|
|
)
|
|
|
|
func (ep *Endpoint) unmarshalZT(b []byte) (int, error) {
|
|
if len(b) == 0 {
|
|
return 0, ErrInvalidEndpoint
|
|
}
|
|
switch b[0] {
|
|
case EndpointTypeNil:
|
|
*ep = Endpoint{Type: EndpointTypeNil}
|
|
return 1, nil
|
|
case EndpointTypeInetAddr:
|
|
ina := new(InetAddress)
|
|
inlen, err := ina.unmarshalZT(b[1:])
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
*ep = Endpoint{
|
|
Type: EndpointTypeInetAddr,
|
|
value: ina,
|
|
}
|
|
return 1 + inlen, nil
|
|
case EndpointTypeDnsName:
|
|
zeroAt := 1
|
|
for i := 1; i < len(b); i++ {
|
|
if b[i] == 0 {
|
|
zeroAt = i
|
|
break
|
|
}
|
|
}
|
|
if zeroAt == 1 || (1 + zeroAt + 3) > len(b) {
|
|
return 0, ErrInvalidEndpoint
|
|
}
|
|
port := binary.BigEndian.Uint16(b[zeroAt+1:zeroAt+3])
|
|
*ep = Endpoint{
|
|
Type: EndpointTypeDnsName,
|
|
value: string(b[1:zeroAt]),
|
|
value2: &port,
|
|
}
|
|
return zeroAt + 3, nil
|
|
case EndpointTypeZeroTier:
|
|
if len(b) != 54 {
|
|
return 0, ErrInvalidEndpoint
|
|
}
|
|
a, err := NewAddressFromBytes(b[1:6])
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
*ep = Endpoint{
|
|
Type: EndpointTypeZeroTier,
|
|
value: a,
|
|
value2: append(make([]byte, 0, 48), b[6:54]...),
|
|
}
|
|
return 54, nil
|
|
case EndpointTypeUrl:
|
|
zeroAt := 1
|
|
for i := 1; i < len(b); i++ {
|
|
if b[i] == 0 {
|
|
zeroAt = i
|
|
break
|
|
}
|
|
}
|
|
if zeroAt == 1 {
|
|
return 0, ErrInvalidEndpoint
|
|
}
|
|
*ep = Endpoint{
|
|
Type: EndpointTypeUrl,
|
|
value: string(b[1:zeroAt]),
|
|
}
|
|
return zeroAt + 2, nil
|
|
case EndpointTypeEthernet:
|
|
if len(b) != 7 {
|
|
return 0, ErrInvalidEndpoint
|
|
}
|
|
m, err := NewMACFromBytes(b[1:7])
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
*ep = Endpoint{
|
|
Type: EndpointTypeEthernet,
|
|
value: m,
|
|
}
|
|
return 7, nil
|
|
default:
|
|
if len(b) < 2 {
|
|
return 0, ErrInvalidEndpoint
|
|
}
|
|
*ep = Endpoint{Type: EndpointTypeUnrecognized}
|
|
return 1 + int(b[1]), nil
|
|
}
|
|
}
|