Janitor.c 28 KB

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