GetPeersResponder.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  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 "subnode/GetPeersResponder.h"
  16. #include "subnode/BoilerplateResponder.h"
  17. #include "dht/dhtcore/ReplySerializer.h"
  18. #include "util/Identity.h"
  19. #define GETPEERS_RESPONSE_NODES 8
  20. struct GetPeersResponder_pvt
  21. {
  22. struct GetPeersResponder pub;
  23. struct MsgCore_Handler* handler;
  24. struct AddrSet* peers;
  25. struct Log* log;
  26. struct Allocator* alloc;
  27. struct MsgCore* msgCore;
  28. struct Address* selfAddr;
  29. struct BoilerplateResponder* br;
  30. struct EncodingScheme* myScheme;
  31. Identity
  32. };
  33. static void onGetPeers(Dict* msg,
  34. struct Address* src,
  35. struct Allocator* tmpAlloc,
  36. struct MsgCore_Handler* handler)
  37. {
  38. struct GetPeersResponder_pvt* gprp =
  39. Identity_check((struct GetPeersResponder_pvt*) handler->userData);
  40. Log_debug(gprp->log, "Received getPeers req from [%s]", Address_toString(src, tmpAlloc)->bytes);
  41. String* txid = Dict_getStringC(msg, "txid");
  42. if (!txid) {
  43. Log_debug(gprp->log, "getPeers missing txid");
  44. return;
  45. }
  46. String* nearLabelStr = Dict_getStringC(msg, "tar");
  47. uint64_t label;
  48. if (!nearLabelStr || nearLabelStr->len != 8) {
  49. Log_debug(gprp->log, "getPeers does not contain proper target");
  50. return;
  51. } else {
  52. uint64_t label_be;
  53. Bits_memcpy(&label_be, nearLabelStr->bytes, 8);
  54. label = Endian_bigEndianToHost64(label_be);
  55. }
  56. struct Address** ptrList =
  57. Allocator_calloc(tmpAlloc, sizeof(uintptr_t), GETPEERS_RESPONSE_NODES+1);
  58. ptrList[GETPEERS_RESPONSE_NODES-1] = gprp->selfAddr;
  59. if (label > 1) {
  60. int formNum = EncodingScheme_getFormNum(gprp->myScheme, label);
  61. if (formNum > -1) {
  62. int bitsUsed = EncodingScheme_formSize(&gprp->myScheme->forms[formNum]);
  63. label = (label & Bits_maxBits64(bitsUsed)) | 1 << bitsUsed;
  64. }
  65. }
  66. for (int i = 0; i < gprp->peers->length; i++) {
  67. struct Address* peer = AddrSet_get(gprp->peers, i);
  68. if (peer->path < label) { continue; }
  69. int j;
  70. for (j = 0; j < GETPEERS_RESPONSE_NODES; j++) {
  71. if (!ptrList[j]) { continue; }
  72. if ((ptrList[j]->path - label) > (peer->path - label)) { continue; }
  73. break;
  74. }
  75. switch (j) {
  76. default: Bits_memmove(ptrList, &ptrList[1], (j - 1) * sizeof(char*));
  77. Gcc_FALLTHRU;
  78. case 1: ptrList[j - 1] = peer;
  79. Gcc_FALLTHRU;
  80. case 0:;
  81. }
  82. }
  83. Assert_true(!ptrList[GETPEERS_RESPONSE_NODES]);
  84. struct Address* addrList =
  85. Allocator_calloc(tmpAlloc, sizeof(struct Address), GETPEERS_RESPONSE_NODES+1);
  86. int size = 0;
  87. for (int i = 0; i < GETPEERS_RESPONSE_NODES; i++) {
  88. if (!ptrList[i]) { continue; }
  89. Bits_memcpy(&addrList[size++], ptrList[i], sizeof(struct Address));
  90. }
  91. Assert_true(Bits_isZero(&addrList[GETPEERS_RESPONSE_NODES], sizeof(struct Address)));
  92. Dict* responseDict = Dict_new(tmpAlloc);
  93. ReplySerializer_serialize((&(struct Address_List) { .elems = addrList, .length = size }),
  94. responseDict,
  95. src,
  96. tmpAlloc);
  97. Dict_putStringC(responseDict, "txid", txid, tmpAlloc);
  98. BoilerplateResponder_addBoilerplate(gprp->br, responseDict, src, tmpAlloc);
  99. MsgCore_sendResponse(gprp->msgCore, responseDict, src, tmpAlloc);
  100. }
  101. struct GetPeersResponder* GetPeersResponder_new(struct Allocator* allocator,
  102. struct Log* log,
  103. struct AddrSet* peers,
  104. struct Address* selfAddr,
  105. struct MsgCore* msgCore,
  106. struct BoilerplateResponder* br,
  107. struct EncodingScheme* myScheme)
  108. {
  109. struct Allocator* alloc = Allocator_child(allocator);
  110. struct GetPeersResponder_pvt* gprp =
  111. Allocator_calloc(alloc, sizeof(struct GetPeersResponder_pvt), 1);
  112. Identity_set(gprp);
  113. gprp->peers = peers;
  114. gprp->log = log;
  115. gprp->alloc = alloc;
  116. gprp->msgCore = msgCore;
  117. gprp->selfAddr = selfAddr;
  118. gprp->handler = MsgCore_onQuery(msgCore, "gp", alloc);
  119. gprp->handler->userData = gprp;
  120. gprp->handler->cb = onGetPeers;
  121. gprp->br = br;
  122. gprp->myScheme = myScheme;
  123. return &gprp->pub;
  124. }