1
0

ReplySerializer.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  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 "benc/Dict.h"
  16. #include "benc/String.h"
  17. #include "crypto/AddressCalc.h"
  18. #include "dht/CJDHTConstants.h"
  19. #include "dht/dhtcore/ReplySerializer.h"
  20. #include "dht/dhtcore/VersionList.h"
  21. #include "dht/Address.h"
  22. #include "memory/Allocator.h"
  23. #include "switch/LabelSplicer.h"
  24. #define NumberCompress_OLD_CODE
  25. #include "switch/NumberCompress.h"
  26. #include "util/Identity.h"
  27. #include "util/log/Log.h"
  28. #include "util/Assert.h"
  29. /**
  30. * For serializing and parsing responses to getPeers and search requests.
  31. */
  32. struct Address_List* ReplySerializer_parse(struct Address* fromNode,
  33. Dict* result,
  34. struct Log* log,
  35. bool splicePath,
  36. struct Allocator* alloc)
  37. {
  38. String* nodes = Dict_getString(result, CJDHTConstants_NODES);
  39. if (!nodes) {
  40. Log_debug(log, "Missing 'n' field in reply");
  41. return NULL;
  42. }
  43. if (nodes->len == 0 || nodes->len % Address_SERIALIZED_SIZE != 0) {
  44. Log_debug(log, "Dropping unrecognized reply");
  45. return NULL;
  46. }
  47. struct VersionList* versions = NULL;
  48. String* versionsStr = Dict_getString(result, CJDHTConstants_NODE_PROTOCOLS);
  49. if (versionsStr) {
  50. versions = VersionList_parse(versionsStr, alloc);
  51. }
  52. if (!versions || versions->length != (nodes->len / Address_SERIALIZED_SIZE)) {
  53. Log_debug(log, "Reply with missing or invalid versions");
  54. return NULL;
  55. }
  56. struct Address_List* out = Address_List_new(versions->length, alloc);
  57. uint32_t j = 0;
  58. for (uint32_t i = 0; nodes && i < nodes->len; i += Address_SERIALIZED_SIZE) {
  59. struct Address addr = { .path = 0 };
  60. Address_parse(&addr, (uint8_t*) &nodes->bytes[i]);
  61. addr.protocolVersion = versions->versions[i / Address_SERIALIZED_SIZE];
  62. // calculate the ipv6
  63. Address_getPrefix(&addr);
  64. if (splicePath) {
  65. // We need to splice the given address on to the end of the
  66. // address of the node which gave it to us.
  67. uint64_t path = LabelSplicer_splice(addr.path, fromNode->path);
  68. if (path == UINT64_MAX) {
  69. /* common, lots of noise
  70. uint8_t discovered[60];
  71. uint8_t fromAddr[60];
  72. Address_print(discovered, &addr);
  73. Address_print(fromAddr, fromNode);
  74. Log_debug(log,
  75. "Dropping response [%s] from [%s] because route could not be spliced",
  76. discovered, fromAddr);*/
  77. continue;
  78. }
  79. addr.path = path;
  80. }
  81. /*#ifdef Log_DEBUG
  82. uint8_t printedAddr[60];
  83. Address_print(printedAddr, &addr);
  84. Log_debug(log, "discovered node [%s]", printedAddr);
  85. #endif*/
  86. Address_getPrefix(&addr);
  87. if (!AddressCalc_validAddress(addr.ip6.bytes)) {
  88. struct Allocator* tmpAlloc = Allocator_child(alloc);
  89. String* printed = Address_toString(&addr, tmpAlloc);
  90. uint8_t ipPrinted[40];
  91. Address_printIp(ipPrinted, &addr);
  92. Log_debug(log, "Was told garbage addr [%s] [%s]", printed->bytes, ipPrinted);
  93. Allocator_free(tmpAlloc);
  94. // This should never happen, badnode.
  95. continue;
  96. }
  97. Bits_memcpy(&out->elems[j++], &addr, sizeof(struct Address));
  98. }
  99. out->length = j;
  100. return out;
  101. }
  102. void ReplySerializer_serialize(struct Address_List* addrs,
  103. Dict* out,
  104. struct Address* convertDirectorFor,
  105. struct Allocator* alloc)
  106. {
  107. if (!addrs->length) { return; }
  108. String* nodes = String_newBinary(NULL, addrs->length * Address_SERIALIZED_SIZE, alloc);
  109. struct VersionList* versions = VersionList_new(addrs->length, alloc);
  110. for (int i = 0; i < addrs->length; i++) {
  111. versions->versions[i] = addrs->elems[i].protocolVersion;
  112. if (!convertDirectorFor) {
  113. Address_serialize(&nodes->bytes[i * Address_SERIALIZED_SIZE], &addrs->elems[i]);
  114. } else {
  115. struct Address addr;
  116. Bits_memcpy(&addr, &addrs->elems[i], sizeof(struct Address));
  117. addr.path = NumberCompress_getLabelFor(addr.path, convertDirectorFor->path);
  118. Address_serialize(&nodes->bytes[i * Address_SERIALIZED_SIZE], &addr);
  119. }
  120. }
  121. Dict_putStringC(out, "n", nodes, alloc);
  122. Dict_putStringC(out, "np", VersionList_stringify(versions, alloc), alloc);
  123. }