123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- /* vim: set expandtab ts=4 sw=4: */
- /*
- * You may redistribute this program and/or modify it under the terms of
- * the GNU General Public License as published by the Free Software Foundation,
- * either version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- #include "dht/EncodingSchemeModule.h"
- #include "dht/Address.h"
- #include "dht/CJDHTConstants.h"
- #include "dht/DHTMessage.h"
- #include "dht/DHTModule.h"
- #include "dht/DHTModuleRegistry.h"
- #include "benc/String.h"
- #include "util/Identity.h"
- #include "switch/NumberCompress.h"
- #include "switch/EncodingScheme.h"
- #include "util/version/Version.h"
- #include "dht/dhtcore/NodeStore.h"
- #include "dht/dhtcore/ReplySerializer.h"
- /**
- * The encoding scheme module tags each message with our encoding scheme
- * representation as well as the number of the smallest encoding form which
- * can represent the return path to the querying node.
- *
- * On incoming messages, it informs NodeStore of the encoding scheme used by
- * the node sending the message and if the node is pre-version-6, it converts
- * the query responses from the pre-version-6 representation to the version-6
- * representation.
- */
- struct EncodingSchemeModule_pvt
- {
- struct DHTModule module;
- /** Our scheme. */
- String* schemeDefinition;
- struct EncodingScheme* scheme;
- struct EncodingScheme* legacyV3x5x8;
- struct Log* logger;
- struct Allocator* alloc;
- Identity
- };
- static int handleIncoming(struct DHTMessage* message, void* vcontext)
- {
- struct EncodingSchemeModule_pvt* ctx =
- Identity_check((struct EncodingSchemeModule_pvt*) vcontext);
- struct EncodingScheme* scheme = NULL;
- String* schemeDefinition = Dict_getString(message->asDict, CJDHTConstants_ENC_SCHEME);
- if (schemeDefinition) {
- scheme = EncodingScheme_deserialize(schemeDefinition, message->allocator);
- } else {
- scheme = ctx->legacyV3x5x8;
- }
- if (!scheme) {
- Log_debug(ctx->logger, "Failed to parse encoding scheme");
- Assert_ifTesting(0);
- return -1;
- }
- message->encodingScheme = scheme;
- int64_t* version = Dict_getInt(message->asDict, CJDHTConstants_PROTOCOL);
- if (!version || !Version_isCompatible(Version_CURRENT_PROTOCOL, *version)) {
- Log_debug(ctx->logger, "Incompatible version");
- Assert_ifTesting(0);
- return -1;
- }
- message->address->protocolVersion = *version;
- int64_t* encIdx = Dict_getInt(message->asDict, CJDHTConstants_ENC_INDEX);
- if (!encIdx) {
- Log_debug(ctx->logger, "Missing encoding index, version [%d]", (int) (*version));
- return -1;
- }
- if (*encIdx < 0 || *encIdx >= scheme->count) {
- Log_debug(ctx->logger, "Invalid encoding index [%lld], version [%d]",
- (long long int) (*encIdx),
- (int) (*version));
- Assert_ifTesting(0);
- return -1;
- }
- message->encIndex = *encIdx;
- struct Allocator* alloc = Allocator_child(ctx->alloc);
- ReplySerializer_parse(message->address, scheme, *encIdx, message->asDict, ctx->logger, alloc);
- Allocator_free(alloc);
- return 0;
- }
- static int handleOutgoing(struct DHTMessage* dmesg, void* vcontext)
- {
- struct EncodingSchemeModule_pvt* ctx =
- Identity_check((struct EncodingSchemeModule_pvt*) vcontext);
- // Send our encoding scheme definition
- Dict_putString(dmesg->asDict,
- CJDHTConstants_ENC_SCHEME,
- ctx->schemeDefinition,
- dmesg->allocator);
- #ifdef TESTING
- // sanity check
- Assert_true(dmesg->address->path ==
- EncodingScheme_convertLabel(ctx->scheme,
- dmesg->address->path,
- EncodingScheme_convertLabel_convertTo_CANNONICAL));
- #endif
- // And tell the asker which interface the message came from
- int encIdx = EncodingScheme_getFormNum(ctx->scheme, dmesg->address->path);
- Assert_true(encIdx != EncodingScheme_getFormNum_INVALID);
- Dict_putInt(dmesg->asDict, CJDHTConstants_ENC_INDEX, encIdx, dmesg->allocator);
- return 0;
- }
- void EncodingSchemeModule_register(struct DHTModuleRegistry* reg,
- struct Log* logger,
- struct Allocator* alloc)
- {
- struct EncodingScheme* scheme = NumberCompress_defineScheme(alloc);
- String* schemeDefinition = EncodingScheme_serialize(scheme, alloc);
- struct EncodingSchemeModule_pvt* ctx =
- Allocator_clone(alloc, (&(struct EncodingSchemeModule_pvt) {
- .module = {
- .name = "EncodingSchemeModule",
- .handleIncoming = handleIncoming,
- .handleOutgoing = handleOutgoing
- },
- .logger = logger,
- .scheme = scheme,
- .schemeDefinition = schemeDefinition,
- .alloc = alloc
- }));
- Identity_set(ctx);
- ctx->module.context = ctx;
- ctx->legacyV3x5x8 = NumberCompress_v3x5x8_defineScheme(alloc);
- DHTModuleRegistry_register(&ctx->module, reg);
- }
|