EncodingSchemeModule.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  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 "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 || !Version_isCompatible(Version_CURRENT_PROTOCOL, *version)) {
  66. Log_debug(ctx->logger, "Incompatible version");
  67. Assert_ifTesting(0);
  68. return -1;
  69. }
  70. message->address->protocolVersion = *version;
  71. int64_t* encIdx = Dict_getInt(message->asDict, CJDHTConstants_ENC_INDEX);
  72. if (!encIdx) {
  73. Log_debug(ctx->logger, "Missing encoding index, version [%d]", (int) (*version));
  74. return -1;
  75. }
  76. if (*encIdx < 0 || *encIdx >= scheme->count) {
  77. Log_debug(ctx->logger, "Invalid encoding index [%lld], version [%d]",
  78. (long long int) (*encIdx),
  79. (int) (*version));
  80. Assert_ifTesting(0);
  81. return -1;
  82. }
  83. message->encIndex = *encIdx;
  84. return 0;
  85. }
  86. static int handleOutgoing(struct DHTMessage* dmesg, void* vcontext)
  87. {
  88. struct EncodingSchemeModule_pvt* ctx =
  89. Identity_check((struct EncodingSchemeModule_pvt*) vcontext);
  90. // Send our encoding scheme definition
  91. Dict_putString(dmesg->asDict,
  92. CJDHTConstants_ENC_SCHEME,
  93. ctx->schemeDefinition,
  94. dmesg->allocator);
  95. // sanity check if in sym, real world broken nodes will trigger this.
  96. Assert_ifTesting(dmesg->address->path ==
  97. EncodingScheme_convertLabel(ctx->scheme,
  98. dmesg->address->path,
  99. EncodingScheme_convertLabel_convertTo_CANNONICAL));
  100. // And tell the asker which interface the message came from
  101. int encIdx = EncodingScheme_getFormNum(ctx->scheme, dmesg->address->path);
  102. Assert_ifParanoid(encIdx != EncodingScheme_getFormNum_INVALID);
  103. Dict_putInt(dmesg->asDict, CJDHTConstants_ENC_INDEX, encIdx, dmesg->allocator);
  104. return 0;
  105. }
  106. void EncodingSchemeModule_register(struct DHTModuleRegistry* reg,
  107. struct Log* logger,
  108. struct Allocator* alloc)
  109. {
  110. struct EncodingScheme* scheme = NumberCompress_defineScheme(alloc);
  111. String* schemeDefinition = EncodingScheme_serialize(scheme, alloc);
  112. struct EncodingSchemeModule_pvt* ctx =
  113. Allocator_clone(alloc, (&(struct EncodingSchemeModule_pvt) {
  114. .module = {
  115. .name = "EncodingSchemeModule",
  116. .handleIncoming = handleIncoming,
  117. .handleOutgoing = handleOutgoing
  118. },
  119. .logger = logger,
  120. .scheme = scheme,
  121. .schemeDefinition = schemeDefinition,
  122. }));
  123. Identity_set(ctx);
  124. ctx->module.context = ctx;
  125. ctx->legacyV3x5x8 = NumberCompress_v3x5x8_defineScheme(alloc);
  126. DHTModuleRegistry_register(&ctx->module, reg);
  127. }