ReplySerializer.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  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. Dict* result,
  32. struct Log* log,
  33. struct Allocator* alloc)
  34. {
  35. String* nodes = Dict_getString(result, CJDHTConstants_NODES);
  36. if (!nodes) { return NULL; }
  37. if (nodes->len == 0 || nodes->len % Address_SERIALIZED_SIZE != 0) {
  38. Log_debug(log, "Dropping unrecognized reply");
  39. return NULL;
  40. }
  41. struct VersionList* versions = NULL;
  42. String* versionsStr = Dict_getString(result, CJDHTConstants_NODE_PROTOCOLS);
  43. if (versionsStr) {
  44. versions = VersionList_parse(versionsStr, alloc);
  45. #ifdef Version_1_COMPAT
  46. // Version 1 lies about the versions of other nodes, assume they're all v1.
  47. if (fromNode->protocolVersion < 2) {
  48. for (int i = 0; i < (int)versions->length; i++) {
  49. versions->versions[i] = 1;
  50. }
  51. }
  52. #endif
  53. }
  54. if (!versions || versions->length != (nodes->len / Address_SERIALIZED_SIZE)) {
  55. Log_debug(log, "Reply with missing or invalid versions");
  56. return NULL;
  57. }
  58. struct Address_List* out = Address_List_new(versions->length, alloc);
  59. uint32_t j = 0;
  60. for (uint32_t i = 0; nodes && i < nodes->len; i += Address_SERIALIZED_SIZE) {
  61. struct Address addr = { .path = 0 };
  62. Address_parse(&addr, (uint8_t*) &nodes->bytes[i]);
  63. addr.protocolVersion = versions->versions[i / Address_SERIALIZED_SIZE];
  64. // calculate the ipv6
  65. Address_getPrefix(&addr);
  66. // We need to splice the given address on to the end of the
  67. // address of the node which gave it to us.
  68. uint64_t path = LabelSplicer_splice(addr.path, fromNode->path);
  69. if (path == UINT64_MAX) {
  70. /* common, lots of noise
  71. uint8_t discovered[60];
  72. uint8_t fromAddr[60];
  73. Address_print(discovered, &addr);
  74. Address_print(fromAddr, fromNode);
  75. Log_debug(log, "Dropping response [%s] from [%s] because route could not be spliced",
  76. discovered, fromAddr);*/
  77. continue;
  78. }
  79. addr.path = path;
  80. /*#ifdef Log_DEBUG
  81. uint8_t printedAddr[60];
  82. Address_print(printedAddr, &addr);
  83. Log_debug(log, "discovered node [%s]", printedAddr);
  84. #endif*/
  85. Address_getPrefix(&addr);
  86. if (!AddressCalc_validAddress(addr.ip6.bytes)) {
  87. Log_debug(log, "Was told garbage.\n");
  88. // This should never happen, badnode.
  89. continue;
  90. }
  91. Bits_memcpyConst(&out->elems[j++], &addr, sizeof(struct Address));
  92. }
  93. out->length = j;
  94. return out;
  95. }