SearchStore.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  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 <https://www.gnu.org/licenses/>.
  14. */
  15. #include "dht/Address.h"
  16. #include "dht/dhtcore/SearchStore.h"
  17. #include "util/Bits.h"
  18. #include "util/log/Log.h"
  19. #include "util/AverageRoller.h"
  20. #include "util/Endian.h"
  21. #include "util/events/Time.h"
  22. /*--------------------Structures--------------------*/
  23. /** An outstanding search for a target. */
  24. struct SearchStore_Search_pvt
  25. {
  26. struct SearchStore_Search pub;
  27. /** Numbert of Address's in searchStack. */
  28. uint16_t searchStackSize;
  29. /** The index to insert the next node in nodesAsked, this will wrap. */
  30. uint16_t nodesAskedIndex;
  31. /** The ID of what we are looking for. */
  32. uint8_t searchTarget[16];
  33. /** The nodes to ask when performing the search. */
  34. struct Address searchStack[SearchStore_SEARCH_NODES];
  35. /** The nodes which have already been queried in this search. */
  36. struct SearchStore_Node nodesAsked[SearchStore_SEARCH_NODES];
  37. };
  38. /*--------------------Functions--------------------*/
  39. /** See: SearchStore.h */
  40. struct SearchStore* SearchStore_new(struct Allocator* allocator, struct Log* logger)
  41. {
  42. return Allocator_clone(allocator, (&(struct SearchStore) {
  43. .allocator = allocator,
  44. .logger = logger
  45. }));
  46. }
  47. /** See: SearchStore.h */
  48. struct SearchStore_Search* SearchStore_newSearch(uint8_t searchTarget[16],
  49. struct SearchStore* store,
  50. struct Allocator* alloc)
  51. {
  52. struct SearchStore_Search_pvt* search =
  53. Allocator_clone(alloc, (&(struct SearchStore_Search_pvt) {
  54. .pub = {
  55. .callbackContext = NULL,
  56. .store = store,
  57. .alloc = alloc
  58. }
  59. }));
  60. Bits_memcpy(search->searchTarget, searchTarget, Address_SEARCH_TARGET_SIZE);
  61. return &search->pub;
  62. }
  63. /** See: SearchStore.h */
  64. int SearchStore_addNodeToSearch(struct Address* addr, struct SearchStore_Search* search)
  65. {
  66. struct SearchStore_Search_pvt* pvtSearch = (struct SearchStore_Search_pvt*) search;
  67. for (int i = 0; i < SearchStore_SEARCH_NODES; i++) {
  68. if (!Bits_memcmp(addr->key, pvtSearch->nodesAsked[i].address.key, 32)) {
  69. // Already bugged this node, skip.
  70. return -1;
  71. } else if (i == pvtSearch->nodesAskedIndex
  72. && Bits_isZero(pvtSearch->nodesAsked[i].address.key, 32))
  73. {
  74. // short circuit a common case where the nodesAskedIndex has not yet wrapped.
  75. break;
  76. }
  77. }
  78. const uint16_t index =
  79. (pvtSearch->searchStackSize < SearchStore_SEARCH_NODES)
  80. // add it to the end...
  81. ? pvtSearch->searchStackSize++
  82. // nodes are added worst-to-best so replace the last entry.
  83. : pvtSearch->searchStackSize - 1;
  84. Bits_memcpy(&pvtSearch->searchStack[index], addr, Address_SIZE);
  85. return 0;
  86. }
  87. /** See: SearchStore.h */
  88. struct SearchStore_Node* SearchStore_getNextNode(struct SearchStore_Search* search)
  89. {
  90. struct SearchStore_Search_pvt* pvtSearch = (struct SearchStore_Search_pvt*) search;
  91. if (!pvtSearch->searchStackSize) {
  92. return NULL;
  93. }
  94. struct SearchStore_Node* nn = &pvtSearch->nodesAsked[pvtSearch->nodesAskedIndex];
  95. Bits_memcpy(&nn->address,
  96. &pvtSearch->searchStack[--pvtSearch->searchStackSize],
  97. sizeof(struct Address));
  98. nn->search = search;
  99. pvtSearch->nodesAskedIndex = (pvtSearch->nodesAskedIndex + 1) % SearchStore_SEARCH_NODES;
  100. return nn;
  101. }