endpoint.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. /*
  2. * Copyright (C)2013-2020 ZeroTier, Inc.
  3. *
  4. * Use of this software is governed by the Business Source License included
  5. * in the LICENSE.TXT file in the project's root directory.
  6. *
  7. * Change Date: 2025-01-01
  8. *
  9. * On the date above, in accordance with the Business Source License, use
  10. * of this software will be governed by version 2.0 of the Apache License.
  11. */
  12. /****/
  13. package zerotier
  14. // #include "../../serviceiocore/GoGlue.h"
  15. // const ZT_Fingerprint *_getFP(const ZT_Endpoint *ep) { return &(ep->value.fp); }
  16. // uint64_t _getAddress(const ZT_Endpoint *ep) { return ep->value.fp.address; }
  17. // uint64_t _getMAC(const ZT_Endpoint *ep) { return ep->value.mac; }
  18. // const struct sockaddr_storage *_getSS(const ZT_Endpoint *ep) { return &(ep->value.ss); }
  19. // void _setSS(ZT_Endpoint *ep,const void *ss) { memcpy(&(ep->value.ss),ss,sizeof(struct sockaddr_storage)); }
  20. import "C"
  21. import (
  22. "encoding/json"
  23. "unsafe"
  24. )
  25. const (
  26. EndpointTypeNil = C.ZT_ENDPOINT_TYPE_NIL
  27. EndpointTypeZeroTier = C.ZT_ENDPOINT_TYPE_ZEROTIER
  28. EndpointTypeEthernet = C.ZT_ENDPOINT_TYPE_ETHERNET
  29. EndpointTypeWifiDirect = C.ZT_ENDPOINT_TYPE_WIFI_DIRECT
  30. EndpointTypeBluetooth = C.ZT_ENDPOINT_TYPE_BLUETOOTH
  31. EndpointTypeIp = C.ZT_ENDPOINT_TYPE_IP
  32. EndpointTypeIpUdp = C.ZT_ENDPOINT_TYPE_IP_UDP
  33. EndpointTypeIpTcp = C.ZT_ENDPOINT_TYPE_IP_TCP
  34. EndpointTypeIpHttp = C.ZT_ENDPOINT_TYPE_IP_HTTP
  35. )
  36. type Endpoint struct {
  37. cep C.ZT_Endpoint
  38. }
  39. func EndpointTypeToString(t int) string {
  40. switch t {
  41. case EndpointTypeZeroTier:
  42. return "zerotier"
  43. case EndpointTypeEthernet:
  44. return "ethernet"
  45. case EndpointTypeWifiDirect:
  46. return "wifi-direct"
  47. case EndpointTypeBluetooth:
  48. return "bluetooth"
  49. case EndpointTypeIp:
  50. return "ip/raw"
  51. case EndpointTypeIpUdp:
  52. return "ip/udp"
  53. case EndpointTypeIpTcp:
  54. return "ip/tcp"
  55. case EndpointTypeIpHttp:
  56. return "ip/http"
  57. }
  58. return "unsupported"
  59. }
  60. // NewEndpointFromString constructs a new endpoint from an InetAddress or Endpoint string.
  61. // This will auto detect whether this is a plain InetAddress or an Endpoint in string
  62. // format. If the former it's created as a ZT_ENDPOINT_TYPE_IP_UDP endpoint.
  63. func NewEndpointFromString(s string) (*Endpoint, error) {
  64. if len(s) == 0 {
  65. var ep Endpoint
  66. ep.cep._type = C.ZT_ENDPOINT_TYPE_NIL
  67. return &ep, nil
  68. }
  69. var ep Endpoint
  70. cs := C.CString(s)
  71. defer C.free(unsafe.Pointer(cs))
  72. if C.ZT_Endpoint_fromString(&ep.cep, cs) != 0 {
  73. return nil, ErrInvalidParameter
  74. }
  75. return &ep, nil
  76. }
  77. func NewEndpointFromInetAddress(addr *InetAddress) (*Endpoint, error) {
  78. var ep Endpoint
  79. var ss C.struct_sockaddr_storage
  80. if !makeSockaddrStorage(addr.IP, addr.Port, &ss) {
  81. return nil, ErrInvalidParameter
  82. }
  83. ep.cep._type = C.ZT_ENDPOINT_TYPE_IP_UDP
  84. C._setSS(&ep.cep, unsafe.Pointer(&ss))
  85. return &ep, nil
  86. }
  87. // Type returns this endpoint's type.
  88. func (ep *Endpoint) Type() int {
  89. return int(ep.cep._type)
  90. }
  91. // TypeString returns a human-readable endpoint type.
  92. func (ep *Endpoint) TypeString() string {
  93. return EndpointTypeToString(int(ep.cep._type))
  94. }
  95. // InetAddress gets this Endpoint as an InetAddress or nil if its type is not addressed by one.
  96. func (ep *Endpoint) InetAddress() *InetAddress {
  97. switch ep.cep._type {
  98. case EndpointTypeIp, EndpointTypeIpUdp, EndpointTypeIpTcp, EndpointTypeIpHttp:
  99. ua := sockaddrStorageToUDPAddr(C._getSS(&ep.cep))
  100. return &InetAddress{IP: ua.IP, Port: ua.Port}
  101. }
  102. return nil
  103. }
  104. // Address returns a ZeroTier address if this is a ZeroTier endpoint or a zero address otherwise.
  105. func (ep *Endpoint) Address() Address {
  106. switch ep.cep._type {
  107. case EndpointTypeZeroTier:
  108. return Address(C._getAddress(&ep.cep))
  109. }
  110. return Address(0)
  111. }
  112. // Fingerprint returns a fingerprint if this is a ZeroTier endpoint or nil otherwise.
  113. func (ep *Endpoint) Fingerprint() *Fingerprint {
  114. switch ep.cep._type {
  115. case EndpointTypeZeroTier:
  116. cfp := C._getFP(&ep.cep)
  117. fp := Fingerprint{Address: Address(cfp.address), Hash: C.GoBytes(unsafe.Pointer(&cfp.hash[0]), 48)}
  118. if allZero(fp.Hash) {
  119. fp.Hash = nil
  120. }
  121. return &fp
  122. }
  123. return nil
  124. }
  125. // MAC returns a MAC address if this is an Ethernet type endpoint or a zero address otherwise.
  126. func (ep *Endpoint) MAC() MAC {
  127. switch ep.cep._type {
  128. case EndpointTypeEthernet, EndpointTypeWifiDirect, EndpointTypeBluetooth:
  129. return MAC(C._getMAC(&ep.cep))
  130. }
  131. return MAC(0)
  132. }
  133. func (ep *Endpoint) String() string {
  134. var buf [4096]byte
  135. cs := C.ZT_Endpoint_toString(&ep.cep, (*C.char)(unsafe.Pointer(&buf[0])), 4096)
  136. if cs == nil {
  137. return "0"
  138. }
  139. return C.GoString(cs)
  140. }
  141. func (ep *Endpoint) MarshalJSON() ([]byte, error) {
  142. s := ep.String()
  143. return json.Marshal(&s)
  144. }
  145. func (ep *Endpoint) UnmarshalJSON(j []byte) error {
  146. var s string
  147. err := json.Unmarshal(j, &s)
  148. if err != nil {
  149. return err
  150. }
  151. ep2, err := NewEndpointFromString(s)
  152. if err != nil {
  153. return err
  154. }
  155. *ep = *ep2
  156. return nil
  157. }
  158. func (ep *Endpoint) setFromCEndpoint(cp *C.ZT_Endpoint) {
  159. ep.cep = *cp
  160. }