/* 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 . */ #include "dht/DHTModule.h" #include "dht/DHTModuleRegistry.h" #include "memory/Allocator.h" #include "io/Reader.h" #include "io/Writer.h" #include "benc/Object.h" #include "benc/serialization/BencSerializer.h" #include "benc/serialization/standard/StandardBencSerializer.h" #include "util/Assert.h" #include "util/platform/libc/string.h" #define DEBUG2(x, y) /* #define DEBUG2(x, y) fprintf(stderr, x, y); fflush(stderr) */ /** This defines what format the registry will be serialized in. */ #define SERIALIZER StandardBencSerializer_get() struct DHTModuleRegistry* DHTModuleRegistry_new(struct Allocator* allocator) { struct DHTModuleRegistry* reg = Allocator_calloc(allocator, sizeof(struct DHTModuleRegistry), 1); reg->allocator = allocator; reg->members = Allocator_calloc(allocator, sizeof(char*), 1); return reg; } int DHTModuleRegistry_register(struct DHTModule* module, struct DHTModuleRegistry* registry) { registry->members = Allocator_realloc(registry->allocator, registry->members, sizeof(char*) * (registry->memberCount + 2)); registry->members[registry->memberCount] = module; registry->memberCount++; registry->members[registry->memberCount] = NULL; return 0; } void DHTModuleRegistry_handleIncoming(struct DHTMessage* message, const struct DHTModuleRegistry* registry) { if (!(message && registry && registry->members && registry->memberCount)) { return; } struct DHTModule** firstModulePtr = registry->members; struct DHTModule** modulePtr = registry->members + registry->memberCount - 1; struct DHTModule* module; while (modulePtr >= firstModulePtr) { module = *modulePtr; if (module && module->handleIncoming) { DEBUG2("<< calling: %s->handleIncoming\n", module->name); if (module->handleIncoming(message, module->context) != 0) { // TODO(cjd): Call a debugger with all unhandlable messages? return; } } else { DEBUG2("<< skipping %s->handleIncoming\n", module->name); } modulePtr--; } } static int dhtModuleHandleOutgoing(struct DHTModule* module, struct DHTMessage* message) { Assert_ifParanoid(module != NULL); if (module->handleOutgoing) { DEBUG2(">> calling: %s->handleOutgoing\n", module->name); return module->handleOutgoing(message, module->context); } else { DEBUG2(">> skipping: %s->handleOutgoing\n", module->name); } return 0; } /** * Do something to every module which is registered. * @param doThis the callback. * @param registry state. */ static void forEachModule(int (*doThis)(struct DHTModule* module, struct DHTMessage* message), struct DHTMessage* message, const struct DHTModuleRegistry* registry) { struct DHTModule** modulePtr = registry->members; struct DHTModule* module = *modulePtr; while (module) { if (doThis(module, message) != 0) { return; } modulePtr++; module = *modulePtr; } } void DHTModuleRegistry_handleOutgoing(struct DHTMessage* message, const struct DHTModuleRegistry* registry) { forEachModule(dhtModuleHandleOutgoing, message, registry); }