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/DHTModule.h"
16 #include "dht/DHTModuleRegistry.h"
17 #include "memory/Allocator.h"
18 #include "util/Assert.h"
19 
20 #include <stddef.h> // NULL
21 
22 #define DEBUG2(x, y)
23 /* #define DEBUG2(x, y) fprintf(stderr, x, y); fflush(stderr) */
24 
DHTModuleRegistry_new(struct Allocator * allocator,struct Log * log)25 struct DHTModuleRegistry* DHTModuleRegistry_new(struct Allocator* allocator, struct Log* log)
26 {
27     struct DHTModuleRegistry* reg =
28         Allocator_calloc(allocator, sizeof(struct DHTModuleRegistry), 1);
29     reg->allocator = allocator;
30     reg->members = Allocator_calloc(allocator, sizeof(char*), 1);
31     reg->log = log;
32     return reg;
33 }
34 
DHTModuleRegistry_register(struct DHTModule * module,struct DHTModuleRegistry * registry)35 int DHTModuleRegistry_register(struct DHTModule* module,
36                                struct DHTModuleRegistry* registry)
37 {
38     registry->members = Allocator_realloc(registry->allocator,
39                                           registry->members,
40                                           sizeof(char*) * (registry->memberCount + 2));
41 
42     registry->members[registry->memberCount] = module;
43     registry->memberCount++;
44     registry->members[registry->memberCount] = NULL;
45 
46     return 0;
47 }
48 
DHTModuleRegistry_handleIncoming(struct DHTMessage * message,const struct DHTModuleRegistry * registry)49 void DHTModuleRegistry_handleIncoming(struct DHTMessage* message,
50                                       const struct DHTModuleRegistry* registry)
51 {
52     if (!(message && registry && registry->members && registry->memberCount)) {
53         return;
54     }
55 
56     struct DHTModule** firstModulePtr = registry->members;
57     struct DHTModule** modulePtr = registry->members + registry->memberCount - 1;
58     struct DHTModule* module;
59 
60     while (modulePtr >= firstModulePtr) {
61         module = *modulePtr;
62         if (module && module->handleIncoming) {
63             DEBUG2("<< calling: %s->handleIncoming\n", module->name);
64             if (module->handleIncoming(message, module->context) != 0) {
65                 // TODO(cjd): Call a debugger with all unhandlable messages?
66                 return;
67             }
68         } else {
69             DEBUG2("<< skipping %s->handleIncoming\n", module->name);
70         }
71         modulePtr--;
72     }
73 }
74 
dhtModuleHandleOutgoing(struct DHTModule * module,struct DHTMessage * message)75 static int dhtModuleHandleOutgoing(struct DHTModule* module, struct DHTMessage* message)
76 {
77     Assert_ifParanoid(module);
78     if (module->handleOutgoing) {
79         DEBUG2(">> calling: %s->handleOutgoing\n", module->name);
80         return module->handleOutgoing(message, module->context);
81     } else {
82         DEBUG2(">> skipping: %s->handleOutgoing\n", module->name);
83     }
84     return 0;
85 }
86 
87 /**
88  * Do something to every module which is registered.
89  * @param doThis the callback.
90  * @param registry state.
91  */
forEachModule(int (* doThis)(struct DHTModule * module,struct DHTMessage * message),struct DHTMessage * message,const struct DHTModuleRegistry * registry)92 static void forEachModule(int (*doThis)(struct DHTModule* module, struct DHTMessage* message),
93                           struct DHTMessage* message,
94                           const struct DHTModuleRegistry* registry)
95 {
96     struct DHTModule** modulePtr = registry->members;
97     struct DHTModule* module = *modulePtr;
98     while (module) {
99         if (doThis(module, message) != 0) {
100             return;
101         }
102         modulePtr++;
103         module = *modulePtr;
104     }
105 }
106 
DHTModuleRegistry_handleOutgoing(struct DHTMessage * message,const struct DHTModuleRegistry * registry)107 void DHTModuleRegistry_handleOutgoing(struct DHTMessage* message,
108                                       const struct DHTModuleRegistry* registry)
109 {
110     forEachModule(dhtModuleHandleOutgoing, message, registry);
111 }
112