-
Notifications
You must be signed in to change notification settings - Fork 587
/
DHTModules.h
200 lines (171 loc) · 5.99 KB
/
DHTModules.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
#ifndef DHTMODULES_H
#define DHTMODULES_H
#include "memory/MemAllocator.h"
#include "io/Reader.h"
#include "io/Writer.h"
#include "libbenc/benc.h"
/**
* Maximum number of bytes in a message.
* Ethernet MTU is 1500 so it's hard to imagine much more.
*/
#define MAX_MESSAGE_SIZE 1536
#define MAX_TRANSACTION_ID_SIZE 16
/**
* This struct represents a DHT message which will be passed to the
* modules. The only part of the message which will be available to
* all modules is Message.peer. Incoming modules will have Message.bytes
* and Message.length when they come from the network module.
*/
struct DHTMessage;
struct DHTMessage
{
struct Address* address;
char padding[512];
/** The message in binary format. */
char bytes[MAX_MESSAGE_SIZE];
/** The length of the binary message. */
unsigned short length;
/** The message as a bencoded dictionary. */
Dict* asDict;
/**
* If this message is an outgoing reply, replyTo is the original query.
* For incoming replies or any queries, it is NULL.
*/
struct DHTMessage* replyTo;
/** A memory allocator which will be freed after this message is sent. */
const struct MemAllocator* allocator;
};
/**
* This represents a DHT module.
* Pass one of these to DHTModule_register() and it
* will handle dht requests and responses.
*/
struct DHTModule;
struct DHTModule {
/**
* A user friendly null terminated string which will be used to
* manipulate the module using the DHTModules API.
*/
const char* const name;
/**
* The module's state.
*/
void* const context;
/**
* Serialize the content of the context into a bencoded object.
*
* @param context the module's state.
* @return a serialized form of context.
*/
Dict* (* const serialize)(void* context);
/**
* Deserialize the context from a bencoded object.
*
* @param serialData the same data which was output by
* moduleContext_serialize.
*
* @param context the existing context to add content to.
*/
void (* const deserialize)(const Dict* serialData,
void* context);
/**
* When a node must be evicted from the table, this will allow the
* module to decide which one it should be. Thus other node with more
* capabilities will be favored.
*
* @param one node's ID.
* @param another node's ID.
* @param context the module's state.
* @return less than 0 if the first node is favorable, greater than 0
* if the second node is more favorable,
* 0 if they are considered equal.
*/
int (* const compareNodes)(const char nodeId[20],
const char otherNodeId[20],
void* context);
/**
* @param the message which came in from a peer.
* @param context the module's state.
* @return 1 if a response should be sent for this message.
* -1 if the message is known invalid and should not be passed
* to any more handlers.
*/
int (* const handleIncoming)(struct DHTMessage* message,
void* context);
/**
* @param message the message which will be sent to the peer.
* @param context the module's state.
* @return -1 if the message should not be propigated to any more modules.
* use with caution as it may be interpreted as network loss.
*/
int (* const handleOutgoing)(struct DHTMessage* message,
void* context);
};
/** State of the registry. */
struct DHTModuleRegistry {
/** Number of members. */
int memberCount;
/** A null terminated list of pointers to members. */
struct DHTModule** members;
/**
* A list of serialized contexts by module name to be
* deserialized when the modules are loaded.
*/
Dict* serializedContexts;
/** Means of getting memory for the registry. */
struct MemAllocator* allocator;
};
/**
* Create a new registry.
*
* @param allocator the means of getting memory to store the registry.
* @return a new (empty) registry.
*/
struct DHTModuleRegistry* DHTModules_new(struct MemAllocator* allocator);
/**
* Register an event handler.
*
* @param module the module to register.
* @return 0 if everything went well.
*/
int DHTModules_register(struct DHTModule* module,
struct DHTModuleRegistry* registry);
/**
* handleIncoming starts by running the last module registered
* and working back. It is assumed that the core modules will
* be registered first and will be the ones to initiate the
* response.
* The last module registered must be the one with access to
* the network.
*
* @see DHTModule->handleIncoming()
*/
void DHTModules_handleIncoming(struct DHTMessage* message,
const struct DHTModuleRegistry* registry);
/**
* @see DHTModule->handleOutgoing()
*/
void DHTModules_handleOutgoing(struct DHTMessage* message,
const struct DHTModuleRegistry* registry);
/**
* Serialize the state of each member in the registry.
*
* @param registry the module registry to serialize.
* @param writer a writer to which the output will be written.
* @see DHTModule->serialize
*/
void DHTModules_serialize(const struct DHTModuleRegistry* registry,
const struct Writer* writer);
/**
* Deserialize a new registry from binary.
* NOTE: After deserialization, the modules still need to be registered.
*
* @param reader a reader which reads a stream of data prepared by a former call to DHTModules_serialize()
* @param allocator a means of acquiring memory.
* @return a new registry, modules will still need to be registered although they will regain their
* former state afterwords.
* @see DHTModule->deserialize
*/
struct DHTModuleRegistry* DHTModules_deserialize(const struct Reader* reader,
struct MemAllocator* allocator);
#endif