Topology.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
  1. /*
  2. * Copyright (c)2019 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: 2023-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_TOPOLOGY_HPP
  14. #define ZT_TOPOLOGY_HPP
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include <vector>
  18. #include <stdexcept>
  19. #include <algorithm>
  20. #include <utility>
  21. #include "Constants.hpp"
  22. #include "../include/ZeroTierOne.h"
  23. #include "Address.hpp"
  24. #include "Identity.hpp"
  25. #include "Peer.hpp"
  26. #include "Path.hpp"
  27. #include "Mutex.hpp"
  28. #include "InetAddress.hpp"
  29. #include "Hashtable.hpp"
  30. #include "Root.hpp"
  31. #include "SharedPtr.hpp"
  32. namespace ZeroTier {
  33. class RuntimeEnvironment;
  34. /**
  35. * Database of network topology
  36. */
  37. class Topology
  38. {
  39. public:
  40. inline Topology(const RuntimeEnvironment *renv,const Identity &myId) :
  41. RR(renv),
  42. _myIdentity(myId),
  43. _numConfiguredPhysicalPaths(0) {}
  44. inline ~Topology() {}
  45. /**
  46. * Add a peer to database
  47. *
  48. * This will not replace existing peers. In that case the existing peer
  49. * record is returned.
  50. *
  51. * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
  52. * @param peer Peer to add
  53. * @return New or existing peer (should replace 'peer')
  54. */
  55. inline SharedPtr<Peer> add(const SharedPtr<Peer> &peer)
  56. {
  57. SharedPtr<Peer> np;
  58. {
  59. Mutex::Lock _l(_peers_m);
  60. SharedPtr<Peer> &hp = _peers[peer->address()];
  61. if (!hp)
  62. hp = peer;
  63. np = hp;
  64. }
  65. return np;
  66. }
  67. /**
  68. * Get a peer from its address
  69. *
  70. * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
  71. * @param zta ZeroTier address of peer
  72. * @return Peer or NULL if not found
  73. */
  74. inline SharedPtr<Peer> get(const Address &zta)
  75. {
  76. if (zta == _myIdentity.address())
  77. return SharedPtr<Peer>();
  78. Mutex::Lock l1(_peers_m);
  79. const SharedPtr<Peer> *const ap = _peers.get(zta);
  80. if (ap)
  81. return *ap;
  82. Mutex::Lock l2(_roots_m);
  83. for(std::vector<Root>::const_iterator r(_roots.begin());r!=_roots.end();++r) {
  84. if (r->address() == zta) {
  85. try {
  86. SharedPtr<Peer> rp(new Peer(RR,_myIdentity,r->id()));
  87. _peers[zta] = rp;
  88. return rp;
  89. } catch ( ... ) {}
  90. }
  91. }
  92. return SharedPtr<Peer>();
  93. }
  94. /**
  95. * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
  96. * @param zta ZeroTier address of peer
  97. * @return Identity or NULL identity if not found
  98. */
  99. inline Identity getIdentity(void *tPtr,const Address &zta)
  100. {
  101. if (zta == _myIdentity.address()) {
  102. return _myIdentity;
  103. } else {
  104. Mutex::Lock _l(_peers_m);
  105. const SharedPtr<Peer> *const ap = _peers.get(zta);
  106. if (ap)
  107. return (*ap)->identity();
  108. }
  109. return Identity();
  110. }
  111. /**
  112. * Get a Path object for a given local and remote physical address, creating if needed
  113. *
  114. * @param l Local socket
  115. * @param r Remote address
  116. * @return Pointer to canonicalized Path object
  117. */
  118. inline SharedPtr<Path> getPath(const int64_t l,const InetAddress &r)
  119. {
  120. Mutex::Lock _l(_paths_m);
  121. SharedPtr<Path> &p = _paths[Path::HashKey(l,r)];
  122. if (!p)
  123. p.set(new Path(l,r));
  124. return p;
  125. }
  126. /**
  127. * @param id Identity to check
  128. * @return True if this identity corresponds to a root
  129. */
  130. inline bool isRoot(const Identity &id) const
  131. {
  132. Mutex::Lock l(_roots_m);
  133. for(std::vector<Root>::const_iterator r(_roots.begin());r!=_roots.end();++r) {
  134. if (r->is(id))
  135. return true;
  136. }
  137. return false;
  138. }
  139. /**
  140. * Do periodic tasks such as database cleanup
  141. */
  142. inline void doPeriodicTasks(int64_t now)
  143. {
  144. {
  145. Mutex::Lock _l1(_peers_m);
  146. Hashtable< Address,SharedPtr<Peer> >::Iterator i(_peers);
  147. Address *a = (Address *)0;
  148. SharedPtr<Peer> *p = (SharedPtr<Peer> *)0;
  149. while (i.next(a,p)) {
  150. if (!(*p)->alive(now)) {
  151. _peers.erase(*a);
  152. }
  153. }
  154. }
  155. {
  156. Mutex::Lock _l(_paths_m);
  157. Hashtable< Path::HashKey,SharedPtr<Path> >::Iterator i(_paths);
  158. Path::HashKey *k = (Path::HashKey *)0;
  159. SharedPtr<Path> *p = (SharedPtr<Path> *)0;
  160. while (i.next(k,p)) {
  161. if (p->references() <= 1)
  162. _paths.erase(*k);
  163. }
  164. }
  165. }
  166. /**
  167. * @param now Current time
  168. * @return Number of peers with active direct paths
  169. */
  170. inline unsigned long countActive(int64_t now) const
  171. {
  172. unsigned long cnt = 0;
  173. Mutex::Lock _l(_peers_m);
  174. Hashtable< Address,SharedPtr<Peer> >::Iterator i(const_cast<Topology *>(this)->_peers);
  175. Address *a = (Address *)0;
  176. SharedPtr<Peer> *p = (SharedPtr<Peer> *)0;
  177. while (i.next(a,p)) {
  178. const SharedPtr<Path> pp((*p)->getAppropriatePath(now,false));
  179. if (pp)
  180. ++cnt;
  181. }
  182. return cnt;
  183. }
  184. /**
  185. * Apply a function or function object to all peers
  186. *
  187. * This locks the peer map during execution, so calls to get() etc. during
  188. * eachPeer() will deadlock.
  189. *
  190. * @param f Function to apply
  191. * @tparam F Function or function object type
  192. */
  193. template<typename F>
  194. inline void eachPeer(F f)
  195. {
  196. Mutex::Lock l(_peers_m);
  197. Hashtable< Address,SharedPtr<Peer> >::Iterator i(_peers);
  198. Address *a = (Address *)0;
  199. SharedPtr<Peer> *p = (SharedPtr<Peer> *)0;
  200. while (i.next(a,p)) {
  201. f(*((const SharedPtr<Peer> *)p));
  202. }
  203. }
  204. /**
  205. * Apply a function or function object to all roots
  206. *
  207. * This locks the root list during execution but other operations
  208. * are fine.
  209. *
  210. * @param f Function to apply
  211. * @tparam F function or function object type
  212. */
  213. template<typename F>
  214. inline void eachRoot(F f)
  215. {
  216. Mutex::Lock l(_roots_m);
  217. SharedPtr<Peer> rp;
  218. for(std::vector<Root>::const_iterator i(_roots.begin());i!=_roots.end();++i) {
  219. {
  220. Mutex::Lock l2(_peers_m);
  221. const SharedPtr<Peer> *const ap = _peers.get(i->address());
  222. if (ap) {
  223. rp = *ap;
  224. } else {
  225. rp.set(new Peer(RR,_myIdentity,i->id()));
  226. _peers.set(rp->address(),rp);
  227. }
  228. }
  229. f(*i,rp);
  230. }
  231. }
  232. /**
  233. * Get the best root, rescanning and re-ranking roots periodically
  234. *
  235. * @param now Current time
  236. * @return Best/fastest currently connected root or NULL if none
  237. */
  238. inline SharedPtr<Peer> root(const int64_t now)
  239. {
  240. Mutex::Lock l(_bestRoot_m);
  241. if ((!_bestRoot)||((now - _lastRankedBestRoot) >= ZT_FIND_BEST_ROOT_PERIOD)) {
  242. _bestRoot.zero();
  243. Mutex::Lock l2(_roots_m);
  244. SharedPtr<Peer> rp;
  245. long bestQuality = 2147483647;
  246. for(std::vector<Root>::const_iterator i(_roots.begin());i!=_roots.end();++i) {
  247. {
  248. Mutex::Lock l2(_peers_m);
  249. const SharedPtr<Peer> *const ap = _peers.get(i->address());
  250. if (ap) {
  251. rp = *ap;
  252. } else {
  253. rp.set(new Peer(RR,_myIdentity,i->id()));
  254. _peers.set(rp->address(),rp);
  255. }
  256. }
  257. SharedPtr<Path> path(rp->getAppropriatePath(now,false));
  258. if (path) {
  259. const long pq = path->quality(now);
  260. if (pq < bestQuality) {
  261. bestQuality = pq;
  262. _bestRoot = rp;
  263. }
  264. }
  265. }
  266. }
  267. return _bestRoot;
  268. }
  269. /**
  270. * Get the best relay to a given address, which may or may not be a root
  271. *
  272. * @param now Current time
  273. * @param toAddr Destination address
  274. * @return Best current relay or NULL if none
  275. */
  276. inline SharedPtr<Peer> findRelayTo(const int64_t now,const Address &toAddr)
  277. {
  278. // TODO: in the future this will check 'mesh-like' relays and if enabled consult LF for other roots (for if this is a root)
  279. return root(now);
  280. }
  281. /**
  282. * @param allPeers vector to fill with all current peers
  283. */
  284. inline void getAllPeers(std::vector< SharedPtr<Peer> > &allPeers) const
  285. {
  286. Mutex::Lock l(_peers_m);
  287. allPeers.clear();
  288. allPeers.reserve(_peers.size());
  289. Hashtable< Address,SharedPtr<Peer> >::Iterator i(*(const_cast<Hashtable< Address,SharedPtr<Peer> > *>(&_peers)));
  290. Address *a = (Address *)0;
  291. SharedPtr<Peer> *p = (SharedPtr<Peer> *)0;
  292. while (i.next(a,p)) {
  293. allPeers.push_back(*p);
  294. }
  295. }
  296. /**
  297. * Get info about a path
  298. *
  299. * The supplied result variables are not modified if no special config info is found.
  300. *
  301. * @param physicalAddress Physical endpoint address
  302. * @param mtu Variable set to MTU
  303. * @param trustedPathId Variable set to trusted path ID
  304. */
  305. inline void getOutboundPathInfo(const InetAddress &physicalAddress,unsigned int &mtu,uint64_t &trustedPathId)
  306. {
  307. for(unsigned int i=0,j=_numConfiguredPhysicalPaths;i<j;++i) {
  308. if (_physicalPathConfig[i].first.containsAddress(physicalAddress)) {
  309. trustedPathId = _physicalPathConfig[i].second.trustedPathId;
  310. mtu = _physicalPathConfig[i].second.mtu;
  311. return;
  312. }
  313. }
  314. }
  315. /**
  316. * Get the payload MTU for an outbound physical path (returns default if not configured)
  317. *
  318. * @param physicalAddress Physical endpoint address
  319. * @return MTU
  320. */
  321. inline unsigned int getOutboundPathMtu(const InetAddress &physicalAddress)
  322. {
  323. for(unsigned int i=0,j=_numConfiguredPhysicalPaths;i<j;++i) {
  324. if (_physicalPathConfig[i].first.containsAddress(physicalAddress))
  325. return _physicalPathConfig[i].second.mtu;
  326. }
  327. return ZT_DEFAULT_PHYSMTU;
  328. }
  329. /**
  330. * Get the outbound trusted path ID for a physical address, or 0 if none
  331. *
  332. * @param physicalAddress Physical address to which we are sending the packet
  333. * @return Trusted path ID or 0 if none (0 is not a valid trusted path ID)
  334. */
  335. inline uint64_t getOutboundPathTrust(const InetAddress &physicalAddress)
  336. {
  337. for(unsigned int i=0,j=_numConfiguredPhysicalPaths;i<j;++i) {
  338. if (_physicalPathConfig[i].first.containsAddress(physicalAddress))
  339. return _physicalPathConfig[i].second.trustedPathId;
  340. }
  341. return 0;
  342. }
  343. /**
  344. * Check whether in incoming trusted path marked packet is valid
  345. *
  346. * @param physicalAddress Originating physical address
  347. * @param trustedPathId Trusted path ID from packet (from MAC field)
  348. */
  349. inline bool shouldInboundPathBeTrusted(const InetAddress &physicalAddress,const uint64_t trustedPathId)
  350. {
  351. for(unsigned int i=0,j=_numConfiguredPhysicalPaths;i<j;++i) {
  352. if ((_physicalPathConfig[i].second.trustedPathId == trustedPathId)&&(_physicalPathConfig[i].first.containsAddress(physicalAddress)))
  353. return true;
  354. }
  355. return false;
  356. }
  357. /**
  358. * Set or clear physical path configuration (called via Node::setPhysicalPathConfiguration)
  359. */
  360. inline void setPhysicalPathConfiguration(const struct sockaddr_storage *pathNetwork,const ZT_PhysicalPathConfiguration *pathConfig)
  361. {
  362. if (!pathNetwork) {
  363. _numConfiguredPhysicalPaths = 0;
  364. } else {
  365. std::map<InetAddress,ZT_PhysicalPathConfiguration> cpaths;
  366. for(unsigned int i=0,j=_numConfiguredPhysicalPaths;i<j;++i)
  367. cpaths[_physicalPathConfig[i].first] = _physicalPathConfig[i].second;
  368. if (pathConfig) {
  369. ZT_PhysicalPathConfiguration pc(*pathConfig);
  370. if (pc.mtu <= 0)
  371. pc.mtu = ZT_DEFAULT_PHYSMTU;
  372. else if (pc.mtu < ZT_MIN_PHYSMTU)
  373. pc.mtu = ZT_MIN_PHYSMTU;
  374. else if (pc.mtu > ZT_MAX_PHYSMTU)
  375. pc.mtu = ZT_MAX_PHYSMTU;
  376. cpaths[*(reinterpret_cast<const InetAddress *>(pathNetwork))] = pc;
  377. } else {
  378. cpaths.erase(*(reinterpret_cast<const InetAddress *>(pathNetwork)));
  379. }
  380. unsigned int cnt = 0;
  381. for(std::map<InetAddress,ZT_PhysicalPathConfiguration>::const_iterator i(cpaths.begin());((i!=cpaths.end())&&(cnt<ZT_MAX_CONFIGURABLE_PATHS));++i) {
  382. _physicalPathConfig[cnt].first = i->first;
  383. _physicalPathConfig[cnt].second = i->second;
  384. ++cnt;
  385. }
  386. _numConfiguredPhysicalPaths = cnt;
  387. }
  388. }
  389. private:
  390. const RuntimeEnvironment *const RR;
  391. const Identity _myIdentity;
  392. std::pair<InetAddress,ZT_PhysicalPathConfiguration> _physicalPathConfig[ZT_MAX_CONFIGURABLE_PATHS];
  393. unsigned int _numConfiguredPhysicalPaths;
  394. std::vector<Root> _roots;
  395. SharedPtr<Peer> _bestRoot;
  396. int64_t _lastRankedBestRoot;
  397. Hashtable< Address,SharedPtr<Peer> > _peers;
  398. Hashtable< Path::HashKey,SharedPtr<Path> > _paths;
  399. Mutex _roots_m;
  400. Mutex _bestRoot_m;
  401. Mutex _peers_m;
  402. Mutex _paths_m;
  403. };
  404. } // namespace ZeroTier
  405. #endif