diff options
author | Nathan S. Evans <evans@in.tum.de> | 2010-03-12 08:38:10 +0000 |
---|---|---|
committer | Nathan S. Evans <evans@in.tum.de> | 2010-03-12 08:38:10 +0000 |
commit | d82a838ef2250f344e8846cdf24504c2cde0f0d4 (patch) | |
tree | 7e07634c284fd49e5e92723792ca6f315171588f /src/dv/gnunet-service-dv.c | |
parent | 40cdfd2a094ad1e1d39d619c84ba04a18637ebef (diff) | |
download | gnunet-d82a838ef2250f344e8846cdf24504c2cde0f0d4.tar.gz gnunet-d82a838ef2250f344e8846cdf24504c2cde0f0d4.zip |
non-compiling, but getting there
Diffstat (limited to 'src/dv/gnunet-service-dv.c')
-rw-r--r-- | src/dv/gnunet-service-dv.c | 620 |
1 files changed, 595 insertions, 25 deletions
diff --git a/src/dv/gnunet-service-dv.c b/src/dv/gnunet-service-dv.c index 3c483746e..bb5e03193 100644 --- a/src/dv/gnunet-service-dv.c +++ b/src/dv/gnunet-service-dv.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include "gnunet_service_lib.h" | 36 | #include "gnunet_service_lib.h" |
37 | #include "gnunet_core_service.h" | 37 | #include "gnunet_core_service.h" |
38 | #include "gnunet_signal_lib.h" | 38 | #include "gnunet_signal_lib.h" |
39 | #include "gnunet_util_lib.h" | ||
39 | #include "dv.h" | 40 | #include "dv.h" |
40 | 41 | ||
41 | /** | 42 | /** |
@@ -50,7 +51,7 @@ static struct GNUNET_CORE_Handle *coreAPI; | |||
50 | /** | 51 | /** |
51 | * The identity of our peer. | 52 | * The identity of our peer. |
52 | */ | 53 | */ |
53 | static struct GNUNET_PeerIdentity *my_identity; | 54 | const struct GNUNET_PeerIdentity *my_identity; |
54 | 55 | ||
55 | /** | 56 | /** |
56 | * The configuration for this service. | 57 | * The configuration for this service. |
@@ -63,6 +64,44 @@ const struct GNUNET_CONFIGURATION_Handle *cfg; | |||
63 | static struct GNUNET_SCHEDULER_Handle *sched; | 64 | static struct GNUNET_SCHEDULER_Handle *sched; |
64 | 65 | ||
65 | /** | 66 | /** |
67 | * How often do we check about sending out more peer information (if | ||
68 | * we are connected to no peers previously). | ||
69 | */ | ||
70 | #define GNUNET_DV_DEFAULT_SEND_INTERVAL (500 * GNUNET_CRON_MILLISECONDS) | ||
71 | |||
72 | /** | ||
73 | * How long do we wait at most between sending out information? | ||
74 | */ | ||
75 | #define GNUNET_DV_MAX_SEND_INTERVAL (5000 * GNUNET_CRON_MILLISECONDS) | ||
76 | |||
77 | /** | ||
78 | * How long can we have not heard from a peer and | ||
79 | * still have it in our tables? | ||
80 | */ | ||
81 | #define GNUNET_DV_PEER_EXPIRATION_TIME (3000 * GNUNET_CRON_SECONDS) | ||
82 | |||
83 | /** | ||
84 | * Priority for gossip. | ||
85 | */ | ||
86 | #define GNUNET_DV_DHT_GOSSIP_PRIORITY (GNUNET_EXTREME_PRIORITY / 10) | ||
87 | |||
88 | /** | ||
89 | * How often should we check if expiration time has elapsed for | ||
90 | * some peer? | ||
91 | */ | ||
92 | #define GNUNET_DV_MAINTAIN_FREQUENCY (5 * GNUNET_CRON_SECONDS) | ||
93 | |||
94 | /** | ||
95 | * How long to allow a message to be delayed? | ||
96 | */ | ||
97 | #define DV_DELAY (5000 * GNUNET_CRON_MILLISECONDS) | ||
98 | |||
99 | /** | ||
100 | * Priority to use for DV data messages. | ||
101 | */ | ||
102 | #define DV_PRIORITY 0 | ||
103 | |||
104 | /** | ||
66 | * The client, should be the DV plugin connected to us. Hopefully | 105 | * The client, should be the DV plugin connected to us. Hopefully |
67 | * this client will never change, although if the plugin dies | 106 | * this client will never change, although if the plugin dies |
68 | * and returns for some reason it may happen. | 107 | * and returns for some reason it may happen. |
@@ -72,21 +111,273 @@ static struct GNUNET_SERVER_Client * client_handle; | |||
72 | GNUNET_SCHEDULER_TaskIdentifier cleanup_task; | 111 | GNUNET_SCHEDULER_TaskIdentifier cleanup_task; |
73 | 112 | ||
74 | /** | 113 | /** |
114 | * Struct where neighbor information is stored. | ||
115 | */ | ||
116 | struct DistantNeighbor *referees; | ||
117 | |||
118 | /** | ||
119 | * Struct to hold information for updating existing neighbors | ||
120 | */ | ||
121 | struct NeighborUpdateInfo | ||
122 | { | ||
123 | /** | ||
124 | * Cost | ||
125 | */ | ||
126 | unsigned int cost; | ||
127 | |||
128 | /** | ||
129 | * The existing neighbor | ||
130 | */ | ||
131 | struct DistantNeighbor *neighbor; | ||
132 | |||
133 | /** | ||
134 | * The referrer of the possibly existing peer | ||
135 | */ | ||
136 | struct DirectNeighbor *referrer; | ||
137 | |||
138 | /** | ||
139 | * The time we heard about this peer | ||
140 | */ | ||
141 | struct GNUNET_TIME_Absolute now; | ||
142 | }; | ||
143 | |||
144 | /** | ||
145 | * Struct where actual neighbor information is stored, | ||
146 | * referenced by min_heap and max_heap. Freeing dealt | ||
147 | * with when items removed from hashmap. | ||
148 | */ | ||
149 | struct DirectNeighbor | ||
150 | { | ||
151 | /** | ||
152 | * Identity of neighbor. | ||
153 | */ | ||
154 | struct GNUNET_PeerIdentity identity; | ||
155 | |||
156 | /** | ||
157 | * Head of DLL of nodes that this direct neighbor referred to us. | ||
158 | */ | ||
159 | struct DistantNeighbor *referee_head; | ||
160 | |||
161 | /** | ||
162 | * Tail of DLL of nodes that this direct neighbor referred to us. | ||
163 | */ | ||
164 | struct DistantNeighbor *referee_tail; | ||
165 | |||
166 | /** | ||
167 | * Is this one of the direct neighbors that we are "hiding" | ||
168 | * from DV? | ||
169 | */ | ||
170 | int hidden; | ||
171 | }; | ||
172 | |||
173 | |||
174 | /** | ||
175 | * Struct where actual neighbor information is stored, | ||
176 | * referenced by min_heap and max_heap. Freeing dealt | ||
177 | * with when items removed from hashmap. | ||
178 | */ | ||
179 | struct DistantNeighbor | ||
180 | { | ||
181 | /** | ||
182 | * We keep distant neighbor's of the same referrer in a DLL. | ||
183 | */ | ||
184 | struct DistantNeighbor *next; | ||
185 | |||
186 | /** | ||
187 | * We keep distant neighbor's of the same referrer in a DLL. | ||
188 | */ | ||
189 | struct DistantNeighbor *prev; | ||
190 | |||
191 | /** | ||
192 | * Node in min heap | ||
193 | */ | ||
194 | struct GNUNET_CONTAINER_HeapNode *min_loc; | ||
195 | |||
196 | /** | ||
197 | * Node in max heap | ||
198 | */ | ||
199 | struct GNUNET_CONTAINER_HeapNode *max_loc; | ||
200 | |||
201 | /** | ||
202 | * Identity of referrer (next hop towards 'neighbor'). | ||
203 | */ | ||
204 | struct DirectNeighbor *referrer; | ||
205 | |||
206 | /** | ||
207 | * Identity of neighbor. | ||
208 | */ | ||
209 | struct GNUNET_PeerIdentity identity; | ||
210 | |||
211 | /** | ||
212 | * Last time we received routing information from this peer | ||
213 | */ | ||
214 | struct GNUNET_TIME_Absolute last_activity; | ||
215 | |||
216 | /** | ||
217 | * Cost to neighbor, used for actual distance vector computations | ||
218 | */ | ||
219 | unsigned int cost; | ||
220 | |||
221 | /** | ||
222 | * Random identifier *we* use for this peer, to be used as shortcut | ||
223 | * instead of sending full peer id for each message | ||
224 | */ | ||
225 | unsigned int our_id; | ||
226 | |||
227 | /** | ||
228 | * Random identifier the *referrer* uses for this peer. | ||
229 | */ | ||
230 | unsigned int referrer_id; | ||
231 | |||
232 | /** | ||
233 | * Is this one of the direct neighbors that we are "hiding" | ||
234 | * from DV? | ||
235 | */ | ||
236 | int hidden; | ||
237 | }; | ||
238 | |||
239 | |||
240 | /** | ||
241 | * Global construct | ||
242 | */ | ||
243 | struct GNUNET_DV_Context | ||
244 | { | ||
245 | /** | ||
246 | * Map of PeerIdentifiers to 'struct GNUNET_dv_neighbor*'s for all | ||
247 | * directly connected peers. | ||
248 | */ | ||
249 | struct GNUNET_CONTAINER_MultiHashMap *direct_neighbors; | ||
250 | |||
251 | /** | ||
252 | * Map of PeerIdentifiers to 'struct GNUNET_dv_neighbor*'s for | ||
253 | * peers connected via DV (extended neighborhood). Does ALSO | ||
254 | * include any peers that are in 'direct_neighbors'; for those | ||
255 | * peers, the cost will be zero and the referrer all zeros. | ||
256 | */ | ||
257 | struct GNUNET_CONTAINER_MultiHashMap *extended_neighbors; | ||
258 | |||
259 | /** | ||
260 | * We use the min heap (min refers to cost) to prefer | ||
261 | * gossipping about peers with small costs. | ||
262 | */ | ||
263 | struct GNUNET_CONTAINER_Heap *neighbor_min_heap; | ||
264 | |||
265 | /** | ||
266 | * We use the max heap (max refers to cost) for general | ||
267 | * iterations over all peers and to remove the most costly | ||
268 | * connection if we have too many. | ||
269 | */ | ||
270 | struct GNUNET_CONTAINER_Heap *neighbor_max_heap; | ||
271 | |||
272 | unsigned long long fisheye_depth; | ||
273 | |||
274 | unsigned long long max_table_size; | ||
275 | |||
276 | unsigned int send_interval; | ||
277 | |||
278 | unsigned int neighbor_id_loc; | ||
279 | |||
280 | int closing; | ||
281 | }; | ||
282 | |||
283 | static char shortID[5]; | ||
284 | |||
285 | static struct GNUNET_DV_Context ctx; | ||
286 | |||
287 | struct FindDestinationContext | ||
288 | { | ||
289 | unsigned int tid; | ||
290 | struct DistantNeighbor *dest; | ||
291 | }; | ||
292 | |||
293 | |||
294 | /** | ||
295 | * We've been given a target ID based on the random numbers that | ||
296 | * we assigned to our DV-neighborhood. Find the entry for the | ||
297 | * respective neighbor. | ||
298 | */ | ||
299 | static int | ||
300 | find_destination (void *cls, | ||
301 | struct GNUNET_CONTAINER_HeapNode *node, | ||
302 | void *element, GNUNET_CONTAINER_HeapCostType cost) | ||
303 | { | ||
304 | struct FindDestinationContext *fdc = cls; | ||
305 | struct DistantNeighbor *dn = element; | ||
306 | |||
307 | if (fdc->tid != dn->our_id) | ||
308 | return GNUNET_YES; | ||
309 | fdc->dest = dn; | ||
310 | return GNUNET_NO; | ||
311 | } | ||
312 | |||
313 | /** | ||
314 | * Function called to notify a client about the socket | ||
315 | * begin ready to queue more data. "buf" will be | ||
316 | * NULL and "size" zero if the socket was closed for | ||
317 | * writing in the meantime. | ||
318 | * | ||
319 | * @param cls closure | ||
320 | * @param size number of bytes available in buf | ||
321 | * @param buf where the callee should write the message | ||
322 | * @return number of bytes written to buf | ||
323 | */ | ||
324 | size_t transmit_to_plugin (void *cls, | ||
325 | size_t size, void *buf) | ||
326 | { | ||
327 | struct GNUNET_DV_MessageReceived *msg = cls; | ||
328 | |||
329 | if (buf == NULL) | ||
330 | return 0; | ||
331 | |||
332 | GNUNET_assert(size >= ntohs(msg->header.size)); | ||
333 | |||
334 | memcpy(buf, msg, size); | ||
335 | GNUNET_free(msg); | ||
336 | return size; | ||
337 | } | ||
338 | |||
339 | |||
340 | void send_to_plugin(const struct GNUNET_PeerIdentity * sender, const struct GNUNET_MessageHeader *message, size_t message_size, struct DistantNeighbor *distant_neighbor) | ||
341 | { | ||
342 | struct GNUNET_DV_MessageReceived *received_msg; | ||
343 | int size; | ||
344 | |||
345 | if (ntohs(msg->size) < sizeof(struct GNUNET_DV_MessageReceived)) | ||
346 | return; | ||
347 | |||
348 | size = sizeof(struct GNUNET_DV_MessageReceived) + message_size + sizeof(struct GNUNET_PeerIdentity); | ||
349 | received_msg = GNUNET_malloc(size); | ||
350 | received_msg->header.size = htons(size); | ||
351 | received_msg->header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_DV_RECEIVE); | ||
352 | received_msg->sender_address_len = sizeof(struct GNUNET_PeerIdentity); | ||
353 | received_msg->distance = htonl(distant_neighbor->cost); | ||
354 | /* Set the sender in this message to be the original sender! */ | ||
355 | memcpy(&received_msg->sender, &distant_neighbor->identity, sizeof(struct GNUNET_PeerIdentity)); | ||
356 | /* Copy the intermediate sender to the end of the message, this is how the transport identifies this peer */ | ||
357 | memcpy(&received_msg[1], sender, sizeof(struct GNUNET_PeerIdentity)); | ||
358 | |||
359 | /* FIXME: Send to the client please */ | ||
360 | GNUNET_SERVER_notify_transmit_ready (client_handle, | ||
361 | size, CLIENT_TRANSMIT_TIMEOUT, | ||
362 | &transmit_to_plugin, &received_msg); | ||
363 | |||
364 | } | ||
365 | |||
366 | /** | ||
75 | * Core handler for dv data messages. Whatever this message | 367 | * Core handler for dv data messages. Whatever this message |
76 | * contains all we really have to do is rip it out of its | 368 | * contains all we really have to do is rip it out of its |
77 | * DV layering and give it to our pal the DV plugin to report | 369 | * DV layering and give it to our pal the DV plugin to report |
78 | * in with. | 370 | * in with. |
79 | * | 371 | * |
80 | * @param cls closure | 372 | * @param cls closure |
81 | * @param client identification of the client | 373 | * @param peer peer which sent the message (immediate sender) |
82 | * @param message the actual message | 374 | * @param message the message |
375 | * @param latency the latency of the connection we received the message from | ||
376 | * @param distance the distance to the immediate peer | ||
83 | */ | 377 | */ |
84 | static void handle_dv_data_message (void *cls, | 378 | static int handle_dv_data_message (void *cls, |
85 | struct GNUNET_PeerIdentity * | 379 | const struct GNUNET_PeerIdentity * peer, |
86 | peer, | 380 | const struct GNUNET_MessageHeader * message, |
87 | const struct | ||
88 | GNUNET_MessageHeader * | ||
89 | message, | ||
90 | struct GNUNET_TIME_Relative latency, | 381 | struct GNUNET_TIME_Relative latency, |
91 | uint32_t distance) | 382 | uint32_t distance) |
92 | { | 383 | { |
@@ -95,6 +386,92 @@ static void handle_dv_data_message (void *cls, | |||
95 | "%s: Receives %s message!\n", "dv", "DV DATA"); | 386 | "%s: Receives %s message!\n", "dv", "DV DATA"); |
96 | #endif | 387 | #endif |
97 | 388 | ||
389 | const p2p_dv_MESSAGE_Data *incoming = (const p2p_dv_MESSAGE_Data *) message; | ||
390 | const struct GNUNET_MessageHeader *packed_message = (const struct GNUNET_MessageHeader *) &incoming[1]; | ||
391 | struct DirectNeighbor *dn; | ||
392 | struct DistantNeighbor *pos; | ||
393 | unsigned int sid; /* Sender id */ | ||
394 | unsigned int tid; /* Target id */ | ||
395 | struct GNUNET_PeerIdentity original_sender; | ||
396 | struct GNUNET_PeerIdentity destination; | ||
397 | struct FindDestinationContext fdc; | ||
398 | int ret; | ||
399 | |||
400 | if ((ntohs (incoming->header.size) < | ||
401 | sizeof (p2p_dv_MESSAGE_Data) + sizeof (struct GNUNET_MessageHeader)) | ||
402 | || (ntohs (incoming->header.size) != | ||
403 | (sizeof (p2p_dv_MESSAGE_Data) + ntohs (packed_message->size)))) | ||
404 | { | ||
405 | return GNUNET_SYSERR; | ||
406 | } | ||
407 | |||
408 | dn = GNUNET_CONTAINER_multihashmap_get (ctx.direct_neighbors, | ||
409 | &peer->hashPubKey); | ||
410 | if (dn == NULL) | ||
411 | { | ||
412 | return GNUNET_OK; | ||
413 | } | ||
414 | sid = ntohl (incoming->sender); | ||
415 | pos = dn->referee_head; | ||
416 | while ((NULL != pos) && (pos->referrer_id != sid)) | ||
417 | pos = pos->next; | ||
418 | if (pos == NULL) | ||
419 | { | ||
420 | /* unknown sender */ | ||
421 | return GNUNET_OK; | ||
422 | } | ||
423 | original_sender = pos->identity; | ||
424 | tid = ntohl (incoming->recipient); | ||
425 | if (tid == 0) | ||
426 | { | ||
427 | /* 0 == us */ | ||
428 | |||
429 | /* FIXME: Will we support wrapped messages being these types? Probably not, they should | ||
430 | * be encrypted messages that need decrypting and junk like that. | ||
431 | */ | ||
432 | GNUNET_break_op (ntohs (packed_message->type) != GNUNET_MESSAGE_TYPE_DV_GOSSIP); | ||
433 | GNUNET_break_op (ntohs (packed_message->type) != GNUNET_MESSAGE_TYPE_DV_DATA); | ||
434 | if ( (ntohs (packed_message->type) != GNUNET_MESSAGE_TYPE_DV_GOSSIP) && | ||
435 | (ntohs (packed_message->type) != GNUNET_MESSAGE_TYPE_DV_DATA) ) | ||
436 | { | ||
437 | /* FIXME: send the message, wrap it up and return it to the DV plugin */ | ||
438 | /*coreAPI->loopback_send (&original_sender, (const char *) packed_message, | ||
439 | ntohs (packed_message->size), GNUNET_YES, NULL);*/ | ||
440 | send_to_plugin(peer, packed_message, ntohs(packed_message->size), pos); | ||
441 | } | ||
442 | |||
443 | return GNUNET_OK; | ||
444 | } | ||
445 | |||
446 | /* FIXME: this is the *only* per-request operation we have in DV | ||
447 | that is O(n) in relation to the number of connected peers; a | ||
448 | hash-table lookup could easily solve this (minor performance | ||
449 | issue) */ | ||
450 | fdc.tid = tid; | ||
451 | fdc.dest = NULL; | ||
452 | GNUNET_CONTAINER_heap_iterate (ctx.neighbor_max_heap, | ||
453 | &find_destination, &fdc); | ||
454 | if (fdc.dest == NULL) | ||
455 | { | ||
456 | return GNUNET_OK; | ||
457 | } | ||
458 | destination = fdc.dest->identity; | ||
459 | |||
460 | if (0 == memcmp (&destination, peer, sizeof (struct GNUNET_PeerIdentity))) | ||
461 | { | ||
462 | /* FIXME: create stat: routing loop-discard! */ | ||
463 | return GNUNET_OK; | ||
464 | } | ||
465 | |||
466 | /* FIXME: Can't send message on, we have to behave. | ||
467 | * We have to tell core we have a message for the next peer, and let | ||
468 | * transport do transport selection on how to get this message to 'em */ | ||
469 | /*ret = send_message (&destination, | ||
470 | &original_sender, | ||
471 | packed_message, DV_PRIORITY, DV_DELAY);*/ | ||
472 | send_to_core(&destination, &original_sender, packed_message, DV_PRIORITY, DV_DELAY); | ||
473 | |||
474 | return GNUNET_OK; | ||
98 | } | 475 | } |
99 | 476 | ||
100 | /** | 477 | /** |
@@ -105,20 +482,23 @@ static void handle_dv_data_message (void *cls, | |||
105 | * transport service so that it can be used by all others. | 482 | * transport service so that it can be used by all others. |
106 | * | 483 | * |
107 | * @param cls closure | 484 | * @param cls closure |
108 | * @param client identification of the client | 485 | * @param peer peer which sent the message (immediate sender) |
109 | * @param message the actual message | 486 | * @param message the message |
487 | * @param latency the latency of the connection we received the message from | ||
488 | * @param distance the distance to the immediate peer | ||
110 | */ | 489 | */ |
111 | static void handle_dv_gossip_message (void *cls, | 490 | static int handle_dv_gossip_message (void *cls, |
112 | struct GNUNET_PeerIdentity * peer, | 491 | const struct GNUNET_PeerIdentity *peer, |
113 | const struct GNUNET_MessageHeader * message, | 492 | const struct GNUNET_MessageHeader *message, |
114 | struct GNUNET_TIME_Relative latency, | 493 | struct GNUNET_TIME_Relative latency, |
115 | uint32_t distance) | 494 | uint32_t distance) |
116 | { | 495 | { |
117 | #if DEBUG_DV | 496 | #if DEBUG_DV |
118 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 497 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
119 | "%s: Receives %s message!\n", "dv", "DV GOSSIP"); | 498 | "%s: Receives %s message!\n", "dv", "DV GOSSIP"); |
120 | #endif | 499 | #endif |
121 | 500 | ||
501 | return 0; | ||
122 | } | 502 | } |
123 | 503 | ||
124 | 504 | ||
@@ -153,8 +533,11 @@ void send_dv_message (void *cls, | |||
153 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 533 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
154 | "%s: Setting client handle (was a different client!)!\n", "dv"); | 534 | "%s: Setting client handle (was a different client!)!\n", "dv"); |
155 | } | 535 | } |
536 | |||
537 | GNUNET_SERVER_receive_done(client, GNUNET_OK); | ||
156 | } | 538 | } |
157 | 539 | ||
540 | |||
158 | /** | 541 | /** |
159 | * List of handlers for the messages understood by this | 542 | * List of handlers for the messages understood by this |
160 | * service. | 543 | * service. |
@@ -171,6 +554,7 @@ static struct GNUNET_CORE_MessageHandler core_handlers[] = { | |||
171 | {NULL, 0, 0} | 554 | {NULL, 0, 0} |
172 | }; | 555 | }; |
173 | 556 | ||
557 | |||
174 | static struct GNUNET_SERVER_MessageHandler plugin_handlers[] = { | 558 | static struct GNUNET_SERVER_MessageHandler plugin_handlers[] = { |
175 | {&send_dv_message, NULL, GNUNET_MESSAGE_TYPE_TRANSPORT_DV_SEND, 0}, | 559 | {&send_dv_message, NULL, GNUNET_MESSAGE_TYPE_TRANSPORT_DV_SEND, 0}, |
176 | {NULL, NULL, 0, 0} | 560 | {NULL, NULL, 0, 0} |
@@ -196,7 +580,7 @@ shutdown_task (void *cls, | |||
196 | */ | 580 | */ |
197 | void core_init (void *cls, | 581 | void core_init (void *cls, |
198 | struct GNUNET_CORE_Handle * server, | 582 | struct GNUNET_CORE_Handle * server, |
199 | const struct GNUNET_PeerIdentity *my_identity, | 583 | const struct GNUNET_PeerIdentity *identity, |
200 | const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded * publicKey) | 584 | const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded * publicKey) |
201 | { | 585 | { |
202 | 586 | ||
@@ -208,29 +592,201 @@ void core_init (void *cls, | |||
208 | } | 592 | } |
209 | #if DEBUG_DV | 593 | #if DEBUG_DV |
210 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 594 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
211 | "%s: Core connection initialized, I am peer: %s\n", "dv", GNUNET_i2s(my_identity)); | 595 | "%s: Core connection initialized, I am peer: %s\n", "dv", GNUNET_i2s(identity)); |
212 | #endif | 596 | #endif |
597 | my_identity = identity; | ||
213 | coreAPI = server; | 598 | coreAPI = server; |
214 | } | 599 | } |
215 | 600 | ||
601 | |||
602 | /** | ||
603 | * Iterator over hash map entries. | ||
604 | * | ||
605 | * @param cls closure | ||
606 | * @param key current key code | ||
607 | * @param value value in the hash map | ||
608 | * @return GNUNET_YES if we should continue to | ||
609 | * iterate, | ||
610 | * GNUNET_NO if not. | ||
611 | */ | ||
612 | static int update_matching_neighbors (void *cls, | ||
613 | const GNUNET_HashCode * key, | ||
614 | void *value) | ||
615 | { | ||
616 | struct NeighborUpdateInfo * update_info = cls; | ||
617 | struct DirectNeighbor *direct_neighbor = value; | ||
618 | |||
619 | if (update_info->referrer == direct_neighbor) /* Direct neighbor matches, update it's info and return GNUNET_NO */ | ||
620 | { | ||
621 | /* same referrer, cost change! */ | ||
622 | GNUNET_CONTAINER_heap_update_cost (ctx.neighbor_max_heap, | ||
623 | update_info->neighbor->max_loc, update_info->cost); | ||
624 | GNUNET_CONTAINER_heap_update_cost (ctx.neighbor_min_heap, | ||
625 | update_info->neighbor->min_loc, update_info->cost); | ||
626 | update_info->neighbor->last_activity = update_info->now; | ||
627 | update_info->neighbor->cost = update_info->cost; | ||
628 | return GNUNET_NO; | ||
629 | } | ||
630 | |||
631 | return GNUNET_YES; | ||
632 | } | ||
633 | |||
634 | |||
635 | /** | ||
636 | * Free a DistantNeighbor node, including removing it | ||
637 | * from the referer's list. | ||
638 | */ | ||
639 | static void | ||
640 | distant_neighbor_free (struct DistantNeighbor *referee) | ||
641 | { | ||
642 | struct DirectNeighbor *referrer; | ||
643 | |||
644 | referrer = referee->referrer; | ||
645 | if (referrer != NULL) | ||
646 | { | ||
647 | GNUNET_CONTAINER_DLL_remove (referrer->referee_head, | ||
648 | referrer->referee_tail, referee); | ||
649 | } | ||
650 | GNUNET_CONTAINER_heap_remove_node (ctx.neighbor_max_heap, referee->max_loc); | ||
651 | GNUNET_CONTAINER_heap_remove_node (ctx.neighbor_min_heap, referee->min_loc); | ||
652 | GNUNET_CONTAINER_multihashmap_remove_all (ctx.extended_neighbors, | ||
653 | &referee->identity.hashPubKey); | ||
654 | GNUNET_free (referee); | ||
655 | } | ||
656 | |||
657 | |||
658 | /** | ||
659 | * Handles when a peer is either added due to being newly connected | ||
660 | * or having been gossiped about, also called when a cost for a neighbor | ||
661 | * needs to be updated. | ||
662 | * | ||
663 | * @param peer identity of the peer whose info is being added/updated | ||
664 | * @param peer_id id to use when sending to 'peer' | ||
665 | * @param referrer if this is a gossiped peer, who did we hear it from? | ||
666 | * @param cost the cost of communicating with this peer via 'referrer' | ||
667 | */ | ||
668 | static void | ||
669 | addUpdateNeighbor (const struct GNUNET_PeerIdentity * peer, | ||
670 | unsigned int referrer_peer_id, | ||
671 | struct DirectNeighbor *referrer, unsigned int cost) | ||
672 | { | ||
673 | struct DistantNeighbor *neighbor; | ||
674 | struct DistantNeighbor *max; | ||
675 | struct GNUNET_TIME_Absolute now; | ||
676 | struct NeighborUpdateInfo *neighbor_update; | ||
677 | unsigned int our_id; | ||
678 | |||
679 | now = GNUNET_TIME_absolute_get (); | ||
680 | our_id = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, RAND_MAX - 1) + 1; | ||
681 | |||
682 | neighbor = GNUNET_CONTAINER_multihashmap_get (ctx.extended_neighbors, | ||
683 | &peer->hashPubKey); | ||
684 | neighbor_update = GNUNET_malloc(sizeof(struct NeighborUpdateInfo)); | ||
685 | neighbor_update->neighbor = neighbor; | ||
686 | neighbor_update->cost = cost; | ||
687 | neighbor_update->now = now; | ||
688 | neighbor_update->referrer = referrer; | ||
689 | |||
690 | /* Either we do not know this peer, or we already do but via a different immediate peer */ | ||
691 | if ((neighbor == NULL) || | ||
692 | (GNUNET_CONTAINER_multihashmap_get_multiple(ctx.extended_neighbors, | ||
693 | &peer->hashPubKey, | ||
694 | &update_matching_neighbors, | ||
695 | neighbor_update) != GNUNET_SYSERR)) | ||
696 | { | ||
697 | /* new neighbor! */ | ||
698 | if (cost > ctx.fisheye_depth) | ||
699 | { | ||
700 | /* too costly */ | ||
701 | return; | ||
702 | } | ||
703 | if (ctx.max_table_size <= | ||
704 | GNUNET_CONTAINER_multihashmap_size (ctx.extended_neighbors)) | ||
705 | { | ||
706 | /* remove most expensive entry */ | ||
707 | max = GNUNET_CONTAINER_heap_peek (ctx.neighbor_max_heap); | ||
708 | if (cost > max->cost) | ||
709 | { | ||
710 | /* new entry most expensive, don't create */ | ||
711 | return; | ||
712 | } | ||
713 | if (max->cost > 0) | ||
714 | { | ||
715 | /* only free if this is not a direct connection; | ||
716 | we could theoretically have more direct | ||
717 | connections than DV entries allowed total! */ | ||
718 | distant_neighbor_free (max); | ||
719 | } | ||
720 | } | ||
721 | |||
722 | neighbor = GNUNET_malloc (sizeof (struct DistantNeighbor)); | ||
723 | GNUNET_CONTAINER_DLL_insert (referrer->referee_head, | ||
724 | referrer->referee_tail, neighbor); | ||
725 | neighbor->max_loc = GNUNET_CONTAINER_heap_insert (ctx.neighbor_max_heap, | ||
726 | neighbor, cost); | ||
727 | neighbor->min_loc = GNUNET_CONTAINER_heap_insert (ctx.neighbor_min_heap, | ||
728 | neighbor, cost); | ||
729 | neighbor->referrer = referrer; | ||
730 | memcpy (&neighbor->identity, peer, sizeof (struct GNUNET_PeerIdentity)); | ||
731 | neighbor->last_activity = now; | ||
732 | neighbor->cost = cost; | ||
733 | neighbor->referrer_id = referrer_peer_id; | ||
734 | neighbor->our_id = our_id; | ||
735 | neighbor->hidden = | ||
736 | (cost == 0) ? (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 4) == | ||
737 | 0) : GNUNET_NO; | ||
738 | GNUNET_CONTAINER_multihashmap_put (ctx.extended_neighbors, &peer->hashPubKey, | ||
739 | neighbor, | ||
740 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
741 | |||
742 | return; | ||
743 | } | ||
744 | |||
745 | /* Old logic to remove entry and replace, not needed now as we only want to remove when full | ||
746 | * or when the referring peer disconnects from us. | ||
747 | */ | ||
748 | /* | ||
749 | GNUNET_DLL_remove (neighbor->referrer->referee_head, | ||
750 | neighbor->referrer->referee_tail, neighbor); | ||
751 | neighbor->referrer = referrer; | ||
752 | GNUNET_DLL_insert (referrer->referee_head, | ||
753 | referrer->referee_tail, neighbor); | ||
754 | GNUNET_CONTAINER_heap_update_cost (ctx.neighbor_max_heap, | ||
755 | neighbor->max_loc, cost); | ||
756 | GNUNET_CONTAINER_heap_update_cost (ctx.neighbor_min_heap, | ||
757 | neighbor->min_loc, cost); | ||
758 | neighbor->referrer_id = referrer_peer_id; | ||
759 | neighbor->last_activity = now; | ||
760 | neighbor->cost = cost; | ||
761 | */ | ||
762 | } | ||
763 | |||
764 | |||
216 | /** | 765 | /** |
217 | * Method called whenever a given peer either connects. | 766 | * Method called whenever a given peer either connects. |
218 | * | 767 | * |
219 | * @param cls closure | 768 | * @param cls closure |
220 | * @param peer peer identity this notification is about | 769 | * @param peer peer identity this notification is about |
221 | * @param latency reported latency of the connection with 'other' | 770 | * @param latency reported latency of the connection with peer |
222 | * @param distance reported distance (DV) to 'other' | 771 | * @param distance reported distance (DV) to peer |
223 | */ | 772 | */ |
224 | void handle_core_connect (void *cls, | 773 | void handle_core_connect (void *cls, |
225 | const struct GNUNET_PeerIdentity * peer, | 774 | const struct GNUNET_PeerIdentity * peer, |
226 | struct GNUNET_TIME_Relative latency, | 775 | struct GNUNET_TIME_Relative latency, |
227 | uint32_t distance) | 776 | uint32_t distance) |
228 | { | 777 | { |
229 | 778 | struct DirectNeighbor *neighbor; | |
230 | #if DEBUG_DV | 779 | #if DEBUG_DV |
231 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 780 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
232 | "%s: Receives core connect message!\n", "dv"); | 781 | "%s: Receives core connect message for peer %s distance %d!\n", "dv", GNUNET_i2s(peer), distance); |
233 | #endif | 782 | #endif |
783 | |||
784 | neighbor = GNUNET_malloc (sizeof (struct DirectNeighbor)); | ||
785 | memcpy (&neighbor->identity, peer, sizeof (struct GNUNET_PeerIdentity)); | ||
786 | GNUNET_CONTAINER_multihashmap_put (ctx.direct_neighbors, | ||
787 | &peer->hashPubKey, | ||
788 | neighbor, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); | ||
789 | addUpdateNeighbor (peer, 0, neighbor, 0); | ||
234 | } | 790 | } |
235 | 791 | ||
236 | /** | 792 | /** |
@@ -238,16 +794,30 @@ void handle_core_connect (void *cls, | |||
238 | * | 794 | * |
239 | * @param cls closure | 795 | * @param cls closure |
240 | * @param peer peer identity this notification is about | 796 | * @param peer peer identity this notification is about |
241 | * @param latency reported latency of the connection with 'other' | ||
242 | * @param distance reported distance (DV) to 'other' | ||
243 | */ | 797 | */ |
244 | void handle_core_disconnect (void *cls, | 798 | void handle_core_disconnect (void *cls, |
245 | const struct GNUNET_PeerIdentity * peer) | 799 | const struct GNUNET_PeerIdentity * peer) |
246 | { | 800 | { |
801 | struct DirectNeighbor *neighbor; | ||
802 | struct DistantNeighbor *referee; | ||
803 | |||
247 | #if DEBUG_DV | 804 | #if DEBUG_DV |
248 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 805 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
249 | "%s: Receives core peer disconnect message!\n", "dv"); | 806 | "%s: Receives core peer disconnect message!\n", "dv"); |
250 | #endif | 807 | #endif |
808 | |||
809 | neighbor = | ||
810 | GNUNET_CONTAINER_multihashmap_get (ctx.direct_neighbors, &peer->hashPubKey); | ||
811 | if (neighbor == NULL) | ||
812 | { | ||
813 | return; | ||
814 | } | ||
815 | while (NULL != (referee = neighbor->referee_head)) | ||
816 | distant_neighbor_free (referee); | ||
817 | GNUNET_assert (neighbor->referee_tail == NULL); | ||
818 | GNUNET_CONTAINER_multihashmap_remove (ctx.direct_neighbors, | ||
819 | &peer->hashPubKey, neighbor); | ||
820 | GNUNET_free (neighbor); | ||
251 | } | 821 | } |
252 | 822 | ||
253 | 823 | ||
@@ -255,7 +825,7 @@ void handle_core_disconnect (void *cls, | |||
255 | * Process dv requests. | 825 | * Process dv requests. |
256 | * | 826 | * |
257 | * @param cls closure | 827 | * @param cls closure |
258 | * @param sched scheduler to use | 828 | * @param scheduler scheduler to use |
259 | * @param server the initialized server | 829 | * @param server the initialized server |
260 | * @param c configuration to use | 830 | * @param c configuration to use |
261 | */ | 831 | */ |