Path.hpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  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: 2024-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. #ifndef ZT_PATH_HPP
  14. #define ZT_PATH_HPP
  15. #include <cstdint>
  16. #include <cstring>
  17. #include <cstdlib>
  18. #include <stdexcept>
  19. #include <algorithm>
  20. #include "Constants.hpp"
  21. #include "InetAddress.hpp"
  22. #include "SharedPtr.hpp"
  23. #include "AtomicCounter.hpp"
  24. #include "Utils.hpp"
  25. #include "Mutex.hpp"
  26. namespace ZeroTier {
  27. class RuntimeEnvironment;
  28. /**
  29. * A path across the physical network
  30. */
  31. class Path
  32. {
  33. friend class SharedPtr<Path>;
  34. public:
  35. /**
  36. * Efficient unique key for paths in a Hashtable
  37. */
  38. class HashKey
  39. {
  40. public:
  41. ZT_ALWAYS_INLINE HashKey() {}
  42. ZT_ALWAYS_INLINE HashKey(const int64_t l,const InetAddress &r)
  43. {
  44. if (r.ss_family == AF_INET) {
  45. _k[0] = (uint64_t)reinterpret_cast<const struct sockaddr_in *>(&r)->sin_addr.s_addr;
  46. _k[1] = (uint64_t)reinterpret_cast<const struct sockaddr_in *>(&r)->sin_port;
  47. _k[2] = (uint64_t)l;
  48. } else if (r.ss_family == AF_INET6) {
  49. memcpy(_k,reinterpret_cast<const struct sockaddr_in6 *>(&r)->sin6_addr.s6_addr,16);
  50. _k[2] = ((uint64_t)reinterpret_cast<const struct sockaddr_in6 *>(&r)->sin6_port << 32) ^ (uint64_t)l;
  51. } else {
  52. memcpy(_k,&r,std::min(sizeof(_k),sizeof(InetAddress)));
  53. _k[2] += (uint64_t)l;
  54. }
  55. }
  56. ZT_ALWAYS_INLINE unsigned long hashCode() const { return (unsigned long)(_k[0] + _k[1] + _k[2]); }
  57. ZT_ALWAYS_INLINE bool operator==(const HashKey &k) const { return ( (_k[0] == k._k[0]) && (_k[1] == k._k[1]) && (_k[2] == k._k[2]) ); }
  58. ZT_ALWAYS_INLINE bool operator!=(const HashKey &k) const { return (!(*this == k)); }
  59. private:
  60. uint64_t _k[3];
  61. };
  62. ZT_ALWAYS_INLINE Path(const int64_t l,const InetAddress &r) :
  63. _localSocket(l),
  64. _lastIn(0),
  65. _lastOut(0),
  66. _addr(r),
  67. __refCount()
  68. {
  69. }
  70. /**
  71. * Send a packet via this path (last out time is also updated)
  72. *
  73. * @param RR Runtime environment
  74. * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
  75. * @param data Packet data
  76. * @param len Packet length
  77. * @param now Current time
  78. * @return True if transport reported success
  79. */
  80. bool send(const RuntimeEnvironment *RR,void *tPtr,const void *data,unsigned int len,int64_t now);
  81. /**
  82. * Explicitly update last sent time
  83. *
  84. * @param t Time of send
  85. */
  86. ZT_ALWAYS_INLINE void sent(const int64_t t) { _lastOut = t; }
  87. /**
  88. * Called when a packet is received from this remote path, regardless of content
  89. *
  90. * @param t Time of receive
  91. */
  92. ZT_ALWAYS_INLINE void received(const int64_t t) { _lastIn = t; }
  93. /**
  94. * Check path aliveness
  95. *
  96. * @param now Current time
  97. */
  98. ZT_ALWAYS_INLINE bool alive(const int64_t now) const { return ((now - _lastIn) < ZT_PATH_ACTIVITY_TIMEOUT); }
  99. /**
  100. * @return Physical address
  101. */
  102. ZT_ALWAYS_INLINE const InetAddress &address() const { return _addr; }
  103. /**
  104. * @return Local socket as specified by external code
  105. */
  106. ZT_ALWAYS_INLINE int64_t localSocket() const { return _localSocket; }
  107. /**
  108. * @return Last time we received anything
  109. */
  110. ZT_ALWAYS_INLINE int64_t lastIn() const { return _lastIn; }
  111. /**
  112. * @return Last time we sent something
  113. */
  114. ZT_ALWAYS_INLINE int64_t lastOut() const { return _lastOut; }
  115. /**
  116. * Check whether this address is valid for a ZeroTier path
  117. *
  118. * This checks the address type and scope against address types and scopes
  119. * that we currently support for ZeroTier communication.
  120. *
  121. * @param a Address to check
  122. * @return True if address is good for ZeroTier path use
  123. */
  124. static bool isAddressValidForPath(const InetAddress &a);
  125. private:
  126. int64_t _localSocket;
  127. int64_t _lastIn;
  128. int64_t _lastOut;
  129. InetAddress _addr;
  130. AtomicCounter __refCount;
  131. };
  132. } // namespace ZeroTier
  133. #endif