EncodingSchemeModule.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  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/EncodingSchemeModule.h"
  16. #include "dht/Address.h"
  17. #include "dht/CJDHTConstants.h"
  18. #include "dht/DHTMessage.h"
  19. #include "dht/DHTModule.h"
  20. #include "dht/DHTModuleRegistry.h"
  21. #include "benc/String.h"
  22. #include "util/Identity.h"
  23. #include "switch/NumberCompress.h"
  24. #include "switch/EncodingScheme.h"
  25. #include "util/version/Version.h"
  26. #include "dht/dhtcore/NodeStore.h"
  27. /**
  28. * The encoding scheme module tags each message with our encoding scheme
  29. * representation as well as the number of the smallest encoding form which
  30. * can represent the return path to the querying node.
  31. *
  32. * On incoming messages, it informs NodeStore of the encoding scheme used by
  33. * the node sending the message and if the node is pre-version-6, it converts
  34. * the query responses from the pre-version-6 representation to the version-6
  35. * representation.
  36. */
  37. struct EncodingSchemeModule_pvt
  38. {
  39. struct DHTModule module;
  40. /** Our scheme. */
  41. String* schemeDefinition;
  42. struct EncodingScheme* scheme;
  43. struct EncodingScheme* legacyV3x5x8;
  44. struct Log* logger;
  45. Identity
  46. };
  47. static int handleIncoming(struct DHTMessage* message, void* vcontext)
  48. {
  49. struct EncodingSchemeModule_pvt* ctx =
  50. Identity_check((struct EncodingSchemeModule_pvt*) vcontext);
  51. struct EncodingScheme* scheme = NULL;
  52. String* schemeDefinition = Dict_getString(message->asDict, CJDHTConstants_ENC_SCHEME);
  53. if (schemeDefinition) {
  54. scheme = EncodingScheme_deserialize(schemeDefinition, message->allocator);
  55. } else {
  56. scheme = ctx->legacyV3x5x8;
  57. }
  58. if (!scheme) {
  59. Log_debug(ctx->logger, "Failed to parse encoding scheme");
  60. Assert_ifTesting(0);
  61. return -1;
  62. }
  63. message->encodingScheme = scheme;
  64. int64_t* version = Dict_getInt(message->asDict, CJDHTConstants_PROTOCOL);
  65. if (!version) {
  66. Log_debug(ctx->logger, "Protocol version missing");
  67. Assert_ifTesting(0);
  68. return -1;
  69. }
  70. if (!Version_compatibleWithCurrent(*version)) {
  71. Log_debug(ctx->logger, "Incompatible version");
  72. Assert_ifTesting(0);
  73. return -1;
  74. }
  75. message->address->protocolVersion = *version;
  76. int64_t* encIdx = Dict_getInt(message->asDict, CJDHTConstants_ENC_INDEX);
  77. if (!encIdx) {
  78. Log_debug(ctx->logger, "Missing encoding index, version [%d]", (int) (*version));
  79. return -1;
  80. }
  81. if (*encIdx < 0 || *encIdx >= scheme->count) {
  82. Log_debug(ctx->logger, "Invalid encoding index [%lld], version [%d]",
  83. (long long int) (*encIdx),
  84. (int) (*version));
  85. Assert_ifTesting(0);
  86. return -1;
  87. }
  88. message->encIndex = *encIdx;
  89. return 0;
  90. }
  91. static int handleOutgoing(struct DHTMessage* dmesg, void* vcontext)
  92. {
  93. struct EncodingSchemeModule_pvt* ctx =
  94. Identity_check((struct EncodingSchemeModule_pvt*) vcontext);
  95. // Send our encoding scheme definition
  96. Dict_putString(dmesg->asDict,
  97. CJDHTConstants_ENC_SCHEME,
  98. ctx->schemeDefinition,
  99. dmesg->allocator);
  100. // sanity check if in sym, real world broken nodes will trigger this.
  101. Assert_ifTesting(dmesg->address->path ==
  102. EncodingScheme_convertLabel(ctx->scheme,
  103. dmesg->address->path,
  104. EncodingScheme_convertLabel_convertTo_CANNONICAL));
  105. // And tell the asker which interface the message came from
  106. int encIdx = EncodingScheme_getFormNum(ctx->scheme, dmesg->address->path);
  107. Assert_ifParanoid(encIdx != EncodingScheme_getFormNum_INVALID);
  108. Dict_putInt(dmesg->asDict, CJDHTConstants_ENC_INDEX, encIdx, dmesg->allocator);
  109. return 0;
  110. }
  111. void EncodingSchemeModule_register(struct DHTModuleRegistry* reg,
  112. struct Log* logger,
  113. struct Allocator* alloc)
  114. {
  115. struct EncodingScheme* scheme = NumberCompress_defineScheme(alloc);
  116. String* schemeDefinition = EncodingScheme_serialize(scheme, alloc);
  117. struct EncodingSchemeModule_pvt* ctx =
  118. Allocator_clone(alloc, (&(struct EncodingSchemeModule_pvt) {
  119. .module = {
  120. .name = "EncodingSchemeModule",
  121. .handleIncoming = handleIncoming,
  122. .handleOutgoing = handleOutgoing
  123. },
  124. .logger = logger,
  125. .scheme = scheme,
  126. .schemeDefinition = schemeDefinition,
  127. }));
  128. Identity_set(ctx);
  129. ctx->module.context = ctx;
  130. ctx->legacyV3x5x8 = NumberCompress_v3x5x8_defineScheme(alloc);
  131. DHTModuleRegistry_register(&ctx->module, reg);
  132. }