address.go 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  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. import (
  15. "encoding/json"
  16. "fmt"
  17. "strconv"
  18. )
  19. // Address represents a 40-bit short ZeroTier address
  20. type Address uint64
  21. // NewAddressFromString parses a 10-digit ZeroTier address
  22. func NewAddressFromString(s string) (Address, error) {
  23. if len(s) != 10 {
  24. return Address(0), ErrInvalidZeroTierAddress
  25. }
  26. a, err := strconv.ParseUint(s, 16, 64)
  27. return Address(a & 0xffffffffff), err
  28. }
  29. // NewAddressFromBytes reads a 5-byte 40-bit address.
  30. func NewAddressFromBytes(b []byte) (Address, error) {
  31. if len(b) < 5 {
  32. return Address(0), ErrInvalidZeroTierAddress
  33. }
  34. return Address((uint64(b[0]) << 32) | (uint64(b[1]) << 24) | (uint64(b[2]) << 16) | (uint64(b[3]) << 8) | uint64(b[4])), nil
  35. }
  36. // CopyTo writes this address to five bytes.
  37. // If b cannot store five bytes this will panic.
  38. func (a Address) CopyTo(b []byte) {
  39. _ = b[4]
  40. b[0] = byte(a >> 32)
  41. b[1] = byte(a >> 24)
  42. b[2] = byte(a >> 16)
  43. b[3] = byte(a >> 8)
  44. b[4] = byte(a)
  45. }
  46. // IsReserved returns true if this address is reserved and therefore is not valid for a real node.
  47. func (a Address) IsReserved() bool { return a == 0 || (a>>32) == 0xff }
  48. // String returns this address's 10-digit hex identifier.
  49. func (a Address) String() string {
  50. return fmt.Sprintf("%.10x", uint64(a))
  51. }
  52. // MarshalJSON marshals this Address as a string
  53. func (a Address) MarshalJSON() ([]byte, error) {
  54. return []byte(fmt.Sprintf("\"%.10x\"", uint64(a))), nil
  55. }
  56. // UnmarshalJSON unmarshals this Address from a string
  57. func (a *Address) UnmarshalJSON(j []byte) error {
  58. var s string
  59. err := json.Unmarshal(j, &s)
  60. if err != nil {
  61. return err
  62. }
  63. tmp, err := NewAddressFromString(s)
  64. *a = tmp
  65. return err
  66. }