ReplySerializer.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  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 "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. #include "util/Identity.h"
  25. #include "util/log/Log.h"
  26. #include "util/Assert.h"
  27. /**
  28. * For serializing and parsing responses to getPeers and search requests.
  29. */
  30. struct Address_List* ReplySerializer_parse(struct Address* fromNode,
  31. struct EncodingScheme* fromNodeScheme,
  32. int inverseLinkEncodingForm,
  33. Dict* result,
  34. struct Log* log,
  35. struct Allocator* alloc)
  36. {
  37. String* nodes = Dict_getString(result, CJDHTConstants_NODES);
  38. if (!nodes) { return NULL; }
  39. if (nodes->len == 0 || nodes->len % Address_SERIALIZED_SIZE != 0) {
  40. Log_debug(log, "Dropping unrecognized reply");
  41. return NULL;
  42. }
  43. struct VersionList* versions = NULL;
  44. String* versionsStr = Dict_getString(result, CJDHTConstants_NODE_PROTOCOLS);
  45. if (versionsStr) {
  46. versions = VersionList_parse(versionsStr, alloc);
  47. #ifdef Version_1_COMPAT
  48. // Version 1 lies about the versions of other nodes, assume they're all v1.
  49. if (fromNode->protocolVersion < 2) {
  50. for (int i = 0; i < (int)versions->length; i++) {
  51. versions->versions[i] = 1;
  52. }
  53. }
  54. #endif
  55. }
  56. if (!versions || versions->length != (nodes->len / Address_SERIALIZED_SIZE)) {
  57. Log_debug(log, "Reply with missing or invalid versions");
  58. return NULL;
  59. }
  60. struct Address_List* out = Address_List_new(versions->length, alloc);
  61. uint32_t j = 0;
  62. for (uint32_t i = 0; nodes && i < nodes->len; i += Address_SERIALIZED_SIZE) {
  63. struct Address addr = { .path = 0 };
  64. Address_parse(&addr, (uint8_t*) &nodes->bytes[i]);
  65. addr.protocolVersion = versions->versions[i / Address_SERIALIZED_SIZE];
  66. // calculate the ipv6
  67. Address_getPrefix(&addr);
  68. if (fromNodeScheme && addr.path != 1) {
  69. int formNum = EncodingScheme_getFormNum(fromNodeScheme, addr.path);
  70. if (formNum < inverseLinkEncodingForm) {
  71. Log_info(log, "Invalid path");
  72. continue;
  73. } else if (formNum > inverseLinkEncodingForm) {
  74. uint64_t cannonicalPath =
  75. EncodingScheme_convertLabel(fromNodeScheme,
  76. addr.path,
  77. EncodingScheme_convertLabel_convertTo_CANNONICAL);
  78. if (cannonicalPath != addr.path) {
  79. Log_info(log, "Wasted space");
  80. }
  81. }
  82. }
  83. // We need to splice the given address on to the end of the
  84. // address of the node which gave it to us.
  85. uint64_t path = LabelSplicer_splice(addr.path, fromNode->path);
  86. if (path == UINT64_MAX) {
  87. uint8_t discovered[60];
  88. uint8_t fromAddr[60];
  89. Address_print(discovered, &addr);
  90. Address_print(fromAddr, fromNode);
  91. Log_debug(log, "Dropping response [%s] from [%s] because route could not be spliced",
  92. discovered, fromAddr);
  93. continue;
  94. }
  95. addr.path = path;
  96. /*#ifdef Log_DEBUG
  97. uint8_t printedAddr[60];
  98. Address_print(printedAddr, &addr);
  99. Log_debug(log, "discovered node [%s]", printedAddr);
  100. #endif*/
  101. Address_getPrefix(&addr);
  102. if (!AddressCalc_validAddress(addr.ip6.bytes)) {
  103. Log_debug(log, "Was told garbage.\n");
  104. // This should never happen, badnode.
  105. continue;
  106. }
  107. Bits_memcpyConst(&out->elems[j++], &addr, sizeof(struct Address));
  108. }
  109. out->length = j;
  110. return out;
  111. }