Janitor.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703
  1. /* vim: set expandtab ts=4 sw=4: */
  2. /*
  3. * You may redistribute this program and/or modify it under the terms of
  4. * the GNU General Public License as published by the Free Software Foundation,
  5. * either version 3 of the License, or (at your option) any later version.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. * You should have received a copy of the GNU General Public License
  13. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. #include "crypto/random/Random.h"
  16. #include "dht/Address.h"
  17. #include "dht/dhtcore/Janitor.h"
  18. #include "dht/dhtcore/Node.h"
  19. #include "dht/dhtcore/NodeList.h"
  20. #include "dht/dhtcore/RumorMill.h"
  21. #include "dht/dhtcore/RouterModule.h"
  22. #include "dht/dhtcore/SearchRunner.h"
  23. #include "dht/dhtcore/ReplySerializer.h"
  24. #include "benc/Object.h"
  25. #include "memory/Allocator.h"
  26. #include "switch/LabelSplicer.h"
  27. #include "util/AddrTools.h"
  28. #include "util/AverageRoller.h"
  29. #include "util/Bits.h"
  30. #include "util/events/EventBase.h"
  31. #include "util/Hex.h"
  32. #include "util/events/Timeout.h"
  33. #include "util/events/Time.h"
  34. #include "util/Defined.h"
  35. #include <stdint.h>
  36. #include <stdbool.h>
  37. #define MAX_SEARCHES 10
  38. /**
  39. * The goal of this is to run searches in the local area of this node.
  40. * it searches for hashes every localMaintainenceSearchPeriod milliseconds.
  41. * it runs searches by picking hashes at random, if a hash is chosen and there is a
  42. * non-zero-reach node which services that space, it stops. This way it will run many
  43. * searches early on but as the number of known nodes increases, it begins to taper off.
  44. */
  45. struct Janitor
  46. {
  47. struct RouterModule* routerModule;
  48. struct NodeStore* nodeStore;
  49. struct SearchRunner* searchRunner;
  50. // Externally accessible RumorMill.
  51. // Used for direct peers and search results that are closer than the responder.
  52. struct RumorMill* rumorMill;
  53. // High priority RumorMill.
  54. // Used to discover new links to nodes we already know about.
  55. struct RumorMill* linkMill;
  56. // Low priority RumorMill.
  57. // Used to discover new nodes.
  58. struct RumorMill* nodeMill;
  59. // Just used to keep track of nodes that we need to check on for DHT health.
  60. struct RumorMill* dhtMill;
  61. struct Timeout* timeout;
  62. struct Log* logger;
  63. uint64_t globalMaintainenceMilliseconds;
  64. uint64_t timeOfNextGlobalMaintainence;
  65. uint64_t localMaintainenceMilliseconds;
  66. struct Allocator* allocator;
  67. uint64_t timeOfNextSearchRepeat;
  68. uint64_t searchRepeatMilliseconds;
  69. struct EventBase* eventBase;
  70. struct Random* rand;
  71. /** Number of concurrent searches taking place. */
  72. int searches;
  73. Identity
  74. };
  75. struct Janitor_Search
  76. {
  77. struct Janitor* janitor;
  78. struct Address best;
  79. uint8_t target[16];
  80. struct Allocator* alloc;
  81. Identity
  82. };
  83. static void responseCallback(struct RouterModule_Promise* promise,
  84. uint32_t lagMilliseconds,
  85. struct Address* from,
  86. Dict* result)
  87. {
  88. struct Janitor_Search* search = Identity_check((struct Janitor_Search*)promise->userData);
  89. if (from) {
  90. Bits_memcpyConst(&search->best, from, sizeof(struct Address));
  91. return;
  92. }
  93. search->janitor->searches--;
  94. if (!search->best.path) {
  95. Log_debug(search->janitor->logger, "Search completed with no nodes found");
  96. }
  97. Allocator_free(search->alloc);
  98. }
  99. static void search(uint8_t target[16], struct Janitor* janitor)
  100. {
  101. if (janitor->searches >= MAX_SEARCHES) {
  102. Log_debug(janitor->logger, "Skipping search because 20 are in progress");
  103. return;
  104. }
  105. #ifdef Log_DEBUG
  106. uint8_t targetStr[40];
  107. AddrTools_printIp(targetStr, target);
  108. Log_debug(janitor->logger, "Beginning search for [%s]", targetStr);
  109. #endif
  110. struct Allocator* searchAlloc = Allocator_child(janitor->allocator);
  111. struct RouterModule_Promise* rp =
  112. SearchRunner_search(target, -1, janitor->searchRunner, searchAlloc);
  113. if (!rp) {
  114. Log_debug(janitor->logger, "SearchRunner_search() returned NULL, probably full.");
  115. Allocator_free(searchAlloc);
  116. return;
  117. }
  118. janitor->searches++;
  119. struct Janitor_Search* search = Allocator_clone(rp->alloc, (&(struct Janitor_Search) {
  120. .janitor = janitor,
  121. .alloc = searchAlloc,
  122. }));
  123. Identity_set(search);
  124. Bits_memcpyConst(search->target, target, 16);
  125. rp->callback = responseCallback;
  126. rp->userData = search;
  127. }
  128. static void searchNoDupe(uint8_t target[Address_SEARCH_TARGET_SIZE], struct Janitor* janitor)
  129. {
  130. // See if we're already searching for this address.
  131. struct Allocator* seachListAlloc = Allocator_child(janitor->allocator);
  132. struct SearchRunner_SearchData* searchData;
  133. for (int i = 0; i < SearchRunner_DEFAULT_MAX_CONCURRENT_SEARCHES; i++) {
  134. searchData = SearchRunner_showActiveSearch(janitor->searchRunner,
  135. i,
  136. seachListAlloc);
  137. if (!searchData) { continue; }
  138. if (!Bits_memcmp(searchData->target, target, Address_SEARCH_TARGET_SIZE)) {
  139. // Already have a search going for this address, so nothing to do.
  140. Allocator_free(seachListAlloc);
  141. return;
  142. }
  143. }
  144. Allocator_free(seachListAlloc);
  145. // There's no search running for this address, so we start one.
  146. search(target, janitor);
  147. #ifdef Log_DEBUG
  148. uint8_t addrStr[40];
  149. AddrTools_printIp(addrStr, target);
  150. Log_debug(janitor->logger, "No active search for [%s], starting one.", addrStr);
  151. #endif
  152. }
  153. static void dhtResponseCallback(struct RouterModule_Promise* promise,
  154. uint32_t lagMilliseconds,
  155. struct Address* from,
  156. Dict* result)
  157. {
  158. struct Janitor* janitor = Identity_check((struct Janitor*)promise->userData);
  159. if (!from) { return; }
  160. struct Address_List* addresses =
  161. ReplySerializer_parse(from, result, janitor->logger, true, promise->alloc);
  162. struct Node_Two* parent = NodeStore_nodeForAddr(janitor->nodeStore, from->ip6.bytes);
  163. if (!parent) { return; }
  164. struct Address* selfAddr = janitor->nodeStore->selfAddress;
  165. for (int i = 0; addresses && i < addresses->length; i++) {
  166. if (addresses->elems[i].path == NodeStore_optimizePath_INVALID) {
  167. // Impossible to ping this (label is probably too large).
  168. continue;
  169. }
  170. if (Address_closest(selfAddr, from, &addresses->elems[i]) < 0) {
  171. // Address is further from us than the node we asked. Skip it.
  172. // FIXME(arceliar): Probably need stronger requirements than this.
  173. continue;
  174. }
  175. struct Node_Link* link = NodeStore_linkForPath(janitor->nodeStore,
  176. addresses->elems[i].path);
  177. if (link) {
  178. // We already know about this path and mill space is precious. Skip it.
  179. continue;
  180. }
  181. // Possibly interesting for dht reasons.
  182. RumorMill_addNode(janitor->dhtMill, &addresses->elems[i]);
  183. }
  184. }
  185. static void peersResponseCallback(struct RouterModule_Promise* promise,
  186. uint32_t lagMilliseconds,
  187. struct Address* from,
  188. Dict* result)
  189. {
  190. struct Janitor* janitor = Identity_check((struct Janitor*)promise->userData);
  191. if (!from) { return; }
  192. struct Address_List* addresses =
  193. ReplySerializer_parse(from, result, janitor->logger, true, promise->alloc);
  194. struct Node_Two* parent = NodeStore_nodeForAddr(janitor->nodeStore, from->ip6.bytes);
  195. if (!parent) { return; }
  196. int loopCount = 0;
  197. for (int i = 0; addresses && i < addresses->length; i++) {
  198. // they're telling us about themselves, how helpful...
  199. if (!Bits_memcmp(addresses->elems[i].key, from->key, 32)) { continue; }
  200. struct Node_Link* nl = NodeStore_linkForPath(janitor->nodeStore, addresses->elems[i].path);
  201. if (!nl || Bits_memcmp(nl->child->address.ip6.bytes,
  202. addresses->elems[i].ip6.bytes,
  203. Address_SEARCH_TARGET_SIZE))
  204. {
  205. struct Node_Two* node = NodeStore_nodeForAddr(janitor->nodeStore,
  206. addresses->elems[i].ip6.bytes);
  207. if (node) {
  208. RumorMill_addNode(janitor->linkMill, &addresses->elems[i]);
  209. } else {
  210. // First check if this node would be useful for keyspace reasons.
  211. uint16_t bucketNodes = 0;
  212. uint16_t bucket = NodeStore_bucketForAddr(janitor->nodeStore->selfAddress,
  213. &addresses->elems[i]);
  214. struct Allocator* nodeListAlloc = Allocator_child(janitor->allocator);
  215. struct NodeList* nodeList = NodeStore_getNodesForBucket(janitor->nodeStore,
  216. nodeListAlloc,
  217. bucket,
  218. NodeStore_bucketSize);
  219. for (uint32_t i = 0 ; i < nodeList->size ; i++) {
  220. if (nodeList->nodes[i] == janitor->nodeStore->selfNode) { continue; }
  221. if (nodeList->nodes[i]->address.path == UINT64_MAX) { continue; }
  222. bucketNodes++;
  223. }
  224. Allocator_free(nodeListAlloc);
  225. if (bucketNodes < NodeStore_bucketSize) {
  226. // Add it and move on to the next address.
  227. RumorMill_addNode(janitor->nodeMill, &addresses->elems[i]);
  228. continue;
  229. }
  230. // If it's not required for keyspace, then check if it can split a path.
  231. node = NodeStore_getNextNode(janitor->nodeStore, NULL);
  232. while (node) {
  233. if (LabelSplicer_routesThrough(node->address.path, addresses->elems[i].path)) {
  234. RumorMill_addNode(janitor->nodeMill, &addresses->elems[i]);
  235. break;
  236. }
  237. node = NodeStore_getNextNode(janitor->nodeStore, node);
  238. }
  239. }
  240. } else if (!Address_isSameIp(&addresses->elems[i], &nl->child->address)) {
  241. if (nl->parent != parent) {
  242. #ifdef Log_INFO
  243. uint8_t newAddr[60];
  244. Address_print(newAddr, from);
  245. uint8_t labelStr[20];
  246. AddrTools_printPath(labelStr, nl->cannonicalLabel);
  247. Log_info(janitor->logger, "Apparently [%s] reported [%s] as it's peer",
  248. newAddr, labelStr);
  249. #endif
  250. continue;
  251. }
  252. #ifdef Log_INFO
  253. uint8_t newAddr[60];
  254. Address_print(newAddr, from);
  255. Log_info(janitor->logger, "Apparently [%s] has renumbered it's switch", newAddr);
  256. #endif
  257. struct Node_Link* link = NodeStore_nextLink(parent, NULL);
  258. while (link) {
  259. struct Node_Link* nextLink = NodeStore_nextLink(parent, link);
  260. NodeStore_unlinkNodes(janitor->nodeStore, link);
  261. link = nextLink;
  262. // restart from the beginning...
  263. i = 0;
  264. Assert_true(!loopCount);
  265. }
  266. Assert_true(!NodeStore_nextLink(parent, NULL));
  267. loopCount++;
  268. }
  269. }
  270. }
  271. static bool checkPeers(struct Janitor* janitor, struct Node_Two* n)
  272. {
  273. // Lets check for non-one-hop links at each node along the path between us and this node.
  274. uint64_t path = n->address.path;
  275. struct Node_Link* link = NULL;
  276. for (;;) {
  277. link = NodeStore_firstHopInPath(janitor->nodeStore, path, &path, link);
  278. if (!link) { break; }
  279. if (link->parent == janitor->nodeStore->selfNode) { continue; }
  280. struct Node_Link* l = NULL;
  281. do {
  282. l = NodeStore_nextLink(link->child, l);
  283. if (l && (!Node_isOneHopLink(l) || Node_getReach(link->parent) == 0)) {
  284. struct RouterModule_Promise* rp =
  285. RouterModule_getPeers(&link->parent->address, l->cannonicalLabel, 0,
  286. janitor->routerModule, janitor->allocator);
  287. rp->callback = peersResponseCallback;
  288. rp->userData = janitor;
  289. // Only send max 1 getPeers req per second.
  290. return true;
  291. }
  292. } while (l);
  293. }
  294. return false;
  295. }
  296. /**
  297. * For a Distributed Hash Table to work, each node must know a valid next hop for every possible
  298. * lookup, unless no such node exists in the network (i.e. the final hop is either us or offline).
  299. *
  300. * This function queries other nodes to find valid next hops for any address.
  301. */
  302. static void keyspaceMaintenance(struct Janitor* janitor)
  303. {
  304. struct Address addr;
  305. struct Address* selfAddr = janitor->nodeStore->selfAddress;
  306. if (!RumorMill_getNode(janitor->dhtMill, &addr)) {
  307. // Try to fill the dhtMill for next time.
  308. for (uint16_t bucket = 0; bucket < NodeStore_bucketNumber ; bucket++) {
  309. // Check if there's a valid next hop for this bit in keyspace.
  310. struct Allocator* nodeListAlloc = Allocator_child(janitor->allocator);
  311. struct NodeList* nodeList = NodeStore_getNodesForBucket(janitor->nodeStore,
  312. nodeListAlloc,
  313. bucket,
  314. NodeStore_bucketSize);
  315. for (uint32_t i = 0 ; i < nodeList->size ; i++) {
  316. if (nodeList->nodes[i] == janitor->nodeStore->selfNode) { continue; }
  317. if (nodeList->nodes[i]->address.path == UINT64_MAX) { continue; }
  318. // There's a valid next hop.
  319. RumorMill_addNode(janitor->dhtMill, &nodeList->nodes[i]->address);
  320. }
  321. Allocator_free(nodeListAlloc);
  322. }
  323. return;
  324. }
  325. struct Node_Two* node = NodeStore_nodeForAddr(janitor->nodeStore, addr.ip6.bytes);
  326. if (node && node->address.path == addr.path) {
  327. if (checkPeers(janitor, node)) {
  328. // If the mills never empty, then returning here can block the dht.
  329. // This would be a sign that the nodeStore is too small for the network size.
  330. // Also blocked if we fail to correctly split the link when we find a hop in the middle.
  331. return;
  332. }
  333. //FIXME(arceliar): This target probably isn't optimal.
  334. uint16_t bucket = NodeStore_bucketForAddr(selfAddr, &addr);
  335. struct Address target = NodeStore_addrForBucket(&addr, bucket);
  336. struct RouterModule_Promise* rp = RouterModule_findNode(&addr,
  337. target.ip6.bytes,
  338. 0,
  339. janitor->routerModule,
  340. janitor->allocator);
  341. rp->callback = dhtResponseCallback;
  342. rp->userData = janitor;
  343. #ifdef Log_DEBUG
  344. uint8_t addrStr[60];
  345. Address_print(addrStr, &addr);
  346. Log_debug(janitor->logger, "Sending findNode to [%s] from "
  347. "dht-checking RumorMill", addrStr);
  348. #endif
  349. } else {
  350. // Node not already in our routing table.
  351. // Ping them. If they're good, we'll ask them to findNodes our next round.
  352. RouterModule_pingNode(&addr, 0, janitor->routerModule, janitor->allocator);
  353. #ifdef Log_DEBUG
  354. uint8_t addrStr[60];
  355. Address_print(addrStr, &addr);
  356. Log_debug(janitor->logger, "Pinging possible node [%s] from "
  357. "dht-checking RumorMill", addrStr);
  358. #endif
  359. }
  360. return;
  361. searchNoDupe(addr.ip6.bytes, janitor); // The last search, unaccessible.
  362. }
  363. // Iterate over all nodes in the table. Try to split any split-able links.
  364. static void splitLinks(struct Janitor* janitor)
  365. {
  366. return; // TODO(cjd): Enabled until we figure out if it's still needed.
  367. struct Node_Two* node = NodeStore_getNextNode(janitor->nodeStore, NULL);
  368. while (node) {
  369. struct Node_Link* bestParent = Node_getBestParent(node);
  370. if (bestParent) {
  371. struct Node_Link* link = NodeStore_nextLink(node, NULL);
  372. while (link) {
  373. if (!Node_isOneHopLink(link)) {
  374. RumorMill_addNode(janitor->linkMill, &node->address);
  375. break;
  376. }
  377. link = NodeStore_nextLink(node, link);
  378. }
  379. }
  380. node = NodeStore_getNextNode(janitor->nodeStore, node);
  381. }
  382. }
  383. static struct Node_Two* getRandomNode(struct Random* rand, struct NodeStore* store)
  384. {
  385. uint32_t index = Random_uint32(rand) % (store->nodeCount);
  386. struct Node_Two* node = NULL;
  387. do {
  388. node = NodeStore_getNextNode(store, node);
  389. } while (index--);
  390. // there's always the self node
  391. Assert_true(node);
  392. return node;
  393. }
  394. static void getPeersMill(struct Janitor* janitor, struct Address* addr)
  395. {
  396. // If we have a node in the store and we ping the same path with a different address
  397. // it can cause an error packet which causes the *good* link to be destroyed.
  398. // Therefore we will always ping the node which we believe to be at the end of the
  399. // path and if there is an error, we will flush the link rediscover the path later.
  400. struct Node_Link* nl = NodeStore_linkForPath(janitor->nodeStore, addr->path);
  401. if (nl) {
  402. addr = &nl->child->address;
  403. }
  404. struct RouterModule_Promise* rp =
  405. RouterModule_getPeers(addr,
  406. Random_uint32(janitor->rand),
  407. 0,
  408. janitor->routerModule,
  409. janitor->allocator);
  410. rp->callback = peersResponseCallback;
  411. rp->userData = janitor;
  412. }
  413. #define debugAddr(janitor, msg, addr) \
  414. if (Defined(Log_DEBUG)) { \
  415. uint8_t addrStr[60]; \
  416. Address_print(addrStr, (addr)); \
  417. Log_debug((janitor)->logger, "%s [%s]", (msg), addrStr); \
  418. } \
  419. do { } while (0)
  420. // CHECKFILES_IGNORE expecting a { or ;
  421. static bool tryExistingNode(struct Janitor* janitor)
  422. {
  423. struct Node_Two* worst = NULL;
  424. uint64_t worstTime = 0;
  425. struct Node_Two* node = NodeStore_getNextNode(janitor->nodeStore, NULL);
  426. while (node) {
  427. uint64_t nodeTime = NodeStore_timeSinceLastPing(janitor->nodeStore, node);
  428. if (node == janitor->nodeStore->selfNode) {
  429. // No reason to ping the selfNode.
  430. } else if (node->address.path != UINT64_MAX &&
  431. (!worst || nodeTime > worstTime))
  432. {
  433. worst = node;
  434. worstTime = nodeTime;
  435. }
  436. node = NodeStore_getNextNode(janitor->nodeStore, node);
  437. }
  438. if (worst) {
  439. getPeersMill(janitor, &worst->address);
  440. debugAddr(janitor, "Pinging existing node", &worst->address);
  441. return true;
  442. }
  443. return false;
  444. }
  445. static bool tryNodeMill(struct Janitor* janitor)
  446. {
  447. struct Address addr = { .protocolVersion = 0 };
  448. if (RumorMill_getNode(janitor->nodeMill, &addr)) {
  449. // ping a node from the low-priority ping queue
  450. getPeersMill(janitor, &addr);
  451. debugAddr(janitor, "Pinging possible node from node-finding RumorMill", &addr);
  452. return true;
  453. }
  454. return false;
  455. }
  456. static bool tryExternalMill(struct Janitor* janitor)
  457. {
  458. struct Address addr = { .protocolVersion = 0 };
  459. if (RumorMill_getNode(janitor->rumorMill, &addr)) {
  460. // ping a node from the externally accessible queue
  461. getPeersMill(janitor, &addr);
  462. debugAddr(janitor, "Pinging possible node from external RumorMill", &addr);
  463. return true;
  464. }
  465. return false;
  466. }
  467. static bool tryLinkMill(struct Janitor* janitor)
  468. {
  469. struct Address addr = { .protocolVersion = 0 };
  470. if (RumorMill_getNode(janitor->linkMill, &addr)) {
  471. // ping a node from the externally accessible queue
  472. getPeersMill(janitor, &addr);
  473. debugAddr(janitor, "Pinging possible node from link-finding RumorMill", &addr);
  474. return true;
  475. }
  476. return false;
  477. }
  478. static bool tryRandomLink(struct Janitor* janitor)
  479. {
  480. // There's not an obvious way to get a random link directly, so first get a random node.
  481. struct Node_Two* node = getRandomNode(janitor->rand, janitor->nodeStore);
  482. // Count the number of links leading from this node.
  483. struct Node_Link* link = NodeStore_nextLink(node, NULL);
  484. uint32_t linkCount = 0;
  485. while (link) {
  486. linkCount++;
  487. link = NodeStore_nextLink(node, link);
  488. }
  489. if (linkCount) {
  490. // Now pick one of these links at random.
  491. uint32_t randLinkIndex = Random_uint32(janitor->rand) % linkCount;
  492. link = NodeStore_nextLink(node, NULL);
  493. linkCount = 0;
  494. while (linkCount < randLinkIndex) {
  495. linkCount++;
  496. link = NodeStore_nextLink(node, link);
  497. }
  498. }
  499. if (link && link->parent != link->child) {
  500. struct Address addr = link->child->address;
  501. uint64_t path = NodeStore_getRouteLabel(janitor->nodeStore,
  502. link->parent->address.path,
  503. link->cannonicalLabel);
  504. if (path != NodeStore_getRouteLabel_PARENT_NOT_FOUND &&
  505. path != NodeStore_getRouteLabel_CHILD_NOT_FOUND)
  506. {
  507. addr.path = path;
  508. }
  509. if (addr.path < UINT64_MAX) {
  510. getPeersMill(janitor, &addr);
  511. #ifdef Log_DEBUG
  512. uint8_t addrStr[60];
  513. Address_print(addrStr, &addr);
  514. Log_debug(janitor->logger, "Pinging random node link [%s] for maintenance.",
  515. addrStr);
  516. #endif
  517. return true;
  518. }
  519. }
  520. return false;
  521. }
  522. static void maintanenceCycle(void* vcontext)
  523. {
  524. struct Janitor* const janitor = Identity_check((struct Janitor*) vcontext);
  525. uint64_t now = Time_currentTimeMilliseconds(janitor->eventBase);
  526. uint64_t nextTimeout = (janitor->localMaintainenceMilliseconds / 2);
  527. nextTimeout += Random_uint32(janitor->rand) % (nextTimeout * 2);
  528. Timeout_resetTimeout(janitor->timeout, nextTimeout);
  529. if (janitor->nodeStore->nodeCount == 0 && janitor->rumorMill->count == 0) {
  530. if (now > janitor->timeOfNextGlobalMaintainence) {
  531. Log_warn(janitor->logger,
  532. "No nodes in routing table, check network connection and configuration.");
  533. janitor->timeOfNextGlobalMaintainence += janitor->globalMaintainenceMilliseconds;
  534. }
  535. return;
  536. }
  537. struct Address addr = { .protocolVersion = 0 };
  538. if (tryExternalMill(janitor)) {
  539. // Always try the external mill first, this is low-traffic.
  540. } else if (tryLinkMill(janitor)) {
  541. // Try to find a new link to a known node.
  542. } else if (tryNodeMill(janitor)) {
  543. // Try to find a new node.
  544. } else if (tryRandomLink(janitor)) {
  545. // Ping a random link from a random node.
  546. } else {
  547. Log_debug(janitor->logger, "Could not find anything to do");
  548. }
  549. // Try to ping the existing node we have heard from least recently.
  550. tryExistingNode(janitor);
  551. // Look for better nodes for the dht.
  552. keyspaceMaintenance(janitor);
  553. // random search
  554. Random_bytes(janitor->rand, addr.ip6.bytes, 16);
  555. // Make this a valid address.
  556. addr.ip6.bytes[0] = 0xfc;
  557. struct Node_Two* n = NodeStore_getBest(janitor->nodeStore, addr.ip6.bytes);
  558. // If the best next node doesn't exist or has 0 reach, run a local maintenance search.
  559. if (n == NULL || Node_getReach(n) == 0) {
  560. //search(addr.ip6.bytes, janitor);
  561. //plugLargestKeyspaceHole(janitor, true);
  562. //return;
  563. } else {
  564. checkPeers(janitor, n);
  565. }
  566. Log_debug(janitor->logger,
  567. "Global Mean Response Time: %u nodes [%d] links [%d]",
  568. RouterModule_globalMeanResponseTime(janitor->routerModule),
  569. janitor->nodeStore->nodeCount,
  570. janitor->nodeStore->linkCount);
  571. if (now > janitor->timeOfNextGlobalMaintainence) {
  572. //search(addr.ip6.bytes, janitor);
  573. splitLinks(janitor);
  574. janitor->timeOfNextGlobalMaintainence += janitor->globalMaintainenceMilliseconds;
  575. }
  576. }
  577. struct Janitor* Janitor_new(uint64_t localMaintainenceMilliseconds,
  578. uint64_t globalMaintainenceMilliseconds,
  579. struct RouterModule* routerModule,
  580. struct NodeStore* nodeStore,
  581. struct SearchRunner* searchRunner,
  582. struct RumorMill* rumorMill,
  583. struct Log* logger,
  584. struct Allocator* allocator,
  585. struct EventBase* eventBase,
  586. struct Random* rand)
  587. {
  588. struct Allocator* alloc = Allocator_child(allocator);
  589. struct Janitor* janitor = Allocator_clone(alloc, (&(struct Janitor) {
  590. .eventBase = eventBase,
  591. .routerModule = routerModule,
  592. .nodeStore = nodeStore,
  593. .searchRunner = searchRunner,
  594. .rumorMill = rumorMill,
  595. .logger = logger,
  596. .globalMaintainenceMilliseconds = globalMaintainenceMilliseconds,
  597. .localMaintainenceMilliseconds = localMaintainenceMilliseconds,
  598. .allocator = alloc,
  599. .rand = rand
  600. }));
  601. Identity_set(janitor);
  602. janitor->linkMill = RumorMill_new(alloc, nodeStore->selfAddress, 64, logger, "linkMill");
  603. janitor->nodeMill = RumorMill_new(alloc, nodeStore->selfAddress, 64, logger, "nodeMill");
  604. janitor->dhtMill = RumorMill_new(alloc,
  605. nodeStore->selfAddress,
  606. (NodeStore_bucketNumber * NodeStore_bucketSize),
  607. logger,
  608. "dhtMill");
  609. janitor->timeOfNextGlobalMaintainence = Time_currentTimeMilliseconds(eventBase);
  610. janitor->timeout = Timeout_setTimeout(maintanenceCycle,
  611. janitor,
  612. localMaintainenceMilliseconds,
  613. eventBase,
  614. alloc);
  615. return janitor;
  616. }