diff options
author | Supriti Singh <supritisingh08@gmail.com> | 2014-04-07 17:23:33 +0000 |
---|---|---|
committer | Supriti Singh <supritisingh08@gmail.com> | 2014-04-07 17:23:33 +0000 |
commit | 395864e0875252a779e783765b955c4193741065 (patch) | |
tree | 7c7b2c8a92732c3ce862fb315f886255f18c0b45 /src/dht | |
parent | daa7b00b515bba437b467e66753a1cda7afa2e3f (diff) | |
download | gnunet-395864e0875252a779e783765b955c4193741065.tar.gz gnunet-395864e0875252a779e783765b955c4193741065.zip |
1.Removed GNUNET_CRYPTO_compute_finger_identity
2.Removed myself as the first element of the trail.
3.Multiple entries in the routing table.
4.Put/Get/Monitor from old DHT added back in clients file.
Diffstat (limited to 'src/dht')
-rw-r--r-- | src/dht/gnunet-service-xdht_clients.c | 1172 | ||||
-rw-r--r-- | src/dht/gnunet-service-xdht_clients.h | 33 | ||||
-rw-r--r-- | src/dht/gnunet-service-xdht_datacache.c | 2 | ||||
-rw-r--r-- | src/dht/gnunet-service-xdht_neighbours.c | 984 | ||||
-rw-r--r-- | src/dht/gnunet-service-xdht_neighbours.h | 15 | ||||
-rw-r--r-- | src/dht/gnunet-service-xdht_routing.c | 99 | ||||
-rw-r--r-- | src/dht/gnunet-service-xdht_routing.h | 8 |
7 files changed, 1716 insertions, 597 deletions
diff --git a/src/dht/gnunet-service-xdht_clients.c b/src/dht/gnunet-service-xdht_clients.c index 050d8a99e..d3b920551 100644 --- a/src/dht/gnunet-service-xdht_clients.c +++ b/src/dht/gnunet-service-xdht_clients.c | |||
@@ -21,7 +21,8 @@ | |||
21 | /** | 21 | /** |
22 | * @file dht/gnunet-service-dht_clients.c | 22 | * @file dht/gnunet-service-dht_clients.c |
23 | * @brief GNUnet DHT service's client management code | 23 | * @brief GNUnet DHT service's client management code |
24 | * @author Supriti Singh | 24 | * @author Christian Grothoff |
25 | * @author Nathan Evans | ||
25 | */ | 26 | */ |
26 | 27 | ||
27 | #include "platform.h" | 28 | #include "platform.h" |
@@ -34,6 +35,14 @@ | |||
34 | #include "gnunet-service-xdht_neighbours.h" | 35 | #include "gnunet-service-xdht_neighbours.h" |
35 | #include "dht.h" | 36 | #include "dht.h" |
36 | 37 | ||
38 | |||
39 | /** | ||
40 | * Should routing details be logged to stderr (for debugging)? | ||
41 | */ | ||
42 | #define LOG_TRAFFIC(kind,...) GNUNET_log_from (kind, "dht-traffic",__VA_ARGS__) | ||
43 | |||
44 | #define LOG(kind,...) GNUNET_log_from (kind, "dht-clients",__VA_ARGS__) | ||
45 | |||
37 | /** | 46 | /** |
38 | * Linked list of messages to send to clients. | 47 | * Linked list of messages to send to clients. |
39 | */ | 48 | */ |
@@ -58,6 +67,7 @@ struct PendingMessage | |||
58 | 67 | ||
59 | }; | 68 | }; |
60 | 69 | ||
70 | |||
61 | /** | 71 | /** |
62 | * Struct containing information about a client, | 72 | * Struct containing information about a client, |
63 | * handle to connect to it, and any pending messages | 73 | * handle to connect to it, and any pending messages |
@@ -100,6 +110,129 @@ struct ClientList | |||
100 | 110 | ||
101 | 111 | ||
102 | /** | 112 | /** |
113 | * Entry in the local forwarding map for a client's GET request. | ||
114 | */ | ||
115 | struct ClientQueryRecord | ||
116 | { | ||
117 | |||
118 | /** | ||
119 | * The key this request was about | ||
120 | */ | ||
121 | struct GNUNET_HashCode key; | ||
122 | |||
123 | /** | ||
124 | * Client responsible for the request. | ||
125 | */ | ||
126 | struct ClientList *client; | ||
127 | |||
128 | /** | ||
129 | * Extended query (see gnunet_block_lib.h), allocated at the end of this struct. | ||
130 | */ | ||
131 | const void *xquery; | ||
132 | |||
133 | /** | ||
134 | * Replies we have already seen for this request. | ||
135 | */ | ||
136 | struct GNUNET_HashCode *seen_replies; | ||
137 | |||
138 | /** | ||
139 | * Pointer to this nodes heap location in the retry-heap (for fast removal) | ||
140 | */ | ||
141 | struct GNUNET_CONTAINER_HeapNode *hnode; | ||
142 | |||
143 | /** | ||
144 | * What's the delay between re-try operations that we currently use for this | ||
145 | * request? | ||
146 | */ | ||
147 | struct GNUNET_TIME_Relative retry_frequency; | ||
148 | |||
149 | /** | ||
150 | * What's the next time we should re-try this request? | ||
151 | */ | ||
152 | struct GNUNET_TIME_Absolute retry_time; | ||
153 | |||
154 | /** | ||
155 | * The unique identifier of this request | ||
156 | */ | ||
157 | uint64_t unique_id; | ||
158 | |||
159 | /** | ||
160 | * Number of bytes in xquery. | ||
161 | */ | ||
162 | size_t xquery_size; | ||
163 | |||
164 | /** | ||
165 | * Number of entries in 'seen_replies'. | ||
166 | */ | ||
167 | unsigned int seen_replies_count; | ||
168 | |||
169 | /** | ||
170 | * Desired replication level | ||
171 | */ | ||
172 | uint32_t replication; | ||
173 | |||
174 | /** | ||
175 | * Any message options for this request | ||
176 | */ | ||
177 | uint32_t msg_options; | ||
178 | |||
179 | /** | ||
180 | * The type for the data for the GET request. | ||
181 | */ | ||
182 | enum GNUNET_BLOCK_Type type; | ||
183 | |||
184 | }; | ||
185 | |||
186 | |||
187 | /** | ||
188 | * Struct containing paremeters of monitoring requests. | ||
189 | */ | ||
190 | struct ClientMonitorRecord | ||
191 | { | ||
192 | |||
193 | /** | ||
194 | * Next element in DLL. | ||
195 | */ | ||
196 | struct ClientMonitorRecord *next; | ||
197 | |||
198 | /** | ||
199 | * Previous element in DLL. | ||
200 | */ | ||
201 | struct ClientMonitorRecord *prev; | ||
202 | |||
203 | /** | ||
204 | * Type of blocks that are of interest | ||
205 | */ | ||
206 | enum GNUNET_BLOCK_Type type; | ||
207 | |||
208 | /** | ||
209 | * Key of data of interest, NULL for all. | ||
210 | */ | ||
211 | struct GNUNET_HashCode *key; | ||
212 | |||
213 | /** | ||
214 | * Flag whether to notify about GET messages. | ||
215 | */ | ||
216 | int16_t get; | ||
217 | |||
218 | /** | ||
219 | * Flag whether to notify about GET_REPONSE messages. | ||
220 | */ | ||
221 | int16_t get_resp; | ||
222 | |||
223 | /** | ||
224 | * Flag whether to notify about PUT messages. | ||
225 | */ | ||
226 | uint16_t put; | ||
227 | |||
228 | /** | ||
229 | * Client to notify of these requests. | ||
230 | */ | ||
231 | struct ClientList *client; | ||
232 | }; | ||
233 | |||
234 | |||
235 | /** | ||
103 | * List of active clients. | 236 | * List of active clients. |
104 | */ | 237 | */ |
105 | static struct ClientList *client_head; | 238 | static struct ClientList *client_head; |
@@ -110,11 +243,40 @@ static struct ClientList *client_head; | |||
110 | static struct ClientList *client_tail; | 243 | static struct ClientList *client_tail; |
111 | 244 | ||
112 | /** | 245 | /** |
246 | * List of active monitoring requests. | ||
247 | */ | ||
248 | static struct ClientMonitorRecord *monitor_head; | ||
249 | |||
250 | /** | ||
251 | * List of active monitoring requests. | ||
252 | */ | ||
253 | static struct ClientMonitorRecord *monitor_tail; | ||
254 | |||
255 | /** | ||
256 | * Hashmap for fast key based lookup, maps keys to `struct ClientQueryRecord` entries. | ||
257 | */ | ||
258 | static struct GNUNET_CONTAINER_MultiHashMap *forward_map; | ||
259 | |||
260 | /** | ||
261 | * Heap with all of our client's request, sorted by retry time (earliest on top). | ||
262 | */ | ||
263 | static struct GNUNET_CONTAINER_Heap *retry_heap; | ||
264 | |||
265 | /** | ||
266 | * Task that re-transmits requests (using retry_heap). | ||
267 | */ | ||
268 | static GNUNET_SCHEDULER_TaskIdentifier retry_task; | ||
269 | |||
270 | |||
271 | /** | ||
113 | * Task run to check for messages that need to be sent to a client. | 272 | * Task run to check for messages that need to be sent to a client. |
114 | * | 273 | * |
115 | * @param client a ClientList, containing the client and any messages to be sent to it | 274 | * @param client a ClientList, containing the client and any messages to be sent to it |
116 | */ | 275 | */ |
117 | static void process_pending_messages (struct ClientList *client); | 276 | static void |
277 | process_pending_messages (struct ClientList *client); | ||
278 | |||
279 | |||
118 | /** | 280 | /** |
119 | * Callback called as a result of issuing a GNUNET_SERVER_notify_transmit_ready | 281 | * Callback called as a result of issuing a GNUNET_SERVER_notify_transmit_ready |
120 | * request. A ClientList is passed as closure, take the head of the list | 282 | * request. A ClientList is passed as closure, take the head of the list |
@@ -208,6 +370,41 @@ add_pending_message (struct ClientList *client, | |||
208 | process_pending_messages (client); | 370 | process_pending_messages (client); |
209 | } | 371 | } |
210 | 372 | ||
373 | |||
374 | /** | ||
375 | * Closure for 'forward_reply' | ||
376 | */ | ||
377 | struct ForwardReplyContext | ||
378 | { | ||
379 | |||
380 | /** | ||
381 | * Actual message to send to matching clients. | ||
382 | */ | ||
383 | struct PendingMessage *pm; | ||
384 | |||
385 | /** | ||
386 | * Embedded payload. | ||
387 | */ | ||
388 | const void *data; | ||
389 | |||
390 | /** | ||
391 | * Type of the data. | ||
392 | */ | ||
393 | enum GNUNET_BLOCK_Type type; | ||
394 | |||
395 | /** | ||
396 | * Number of bytes in data. | ||
397 | */ | ||
398 | size_t data_size; | ||
399 | |||
400 | /** | ||
401 | * Do we need to copy 'pm' because it was already used? | ||
402 | */ | ||
403 | int do_copy; | ||
404 | |||
405 | }; | ||
406 | |||
407 | |||
211 | /** | 408 | /** |
212 | * Find a client if it exists, add it otherwise. | 409 | * Find a client if it exists, add it otherwise. |
213 | * | 410 | * |
@@ -235,118 +432,476 @@ find_active_client (struct GNUNET_SERVER_Client *client) | |||
235 | 432 | ||
236 | 433 | ||
237 | /** | 434 | /** |
238 | * SUPU: Call made from dht_api.c | 435 | * Iterator over hash map entries that frees all entries |
239 | * Handler for monitor stop messages | 436 | * associated with the given client. |
240 | * | 437 | * |
241 | * @param cls closure for the service | 438 | * @param cls client to search for in source routes |
242 | * @param client the client we received this message from | 439 | * @param key current key code (ignored) |
243 | * @param message the actual message received | 440 | * @param value value in the hash map, a ClientQueryRecord |
441 | * @return #GNUNET_YES (we should continue to iterate) | ||
442 | */ | ||
443 | static int | ||
444 | remove_client_records (void *cls, const struct GNUNET_HashCode * key, void *value) | ||
445 | { | ||
446 | struct ClientList *client = cls; | ||
447 | struct ClientQueryRecord *record = value; | ||
448 | |||
449 | if (record->client != client) | ||
450 | return GNUNET_YES; | ||
451 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
452 | "Removing client %p's record for key %s\n", client, | ||
453 | GNUNET_h2s (key)); | ||
454 | GNUNET_assert (GNUNET_YES == | ||
455 | GNUNET_CONTAINER_multihashmap_remove (forward_map, key, | ||
456 | record)); | ||
457 | if (NULL != record->hnode) | ||
458 | GNUNET_CONTAINER_heap_remove_node (record->hnode); | ||
459 | GNUNET_array_grow (record->seen_replies, record->seen_replies_count, 0); | ||
460 | GNUNET_free (record); | ||
461 | return GNUNET_YES; | ||
462 | } | ||
463 | |||
464 | |||
465 | /** | ||
466 | * Iterator over hash map entries that send a given reply to | ||
467 | * each of the matching clients. With some tricky recycling | ||
468 | * of the buffer. | ||
244 | * | 469 | * |
470 | * @param cls the 'struct ForwardReplyContext' | ||
471 | * @param key current key | ||
472 | * @param value value in the hash map, a ClientQueryRecord | ||
473 | * @return GNUNET_YES (we should continue to iterate), | ||
474 | * if the result is mal-formed, GNUNET_NO | ||
245 | */ | 475 | */ |
246 | static void | 476 | static int |
247 | handle_dht_local_monitor_stop (void *cls, struct GNUNET_SERVER_Client *client, | 477 | forward_reply (void *cls, const struct GNUNET_HashCode * key, void *value) |
248 | const struct GNUNET_MessageHeader *message) | ||
249 | { | 478 | { |
250 | //const struct GNUNET_DHT_MonitorStartStopMessage *msg; | 479 | struct ForwardReplyContext *frc = cls; |
480 | struct ClientQueryRecord *record = value; | ||
481 | struct PendingMessage *pm; | ||
482 | struct GNUNET_DHT_ClientResultMessage *reply; | ||
483 | enum GNUNET_BLOCK_EvaluationResult eval; | ||
484 | int do_free; | ||
485 | struct GNUNET_HashCode ch; | ||
486 | unsigned int i; | ||
487 | |||
488 | LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG, | ||
489 | "R5N CLIENT-RESULT %s\n", | ||
490 | GNUNET_h2s_full (key)); | ||
491 | if ((record->type != GNUNET_BLOCK_TYPE_ANY) && (record->type != frc->type)) | ||
492 | { | ||
493 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
494 | "Record type missmatch, not passing request for key %s to local client\n", | ||
495 | GNUNET_h2s (key)); | ||
496 | GNUNET_STATISTICS_update (GDS_stats, | ||
497 | gettext_noop | ||
498 | ("# Key match, type mismatches in REPLY to CLIENT"), | ||
499 | 1, GNUNET_NO); | ||
500 | return GNUNET_YES; /* type mismatch */ | ||
501 | } | ||
502 | GNUNET_CRYPTO_hash (frc->data, frc->data_size, &ch); | ||
503 | for (i = 0; i < record->seen_replies_count; i++) | ||
504 | if (0 == memcmp (&record->seen_replies[i], &ch, sizeof (struct GNUNET_HashCode))) | ||
505 | { | ||
506 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
507 | "Duplicate reply, not passing request for key %s to local client\n", | ||
508 | GNUNET_h2s (key)); | ||
509 | GNUNET_STATISTICS_update (GDS_stats, | ||
510 | gettext_noop | ||
511 | ("# Duplicate REPLIES to CLIENT request dropped"), | ||
512 | 1, GNUNET_NO); | ||
513 | return GNUNET_YES; /* duplicate */ | ||
514 | } | ||
515 | eval = | ||
516 | GNUNET_BLOCK_evaluate (GDS_block_context, record->type, key, NULL, 0, | ||
517 | record->xquery, record->xquery_size, frc->data, | ||
518 | frc->data_size); | ||
519 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
520 | "Evaluation result is %d for key %s for local client's query\n", | ||
521 | (int) eval, GNUNET_h2s (key)); | ||
522 | switch (eval) | ||
523 | { | ||
524 | case GNUNET_BLOCK_EVALUATION_OK_LAST: | ||
525 | do_free = GNUNET_YES; | ||
526 | break; | ||
527 | case GNUNET_BLOCK_EVALUATION_OK_MORE: | ||
528 | GNUNET_array_append (record->seen_replies, record->seen_replies_count, ch); | ||
529 | do_free = GNUNET_NO; | ||
530 | break; | ||
531 | case GNUNET_BLOCK_EVALUATION_OK_DUPLICATE: | ||
532 | /* should be impossible to encounter here */ | ||
533 | GNUNET_break (0); | ||
534 | return GNUNET_YES; | ||
535 | case GNUNET_BLOCK_EVALUATION_RESULT_INVALID: | ||
536 | GNUNET_break_op (0); | ||
537 | return GNUNET_NO; | ||
538 | case GNUNET_BLOCK_EVALUATION_REQUEST_VALID: | ||
539 | GNUNET_break (0); | ||
540 | return GNUNET_NO; | ||
541 | case GNUNET_BLOCK_EVALUATION_REQUEST_INVALID: | ||
542 | GNUNET_break (0); | ||
543 | return GNUNET_NO; | ||
544 | case GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT: | ||
545 | return GNUNET_YES; | ||
546 | case GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED: | ||
547 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
548 | _("Unsupported block type (%u) in request!\n"), record->type); | ||
549 | return GNUNET_NO; | ||
550 | default: | ||
551 | GNUNET_break (0); | ||
552 | return GNUNET_NO; | ||
553 | } | ||
554 | if (GNUNET_NO == frc->do_copy) | ||
555 | { | ||
556 | /* first time, we can use the original data */ | ||
557 | pm = frc->pm; | ||
558 | frc->do_copy = GNUNET_YES; | ||
559 | } | ||
560 | else | ||
561 | { | ||
562 | /* two clients waiting for same reply, must copy for queueing */ | ||
563 | pm = GNUNET_malloc (sizeof (struct PendingMessage) + | ||
564 | ntohs (frc->pm->msg->size)); | ||
565 | memcpy (pm, frc->pm, | ||
566 | sizeof (struct PendingMessage) + ntohs (frc->pm->msg->size)); | ||
567 | pm->next = pm->prev = NULL; | ||
568 | pm->msg = (struct GNUNET_MessageHeader *) &pm[1]; | ||
569 | } | ||
570 | GNUNET_STATISTICS_update (GDS_stats, | ||
571 | gettext_noop ("# RESULTS queued for clients"), 1, | ||
572 | GNUNET_NO); | ||
573 | reply = (struct GNUNET_DHT_ClientResultMessage *) &pm[1]; | ||
574 | reply->unique_id = record->unique_id; | ||
575 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
576 | "Queueing reply to query %s for client %p\n", | ||
577 | GNUNET_h2s (key), | ||
578 | record->client->client_handle); | ||
579 | add_pending_message (record->client, pm); | ||
580 | if (GNUNET_YES == do_free) | ||
581 | remove_client_records (record->client, key, record); | ||
582 | return GNUNET_YES; | ||
251 | } | 583 | } |
252 | 584 | ||
253 | 585 | ||
254 | /** | 586 | /** |
255 | * SUPU: Monitor call made from dht_api.c | 587 | * Handle a reply we've received from another peer. If the reply |
256 | * Handler for monitor start messages | 588 | * matches any of our pending queries, forward it to the respective |
589 | * client(s). | ||
257 | * | 590 | * |
258 | * @param cls closure for the service | 591 | * @param expiration when will the reply expire |
259 | * @param client the client we received this message from | 592 | * @param key the query this reply is for |
260 | * @param message the actual message received | 593 | * @param get_path_length number of peers in @a get_path |
594 | * @param get_path path the reply took on get | ||
595 | * @param put_path_length number of peers in @a put_path | ||
596 | * @param put_path path the reply took on put | ||
597 | * @param type type of the reply | ||
598 | * @param data_size number of bytes in @a data | ||
599 | * @param data application payload data | ||
600 | */ | ||
601 | void | ||
602 | GDS_CLIENTS_handle_reply (struct GNUNET_TIME_Absolute expiration, | ||
603 | const struct GNUNET_HashCode *key, | ||
604 | unsigned int get_path_length, | ||
605 | const struct GNUNET_PeerIdentity *get_path, | ||
606 | unsigned int put_path_length, | ||
607 | const struct GNUNET_PeerIdentity *put_path, | ||
608 | enum GNUNET_BLOCK_Type type, size_t data_size, | ||
609 | const void *data) | ||
610 | { | ||
611 | struct ForwardReplyContext frc; | ||
612 | struct PendingMessage *pm; | ||
613 | struct GNUNET_DHT_ClientResultMessage *reply; | ||
614 | struct GNUNET_PeerIdentity *paths; | ||
615 | size_t msize; | ||
616 | |||
617 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
618 | "reply for key %s\n", | ||
619 | GNUNET_h2s (key)); | ||
620 | |||
621 | if (NULL == GNUNET_CONTAINER_multihashmap_get (forward_map, key)) | ||
622 | { | ||
623 | GNUNET_STATISTICS_update (GDS_stats, | ||
624 | gettext_noop | ||
625 | ("# REPLIES ignored for CLIENTS (no match)"), 1, | ||
626 | GNUNET_NO); | ||
627 | return; /* no matching request, fast exit! */ | ||
628 | } | ||
629 | msize = | ||
630 | sizeof (struct GNUNET_DHT_ClientResultMessage) + data_size + | ||
631 | (get_path_length + put_path_length) * sizeof (struct GNUNET_PeerIdentity); | ||
632 | if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) | ||
633 | { | ||
634 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
635 | _("Could not pass reply to client, message too big!\n")); | ||
636 | return; | ||
637 | } | ||
638 | pm = GNUNET_malloc (msize + sizeof (struct PendingMessage)); | ||
639 | reply = (struct GNUNET_DHT_ClientResultMessage *) &pm[1]; | ||
640 | pm->msg = &reply->header; | ||
641 | reply->header.size = htons ((uint16_t) msize); | ||
642 | reply->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_CLIENT_RESULT); | ||
643 | reply->type = htonl (type); | ||
644 | reply->get_path_length = htonl (get_path_length); | ||
645 | reply->put_path_length = htonl (put_path_length); | ||
646 | reply->unique_id = 0; /* filled in later */ | ||
647 | reply->expiration = GNUNET_TIME_absolute_hton (expiration); | ||
648 | reply->key = *key; | ||
649 | paths = (struct GNUNET_PeerIdentity *) &reply[1]; | ||
650 | memcpy (paths, put_path, | ||
651 | sizeof (struct GNUNET_PeerIdentity) * put_path_length); | ||
652 | memcpy (&paths[put_path_length], get_path, | ||
653 | sizeof (struct GNUNET_PeerIdentity) * get_path_length); | ||
654 | memcpy (&paths[get_path_length + put_path_length], data, data_size); | ||
655 | frc.do_copy = GNUNET_NO; | ||
656 | frc.pm = pm; | ||
657 | frc.data = data; | ||
658 | frc.data_size = data_size; | ||
659 | frc.type = type; | ||
660 | GNUNET_CONTAINER_multihashmap_get_multiple (forward_map, key, &forward_reply, | ||
661 | &frc); | ||
662 | |||
663 | if (GNUNET_NO == frc.do_copy) | ||
664 | { | ||
665 | /* did not match any of the requests, free! */ | ||
666 | GNUNET_STATISTICS_update (GDS_stats, | ||
667 | gettext_noop | ||
668 | ("# REPLIES ignored for CLIENTS (no match)"), 1, | ||
669 | GNUNET_NO); | ||
670 | GNUNET_free (pm); | ||
671 | } | ||
672 | } | ||
673 | |||
674 | /** | ||
675 | * Check if some client is monitoring GET messages and notify | ||
676 | * them in that case. | ||
261 | * | 677 | * |
678 | * @param options Options, for instance RecordRoute, DemultiplexEverywhere. | ||
679 | * @param type The type of data in the request. | ||
680 | * @param hop_count Hop count so far. | ||
681 | * @param path_length number of entries in path (or 0 if not recorded). | ||
682 | * @param path peers on the GET path (or NULL if not recorded). | ||
683 | * @param desired_replication_level Desired replication level. | ||
684 | * @param key Key of the requested data. | ||
262 | */ | 685 | */ |
263 | static void | 686 | void |
264 | handle_dht_local_monitor (void *cls, struct GNUNET_SERVER_Client *client, | 687 | GDS_CLIENTS_process_get (uint32_t options, |
265 | const struct GNUNET_MessageHeader *message) | 688 | enum GNUNET_BLOCK_Type type, |
689 | uint32_t hop_count, | ||
690 | uint32_t desired_replication_level, | ||
691 | unsigned int path_length, | ||
692 | const struct GNUNET_PeerIdentity *path, | ||
693 | const struct GNUNET_HashCode * key) | ||
266 | { | 694 | { |
267 | //const struct GNUNET_DHT_MonitorStartStopMessage *msg; | 695 | struct ClientMonitorRecord *m; |
268 | /* FIXME: At the moment I don't know exact usage of monitor message. But most | 696 | struct ClientList **cl; |
269 | probably it will be just copy and paste from old implementation. */ | 697 | unsigned int cl_size; |
698 | |||
699 | cl = NULL; | ||
700 | cl_size = 0; | ||
701 | for (m = monitor_head; NULL != m; m = m->next) | ||
702 | { | ||
703 | if ((GNUNET_BLOCK_TYPE_ANY == m->type || m->type == type) && | ||
704 | (NULL == m->key || | ||
705 | memcmp (key, m->key, sizeof(struct GNUNET_HashCode)) == 0)) | ||
706 | { | ||
707 | struct PendingMessage *pm; | ||
708 | struct GNUNET_DHT_MonitorGetMessage *mmsg; | ||
709 | struct GNUNET_PeerIdentity *msg_path; | ||
710 | size_t msize; | ||
711 | unsigned int i; | ||
712 | |||
713 | /* Don't send duplicates */ | ||
714 | for (i = 0; i < cl_size; i++) | ||
715 | if (cl[i] == m->client) | ||
716 | break; | ||
717 | if (i < cl_size) | ||
718 | continue; | ||
719 | GNUNET_array_append (cl, cl_size, m->client); | ||
720 | |||
721 | msize = path_length * sizeof (struct GNUNET_PeerIdentity); | ||
722 | msize += sizeof (struct GNUNET_DHT_MonitorGetMessage); | ||
723 | msize += sizeof (struct PendingMessage); | ||
724 | pm = GNUNET_malloc (msize); | ||
725 | mmsg = (struct GNUNET_DHT_MonitorGetMessage *) &pm[1]; | ||
726 | pm->msg = &mmsg->header; | ||
727 | mmsg->header.size = htons (msize - sizeof (struct PendingMessage)); | ||
728 | mmsg->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_MONITOR_GET); | ||
729 | mmsg->options = htonl(options); | ||
730 | mmsg->type = htonl(type); | ||
731 | mmsg->hop_count = htonl(hop_count); | ||
732 | mmsg->desired_replication_level = htonl(desired_replication_level); | ||
733 | mmsg->get_path_length = htonl(path_length); | ||
734 | memcpy (&mmsg->key, key, sizeof (struct GNUNET_HashCode)); | ||
735 | msg_path = (struct GNUNET_PeerIdentity *) &mmsg[1]; | ||
736 | if (path_length > 0) | ||
737 | memcpy (msg_path, path, | ||
738 | path_length * sizeof (struct GNUNET_PeerIdentity)); | ||
739 | add_pending_message (m->client, pm); | ||
740 | } | ||
741 | } | ||
742 | GNUNET_free_non_null (cl); | ||
270 | } | 743 | } |
271 | 744 | ||
272 | 745 | ||
273 | /**SUPU: Call to this function is made whenever a client does not want the | 746 | /** |
274 | * get request any more. There is a function in dht_api.c but I don't know | 747 | * Check if some client is monitoring PUT messages and notify |
275 | * yet how the call is made to this function. | 748 | * them in that case. |
276 | * Handler for any generic DHT stop messages, calls the appropriate handler | ||
277 | * depending on message type (if processed locally) | ||
278 | * | ||
279 | * @param cls closure for the service | ||
280 | * @param client the client we received this message from | ||
281 | * @param message the actual message received | ||
282 | * | 749 | * |
750 | * @param options Options, for instance RecordRoute, DemultiplexEverywhere. | ||
751 | * @param type The type of data in the request. | ||
752 | * @param hop_count Hop count so far. | ||
753 | * @param path_length number of entries in path (or 0 if not recorded). | ||
754 | * @param path peers on the PUT path (or NULL if not recorded). | ||
755 | * @param desired_replication_level Desired replication level. | ||
756 | * @param exp Expiration time of the data. | ||
757 | * @param key Key under which data is to be stored. | ||
758 | * @param data Pointer to the data carried. | ||
759 | * @param size Number of bytes in data. | ||
760 | */ | ||
761 | void | ||
762 | GDS_CLIENTS_process_put (uint32_t options, | ||
763 | enum GNUNET_BLOCK_Type type, | ||
764 | uint32_t hop_count, | ||
765 | uint32_t desired_replication_level, | ||
766 | unsigned int path_length, | ||
767 | const struct GNUNET_PeerIdentity *path, | ||
768 | struct GNUNET_TIME_Absolute exp, | ||
769 | const struct GNUNET_HashCode * key, | ||
770 | const void *data, | ||
771 | size_t size) | ||
772 | { | ||
773 | struct ClientMonitorRecord *m; | ||
774 | struct ClientList **cl; | ||
775 | unsigned int cl_size; | ||
776 | |||
777 | cl = NULL; | ||
778 | cl_size = 0; | ||
779 | for (m = monitor_head; NULL != m; m = m->next) | ||
780 | { | ||
781 | if ((GNUNET_BLOCK_TYPE_ANY == m->type || m->type == type) && | ||
782 | (NULL == m->key || | ||
783 | memcmp (key, m->key, sizeof(struct GNUNET_HashCode)) == 0)) | ||
784 | { | ||
785 | struct PendingMessage *pm; | ||
786 | struct GNUNET_DHT_MonitorPutMessage *mmsg; | ||
787 | struct GNUNET_PeerIdentity *msg_path; | ||
788 | size_t msize; | ||
789 | unsigned int i; | ||
790 | |||
791 | /* Don't send duplicates */ | ||
792 | for (i = 0; i < cl_size; i++) | ||
793 | if (cl[i] == m->client) | ||
794 | break; | ||
795 | if (i < cl_size) | ||
796 | continue; | ||
797 | GNUNET_array_append (cl, cl_size, m->client); | ||
798 | |||
799 | msize = size; | ||
800 | msize += path_length * sizeof (struct GNUNET_PeerIdentity); | ||
801 | msize += sizeof (struct GNUNET_DHT_MonitorPutMessage); | ||
802 | msize += sizeof (struct PendingMessage); | ||
803 | pm = GNUNET_malloc (msize); | ||
804 | mmsg = (struct GNUNET_DHT_MonitorPutMessage *) &pm[1]; | ||
805 | pm->msg = (struct GNUNET_MessageHeader *) mmsg; | ||
806 | mmsg->header.size = htons (msize - sizeof (struct PendingMessage)); | ||
807 | mmsg->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_MONITOR_PUT); | ||
808 | mmsg->options = htonl(options); | ||
809 | mmsg->type = htonl(type); | ||
810 | mmsg->hop_count = htonl(hop_count); | ||
811 | mmsg->desired_replication_level = htonl(desired_replication_level); | ||
812 | mmsg->put_path_length = htonl(path_length); | ||
813 | msg_path = (struct GNUNET_PeerIdentity *) &mmsg[1]; | ||
814 | if (path_length > 0) | ||
815 | { | ||
816 | memcpy (msg_path, path, | ||
817 | path_length * sizeof (struct GNUNET_PeerIdentity)); | ||
818 | } | ||
819 | mmsg->expiration_time = GNUNET_TIME_absolute_hton(exp); | ||
820 | memcpy (&mmsg->key, key, sizeof (struct GNUNET_HashCode)); | ||
821 | if (size > 0) | ||
822 | memcpy (&msg_path[path_length], data, size); | ||
823 | add_pending_message (m->client, pm); | ||
824 | } | ||
825 | } | ||
826 | GNUNET_free_non_null (cl); | ||
827 | } | ||
828 | |||
829 | |||
830 | /** | ||
831 | * Route the given request via the DHT. | ||
283 | */ | 832 | */ |
284 | static void | 833 | static void |
285 | handle_dht_local_get_stop (void *cls, struct GNUNET_SERVER_Client *client, | 834 | transmit_request (struct ClientQueryRecord *cqr) |
286 | const struct GNUNET_MessageHeader *message) | ||
287 | { | 835 | { |
288 | //const struct GNUNET_DHT_ClientGetStopMessage *dht_stop_msg; | 836 | GNUNET_STATISTICS_update (GDS_stats, |
289 | /* FIXME: Whats the use of get_stop. A client notifies the server to stop asking | 837 | gettext_noop |
290 | for the get message. But in case of x-vine, it asks for get only once. So, | 838 | ("# GET requests from clients injected"), 1, |
291 | when it has already send the get message, after that if client asks it to | 839 | GNUNET_NO); |
292 | stop, it really can't do anything. Its better to wait for the result, discard | 840 | |
293 | it and don't communicate with client about the result instead of generating | 841 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
294 | more traffic.*/ | 842 | "Initiating GET for %s, replication %u, already have %u replies\n", |
843 | GNUNET_h2s (&cqr->key), | ||
844 | cqr->replication, | ||
845 | cqr->seen_replies_count); | ||
846 | #if 0 | ||
847 | /* FIXME: Change it to your own handle_get. */ | ||
848 | GDS_NEIGHBOURS_handle_get (cqr->type, cqr->msg_options, cqr->replication, | ||
849 | 0 /* hop count */ , | ||
850 | &cqr->key, cqr->xquery, cqr->xquery_size, reply_bf, | ||
851 | reply_bf_mutator, peer_bf); | ||
852 | #endif | ||
853 | |||
854 | |||
855 | /* exponential back-off for retries. | ||
856 | * max GNUNET_TIME_STD_EXPONENTIAL_BACKOFF_THRESHOLD (15 min) */ | ||
857 | cqr->retry_frequency = GNUNET_TIME_STD_BACKOFF (cqr->retry_frequency); | ||
858 | cqr->retry_time = GNUNET_TIME_relative_to_absolute (cqr->retry_frequency); | ||
295 | } | 859 | } |
296 | 860 | ||
861 | |||
297 | /** | 862 | /** |
298 | * FIXME: Call to this function is made whenever we have a get request. | 863 | * Task that looks at the 'retry_heap' and transmits all of the requests |
299 | * Handler for DHT GET messages from the client. | 864 | * on the heap that are ready for transmission. Then re-schedules |
865 | * itself (unless the heap is empty). | ||
300 | * | 866 | * |
301 | * @param cls closure for the service | 867 | * @param cls unused |
302 | * @param client the client we received this message from | 868 | * @param tc scheduler context |
303 | * @param message the actual message received | ||
304 | */ | 869 | */ |
305 | static void | 870 | static void |
306 | handle_dht_local_get (void *cls, struct GNUNET_SERVER_Client *client, | 871 | transmit_next_request_task (void *cls, |
307 | const struct GNUNET_MessageHeader *message) | 872 | const struct GNUNET_SCHEDULER_TaskContext *tc) |
308 | { | 873 | { |
309 | struct GNUNET_DHT_ClientGetMessage *get_msg; | 874 | struct ClientQueryRecord *cqr; |
310 | struct GNUNET_PeerIdentity *get_path; | 875 | struct GNUNET_TIME_Relative delay; |
311 | struct GNUNET_PeerIdentity *my_identity; | 876 | |
312 | unsigned int get_path_length; | 877 | retry_task = GNUNET_SCHEDULER_NO_TASK; |
313 | uint16_t size; | 878 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) |
314 | |||
315 | size = ntohs (message->size); | ||
316 | if (size < sizeof (struct GNUNET_DHT_ClientGetMessage)) | ||
317 | { | ||
318 | GNUNET_break (0); | ||
319 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
320 | return; | 879 | return; |
880 | while (NULL != (cqr = GNUNET_CONTAINER_heap_remove_root (retry_heap))) | ||
881 | { | ||
882 | cqr->hnode = NULL; | ||
883 | delay = GNUNET_TIME_absolute_get_remaining (cqr->retry_time); | ||
884 | if (delay.rel_value_us > 0) | ||
885 | { | ||
886 | cqr->hnode = | ||
887 | GNUNET_CONTAINER_heap_insert (retry_heap, cqr, | ||
888 | cqr->retry_time.abs_value_us); | ||
889 | retry_task = | ||
890 | GNUNET_SCHEDULER_add_delayed (delay, &transmit_next_request_task, | ||
891 | NULL); | ||
892 | return; | ||
893 | } | ||
894 | transmit_request (cqr); | ||
895 | cqr->hnode = | ||
896 | GNUNET_CONTAINER_heap_insert (retry_heap, cqr, | ||
897 | cqr->retry_time.abs_value_us); | ||
321 | } | 898 | } |
322 | |||
323 | get_msg = (struct GNUNET_DHT_ClientGetMessage *) message; | ||
324 | |||
325 | /* FIXME: Search locally? Why should we always search locally? | ||
326 | Current implementation of datacache needs to be modified. If found here, then | ||
327 | notify the requesting client. */ | ||
328 | |||
329 | /* FIXME: Call GDS_NEIGHBOURS_handle_get | ||
330 | Here you need to remember the whole path because you need to travel that path | ||
331 | and reach back here with the result. So, you should send your own id, client | ||
332 | id, get path, get path length. You also need to add yourself to the get path. */ | ||
333 | my_identity = GDS_NEIGHBOURS_get_id(); | ||
334 | get_path = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); | ||
335 | memcpy (get_path, &my_identity, sizeof (struct GNUNET_PeerIdentity)); | ||
336 | get_path_length = 1; | ||
337 | |||
338 | /* FIXME: | ||
339 | * 1. Find some unique identifier for the client. | ||
340 | * 2. Also, I don't know the usage of block, replication and type. So, I | ||
341 | * am not sending the parameters now. */ | ||
342 | GDS_NEIGHBOURS_handle_get (my_identity, get_path, get_path_length, | ||
343 | &(get_msg->key), NULL, NULL, NULL); | ||
344 | |||
345 | } | 899 | } |
346 | 900 | ||
347 | 901 | ||
348 | /** | 902 | /** |
349 | * Handler for PUT messages. | 903 | * Handler for PUT messages. |
904 | * | ||
350 | * @param cls closure for the service | 905 | * @param cls closure for the service |
351 | * @param client the client we received this message from | 906 | * @param client the client we received this message from |
352 | * @param message the actual message received | 907 | * @param message the actual message received |
@@ -355,10 +910,10 @@ static void | |||
355 | handle_dht_local_put (void *cls, struct GNUNET_SERVER_Client *client, | 910 | handle_dht_local_put (void *cls, struct GNUNET_SERVER_Client *client, |
356 | const struct GNUNET_MessageHeader *message) | 911 | const struct GNUNET_MessageHeader *message) |
357 | { | 912 | { |
358 | struct GNUNET_DHT_ClientPutMessage *put_msg; | 913 | const struct GNUNET_DHT_ClientPutMessage *put_msg; |
359 | struct GNUNET_DHT_ClientPutConfirmationMessage *conf; | ||
360 | struct PendingMessage *pm; | 914 | struct PendingMessage *pm; |
361 | uint16_t size; /* FIXME: When to use size_t and when uint16_t */ | 915 | struct GNUNET_DHT_ClientPutConfirmationMessage *conf; |
916 | uint16_t size; | ||
362 | 917 | ||
363 | size = ntohs (message->size); | 918 | size = ntohs (message->size); |
364 | if (size < sizeof (struct GNUNET_DHT_ClientPutMessage)) | 919 | if (size < sizeof (struct GNUNET_DHT_ClientPutMessage)) |
@@ -367,19 +922,32 @@ handle_dht_local_put (void *cls, struct GNUNET_SERVER_Client *client, | |||
367 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | 922 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); |
368 | return; | 923 | return; |
369 | } | 924 | } |
925 | GNUNET_STATISTICS_update (GDS_stats, | ||
926 | gettext_noop | ||
927 | ("# PUT requests received from clients"), 1, | ||
928 | GNUNET_NO); | ||
929 | put_msg = (const struct GNUNET_DHT_ClientPutMessage *) message; | ||
930 | LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG, "R5N CLIENT-PUT %s\n", | ||
931 | GNUNET_h2s_full (&put_msg->key)); | ||
932 | /* give to local clients */ | ||
933 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
934 | "Handling local PUT of %u-bytes for query %s\n", | ||
935 | size - sizeof (struct GNUNET_DHT_ClientPutMessage), | ||
936 | GNUNET_h2s (&put_msg->key)); | ||
370 | 937 | ||
371 | /* FIXME:Should we define put_msg as const? */ | 938 | GDS_CLIENTS_handle_reply (GNUNET_TIME_absolute_ntoh (put_msg->expiration), |
372 | put_msg = (struct GNUNET_DHT_ClientPutMessage *) message; | 939 | &put_msg->key, 0, NULL, 0, NULL, |
373 | 940 | ntohl (put_msg->type), | |
374 | /* store locally. FIXME: Is it secure to allow each peer to store the data? */ | 941 | size - sizeof (struct GNUNET_DHT_ClientPutMessage), |
942 | &put_msg[1]); | ||
943 | /* store locally */ | ||
375 | GDS_DATACACHE_handle_put (GNUNET_TIME_absolute_ntoh (put_msg->expiration), | 944 | GDS_DATACACHE_handle_put (GNUNET_TIME_absolute_ntoh (put_msg->expiration), |
376 | &put_msg->key, 0, NULL, ntohl (put_msg->type), | 945 | &put_msg->key, 0, NULL, ntohl (put_msg->type), |
377 | size - sizeof (struct GNUNET_DHT_ClientPutMessage), | 946 | size - sizeof (struct GNUNET_DHT_ClientPutMessage), |
378 | &put_msg[1]); | 947 | &put_msg[1]); |
379 | 948 | ||
380 | /* FIXME: Right now I have just kept all the fields from the old function. | 949 | /* FIXME: At the moment we don't use replication in x-vine. But keep it for |
381 | It may be possible that most of them are not needed. Check and remove if | 950 | time being. Check all the fields again. */ |
382 | not needed. Usage of replication, options and type is still not clear. */ | ||
383 | GDS_NEIGHBOURS_handle_put (ntohl (put_msg->type), ntohl (put_msg->options), | 951 | GDS_NEIGHBOURS_handle_put (ntohl (put_msg->type), ntohl (put_msg->options), |
384 | ntohl (put_msg->desired_replication_level), | 952 | ntohl (put_msg->desired_replication_level), |
385 | GNUNET_TIME_absolute_ntoh (put_msg->expiration), | 953 | GNUNET_TIME_absolute_ntoh (put_msg->expiration), |
@@ -387,10 +955,19 @@ handle_dht_local_put (void *cls, struct GNUNET_SERVER_Client *client, | |||
387 | &put_msg->key, 0, NULL, &put_msg[1], | 955 | &put_msg->key, 0, NULL, &put_msg[1], |
388 | size - | 956 | size - |
389 | sizeof (struct GNUNET_DHT_ClientPutMessage), | 957 | sizeof (struct GNUNET_DHT_ClientPutMessage), |
390 | NULL, NULL, NULL); | 958 | NULL, 0, NULL); |
959 | |||
960 | GDS_CLIENTS_process_put (ntohl (put_msg->options), | ||
961 | ntohl (put_msg->type), | ||
962 | 0, | ||
963 | ntohl (put_msg->desired_replication_level), | ||
964 | 1, | ||
965 | GDS_NEIGHBOURS_get_id(), | ||
966 | GNUNET_TIME_absolute_ntoh (put_msg->expiration), | ||
967 | &put_msg->key, | ||
968 | &put_msg[1], | ||
969 | size - sizeof (struct GNUNET_DHT_ClientPutMessage)); | ||
391 | 970 | ||
392 | /* FIXME: Here we send back the confirmation before verifying if put was successful | ||
393 | or not. */ | ||
394 | pm = GNUNET_malloc (sizeof (struct PendingMessage) + | 971 | pm = GNUNET_malloc (sizeof (struct PendingMessage) + |
395 | sizeof (struct GNUNET_DHT_ClientPutConfirmationMessage)); | 972 | sizeof (struct GNUNET_DHT_ClientPutConfirmationMessage)); |
396 | conf = (struct GNUNET_DHT_ClientPutConfirmationMessage *) &pm[1]; | 973 | conf = (struct GNUNET_DHT_ClientPutConfirmationMessage *) &pm[1]; |
@@ -403,6 +980,334 @@ handle_dht_local_put (void *cls, struct GNUNET_SERVER_Client *client, | |||
403 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | 980 | GNUNET_SERVER_receive_done (client, GNUNET_OK); |
404 | } | 981 | } |
405 | 982 | ||
983 | |||
984 | /** | ||
985 | * Handler for DHT GET messages from the client. | ||
986 | * | ||
987 | * @param cls closure for the service | ||
988 | * @param client the client we received this message from | ||
989 | * @param message the actual message received | ||
990 | */ | ||
991 | static void | ||
992 | handle_dht_local_get (void *cls, struct GNUNET_SERVER_Client *client, | ||
993 | const struct GNUNET_MessageHeader *message) | ||
994 | { | ||
995 | const struct GNUNET_DHT_ClientGetMessage *get; | ||
996 | struct ClientQueryRecord *cqr; | ||
997 | size_t xquery_size; | ||
998 | const char *xquery; | ||
999 | uint16_t size; | ||
1000 | |||
1001 | size = ntohs (message->size); | ||
1002 | if (size < sizeof (struct GNUNET_DHT_ClientGetMessage)) | ||
1003 | { | ||
1004 | GNUNET_break (0); | ||
1005 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
1006 | return; | ||
1007 | } | ||
1008 | xquery_size = size - sizeof (struct GNUNET_DHT_ClientGetMessage); | ||
1009 | get = (const struct GNUNET_DHT_ClientGetMessage *) message; | ||
1010 | xquery = (const char *) &get[1]; | ||
1011 | GNUNET_STATISTICS_update (GDS_stats, | ||
1012 | gettext_noop | ||
1013 | ("# GET requests received from clients"), 1, | ||
1014 | GNUNET_NO); | ||
1015 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1016 | "Received GET request for %s from local client %p, xq: %.*s\n", | ||
1017 | GNUNET_h2s (&get->key), client, xquery_size, xquery); | ||
1018 | |||
1019 | LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG, "R5N CLIENT-GET %s\n", | ||
1020 | GNUNET_h2s_full (&get->key)); | ||
1021 | |||
1022 | |||
1023 | cqr = GNUNET_malloc (sizeof (struct ClientQueryRecord) + xquery_size); | ||
1024 | cqr->key = get->key; | ||
1025 | cqr->client = find_active_client (client); | ||
1026 | cqr->xquery = (void *) &cqr[1]; | ||
1027 | memcpy (&cqr[1], xquery, xquery_size); | ||
1028 | cqr->hnode = GNUNET_CONTAINER_heap_insert (retry_heap, cqr, 0); | ||
1029 | cqr->retry_frequency = GNUNET_TIME_UNIT_SECONDS; | ||
1030 | cqr->retry_time = GNUNET_TIME_absolute_get (); | ||
1031 | cqr->unique_id = get->unique_id; | ||
1032 | cqr->xquery_size = xquery_size; | ||
1033 | cqr->replication = ntohl (get->desired_replication_level); | ||
1034 | cqr->msg_options = ntohl (get->options); | ||
1035 | cqr->type = ntohl (get->type); | ||
1036 | // FIXME use cqr->key, set multihashmap create to GNUNET_YES | ||
1037 | GNUNET_CONTAINER_multihashmap_put (forward_map, &get->key, cqr, | ||
1038 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
1039 | GDS_CLIENTS_process_get (ntohl (get->options), | ||
1040 | ntohl (get->type), | ||
1041 | 0, | ||
1042 | ntohl (get->desired_replication_level), | ||
1043 | 1, | ||
1044 | GDS_NEIGHBOURS_get_id(), | ||
1045 | &get->key); | ||
1046 | /* start remote requests */ | ||
1047 | if (GNUNET_SCHEDULER_NO_TASK != retry_task) | ||
1048 | GNUNET_SCHEDULER_cancel (retry_task); | ||
1049 | retry_task = GNUNET_SCHEDULER_add_now (&transmit_next_request_task, NULL); | ||
1050 | /* perform local lookup */ | ||
1051 | GDS_DATACACHE_handle_get (&get->key, cqr->type, cqr->xquery, xquery_size, | ||
1052 | NULL, 0); | ||
1053 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
1054 | } | ||
1055 | |||
1056 | |||
1057 | /** | ||
1058 | * Closure for 'find_by_unique_id'. | ||
1059 | */ | ||
1060 | struct FindByUniqueIdContext | ||
1061 | { | ||
1062 | /** | ||
1063 | * Where to store the result, if found. | ||
1064 | */ | ||
1065 | struct ClientQueryRecord *cqr; | ||
1066 | |||
1067 | uint64_t unique_id; | ||
1068 | }; | ||
1069 | |||
1070 | |||
1071 | /** | ||
1072 | * Function called for each existing DHT record for the given | ||
1073 | * query. Checks if it matches the UID given in the closure | ||
1074 | * and if so returns the entry as a result. | ||
1075 | * | ||
1076 | * @param cls the search context | ||
1077 | * @param key query for the lookup (not used) | ||
1078 | * @param value the 'struct ClientQueryRecord' | ||
1079 | * @return GNUNET_YES to continue iteration (result not yet found) | ||
1080 | */ | ||
1081 | static int | ||
1082 | find_by_unique_id (void *cls, | ||
1083 | const struct GNUNET_HashCode *key, | ||
1084 | void *value) | ||
1085 | { | ||
1086 | struct FindByUniqueIdContext *fui_ctx = cls; | ||
1087 | struct ClientQueryRecord *cqr = value; | ||
1088 | |||
1089 | if (cqr->unique_id != fui_ctx->unique_id) | ||
1090 | return GNUNET_YES; | ||
1091 | fui_ctx->cqr = cqr; | ||
1092 | return GNUNET_NO; | ||
1093 | } | ||
1094 | |||
1095 | |||
1096 | /** | ||
1097 | * Handler for "GET result seen" messages from the client. | ||
1098 | * | ||
1099 | * @param cls closure for the service | ||
1100 | * @param client the client we received this message from | ||
1101 | * @param message the actual message received | ||
1102 | */ | ||
1103 | static void | ||
1104 | handle_dht_local_get_result_seen (void *cls, struct GNUNET_SERVER_Client *client, | ||
1105 | const struct GNUNET_MessageHeader *message) | ||
1106 | { | ||
1107 | const struct GNUNET_DHT_ClientGetResultSeenMessage *seen; | ||
1108 | uint16_t size; | ||
1109 | unsigned int hash_count; | ||
1110 | unsigned int old_count; | ||
1111 | const struct GNUNET_HashCode *hc; | ||
1112 | struct FindByUniqueIdContext fui_ctx; | ||
1113 | struct ClientQueryRecord *cqr; | ||
1114 | |||
1115 | size = ntohs (message->size); | ||
1116 | if (size < sizeof (struct GNUNET_DHT_ClientGetResultSeenMessage)) | ||
1117 | { | ||
1118 | GNUNET_break (0); | ||
1119 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
1120 | return; | ||
1121 | } | ||
1122 | seen = (const struct GNUNET_DHT_ClientGetResultSeenMessage *) message; | ||
1123 | hash_count = (size - sizeof (struct GNUNET_DHT_ClientGetResultSeenMessage)) / sizeof (struct GNUNET_HashCode); | ||
1124 | if (size != sizeof (struct GNUNET_DHT_ClientGetResultSeenMessage) + hash_count * sizeof (struct GNUNET_HashCode)) | ||
1125 | { | ||
1126 | GNUNET_break (0); | ||
1127 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
1128 | return; | ||
1129 | } | ||
1130 | hc = (const struct GNUNET_HashCode*) &seen[1]; | ||
1131 | fui_ctx.unique_id = seen->unique_id; | ||
1132 | fui_ctx.cqr = NULL; | ||
1133 | GNUNET_CONTAINER_multihashmap_get_multiple (forward_map, | ||
1134 | &seen->key, | ||
1135 | &find_by_unique_id, | ||
1136 | &fui_ctx); | ||
1137 | if (NULL == (cqr = fui_ctx.cqr)) | ||
1138 | { | ||
1139 | GNUNET_break (0); | ||
1140 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
1141 | return; | ||
1142 | } | ||
1143 | /* finally, update 'seen' list */ | ||
1144 | old_count = cqr->seen_replies_count; | ||
1145 | GNUNET_array_grow (cqr->seen_replies, | ||
1146 | cqr->seen_replies_count, | ||
1147 | cqr->seen_replies_count + hash_count); | ||
1148 | memcpy (&cqr->seen_replies[old_count], | ||
1149 | hc, | ||
1150 | sizeof (struct GNUNET_HashCode) * hash_count); | ||
1151 | } | ||
1152 | |||
1153 | |||
1154 | /** | ||
1155 | * Closure for 'remove_by_unique_id'. | ||
1156 | */ | ||
1157 | struct RemoveByUniqueIdContext | ||
1158 | { | ||
1159 | /** | ||
1160 | * Client that issued the removal request. | ||
1161 | */ | ||
1162 | struct ClientList *client; | ||
1163 | |||
1164 | /** | ||
1165 | * Unique ID of the request. | ||
1166 | */ | ||
1167 | uint64_t unique_id; | ||
1168 | }; | ||
1169 | |||
1170 | |||
1171 | /** | ||
1172 | * Iterator over hash map entries that frees all entries | ||
1173 | * that match the given client and unique ID. | ||
1174 | * | ||
1175 | * @param cls unique ID and client to search for in source routes | ||
1176 | * @param key current key code | ||
1177 | * @param value value in the hash map, a ClientQueryRecord | ||
1178 | * @return GNUNET_YES (we should continue to iterate) | ||
1179 | */ | ||
1180 | static int | ||
1181 | remove_by_unique_id (void *cls, const struct GNUNET_HashCode * key, void *value) | ||
1182 | { | ||
1183 | const struct RemoveByUniqueIdContext *ctx = cls; | ||
1184 | struct ClientQueryRecord *record = value; | ||
1185 | |||
1186 | if (record->unique_id != ctx->unique_id) | ||
1187 | return GNUNET_YES; | ||
1188 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1189 | "Removing client %p's record for key %s (by unique id)\n", | ||
1190 | ctx->client->client_handle, GNUNET_h2s (key)); | ||
1191 | return remove_client_records (ctx->client, key, record); | ||
1192 | } | ||
1193 | |||
1194 | |||
1195 | /** | ||
1196 | * Handler for any generic DHT stop messages, calls the appropriate handler | ||
1197 | * depending on message type (if processed locally) | ||
1198 | * | ||
1199 | * @param cls closure for the service | ||
1200 | * @param client the client we received this message from | ||
1201 | * @param message the actual message received | ||
1202 | * | ||
1203 | */ | ||
1204 | static void | ||
1205 | handle_dht_local_get_stop (void *cls, struct GNUNET_SERVER_Client *client, | ||
1206 | const struct GNUNET_MessageHeader *message) | ||
1207 | { | ||
1208 | const struct GNUNET_DHT_ClientGetStopMessage *dht_stop_msg = | ||
1209 | (const struct GNUNET_DHT_ClientGetStopMessage *) message; | ||
1210 | struct RemoveByUniqueIdContext ctx; | ||
1211 | |||
1212 | GNUNET_STATISTICS_update (GDS_stats, | ||
1213 | gettext_noop | ||
1214 | ("# GET STOP requests received from clients"), 1, | ||
1215 | GNUNET_NO); | ||
1216 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1217 | "Received GET STOP request for %s from local client %p\n", | ||
1218 | client, GNUNET_h2s (&dht_stop_msg->key)); | ||
1219 | ctx.client = find_active_client (client); | ||
1220 | ctx.unique_id = dht_stop_msg->unique_id; | ||
1221 | GNUNET_CONTAINER_multihashmap_get_multiple (forward_map, &dht_stop_msg->key, | ||
1222 | &remove_by_unique_id, &ctx); | ||
1223 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
1224 | } | ||
1225 | |||
1226 | |||
1227 | /** | ||
1228 | * Handler for monitor start messages | ||
1229 | * | ||
1230 | * @param cls closure for the service | ||
1231 | * @param client the client we received this message from | ||
1232 | * @param message the actual message received | ||
1233 | * | ||
1234 | */ | ||
1235 | static void | ||
1236 | handle_dht_local_monitor (void *cls, struct GNUNET_SERVER_Client *client, | ||
1237 | const struct GNUNET_MessageHeader *message) | ||
1238 | { | ||
1239 | struct ClientMonitorRecord *r; | ||
1240 | const struct GNUNET_DHT_MonitorStartStopMessage *msg; | ||
1241 | |||
1242 | msg = (struct GNUNET_DHT_MonitorStartStopMessage *) message; | ||
1243 | r = GNUNET_new (struct ClientMonitorRecord); | ||
1244 | |||
1245 | r->client = find_active_client(client); | ||
1246 | r->type = ntohl(msg->type); | ||
1247 | r->get = ntohs(msg->get); | ||
1248 | r->get_resp = ntohs(msg->get_resp); | ||
1249 | r->put = ntohs(msg->put); | ||
1250 | if (0 == ntohs(msg->filter_key)) | ||
1251 | r->key = NULL; | ||
1252 | else | ||
1253 | { | ||
1254 | r->key = GNUNET_new (struct GNUNET_HashCode); | ||
1255 | memcpy (r->key, &msg->key, sizeof (struct GNUNET_HashCode)); | ||
1256 | } | ||
1257 | GNUNET_CONTAINER_DLL_insert (monitor_head, monitor_tail, r); | ||
1258 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
1259 | } | ||
1260 | |||
1261 | |||
1262 | /** | ||
1263 | * Handler for monitor stop messages | ||
1264 | * | ||
1265 | * @param cls closure for the service | ||
1266 | * @param client the client we received this message from | ||
1267 | * @param message the actual message received | ||
1268 | * | ||
1269 | */ | ||
1270 | static void | ||
1271 | handle_dht_local_monitor_stop (void *cls, struct GNUNET_SERVER_Client *client, | ||
1272 | const struct GNUNET_MessageHeader *message) | ||
1273 | { | ||
1274 | struct ClientMonitorRecord *r; | ||
1275 | const struct GNUNET_DHT_MonitorStartStopMessage *msg; | ||
1276 | int keys_match; | ||
1277 | |||
1278 | msg = (struct GNUNET_DHT_MonitorStartStopMessage *) message; | ||
1279 | r = monitor_head; | ||
1280 | |||
1281 | while (NULL != r) | ||
1282 | { | ||
1283 | if (NULL == r->key) | ||
1284 | keys_match = (0 == ntohs(msg->filter_key)); | ||
1285 | else | ||
1286 | { | ||
1287 | keys_match = (0 != ntohs(msg->filter_key) | ||
1288 | && !memcmp(r->key, &msg->key, sizeof(struct GNUNET_HashCode))); | ||
1289 | } | ||
1290 | if (find_active_client(client) == r->client | ||
1291 | && ntohl(msg->type) == r->type | ||
1292 | && r->get == msg->get | ||
1293 | && r->get_resp == msg->get_resp | ||
1294 | && r->put == msg->put | ||
1295 | && keys_match | ||
1296 | ) | ||
1297 | { | ||
1298 | GNUNET_CONTAINER_DLL_remove (monitor_head, monitor_tail, r); | ||
1299 | GNUNET_free_non_null (r->key); | ||
1300 | GNUNET_free (r); | ||
1301 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
1302 | return; /* Delete only ONE entry */ | ||
1303 | } | ||
1304 | r = r->next; | ||
1305 | } | ||
1306 | |||
1307 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
1308 | } | ||
1309 | |||
1310 | |||
406 | /** | 1311 | /** |
407 | * Functions with this signature are called whenever a client | 1312 | * Functions with this signature are called whenever a client |
408 | * is disconnected on the network level. | 1313 | * is disconnected on the network level. |
@@ -415,26 +1320,46 @@ static void | |||
415 | handle_client_disconnect (void *cls, | 1320 | handle_client_disconnect (void *cls, |
416 | struct GNUNET_SERVER_Client *client) | 1321 | struct GNUNET_SERVER_Client *client) |
417 | { | 1322 | { |
418 | /* You should maintain a list of client attached to this service. Then | 1323 | struct ClientList *pos; |
419 | search for the correct client and stop all its ongoing activites and | 1324 | struct PendingMessage *reply; |
420 | delete it from the list. */ | 1325 | struct ClientMonitorRecord *monitor; |
421 | } | ||
422 | 1326 | ||
1327 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1328 | "Local client %p disconnects\n", | ||
1329 | client); | ||
1330 | pos = find_active_client (client); | ||
1331 | GNUNET_CONTAINER_DLL_remove (client_head, client_tail, pos); | ||
1332 | if (pos->transmit_handle != NULL) | ||
1333 | GNUNET_SERVER_notify_transmit_ready_cancel (pos->transmit_handle); | ||
1334 | while (NULL != (reply = pos->pending_head)) | ||
1335 | { | ||
1336 | GNUNET_CONTAINER_DLL_remove (pos->pending_head, pos->pending_tail, reply); | ||
1337 | GNUNET_free (reply); | ||
1338 | } | ||
1339 | monitor = monitor_head; | ||
1340 | while (NULL != monitor) | ||
1341 | { | ||
1342 | if (monitor->client == pos) | ||
1343 | { | ||
1344 | struct ClientMonitorRecord *next; | ||
423 | 1345 | ||
424 | /** | 1346 | GNUNET_free_non_null (monitor->key); |
425 | * Get result from neighbours file. | 1347 | next = monitor->next; |
426 | */ | 1348 | GNUNET_CONTAINER_DLL_remove (monitor_head, monitor_tail, monitor); |
427 | void | 1349 | GNUNET_free (monitor); |
428 | GDS_CLIENTS_process_get_result() | 1350 | monitor = next; |
429 | { | 1351 | } |
430 | 1352 | else | |
1353 | monitor = monitor->next; | ||
1354 | } | ||
1355 | GNUNET_CONTAINER_multihashmap_iterate (forward_map, &remove_client_records, | ||
1356 | pos); | ||
1357 | GNUNET_free (pos); | ||
431 | } | 1358 | } |
432 | 1359 | ||
433 | 1360 | ||
1361 | |||
434 | /** | 1362 | /** |
435 | * SUPU: Call to this function is made from gnunet-service-xdht.c | ||
436 | * Here we register handlers for each possible kind of message the service | ||
437 | * receives from the clients. | ||
438 | * Initialize client subsystem. | 1363 | * Initialize client subsystem. |
439 | * | 1364 | * |
440 | * @param server the initialized server | 1365 | * @param server the initialized server |
@@ -456,19 +1381,42 @@ GDS_CLIENTS_init (struct GNUNET_SERVER_Handle *server) | |||
456 | {&handle_dht_local_monitor_stop, NULL, | 1381 | {&handle_dht_local_monitor_stop, NULL, |
457 | GNUNET_MESSAGE_TYPE_DHT_MONITOR_STOP, | 1382 | GNUNET_MESSAGE_TYPE_DHT_MONITOR_STOP, |
458 | sizeof (struct GNUNET_DHT_MonitorStartStopMessage)}, | 1383 | sizeof (struct GNUNET_DHT_MonitorStartStopMessage)}, |
1384 | {&handle_dht_local_get_result_seen, NULL, | ||
1385 | GNUNET_MESSAGE_TYPE_DHT_CLIENT_GET_RESULTS_KNOWN, 0}, | ||
459 | {NULL, NULL, 0, 0} | 1386 | {NULL, NULL, 0, 0} |
460 | }; | 1387 | }; |
461 | 1388 | forward_map = GNUNET_CONTAINER_multihashmap_create (1024, GNUNET_NO); | |
1389 | retry_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); | ||
462 | GNUNET_SERVER_add_handlers (server, plugin_handlers); | 1390 | GNUNET_SERVER_add_handlers (server, plugin_handlers); |
463 | GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL); | 1391 | GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL); |
464 | } | 1392 | } |
465 | 1393 | ||
1394 | |||
466 | /** | 1395 | /** |
467 | * SUPU: Call made from gnunet-service-dht.c | ||
468 | * Shutdown client subsystem. | 1396 | * Shutdown client subsystem. |
469 | */ | 1397 | */ |
470 | void | 1398 | void |
471 | GDS_CLIENTS_done () | 1399 | GDS_CLIENTS_done () |
472 | { | 1400 | { |
473 | 1401 | GNUNET_assert (client_head == NULL); | |
474 | } \ No newline at end of file | 1402 | GNUNET_assert (client_tail == NULL); |
1403 | if (GNUNET_SCHEDULER_NO_TASK != retry_task) | ||
1404 | { | ||
1405 | GNUNET_SCHEDULER_cancel (retry_task); | ||
1406 | retry_task = GNUNET_SCHEDULER_NO_TASK; | ||
1407 | } | ||
1408 | if (NULL != retry_heap) | ||
1409 | { | ||
1410 | GNUNET_assert (0 == GNUNET_CONTAINER_heap_get_size (retry_heap)); | ||
1411 | GNUNET_CONTAINER_heap_destroy (retry_heap); | ||
1412 | retry_heap = NULL; | ||
1413 | } | ||
1414 | if (NULL != forward_map) | ||
1415 | { | ||
1416 | GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap_size (forward_map)); | ||
1417 | GNUNET_CONTAINER_multihashmap_destroy (forward_map); | ||
1418 | forward_map = NULL; | ||
1419 | } | ||
1420 | } | ||
1421 | |||
1422 | /* end of gnunet-service-dht_clients.c */ | ||
diff --git a/src/dht/gnunet-service-xdht_clients.h b/src/dht/gnunet-service-xdht_clients.h index 828d2c08a..2aac7f2b0 100644 --- a/src/dht/gnunet-service-xdht_clients.h +++ b/src/dht/gnunet-service-xdht_clients.h | |||
@@ -21,10 +21,11 @@ | |||
21 | /** | 21 | /** |
22 | * @file dht/gnunet-service-xdht_clients.h | 22 | * @file dht/gnunet-service-xdht_clients.h |
23 | * @brief GNUnet DHT service's client management code | 23 | * @brief GNUnet DHT service's client management code |
24 | * @author Supriti Singh | 24 | * @author Christian Grothoff |
25 | * @author Nathan Evans | ||
25 | */ | 26 | */ |
26 | #ifndef GNUNET_SERVICE_XDHT_CLIENT_H | 27 | #ifndef GNUNET_SERVICE_DHT_CLIENT_H |
27 | #define GNUNET_SERVICE_XDHT_CLIENT_H | 28 | #define GNUNET_SERVICE_DHT_CLIENT_H |
28 | 29 | ||
29 | #include "gnunet_util_lib.h" | 30 | #include "gnunet_util_lib.h" |
30 | #include "gnunet_block_lib.h" | 31 | #include "gnunet_block_lib.h" |
@@ -36,17 +37,17 @@ | |||
36 | * | 37 | * |
37 | * @param expiration when will the reply expire | 38 | * @param expiration when will the reply expire |
38 | * @param key the query this reply is for | 39 | * @param key the query this reply is for |
39 | * @param get_path_length number of peers in 'get_path' | 40 | * @param get_path_length number of peers in @a get_path |
40 | * @param get_path path the reply took on get | 41 | * @param get_path path the reply took on get |
41 | * @param put_path_length number of peers in 'put_path' | 42 | * @param put_path_length number of peers in @a put_path |
42 | * @param put_path path the reply took on put | 43 | * @param put_path path the reply took on put |
43 | * @param type type of the reply | 44 | * @param type type of the reply |
44 | * @param data_size number of bytes in 'data' | 45 | * @param data_size number of bytes in @a data |
45 | * @param data application payload data | 46 | * @param data application payload data |
46 | */ | 47 | */ |
47 | void | 48 | void |
48 | GDS_CLIENTS_handle_reply (struct GNUNET_TIME_Absolute expiration, | 49 | GDS_CLIENTS_handle_reply (struct GNUNET_TIME_Absolute expiration, |
49 | const struct GNUNET_HashCode * key, | 50 | const struct GNUNET_HashCode *key, |
50 | unsigned int get_path_length, | 51 | unsigned int get_path_length, |
51 | const struct GNUNET_PeerIdentity *get_path, | 52 | const struct GNUNET_PeerIdentity *get_path, |
52 | unsigned int put_path_length, | 53 | unsigned int put_path_length, |
@@ -74,7 +75,8 @@ GDS_CLIENTS_process_get (uint32_t options, | |||
74 | uint32_t desired_replication_level, | 75 | uint32_t desired_replication_level, |
75 | unsigned int path_length, | 76 | unsigned int path_length, |
76 | const struct GNUNET_PeerIdentity *path, | 77 | const struct GNUNET_PeerIdentity *path, |
77 | const struct GNUNET_HashCode * key); | 78 | const struct GNUNET_HashCode *key); |
79 | |||
78 | 80 | ||
79 | /** | 81 | /** |
80 | * Check if some client is monitoring GET RESP messages and notify | 82 | * Check if some client is monitoring GET RESP messages and notify |
@@ -82,13 +84,13 @@ GDS_CLIENTS_process_get (uint32_t options, | |||
82 | * | 84 | * |
83 | * @param type The type of data in the result. | 85 | * @param type The type of data in the result. |
84 | * @param get_path Peers on GET path (or NULL if not recorded). | 86 | * @param get_path Peers on GET path (or NULL if not recorded). |
85 | * @param get_path_length number of entries in get_path. | 87 | * @param get_path_length number of entries in @a get_path. |
86 | * @param put_path peers on the PUT path (or NULL if not recorded). | 88 | * @param put_path peers on the PUT path (or NULL if not recorded). |
87 | * @param put_path_length number of entries in get_path. | 89 | * @param put_path_length number of entries in @a get_path. |
88 | * @param exp Expiration time of the data. | 90 | * @param exp Expiration time of the data. |
89 | * @param key Key of the data. | 91 | * @param key Key of the @a data. |
90 | * @param data Pointer to the result data. | 92 | * @param data Pointer to the result data. |
91 | * @param size Number of bytes in data. | 93 | * @param size Number of bytes in @a data. |
92 | */ | 94 | */ |
93 | void | 95 | void |
94 | GDS_CLIENTS_process_get_resp (enum GNUNET_BLOCK_Type type, | 96 | GDS_CLIENTS_process_get_resp (enum GNUNET_BLOCK_Type type, |
@@ -101,6 +103,7 @@ GDS_CLIENTS_process_get_resp (enum GNUNET_BLOCK_Type type, | |||
101 | const void *data, | 103 | const void *data, |
102 | size_t size); | 104 | size_t size); |
103 | 105 | ||
106 | |||
104 | /** | 107 | /** |
105 | * Check if some client is monitoring PUT messages and notify | 108 | * Check if some client is monitoring PUT messages and notify |
106 | * them in that case. | 109 | * them in that case. |
@@ -129,12 +132,6 @@ GDS_CLIENTS_process_put (uint32_t options, | |||
129 | size_t size); | 132 | size_t size); |
130 | 133 | ||
131 | /** | 134 | /** |
132 | * | ||
133 | */ | ||
134 | void | ||
135 | GDS_CLIENTS_process_get_result(); | ||
136 | |||
137 | /** | ||
138 | * Initialize client subsystem. | 135 | * Initialize client subsystem. |
139 | * | 136 | * |
140 | * @param server the initialized server | 137 | * @param server the initialized server |
diff --git a/src/dht/gnunet-service-xdht_datacache.c b/src/dht/gnunet-service-xdht_datacache.c index bdc247690..77673cf66 100644 --- a/src/dht/gnunet-service-xdht_datacache.c +++ b/src/dht/gnunet-service-xdht_datacache.c | |||
@@ -61,7 +61,7 @@ GDS_DATACACHE_handle_put (struct GNUNET_TIME_Absolute expiration, | |||
61 | const void *data) | 61 | const void *data) |
62 | { | 62 | { |
63 | int r; | 63 | int r; |
64 | 64 | ||
65 | if (NULL == datacache) | 65 | if (NULL == datacache) |
66 | { | 66 | { |
67 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 67 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
diff --git a/src/dht/gnunet-service-xdht_neighbours.c b/src/dht/gnunet-service-xdht_neighbours.c index 4c290895b..aa8f70d12 100644 --- a/src/dht/gnunet-service-xdht_neighbours.c +++ b/src/dht/gnunet-service-xdht_neighbours.c | |||
@@ -57,7 +57,15 @@ | |||
57 | * them as they come. | 57 | * them as they come. |
58 | * 3. Everywhere you are storing yourself as the first element in the trail. | 58 | * 3. Everywhere you are storing yourself as the first element in the trail. |
59 | * It is obviously taking too much space. Try to remove it and think of something | 59 | * It is obviously taking too much space. Try to remove it and think of something |
60 | * better. */ | 60 | * better. |
61 | 4. Choose the correct interval to send finger and verify message. | ||
62 | 5. Do we need expiration time for trail setup and all other messages? TTL | ||
63 | 6. In case of trail setup after TTL, we should again send the request but | ||
64 | * through a different route. How do we remeber each time which friend we | ||
65 | * chose last time for the trail setup. We will need a data structure where we | ||
66 | * add entry in finger table add and when setup is done remove it. | ||
67 | * 7. I have not added any authentication on messages exachanged between peers. | ||
68 | * Only when basic put/get is correct I will add it. */ | ||
61 | 69 | ||
62 | /** | 70 | /** |
63 | * Maximum possible fingers of a peer. | 71 | * Maximum possible fingers of a peer. |
@@ -85,18 +93,9 @@ | |||
85 | #define GET_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 2) | 93 | #define GET_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 2) |
86 | 94 | ||
87 | /** | 95 | /** |
88 | * FIXME: Use this variable. Should it be moved to routing.c | 96 | * Maximum number of trails allowed to go through a friend. |
89 | * Threshold on routing table entries for a peer. | ||
90 | */ | 97 | */ |
91 | #define ROUTING_TABLE_THRESHOLD 64 | 98 | #define LINK_THRESHOLD 64 |
92 | |||
93 | /** | ||
94 | * FIXME: Use this variable. When adding an entry in finger table, check | ||
95 | * this threshold value. At the moment, its just a random value. Also, | ||
96 | * implement teardown feature from the paper. | ||
97 | * Threshold on number of peers in a trail length | ||
98 | */ | ||
99 | #define TRAIL_LENGTH_THRESHOLD 64 | ||
100 | 99 | ||
101 | 100 | ||
102 | GNUNET_NETWORK_STRUCT_BEGIN | 101 | GNUNET_NETWORK_STRUCT_BEGIN |
@@ -208,7 +207,7 @@ struct PeerGetResultMessage | |||
208 | * The key of the corresponding GET request. | 207 | * The key of the corresponding GET request. |
209 | */ | 208 | */ |
210 | struct GNUNET_HashCode key; | 209 | struct GNUNET_HashCode key; |
211 | 210 | ||
212 | /* put path (if tracked) */ | 211 | /* put path (if tracked) */ |
213 | 212 | ||
214 | /* get path (if tracked) */ | 213 | /* get path (if tracked) */ |
@@ -246,9 +245,13 @@ struct PeerGetMessage | |||
246 | /** | 245 | /** |
247 | * | 246 | * |
248 | */ | 247 | */ |
249 | enum current_destination_type dest_type; | 248 | enum current_destination_type current_dest_type; |
250 | 249 | ||
251 | /** | 250 | /** |
251 | * Unique identifier of the request. | ||
252 | */ | ||
253 | uint64_t request_id; | ||
254 | /** | ||
252 | * When does the content expire? | 255 | * When does the content expire? |
253 | */ | 256 | */ |
254 | struct GNUNET_TIME_AbsoluteNBO expiration_time; | 257 | struct GNUNET_TIME_AbsoluteNBO expiration_time; |
@@ -527,6 +530,11 @@ struct FriendInfo | |||
527 | struct GNUNET_PeerIdentity id; | 530 | struct GNUNET_PeerIdentity id; |
528 | 531 | ||
529 | /** | 532 | /** |
533 | * Number of trail of which this friend is the first hop. | ||
534 | */ | ||
535 | unsigned int trail_links; | ||
536 | |||
537 | /** | ||
530 | * Count of outstanding messages for this friend. | 538 | * Count of outstanding messages for this friend. |
531 | */ | 539 | */ |
532 | unsigned int pending_count; | 540 | unsigned int pending_count; |
@@ -632,11 +640,6 @@ static struct GNUNET_CONTAINER_MultiPeerMap *friend_peermap; | |||
632 | static struct GNUNET_CONTAINER_MultiPeerMap *finger_peermap; | 640 | static struct GNUNET_CONTAINER_MultiPeerMap *finger_peermap; |
633 | 641 | ||
634 | /** | 642 | /** |
635 | * Handle to ATS. | ||
636 | */ | ||
637 | static struct GNUNET_ATS_PerformanceHandle *atsAPI; | ||
638 | |||
639 | /** | ||
640 | * Handle to CORE. | 643 | * Handle to CORE. |
641 | */ | 644 | */ |
642 | static struct GNUNET_CORE_Handle *core_api; | 645 | static struct GNUNET_CORE_Handle *core_api; |
@@ -806,8 +809,12 @@ GDS_NEIGHBOURS_send_trail_setup (struct GNUNET_PeerIdentity *source_peer, | |||
806 | tsm->trail_length = htonl (trail_length); | 809 | tsm->trail_length = htonl (trail_length); |
807 | tsm->finger_map_index = htonl (finger_map_index); | 810 | tsm->finger_map_index = htonl (finger_map_index); |
808 | 811 | ||
809 | peer_list = (struct GNUNET_PeerIdentity *) &tsm[1]; | 812 | if (trail_peer_list != NULL) |
810 | memcpy (peer_list, trail_peer_list, trail_length * sizeof(struct GNUNET_PeerIdentity)); | 813 | { |
814 | peer_list = (struct GNUNET_PeerIdentity *) &tsm[1]; | ||
815 | memcpy (peer_list, trail_peer_list, trail_length * sizeof(struct GNUNET_PeerIdentity)); | ||
816 | } | ||
817 | |||
811 | GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending); | 818 | GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending); |
812 | target_friend->pending_count++; | 819 | target_friend->pending_count++; |
813 | process_friend_queue (target_friend); | 820 | process_friend_queue (target_friend); |
@@ -822,8 +829,7 @@ GDS_NEIGHBOURS_send_trail_setup (struct GNUNET_PeerIdentity *source_peer, | |||
822 | * @param target_friend Friend to which this message should be forwarded. | 829 | * @param target_friend Friend to which this message should be forwarded. |
823 | * @param trail_length Numbers of peers in the trail. | 830 | * @param trail_length Numbers of peers in the trail. |
824 | * @param trail_peer_list Peers which are part of the trail from source to destination. | 831 | * @param trail_peer_list Peers which are part of the trail from source to destination. |
825 | * @param current_trail_index Index in the trial list at which receiving peer should | 832 | * @param current_trail_index Index at which sender of this message is located. |
826 | * read the next element. | ||
827 | * @param finger_map_index Index in finger peer map | 833 | * @param finger_map_index Index in finger peer map |
828 | */ | 834 | */ |
829 | void | 835 | void |
@@ -1059,6 +1065,12 @@ GDS_NEIGHBOURS_send_notify_new_successor (struct GNUNET_PeerIdentity *source_pee | |||
1059 | 1065 | ||
1060 | 1066 | ||
1061 | /** | 1067 | /** |
1068 | * FIXME: Optimizaiton Once the basic code is running. Add the optimization | ||
1069 | * where you check if the threshold on number of links that should go through | ||
1070 | * a particular friend has crossed. If yes then again choose a different | ||
1071 | * friend. Important that the new friend chosen should be different. How to | ||
1072 | * ensure this? This is an important optimization as without this one x-vine | ||
1073 | * is actually not a sybil tolerant DHT. | ||
1062 | * Randomly choose one of your friends from the friends_peer map | 1074 | * Randomly choose one of your friends from the friends_peer map |
1063 | * @return Friend | 1075 | * @return Friend |
1064 | */ | 1076 | */ |
@@ -1073,14 +1085,9 @@ select_random_friend() | |||
1073 | struct FriendInfo *friend; | 1085 | struct FriendInfo *friend; |
1074 | 1086 | ||
1075 | current_size = GNUNET_CONTAINER_multipeermap_size (friend_peermap); | 1087 | current_size = GNUNET_CONTAINER_multipeermap_size (friend_peermap); |
1076 | |||
1077 | /* Element stored at this index in friend_peermap should be selected friend. */ | ||
1078 | index = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK, current_size); | 1088 | index = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK, current_size); |
1079 | |||
1080 | /* Create an iterator for friend_peermap. */ | ||
1081 | iter = GNUNET_CONTAINER_multipeermap_iterator_create (friend_peermap); | 1089 | iter = GNUNET_CONTAINER_multipeermap_iterator_create (friend_peermap); |
1082 | 1090 | ||
1083 | /* Set the position of iterator to index. */ | ||
1084 | while(j < (*index)) | 1091 | while(j < (*index)) |
1085 | { | 1092 | { |
1086 | if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (iter,NULL,NULL)) | 1093 | if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (iter,NULL,NULL)) |
@@ -1091,13 +1098,10 @@ select_random_friend() | |||
1091 | return NULL; | 1098 | return NULL; |
1092 | } | 1099 | } |
1093 | 1100 | ||
1094 | |||
1095 | if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (iter,&key_ret,(const void **)&friend)) | 1101 | if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (iter,&key_ret,(const void **)&friend)) |
1096 | { | ||
1097 | return friend; | 1102 | return friend; |
1098 | } | 1103 | else |
1099 | 1104 | return NULL; | |
1100 | return NULL; | ||
1101 | } | 1105 | } |
1102 | 1106 | ||
1103 | 1107 | ||
@@ -1112,9 +1116,7 @@ compute_finger_identity() | |||
1112 | uint64_t *finger_identity64; | 1116 | uint64_t *finger_identity64; |
1113 | 1117 | ||
1114 | finger_identity64 = GNUNET_malloc (sizeof (uint64_t)); | 1118 | finger_identity64 = GNUNET_malloc (sizeof (uint64_t)); |
1115 | |||
1116 | memcpy (&my_id64, &my_identity, sizeof (uint64_t)); | 1119 | memcpy (&my_id64, &my_identity, sizeof (uint64_t)); |
1117 | |||
1118 | /*FIXME: Do we need a mod finger = ((my_id + pow(2, finger_index)) mod (pow (2, MAX_FINGERS))*/ | 1120 | /*FIXME: Do we need a mod finger = ((my_id + pow(2, finger_index)) mod (pow (2, MAX_FINGERS))*/ |
1119 | *finger_identity64 = (my_id64 + (unsigned long) pow (2,current_finger_index)); | 1121 | *finger_identity64 = (my_id64 + (unsigned long) pow (2,current_finger_index)); |
1120 | 1122 | ||
@@ -1162,6 +1164,7 @@ send_verify_successor_message (void *cls, | |||
1162 | unsigned int finger_index; | 1164 | unsigned int finger_index; |
1163 | unsigned int i; | 1165 | unsigned int i; |
1164 | int flag = 0; | 1166 | int flag = 0; |
1167 | |||
1165 | finger_iter = GNUNET_CONTAINER_multipeermap_iterator_create (finger_peermap); | 1168 | finger_iter = GNUNET_CONTAINER_multipeermap_iterator_create (finger_peermap); |
1166 | for (finger_index = 0; finger_index < GNUNET_CONTAINER_multipeermap_size (finger_peermap); finger_index++) | 1169 | for (finger_index = 0; finger_index < GNUNET_CONTAINER_multipeermap_size (finger_peermap); finger_index++) |
1167 | { | 1170 | { |
@@ -1181,7 +1184,7 @@ send_verify_successor_message (void *cls, | |||
1181 | goto send_new_request; | 1184 | goto send_new_request; |
1182 | 1185 | ||
1183 | peer_list = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * finger->trail_length); | 1186 | peer_list = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * finger->trail_length); |
1184 | 1187 | ||
1185 | struct TrailPeerList *iterate; | 1188 | struct TrailPeerList *iterate; |
1186 | iterate = finger->head; | 1189 | iterate = finger->head; |
1187 | i = 0; | 1190 | i = 0; |
@@ -1193,10 +1196,11 @@ send_verify_successor_message (void *cls, | |||
1193 | } | 1196 | } |
1194 | 1197 | ||
1195 | next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); | 1198 | next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); |
1196 | memcpy (next_hop, &peer_list[1], sizeof (struct GNUNET_PeerIdentity)); | 1199 | memcpy (next_hop, &peer_list[0], sizeof (struct GNUNET_PeerIdentity)); |
1197 | target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop); | 1200 | target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop); |
1198 | finger_trail_current_index = 2; | 1201 | finger_trail_current_index = 0; |
1199 | 1202 | ||
1203 | |||
1200 | GDS_NEIGHBOURS_send_verify_successor (&my_identity, | 1204 | GDS_NEIGHBOURS_send_verify_successor (&my_identity, |
1201 | &(finger->finger_identity), | 1205 | &(finger->finger_identity), |
1202 | target_friend, | 1206 | target_friend, |
@@ -1233,14 +1237,11 @@ send_find_finger_trail_message (void *cls, | |||
1233 | { | 1237 | { |
1234 | struct FriendInfo *target_friend; | 1238 | struct FriendInfo *target_friend; |
1235 | struct GNUNET_TIME_Relative next_send_time; | 1239 | struct GNUNET_TIME_Relative next_send_time; |
1236 | struct GNUNET_PeerIdentity *peer_list; | ||
1237 | uint64_t *finger_identity; | 1240 | uint64_t *finger_identity; |
1238 | unsigned int finger_map_index; | 1241 | unsigned int finger_map_index; |
1239 | 1242 | ||
1240 | if (1 == current_finger_index) | 1243 | if (1 == current_finger_index) |
1241 | { | 1244 | { |
1242 | /* We have started the process to find the successor. We should search | ||
1243 | for our predecessor. */ | ||
1244 | finger_identity = compute_predecessor_identity(); | 1245 | finger_identity = compute_predecessor_identity(); |
1245 | goto select_friend; | 1246 | goto select_friend; |
1246 | } | 1247 | } |
@@ -1250,27 +1251,20 @@ send_find_finger_trail_message (void *cls, | |||
1250 | } | 1251 | } |
1251 | 1252 | ||
1252 | select_friend: | 1253 | select_friend: |
1254 | /* FIXME: Here should we choose randomly or not. */ | ||
1253 | target_friend = select_random_friend(); | 1255 | target_friend = select_random_friend(); |
1254 | 1256 | ||
1255 | |||
1256 | finger_map_index = current_finger_index; | 1257 | finger_map_index = current_finger_index; |
1257 | current_finger_index = ( current_finger_index + 1) % MAX_FINGERS; | 1258 | current_finger_index = ( current_finger_index + 1) % MAX_FINGERS; |
1258 | 1259 | ||
1259 | /* We found a friend.*/ | ||
1260 | if(NULL != target_friend) | 1260 | if(NULL != target_friend) |
1261 | { | 1261 | { |
1262 | /* Add yourself and selected friend in the trail list. */ | ||
1263 | unsigned int trail_length = 2; | ||
1264 | peer_list = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * trail_length); | ||
1265 | memcpy (&peer_list[0], &(my_identity), sizeof (struct GNUNET_PeerIdentity)); | ||
1266 | memcpy (&peer_list[1], &(target_friend->id), sizeof (struct GNUNET_PeerIdentity)); | ||
1267 | |||
1268 | GDS_NEIGHBOURS_send_trail_setup (&my_identity, *finger_identity, &(target_friend->id), | 1262 | GDS_NEIGHBOURS_send_trail_setup (&my_identity, *finger_identity, &(target_friend->id), |
1269 | target_friend, trail_length, peer_list, | 1263 | target_friend, 0, NULL, |
1270 | finger_map_index, FRIEND); | 1264 | finger_map_index, FRIEND); |
1271 | } | 1265 | } |
1272 | 1266 | ||
1273 | /* FIXME: Should we be using current_finger_index to generate random interval.*/ | 1267 | /* FIXME: How to decide the correct interval? */ |
1274 | next_send_time.rel_value_us = | 1268 | next_send_time.rel_value_us = |
1275 | DHT_MINIMUM_FIND_FINGER_TRAIL_INTERVAL.rel_value_us + | 1269 | DHT_MINIMUM_FIND_FINGER_TRAIL_INTERVAL.rel_value_us + |
1276 | GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, | 1270 | GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, |
@@ -1396,26 +1390,91 @@ core_init (void *cls, | |||
1396 | { | 1390 | { |
1397 | my_identity = *identity; | 1391 | my_identity = *identity; |
1398 | 1392 | ||
1393 | #if 0 | ||
1394 | /* SUPU TEST CODE */ | ||
1395 | struct GNUNET_PeerIdentity *print_peer; | ||
1396 | print_peer = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); | ||
1397 | memcpy (print_peer, &my_identity, sizeof (struct GNUNET_PeerIdentity)); | ||
1398 | FPRINTF (stderr,_("\nSUPU %s, %s, %d,my_identity = %s"), | ||
1399 | __FILE__, __func__,__LINE__, GNUNET_i2s (print_peer)); | ||
1400 | /* SUPU TEST CODE ENDS */ | ||
1401 | #endif | ||
1399 | } | 1402 | } |
1400 | 1403 | ||
1401 | 1404 | ||
1405 | /** | ||
1406 | * | ||
1407 | * @param destination_peer | ||
1408 | * @param existing_trail | ||
1409 | * @param trail_length | ||
1410 | * @return | ||
1411 | */ | ||
1412 | static struct GNUNET_PeerIdentity * | ||
1413 | invert_trail_list (struct GNUNET_PeerIdentity *destination_peer, | ||
1414 | struct GNUNET_PeerIdentity *existing_trail, | ||
1415 | unsigned int trail_length) | ||
1416 | { | ||
1417 | int i; | ||
1418 | int j; | ||
1419 | struct GNUNET_PeerIdentity *new_trail; | ||
1420 | |||
1421 | j = 0; | ||
1422 | new_trail = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * trail_length); | ||
1423 | |||
1424 | if (trail_length > 1) | ||
1425 | { | ||
1426 | i = trail_length - 2; | ||
1427 | while (i >= 0 ) | ||
1428 | { | ||
1429 | memcpy( &new_trail[j], &existing_trail[i], sizeof (struct GNUNET_PeerIdentity)); | ||
1430 | i--; | ||
1431 | j++; | ||
1432 | } | ||
1433 | } | ||
1434 | memcpy (&new_trail[j], destination_peer, sizeof(struct GNUNET_PeerIdentity)); | ||
1435 | |||
1436 | return new_trail; | ||
1437 | } | ||
1402 | 1438 | ||
1403 | 1439 | ||
1440 | /** | ||
1441 | * | ||
1442 | * @param existing_finger | ||
1443 | * @param new_finger | ||
1444 | * @return | ||
1445 | */ | ||
1446 | #if 0 | ||
1447 | static int | ||
1448 | compare_finger_identity (struct GNUNET_PeerIdentity *existing_finger, | ||
1449 | struct GNUNET_PeerIdentity *new_finger) | ||
1450 | { | ||
1451 | int ret; | ||
1452 | ret = (existing_finger > new_finger) ? 1 : | ||
1453 | (existing_finger == new_finger) ? 0 : -1; | ||
1454 | return ret; | ||
1455 | } | ||
1456 | #endif | ||
1404 | 1457 | ||
1405 | /** | 1458 | /** |
1406 | * FIXME: When we add a successor or predecessor should we check the entry in | 1459 | * FIXME: Not sure of the logic to find the correct predecessor. |
1407 | * finger map index. If we don't replace the old entry then should we notify | 1460 | * Given two finger identities, find the closest predecessor. |
1408 | * peer which think it is our predecessor or successor. Or will send verify | 1461 | * @param existing_predecessor |
1409 | * successor message will handle this case on its own. | 1462 | * @param new_predecessor |
1410 | * * FIXME: For redundant routing, we may start looking for different | 1463 | * @return |
1411 | * paths to reach to same finger. So, in send_find_finger, we are starting | 1464 | */ |
1412 | * the search for trail to a finger, even if we already have found trail to | 1465 | #if 0 |
1413 | * reach to it. There are several reasons for doing so | 1466 | static int |
1414 | * 1. We may reach to a closer successor than we have at the moment. So, we | 1467 | compare_predecessor(struct GNUNET_PeerIdentity *existing_predecessor, |
1415 | * should keep looking for the successor. | 1468 | struct GNUNET_PeerIdentity *new_predecessor) |
1416 | * 2. We may reach to the same successor but through a shorter path. | 1469 | { |
1417 | * 3. As I don't know how keys are distributed and how put/get will react | 1470 | int ret; |
1418 | * because of this, I have to think further before implementing it. | 1471 | ret = (existing_predecessor < new_predecessor) ? 1 : |
1472 | (existing_predecessor == new_predecessor) ? 0 : -1; | ||
1473 | return ret; | ||
1474 | } | ||
1475 | #endif | ||
1476 | |||
1477 | /* | ||
1419 | * Add an entry in finger table. | 1478 | * Add an entry in finger table. |
1420 | * Add an entry into finger table | 1479 | * Add an entry into finger table |
1421 | * @param finger_identity Peer identity of finger | 1480 | * @param finger_identity Peer identity of finger |
@@ -1430,14 +1489,17 @@ void finger_table_add (struct GNUNET_PeerIdentity *finger_identity, | |||
1430 | unsigned int finger_map_index) | 1489 | unsigned int finger_map_index) |
1431 | { | 1490 | { |
1432 | struct FingerInfo *new_finger_entry; | 1491 | struct FingerInfo *new_finger_entry; |
1492 | int i; | ||
1493 | #if 0 | ||
1433 | struct GNUNET_CONTAINER_MultiPeerMapIterator *finger_iter; | 1494 | struct GNUNET_CONTAINER_MultiPeerMapIterator *finger_iter; |
1434 | struct GNUNET_PeerIdentity key_ret; | 1495 | struct GNUNET_PeerIdentity key_ret; |
1435 | struct FingerInfo *existing_finger; | 1496 | struct FingerInfo *existing_finger; |
1436 | int finger_index; | 1497 | int finger_index; |
1437 | int i; | 1498 | int i; |
1499 | |||
1438 | 1500 | ||
1439 | finger_iter = GNUNET_CONTAINER_multipeermap_iterator_create (finger_peermap); | 1501 | finger_iter = GNUNET_CONTAINER_multipeermap_iterator_create (finger_peermap); |
1440 | 1502 | ||
1441 | for (finger_index = 0; finger_index < GNUNET_CONTAINER_multipeermap_size (finger_peermap); finger_index++) | 1503 | for (finger_index = 0; finger_index < GNUNET_CONTAINER_multipeermap_size (finger_peermap); finger_index++) |
1442 | { | 1504 | { |
1443 | if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (finger_iter, &key_ret, | 1505 | if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (finger_iter, &key_ret, |
@@ -1449,40 +1511,47 @@ void finger_table_add (struct GNUNET_PeerIdentity *finger_identity, | |||
1449 | /* Check if the finger entry are same. */ | 1511 | /* Check if the finger entry are same. */ |
1450 | if (0 == GNUNET_CRYPTO_cmp_peer_identity (&(existing_finger->finger_identity),finger_identity)) | 1512 | if (0 == GNUNET_CRYPTO_cmp_peer_identity (&(existing_finger->finger_identity),finger_identity)) |
1451 | { | 1513 | { |
1452 | /* Compare the trail length. */ | 1514 | FPRINTF (stderr,_("\nSUPU %s, %s, %d"), __FILE__, __func__,__LINE__); |
1453 | if ((trail_length == existing_finger->trail_length)|| | 1515 | goto add_new_entry; |
1454 | (trail_length > existing_finger->trail_length)) | 1516 | } |
1517 | else | ||
1518 | { | ||
1519 | /* FIXME: here you should have something better to check which finger | ||
1520 | is closer one. */ | ||
1521 | int ret; | ||
1522 | if (finger_map_index == 1) | ||
1455 | { | 1523 | { |
1456 | return; | 1524 | FPRINTF (stderr,_("\nSUPU %s, %s, %d"), __FILE__, __func__,__LINE__); |
1525 | ret = compare_predecessor (&(existing_finger->finger_identity), | ||
1526 | finger_identity); | ||
1457 | } | 1527 | } |
1458 | else if (trail_length < existing_finger->trail_length) | 1528 | else |
1459 | { | 1529 | { |
1460 | /* FIXME: As an optimization, when you add limit on trail length | 1530 | FPRINTF (stderr,_("\nSUPU %s, %s, %d"), __FILE__, __func__,__LINE__); |
1461 | going through a particular friend, then check if the friend to | 1531 | ret = compare_finger_identity (&(existing_finger->finger_identity), |
1462 | reach the two trails are same or not. If not then choose one | 1532 | finger_identity); |
1463 | whose threshold value has not yet reached. Also, think about | 1533 | } |
1464 | redundant routing, where you want to keep multiple paths | 1534 | if (ret > 0) |
1465 | to reach to the same finger. In that case you should allow multiple | 1535 | { |
1466 | entries with same finger identity. */ | 1536 | FPRINTF (stderr,_("\nSUPU %s, %s, %d"), __FILE__, __func__,__LINE__); |
1467 | if ( GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (finger_peermap, | 1537 | GNUNET_assert (GNUNET_YES == |
1468 | &(existing_finger->finger_identity), | 1538 | GNUNET_CONTAINER_multipeermap_remove (finger_peermap, |
1469 | existing_finger)) | 1539 | &(existing_finger->finger_identity), |
1470 | { | 1540 | existing_finger)); |
1471 | goto add_new_entry; | 1541 | goto add_new_entry; |
1472 | } | 1542 | } |
1543 | else | ||
1544 | { | ||
1545 | FPRINTF (stderr,_("\nSUPU %s, %s, %d"), __FILE__, __func__,__LINE__); | ||
1546 | return; | ||
1473 | } | 1547 | } |
1474 | } | ||
1475 | else | ||
1476 | { | ||
1477 | /* FIXME: Here you are if you got different finger identity then one | ||
1478 | you already have at that index. Then you should choose the | ||
1479 | one which is closest. */ | ||
1480 | } | 1548 | } |
1481 | } | 1549 | } |
1482 | } | 1550 | } |
1483 | } | 1551 | } |
1484 | 1552 | ||
1485 | add_new_entry: | 1553 | add_new_entry: |
1554 | #endif | ||
1486 | new_finger_entry = GNUNET_malloc (sizeof (struct FingerInfo)); | 1555 | new_finger_entry = GNUNET_malloc (sizeof (struct FingerInfo)); |
1487 | memcpy (&(new_finger_entry->finger_identity), finger_identity, sizeof (struct GNUNET_PeerIdentity)); | 1556 | memcpy (&(new_finger_entry->finger_identity), finger_identity, sizeof (struct GNUNET_PeerIdentity)); |
1488 | 1557 | ||
@@ -1503,12 +1572,14 @@ void finger_table_add (struct GNUNET_PeerIdentity *finger_identity, | |||
1503 | new_finger_entry->trail_length = trail_length; | 1572 | new_finger_entry->trail_length = trail_length; |
1504 | 1573 | ||
1505 | /* FIXME: Here we are keeping multiple hashmap option so that there are | 1574 | /* FIXME: Here we are keeping multiple hashmap option so that there are |
1506 | multiple routes to reach to same finger, redundant routing. */ | 1575 | multiple routes to reach to same finger, redundant routing. |
1576 | * Also same peers could be our fingers for different finger map index */ | ||
1507 | GNUNET_assert (GNUNET_OK == | 1577 | GNUNET_assert (GNUNET_OK == |
1508 | GNUNET_CONTAINER_multipeermap_put (finger_peermap, | 1578 | GNUNET_CONTAINER_multipeermap_put (finger_peermap, |
1509 | &(new_finger_entry->finger_identity), | 1579 | &(new_finger_entry->finger_identity), |
1510 | new_finger_entry, | 1580 | new_finger_entry, |
1511 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); | 1581 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); /* Fixme: change to multiple */ |
1582 | |||
1512 | 1583 | ||
1513 | if (1 == GNUNET_CONTAINER_multipeermap_size (finger_peermap) | 1584 | if (1 == GNUNET_CONTAINER_multipeermap_size (finger_peermap) |
1514 | && (new_finger_entry->finger_map_index!= 1)) | 1585 | && (new_finger_entry->finger_map_index!= 1)) |
@@ -1688,7 +1759,7 @@ find_successor (uint64_t value, struct GNUNET_PeerIdentity *current_destination, | |||
1688 | struct TrailPeerList *iterator; | 1759 | struct TrailPeerList *iterator; |
1689 | iterator = GNUNET_malloc (sizeof (struct TrailPeerList)); | 1760 | iterator = GNUNET_malloc (sizeof (struct TrailPeerList)); |
1690 | finger = successor->data; | 1761 | finger = successor->data; |
1691 | iterator = finger->head->next; | 1762 | iterator = finger->head; |
1692 | next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); | 1763 | next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); |
1693 | memcpy (next_hop, &(iterator->peer), sizeof (struct GNUNET_PeerIdentity)); | 1764 | memcpy (next_hop, &(iterator->peer), sizeof (struct GNUNET_PeerIdentity)); |
1694 | memcpy (current_destination, &(finger->finger_identity), sizeof (struct GNUNET_PeerIdentity)); | 1765 | memcpy (current_destination, &(finger->finger_identity), sizeof (struct GNUNET_PeerIdentity)); |
@@ -1701,37 +1772,34 @@ find_successor (uint64_t value, struct GNUNET_PeerIdentity *current_destination, | |||
1701 | } | 1772 | } |
1702 | } | 1773 | } |
1703 | 1774 | ||
1704 | #if 0 | ||
1705 | static void | ||
1706 | replicate_put() | ||
1707 | { | ||
1708 | /* In this function, you should find 'r' (r = desired replication level) successors | ||
1709 | and send put message to all of these r successors. Now, I really don't know | ||
1710 | if in case of node failure it will be able to find data. Or if we start with | ||
1711 | a random peer id, do we even reach to correct successor ever in case of | ||
1712 | get. */ | ||
1713 | } | ||
1714 | #endif | ||
1715 | 1775 | ||
1716 | /** | 1776 | /** |
1717 | * | 1777 | * FIXME: |
1718 | * @param source_peer | 1778 | * 1. Do we have an expiration time for get request? Yes but I don't know its |
1719 | * @param get_path | 1779 | * use case and how to handle it |
1720 | * @param get_path_length | 1780 | * Send a get message to selected target friend. If target friend in NULL, |
1721 | * @param key | 1781 | * then search for a target friend. |
1782 | * @param request_id Unique ID identifying this request | ||
1783 | * @param source_peer Peer which started get request | ||
1784 | * @param get_peer_path Peer list to reach to final destination which contains the data. | ||
1785 | * @param get_path_length Total numbers of peer in get_path | ||
1786 | * @param key Key key for the content | ||
1787 | * @param target_peer Next peer to forward the message to. | ||
1788 | * @param current_destination Peer which will get this message. | ||
1789 | * @param current_dest_type Type of current destination can be either FRIEND or FINGER | ||
1722 | */ | 1790 | */ |
1723 | void | 1791 | void |
1724 | GDS_NEIGHBOURS_handle_get (struct GNUNET_PeerIdentity *source_peer, | 1792 | GDS_NEIGHBOURS_handle_get (struct GNUNET_PeerIdentity *source_peer, |
1725 | struct GNUNET_PeerIdentity *get_path, | 1793 | struct GNUNET_PeerIdentity *get_peer_path, |
1726 | unsigned int get_path_length, | 1794 | unsigned int get_path_length, |
1727 | struct GNUNET_HashCode *key, | 1795 | struct GNUNET_HashCode *key, |
1728 | struct GNUNET_PeerIdentity *target_peer, | 1796 | struct GNUNET_PeerIdentity *target_peer, |
1729 | struct GNUNET_PeerIdentity *current_destination, | 1797 | struct GNUNET_PeerIdentity *current_destination, |
1730 | enum current_destination_type *type) | 1798 | enum current_destination_type *current_dest_type) |
1731 | { | 1799 | { |
1732 | struct PeerGetMessage *get_msg; | 1800 | struct PeerGetMessage *get_request; |
1733 | struct P2PPendingMessage *pending; | 1801 | struct P2PPendingMessage *pending; |
1734 | struct GNUNET_PeerIdentity *gp; | 1802 | struct GNUNET_PeerIdentity *get_path; |
1735 | struct FriendInfo *target_friend; | 1803 | struct FriendInfo *target_friend; |
1736 | uint64_t key_value; | 1804 | uint64_t key_value; |
1737 | size_t msize; | 1805 | size_t msize; |
@@ -1747,27 +1815,30 @@ GDS_NEIGHBOURS_handle_get (struct GNUNET_PeerIdentity *source_peer, | |||
1747 | 1815 | ||
1748 | memcpy (&key_value, key, sizeof (uint64_t)); | 1816 | memcpy (&key_value, key, sizeof (uint64_t)); |
1749 | 1817 | ||
1818 | /* FIXME: Is this correct comparison? */ | ||
1750 | if (NULL == target_peer) | 1819 | if (NULL == target_peer) |
1751 | { | 1820 | { |
1752 | /* This is the first call made from client file. */ | 1821 | /* This is the first call made from client file. */ |
1753 | struct GNUNET_PeerIdentity *next_hop; | 1822 | struct GNUNET_PeerIdentity *next_hop; |
1754 | next_hop = find_successor (key_value, current_destination, type); | 1823 | next_hop = find_successor (key_value, current_destination, current_dest_type); |
1755 | 1824 | ||
1756 | if (*type == MY_ID) | 1825 | if (*current_dest_type == MY_ID) |
1757 | { | 1826 | { |
1758 | struct GNUNET_PeerIdentity *destination_peer; | 1827 | struct GNUNET_PeerIdentity *destination_peer; |
1759 | int current_path_index; | 1828 | get_path = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); |
1760 | 1829 | memcpy (get_path, &my_identity, sizeof (struct GNUNET_PeerIdentity)); | |
1761 | /* FIXME: You enter in this part of code only if the call is made from the | 1830 | get_path_length = 1; |
1762 | client file. And in client file you already have done the datacache_get. | ||
1763 | So, ideally you don't need it. Remove it after checking. */ | ||
1764 | if (get_path_length != 1) | ||
1765 | current_path_index = get_path_length - 2; | ||
1766 | destination_peer = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); | 1831 | destination_peer = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); |
1767 | memcpy (destination_peer, source_peer, sizeof (struct GNUNET_PeerIdentity)); | 1832 | memcpy (destination_peer, source_peer, sizeof (struct GNUNET_PeerIdentity)); |
1768 | /* I am the final destination, then call GDS_NEIGHBOURS_send_get_result.*/ | 1833 | /* FIXME: We enter in this part of code only when this is our first |
1834 | call from client file. In client file we already have done datacache_get | ||
1835 | and if we already have the result. So, ideally code should never reach | ||
1836 | here. Remove it after verifying. */ | ||
1837 | /* FIXME: Call datacache_get but remove after verified above thing. */ | ||
1769 | GDS_NEIGHBOURS_send_get_result (&my_identity,get_path, get_path_length, | 1838 | GDS_NEIGHBOURS_send_get_result (&my_identity,get_path, get_path_length, |
1770 | destination_peer, current_path_index); | 1839 | key,destination_peer, 0, |
1840 | NULL,0,NULL); | ||
1841 | |||
1771 | return; | 1842 | return; |
1772 | } | 1843 | } |
1773 | else | 1844 | else |
@@ -1782,18 +1853,18 @@ GDS_NEIGHBOURS_handle_get (struct GNUNET_PeerIdentity *source_peer, | |||
1782 | pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize); | 1853 | pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize); |
1783 | pending->importance = 0; /* FIXME */ | 1854 | pending->importance = 0; /* FIXME */ |
1784 | /* FIXME: Do we have an expiration time for get request */ | 1855 | /* FIXME: Do we have an expiration time for get request */ |
1785 | get_msg = (struct PeerGetMessage *) &pending[1]; | 1856 | get_request = (struct PeerGetMessage *) &pending[1]; |
1786 | pending->msg = &get_msg->header; | 1857 | pending->msg = &get_request->header; |
1787 | get_msg->header.size = htons (msize); | 1858 | get_request->header.size = htons (msize); |
1788 | get_msg->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_GET); | 1859 | get_request->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_GET); |
1789 | get_msg->get_path_length = htonl (get_path_length); | 1860 | get_request->get_path_length = htonl (get_path_length); |
1790 | get_msg->key = *key; | 1861 | get_request->key = *key; |
1791 | memcpy (&(get_msg->source_peer), source_peer, sizeof (struct GNUNET_PeerIdentity)); | 1862 | |
1792 | memcpy (&(get_msg->current_destination), current_destination, sizeof (struct GNUNET_PeerIdentity)); | 1863 | memcpy (&(get_request->source_peer), source_peer, sizeof (struct GNUNET_PeerIdentity)); |
1793 | get_msg->dest_type = htonl (*type); | 1864 | memcpy (&(get_request->current_destination), current_destination, sizeof (struct GNUNET_PeerIdentity)); |
1794 | 1865 | get_request->current_dest_type = htonl (*current_dest_type); | |
1795 | gp = (struct GNUNET_PeerIdentity *) &get_msg[1]; | 1866 | get_path = (struct GNUNET_PeerIdentity *) &get_request[1]; |
1796 | memcpy (gp, get_path, get_path_length * sizeof (struct GNUNET_PeerIdentity)); | 1867 | memcpy (get_path, get_peer_path, get_path_length * sizeof (struct GNUNET_PeerIdentity)); |
1797 | GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending); | 1868 | GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending); |
1798 | target_friend->pending_count++; | 1869 | target_friend->pending_count++; |
1799 | process_friend_queue (target_friend); | 1870 | process_friend_queue (target_friend); |
@@ -1826,12 +1897,12 @@ GDS_NEIGHBOURS_handle_put (enum GNUNET_BLOCK_Type type, | |||
1826 | uint32_t desired_replication_level, | 1897 | uint32_t desired_replication_level, |
1827 | struct GNUNET_TIME_Absolute expiration_time, | 1898 | struct GNUNET_TIME_Absolute expiration_time, |
1828 | uint32_t hop_count, | 1899 | uint32_t hop_count, |
1829 | struct GNUNET_HashCode *key, | 1900 | const struct GNUNET_HashCode *key, |
1830 | unsigned int put_path_length, | 1901 | unsigned int put_path_length, |
1831 | struct GNUNET_PeerIdentity *put_path, | 1902 | struct GNUNET_PeerIdentity *put_path, |
1832 | const void *data, size_t data_size, | 1903 | const void *data, size_t data_size, |
1833 | struct GNUNET_PeerIdentity *current_destination, | 1904 | struct GNUNET_PeerIdentity *current_destination, |
1834 | enum current_destination_type *dest_type, | 1905 | enum current_destination_type dest_type, |
1835 | struct GNUNET_PeerIdentity *target_peer) | 1906 | struct GNUNET_PeerIdentity *target_peer) |
1836 | { | 1907 | { |
1837 | struct PeerPutMessage *ppm; | 1908 | struct PeerPutMessage *ppm; |
@@ -1857,14 +1928,18 @@ GDS_NEIGHBOURS_handle_put (enum GNUNET_BLOCK_Type type, | |||
1857 | } | 1928 | } |
1858 | 1929 | ||
1859 | memcpy (&key_value, key, sizeof (uint64_t)); | 1930 | memcpy (&key_value, key, sizeof (uint64_t)); |
1931 | struct GNUNET_PeerIdentity *current_dest; | ||
1932 | current_dest = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); | ||
1860 | if (target_peer == NULL) | 1933 | if (target_peer == NULL) |
1861 | { | 1934 | { |
1862 | /* This is the first time the call has been made from handle_dht_local_put. | 1935 | /* This is the first time the call has been made from handle_dht_local_put. |
1863 | So, you need to search for the next peer to send this message to. */ | 1936 | So, you need to search for the next peer to send this message to. */ |
1864 | struct GNUNET_PeerIdentity *next_hop; | 1937 | struct GNUNET_PeerIdentity *next_hop; |
1865 | next_hop = find_successor (key_value, current_destination, dest_type); | 1938 | |
1939 | next_hop = find_successor (key_value, current_dest, &dest_type); | ||
1940 | |||
1866 | 1941 | ||
1867 | if (*dest_type == MY_ID) | 1942 | if (dest_type == MY_ID) |
1868 | { | 1943 | { |
1869 | /* FIXME: How do we handle different block types? */ | 1944 | /* FIXME: How do we handle different block types? */ |
1870 | /* FIXME: Here depending on the replication level choose 'r' successors | 1945 | /* FIXME: Here depending on the replication level choose 'r' successors |
@@ -1896,8 +1971,11 @@ GDS_NEIGHBOURS_handle_put (enum GNUNET_BLOCK_Type type, | |||
1896 | ppm->desired_replication_level = htonl (desired_replication_level); | 1971 | ppm->desired_replication_level = htonl (desired_replication_level); |
1897 | ppm->put_path_length = htonl (put_path_length); | 1972 | ppm->put_path_length = htonl (put_path_length); |
1898 | ppm->expiration_time = GNUNET_TIME_absolute_hton (expiration_time); | 1973 | ppm->expiration_time = GNUNET_TIME_absolute_hton (expiration_time); |
1899 | memcpy (&(ppm->current_destination), current_destination, sizeof (struct GNUNET_PeerIdentity)); | 1974 | if (current_destination != NULL) |
1900 | ppm->current_destination_type = htonl (*dest_type); | 1975 | memcpy (&(ppm->current_destination), current_destination, sizeof (struct GNUNET_PeerIdentity)); |
1976 | else | ||
1977 | memcpy (&(ppm->current_destination), current_dest, sizeof (struct GNUNET_PeerIdentity)); | ||
1978 | ppm->current_destination_type = htonl (dest_type); | ||
1901 | ppm->key = *key; | 1979 | ppm->key = *key; |
1902 | 1980 | ||
1903 | pp = (struct GNUNET_PeerIdentity *) &ppm[1]; | 1981 | pp = (struct GNUNET_PeerIdentity *) &ppm[1]; |
@@ -1911,48 +1989,145 @@ GDS_NEIGHBOURS_handle_put (enum GNUNET_BLOCK_Type type, | |||
1911 | 1989 | ||
1912 | 1990 | ||
1913 | /** | 1991 | /** |
1914 | * | 1992 | * Send get result back to requesting client. |
1915 | * @param source_peer | 1993 | * @param source_peer |
1916 | * @param get_path | 1994 | * @param get_path |
1995 | * @param target_friend | ||
1917 | * @param get_path_length | 1996 | * @param get_path_length |
1997 | * @param key | ||
1918 | * @param destination_peer | 1998 | * @param destination_peer |
1999 | * @param current_path_index | ||
2000 | * @param data | ||
2001 | * @param data_size | ||
1919 | */ | 2002 | */ |
1920 | void | 2003 | void |
1921 | GDS_NEIGHBOURS_send_get_result (struct GNUNET_PeerIdentity *source_peer, | 2004 | GDS_NEIGHBOURS_send_get_result (struct GNUNET_PeerIdentity *source_peer, |
1922 | struct GNUNET_PeerIdentity *get_path, | 2005 | struct GNUNET_PeerIdentity *get_path, |
1923 | unsigned int get_path_length, | 2006 | unsigned int get_path_length, |
2007 | struct GNUNET_HashCode *key, | ||
1924 | struct GNUNET_PeerIdentity *destination_peer, | 2008 | struct GNUNET_PeerIdentity *destination_peer, |
1925 | unsigned int current_path_index) | 2009 | unsigned int current_path_index, |
2010 | const void *data, size_t data_size, | ||
2011 | struct GNUNET_PeerIdentity *next_hop) | ||
1926 | { | 2012 | { |
1927 | /* Add get_result into pending message and send the data to target friend. */ | 2013 | /* Add get_result into pending message and send the data to target friend. |
1928 | #if 0 | 2014 | make a call GDS_CLIENTS_process_get_result() with all the fields. */ |
1929 | struct PeerGetResultMessage *get_result; | 2015 | struct PeerGetResultMessage *get_result; |
2016 | struct GNUNET_PeerIdentity *get_result_path; | ||
1930 | struct P2PPendingMessage *pending; | 2017 | struct P2PPendingMessage *pending; |
2018 | struct FriendInfo *target_friend; | ||
1931 | size_t msize; | 2019 | size_t msize; |
1932 | 2020 | ||
1933 | msize = (get_path_length * sizeof (struct GNUNET_PeerIdentity)) + | 2021 | msize = get_path_length * sizeof (struct GNUNET_PeerIdentity) + data_size + |
1934 | sizeof (struct PeerGetResultMessage); | 2022 | sizeof (struct PeerPutMessage); |
1935 | 2023 | ||
1936 | if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) | 2024 | if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) |
1937 | { | 2025 | { |
1938 | GNUNET_break (0); | 2026 | GNUNET_break (0); |
1939 | return; | 2027 | return; |
1940 | } | 2028 | } |
1941 | 2029 | ||
1942 | #endif | 2030 | pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize); |
2031 | pending->importance = 0; /* FIXME */ | ||
2032 | /* FIXME: Should we add an expiration time like in put message. */ | ||
2033 | get_result = (struct PeerGetResultMessage *)&pending[1]; | ||
2034 | pending->msg = &get_result->header; | ||
2035 | get_result->header.size = htons (msize); | ||
2036 | get_result->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_GET_RESULT); | ||
2037 | memcpy (&(get_result->source_peer), source_peer, sizeof (struct GNUNET_PeerIdentity)); | ||
2038 | memcpy (&(get_result->destination_peer), destination_peer, sizeof (struct GNUNET_PeerIdentity)); | ||
2039 | get_result->current_path_index = current_path_index; | ||
2040 | get_result->key = *key; | ||
2041 | |||
2042 | get_result_path = (struct GNUNET_PeerIdentity *)&get_result[1]; | ||
2043 | memcpy (get_result_path, get_path, | ||
2044 | sizeof (struct GNUNET_PeerIdentity) * get_path_length); | ||
2045 | memcpy (&get_result_path[get_path_length], data, data_size); | ||
2046 | |||
2047 | target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop); | ||
2048 | GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending); | ||
2049 | target_friend->pending_count++; | ||
2050 | process_friend_queue (target_friend); | ||
1943 | } | 2051 | } |
1944 | 2052 | ||
1945 | 2053 | ||
1946 | /** | 2054 | /** |
1947 | * | 2055 | * |
2056 | * @param cls | ||
2057 | * @param peer | ||
2058 | * @param message | ||
1948 | * @return | 2059 | * @return |
1949 | */ | 2060 | */ |
1950 | static int | 2061 | static int |
1951 | handle_dht_p2p_get_result () | 2062 | handle_dht_p2p_get_result (void *cls, const struct GNUNET_PeerIdentity *peer, |
2063 | const struct GNUNET_MessageHeader *message) | ||
1952 | { | 2064 | { |
1953 | /* If you are the source, go back to the client file and there search for | 2065 | /* If you are the source, go back to the client file and there search for |
1954 | the requesting client and send back the result. */ | 2066 | the requesting client and send back the result. */ |
1955 | return GNUNET_YES; | 2067 | struct PeerGetResultMessage *get_result; |
2068 | struct GNUNET_PeerIdentity *get_path; | ||
2069 | void *payload; | ||
2070 | size_t payload_size; | ||
2071 | size_t msize; | ||
2072 | unsigned int getlen; | ||
2073 | int current_path_index; | ||
2074 | |||
2075 | msize = ntohs (message->size); | ||
2076 | if (msize < sizeof (struct PeerGetResultMessage)) | ||
2077 | { | ||
2078 | GNUNET_break_op (0); | ||
2079 | return GNUNET_YES; | ||
2080 | } | ||
2081 | |||
2082 | get_result = (struct PeerGetResultMessage *)message; | ||
2083 | getlen = ntohl (get_result->get_path_length); | ||
2084 | |||
2085 | if ((msize < | ||
2086 | sizeof (struct PeerGetResultMessage) + | ||
2087 | getlen * sizeof (struct GNUNET_PeerIdentity)) || | ||
2088 | (getlen > | ||
2089 | GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity))) | ||
2090 | { | ||
2091 | GNUNET_break_op (0); | ||
2092 | return GNUNET_YES; | ||
2093 | } | ||
2094 | |||
2095 | get_path = (struct GNUNET_PeerIdentity *) &get_result[1]; | ||
2096 | payload = &get_path[getlen]; | ||
2097 | payload_size = msize - (sizeof (struct PeerGetResultMessage) + | ||
2098 | getlen * sizeof (struct GNUNET_PeerIdentity)); | ||
2099 | current_path_index = ntohl (get_result->current_path_index); | ||
2100 | |||
2101 | /* Here you just have to check if you are the destination or not if not | ||
2102 | then read the next peer and send the message. */ | ||
2103 | if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &(get_result->destination_peer)))) | ||
2104 | { | ||
2105 | /* I am the destination. Call the function in client file. | ||
2106 | * FIXME: Here I don't know how I communicate the result back to client | ||
2107 | file. */ | ||
2108 | //GDS_CLIENTS_process_get_result(); | ||
2109 | return GNUNET_YES; | ||
2110 | } | ||
2111 | else | ||
2112 | { | ||
2113 | /* Read the element from the get path at trail index. set the trail index | ||
2114 | and call gds_neighbours_send_get_result.*/ | ||
2115 | struct GNUNET_PeerIdentity *next_hop; | ||
2116 | |||
2117 | next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); | ||
2118 | memcpy (next_hop, &get_path[current_path_index], sizeof (struct GNUNET_PeerIdentity)); | ||
2119 | |||
2120 | |||
2121 | if (current_path_index != 0) | ||
2122 | current_path_index--; | ||
2123 | |||
2124 | GDS_NEIGHBOURS_send_get_result (&my_identity, get_path, | ||
2125 | getlen,&(get_result->key),&(get_result->destination_peer), | ||
2126 | current_path_index, | ||
2127 | payload, payload_size, next_hop); | ||
2128 | return GNUNET_YES; | ||
2129 | } | ||
2130 | return GNUNET_SYSERR; | ||
1956 | } | 2131 | } |
1957 | 2132 | ||
1958 | 2133 | ||
@@ -1985,15 +2160,10 @@ handle_dht_p2p_put (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
1985 | size_t msize; | 2160 | size_t msize; |
1986 | uint32_t putlen; | 2161 | uint32_t putlen; |
1987 | 2162 | ||
1988 | msize = ntohs (message->size); | ||
1989 | if (msize < sizeof (struct PeerPutMessage)) | ||
1990 | { | ||
1991 | GNUNET_break_op (0); | ||
1992 | return GNUNET_YES; | ||
1993 | } | ||
1994 | |||
1995 | put = (struct PeerPutMessage *) message; | 2163 | put = (struct PeerPutMessage *) message; |
1996 | putlen = ntohl (put->put_path_length); | 2164 | putlen = ntohl (put->put_path_length); |
2165 | msize = ntohs (message->size); | ||
2166 | |||
1997 | if ((msize < | 2167 | if ((msize < |
1998 | sizeof (struct PeerPutMessage) + | 2168 | sizeof (struct PeerPutMessage) + |
1999 | putlen * sizeof (struct GNUNET_PeerIdentity)) || | 2169 | putlen * sizeof (struct GNUNET_PeerIdentity)) || |
@@ -2090,7 +2260,7 @@ handle_dht_p2p_put (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
2090 | } | 2260 | } |
2091 | else if (current_dst_type == FINGER) | 2261 | else if (current_dst_type == FINGER) |
2092 | { | 2262 | { |
2093 | next_hop = GDS_ROUTING_search (source_peer, current_destination); | 2263 | next_hop = GDS_ROUTING_search (source_peer, current_destination, peer); |
2094 | } | 2264 | } |
2095 | 2265 | ||
2096 | if (current_dst_type == MY_ID) | 2266 | if (current_dst_type == MY_ID) |
@@ -2111,7 +2281,7 @@ handle_dht_p2p_put (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
2111 | GNUNET_TIME_absolute_ntoh (put->expiration_time), | 2281 | GNUNET_TIME_absolute_ntoh (put->expiration_time), |
2112 | ntohl (put->hop_count),&put->key, putlen, | 2282 | ntohl (put->hop_count),&put->key, putlen, |
2113 | pp, payload, payload_size, | 2283 | pp, payload, payload_size, |
2114 | current_destination, ¤t_dst_type, next_hop); | 2284 | current_destination, current_dst_type, next_hop); |
2115 | return GNUNET_YES; | 2285 | return GNUNET_YES; |
2116 | } | 2286 | } |
2117 | return GNUNET_SYSERR; | 2287 | return GNUNET_SYSERR; |
@@ -2136,7 +2306,7 @@ handle_dht_p2p_get (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
2136 | struct PeerGetMessage *get; | 2306 | struct PeerGetMessage *get; |
2137 | struct GNUNET_PeerIdentity *current_destination; | 2307 | struct GNUNET_PeerIdentity *current_destination; |
2138 | uint64_t key_value; | 2308 | uint64_t key_value; |
2139 | enum current_destination_type dest_type; | 2309 | enum current_destination_type cuurent_dest_type; |
2140 | struct GNUNET_PeerIdentity *next_hop; | 2310 | struct GNUNET_PeerIdentity *next_hop; |
2141 | struct GNUNET_PeerIdentity *get_path; | 2311 | struct GNUNET_PeerIdentity *get_path; |
2142 | size_t msize; | 2312 | size_t msize; |
@@ -2167,30 +2337,38 @@ handle_dht_p2p_get (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
2167 | current_destination = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); | 2337 | current_destination = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); |
2168 | memcpy (current_destination, &(get->current_destination), sizeof (struct GNUNET_PeerIdentity)); | 2338 | memcpy (current_destination, &(get->current_destination), sizeof (struct GNUNET_PeerIdentity)); |
2169 | memcpy (&key_value, &(get->key), sizeof (uint64_t)); | 2339 | memcpy (&key_value, &(get->key), sizeof (uint64_t)); |
2170 | dest_type = ntohl (get->dest_type); | 2340 | cuurent_dest_type = ntohl (get->current_dest_type); |
2171 | 2341 | ||
2172 | if (dest_type == FRIEND) | 2342 | if (cuurent_dest_type == FRIEND) |
2173 | { | 2343 | { |
2174 | next_hop = find_successor (key_value, current_destination, &dest_type); | 2344 | next_hop = find_successor (key_value, current_destination, &cuurent_dest_type); |
2175 | } | 2345 | } |
2176 | else if (dest_type == FINGER) | 2346 | else if (cuurent_dest_type == FINGER) |
2177 | { | 2347 | { |
2178 | next_hop = GDS_ROUTING_search (&(get->source_peer), current_destination); | 2348 | next_hop = GDS_ROUTING_search (&(get->source_peer), current_destination, peer); |
2179 | } | 2349 | } |
2180 | 2350 | ||
2181 | if (dest_type == MY_ID) | 2351 | if (cuurent_dest_type == MY_ID) |
2182 | { | 2352 | { |
2183 | struct GNUNET_PeerIdentity *destination_peer; | 2353 | struct GNUNET_PeerIdentity *destination_peer; |
2184 | int current_path_index; | 2354 | //struct GNUNET_PeerIdentity *next_hop; |
2355 | //int current_path_index; | ||
2185 | 2356 | ||
2186 | /* Add yourself to the get path, increment the get length. */ | 2357 | /* Add yourself to the get path, increment the get length. */ |
2187 | destination_peer = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); | 2358 | destination_peer = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); |
2188 | memcpy (destination_peer, &(get->source_peer), sizeof (struct GNUNET_PeerIdentity)); | 2359 | memcpy (destination_peer, &(get->source_peer), sizeof (struct GNUNET_PeerIdentity)); |
2189 | current_path_index = get_length - 2; | 2360 | //current_path_index = get_length - 1; |
2190 | 2361 | ||
2191 | /* I am the final destination. Call GDS_NEIGHBOURS_send_get_result. */ | 2362 | /* I am the final destination. Call GDS_NEIGHBOURS_send_get_result. |
2192 | GDS_NEIGHBOURS_send_get_result (&my_identity, get_path, get_length, | 2363 | * FIXME: Last parameters are data and data size. First implement datacache get |
2193 | destination_peer, current_path_index); | 2364 | * and get the result and send the data. Also seach for the next friend to pass |
2365 | * this message to. */ | ||
2366 | #if 0 | ||
2367 | /* FIXME: Here we should call GDS_CLIENT_handle_reply. */ | ||
2368 | GDS_NEIGHBOURS_send_get_result (get->request_id, &my_identity, get_path, | ||
2369 | get_length,&(get->key), destination_peer, current_path_index, | ||
2370 | NULL, 0, next_hop); | ||
2371 | #endif | ||
2194 | return GNUNET_YES; | 2372 | return GNUNET_YES; |
2195 | } | 2373 | } |
2196 | else | 2374 | else |
@@ -2198,8 +2376,9 @@ handle_dht_p2p_get (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
2198 | /* FIXME: Add your self to the get path and increment the get length. */ | 2376 | /* FIXME: Add your self to the get path and increment the get length. */ |
2199 | 2377 | ||
2200 | /* FIXME: Does it matter if the dest_type is friend or finger. */ | 2378 | /* FIXME: Does it matter if the dest_type is friend or finger. */ |
2201 | GDS_NEIGHBOURS_handle_get (&(get->source_peer), get_path, get_length, &(get->key), | 2379 | GDS_NEIGHBOURS_handle_get (&(get->source_peer), get_path, |
2202 | next_hop, current_destination,&dest_type); | 2380 | get_length, &(get->key),next_hop, |
2381 | current_destination,&cuurent_dest_type); | ||
2203 | 2382 | ||
2204 | return GNUNET_YES; | 2383 | return GNUNET_YES; |
2205 | } | 2384 | } |
@@ -2222,16 +2401,15 @@ handle_dht_p2p_trail_setup(void *cls, const struct GNUNET_PeerIdentity *peer, | |||
2222 | struct GNUNET_PeerIdentity *next_hop; | 2401 | struct GNUNET_PeerIdentity *next_hop; |
2223 | struct FriendInfo *target_friend; | 2402 | struct FriendInfo *target_friend; |
2224 | struct GNUNET_PeerIdentity *current_destination; | 2403 | struct GNUNET_PeerIdentity *current_destination; |
2225 | struct GNUNET_PeerIdentity *next_peer; | ||
2226 | struct GNUNET_PeerIdentity *trail_peer_list; | 2404 | struct GNUNET_PeerIdentity *trail_peer_list; |
2227 | enum current_destination_type peer_type; | 2405 | enum current_destination_type current_dest_type; |
2406 | struct GNUNET_PeerIdentity *next_peer; | ||
2228 | unsigned int trail_length; | 2407 | unsigned int trail_length; |
2229 | uint32_t current_trail_index; | 2408 | uint32_t current_trail_index; |
2230 | unsigned int finger_map_index; | 2409 | unsigned int finger_map_index; |
2231 | uint64_t finger_value; | 2410 | uint64_t destination_finger_value; |
2232 | size_t msize; | 2411 | size_t msize; |
2233 | 2412 | ||
2234 | /* parse and validate message. */ | ||
2235 | msize = ntohs (message->size); | 2413 | msize = ntohs (message->size); |
2236 | if (msize < sizeof (struct PeerTrailSetupMessage)) | 2414 | if (msize < sizeof (struct PeerTrailSetupMessage)) |
2237 | { | 2415 | { |
@@ -2242,8 +2420,7 @@ handle_dht_p2p_trail_setup(void *cls, const struct GNUNET_PeerIdentity *peer, | |||
2242 | trail_setup = (struct PeerTrailSetupMessage *) message; | 2420 | trail_setup = (struct PeerTrailSetupMessage *) message; |
2243 | trail_length = ntohl (trail_setup->trail_length); | 2421 | trail_length = ntohl (trail_setup->trail_length); |
2244 | 2422 | ||
2245 | if ((msize < | 2423 | if ((msize < sizeof (struct PeerTrailSetupMessage) + |
2246 | sizeof (struct PeerTrailSetupMessage) + | ||
2247 | trail_length * sizeof (struct GNUNET_PeerIdentity)) || | 2424 | trail_length * sizeof (struct GNUNET_PeerIdentity)) || |
2248 | (trail_length > | 2425 | (trail_length > |
2249 | GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity))) | 2426 | GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity))) |
@@ -2252,123 +2429,118 @@ handle_dht_p2p_trail_setup(void *cls, const struct GNUNET_PeerIdentity *peer, | |||
2252 | return GNUNET_YES; | 2429 | return GNUNET_YES; |
2253 | } | 2430 | } |
2254 | 2431 | ||
2255 | peer_type = ntohl (trail_setup->current_destination_type); | 2432 | current_dest_type = ntohl (trail_setup->current_destination_type); |
2256 | finger_map_index = ntohl (trail_setup->finger_map_index); | 2433 | finger_map_index = ntohl (trail_setup->finger_map_index); |
2257 | trail_peer_list = (struct GNUNET_PeerIdentity *) &trail_setup[1]; | 2434 | trail_peer_list = (struct GNUNET_PeerIdentity *)&trail_setup[1]; |
2258 | finger_value = trail_setup->destination_finger; | 2435 | destination_finger_value = trail_setup->destination_finger; |
2259 | current_destination = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); | 2436 | current_destination = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); |
2260 | memcpy (current_destination, &(trail_setup->current_destination), sizeof (struct GNUNET_PeerIdentity)); | 2437 | memcpy (current_destination, &(trail_setup->current_destination), sizeof (struct GNUNET_PeerIdentity)); |
2261 | 2438 | ||
2262 | if (peer_type == FRIEND) | 2439 | /* Find the next hop to send the packet to. */ |
2440 | if (current_dest_type == FRIEND) | ||
2263 | { | 2441 | { |
2264 | if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&(trail_setup->current_destination), | 2442 | if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&(trail_setup->current_destination), |
2265 | &my_identity))) | 2443 | &my_identity))) |
2266 | { | 2444 | { |
2267 | next_hop = find_successor (finger_value, current_destination, &(peer_type)); | 2445 | next_hop = find_successor (destination_finger_value, current_destination, &(current_dest_type)); |
2268 | } | 2446 | } |
2269 | else | 2447 | else |
2270 | return GNUNET_SYSERR; | 2448 | return GNUNET_SYSERR; |
2271 | } | 2449 | } |
2272 | else if (peer_type == FINGER) | 2450 | else if (current_dest_type == FINGER) |
2273 | { | 2451 | { |
2274 | if (0 != (GNUNET_CRYPTO_cmp_peer_identity (&(trail_setup->current_destination), | 2452 | if (0 != (GNUNET_CRYPTO_cmp_peer_identity (&(trail_setup->current_destination), |
2275 | &my_identity))) | 2453 | &my_identity))) |
2276 | { | 2454 | { |
2277 | next_hop = GDS_ROUTING_search (&(trail_setup->source_peer), | 2455 | next_hop = GDS_ROUTING_search (&(trail_setup->source_peer), |
2278 | &(trail_setup->current_destination)); | 2456 | &(trail_setup->current_destination), peer); |
2279 | 2457 | /* As an optimization, find the successor from the find successor and | |
2280 | #if 0 | 2458 | compare both the ids to find the closest peer. */ |
2281 | /* This is an optimization. Uncomment when basic code is running first. */ | ||
2282 | /* I am part of trail.*/ | ||
2283 | struct GNUNET_PeerIdentity *next_peer_routing_table; | ||
2284 | next_peer_routing_table = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); | ||
2285 | next_peer_routing_table = GDS_ROUTING_search (&(trail_setup->source_peer), | ||
2286 | &(trail_setup->current_destination)); | ||
2287 | |||
2288 | struct GNUNET_PeerIdentity *next_peer_find_successor; | ||
2289 | next_peer_find_successor = find_successor (&(trail_setup->destination_finger), | ||
2290 | &(trail_setup->current_destination), | ||
2291 | &(peer_type)); | ||
2292 | |||
2293 | next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); | ||
2294 | next_hop = find_closest_destination (next_peer_routing_table, | ||
2295 | next_peer_find_successor, | ||
2296 | &(trail_setup->destination_finger) ); | ||
2297 | #endif | ||
2298 | } | 2459 | } |
2299 | else | 2460 | else |
2300 | { | 2461 | { |
2301 | /* I am the current_destination finger */ | 2462 | next_hop = find_successor (destination_finger_value, current_destination, &(current_dest_type)); |
2302 | next_hop = find_successor (finger_value, current_destination, &(peer_type)); | ||
2303 | } | 2463 | } |
2304 | } | 2464 | } |
2465 | |||
2466 | /* Add yourself to the trail list and increment the trail length. */ | ||
2467 | struct GNUNET_PeerIdentity *peer_list; | ||
2468 | peer_list = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * (trail_length + 1)); | ||
2469 | if ( trail_length > 0) | ||
2470 | { | ||
2471 | memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity)); | ||
2472 | } | ||
2473 | memcpy (&peer_list[trail_length], &my_identity, sizeof (struct GNUNET_PeerIdentity)); | ||
2474 | trail_length++; | ||
2305 | 2475 | ||
2306 | /* If you are the next hop, then you are the final destination */ | 2476 | if (current_dest_type == MY_ID || |
2307 | if (peer_type == MY_ID) | 2477 | (0 == GNUNET_CRYPTO_cmp_peer_identity(next_hop, &(trail_setup->source_peer)))) |
2308 | { | 2478 | { |
2309 | struct GNUNET_PeerIdentity *source; | 2479 | struct GNUNET_PeerIdentity *source_peer; |
2310 | source = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); | 2480 | source_peer = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); |
2311 | memcpy (source, &(trail_setup->source_peer), sizeof (struct GNUNET_PeerIdentity)); | 2481 | memcpy (source_peer, &(trail_setup->source_peer), sizeof (struct GNUNET_PeerIdentity)); |
2312 | current_trail_index = trail_length - 2; | 2482 | |
2313 | next_peer = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); | 2483 | current_trail_index = trail_length - 1; |
2314 | memcpy (next_peer, &trail_peer_list[current_trail_index], sizeof (struct GNUNET_PeerIdentity)); | 2484 | next_peer= GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); |
2485 | if (current_trail_index == 0) | ||
2486 | { | ||
2487 | memcpy (next_peer, &(trail_setup->source_peer), sizeof (struct GNUNET_PeerIdentity)); | ||
2488 | } | ||
2489 | else | ||
2490 | { | ||
2491 | memcpy (next_peer, &trail_peer_list[current_trail_index-1], sizeof (struct GNUNET_PeerIdentity)); | ||
2492 | } | ||
2493 | |||
2315 | target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_peer); | 2494 | target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_peer); |
2316 | GNUNET_free (next_peer); | 2495 | GNUNET_free (next_peer); |
2317 | 2496 | ||
2318 | if(current_trail_index != 0) | ||
2319 | current_trail_index = current_trail_index - 1; | ||
2320 | |||
2321 | if (0 == trail_setup->finger_map_index) | 2497 | if (0 == trail_setup->finger_map_index) |
2322 | { | 2498 | { |
2323 | struct GNUNET_PeerIdentity *new_trail; | 2499 | struct GNUNET_PeerIdentity *new_trail_list; |
2324 | int i; | 2500 | new_trail_list = invert_trail_list (source_peer, peer_list, trail_length); |
2325 | int j; | 2501 | finger_table_add (source_peer, new_trail_list, trail_length, 1); |
2326 | |||
2327 | i = trail_length - 1; | ||
2328 | j = 0; | ||
2329 | new_trail = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * | ||
2330 | trail_length); | ||
2331 | while (i > 0) | ||
2332 | { | ||
2333 | memcpy( &new_trail[j], &trail_peer_list[i], sizeof (struct GNUNET_PeerIdentity)); | ||
2334 | i--; | ||
2335 | j++; | ||
2336 | } | ||
2337 | memcpy (&new_trail[j], &trail_peer_list[i], sizeof(struct GNUNET_PeerIdentity)); | ||
2338 | finger_table_add (source, new_trail, trail_length, 1); | ||
2339 | } | 2502 | } |
2340 | 2503 | ||
2341 | GDS_NEIGHBOURS_send_trail_setup_result (&(trail_setup->source_peer), | 2504 | GDS_NEIGHBOURS_send_trail_setup_result (&(trail_setup->source_peer), |
2342 | &(my_identity), | 2505 | &(my_identity), |
2343 | target_friend, trail_length, | 2506 | target_friend, trail_length, |
2344 | trail_peer_list, current_trail_index, | 2507 | peer_list, current_trail_index, |
2345 | finger_map_index); | 2508 | finger_map_index); |
2346 | 2509 | ||
2347 | return GNUNET_YES; | 2510 | return GNUNET_YES; |
2348 | } | 2511 | } |
2349 | 2512 | else if (next_hop == NULL) | |
2350 | /* Add next hop to list of peers. */ | ||
2351 | struct GNUNET_PeerIdentity *peer_list; | ||
2352 | peer_list = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * (trail_length + 1)); | ||
2353 | memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity)); | ||
2354 | memcpy (&peer_list[trail_length], next_hop, sizeof (struct GNUNET_PeerIdentity)); | ||
2355 | trail_length++; | ||
2356 | |||
2357 | target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop); | ||
2358 | |||
2359 | if(peer_type == FINGER) | ||
2360 | { | 2513 | { |
2361 | GDS_ROUTING_add (&(trail_setup->source_peer), | 2514 | return GNUNET_SYSERR; |
2362 | &(trail_setup->current_destination), | ||
2363 | next_hop); | ||
2364 | } | 2515 | } |
2516 | else | ||
2517 | { | ||
2518 | target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop); | ||
2519 | if(current_dest_type == FINGER) | ||
2520 | { | ||
2521 | /* FIXME: Here it can even return err if routing entries have crossed the | ||
2522 | threshold. In such a case, you should send back a trail setup fail message | ||
2523 | to node just before your. THen its the responsiblity of node before you | ||
2524 | to find an alternate path to reach to the current_desintation which doesnot | ||
2525 | involve you.*/ | ||
2526 | |||
2527 | if ( GNUNET_SYSERR == GDS_ROUTING_add (&(trail_setup->source_peer), | ||
2528 | &(trail_setup->current_destination), | ||
2529 | next_hop, peer)) | ||
2530 | { | ||
2531 | //trail_setup_rejection()--> add to a list of fail trails and start | ||
2532 | // a new search rejecting this peer. | ||
2533 | } | ||
2534 | } | ||
2365 | 2535 | ||
2366 | GDS_NEIGHBOURS_send_trail_setup (&(trail_setup->source_peer), | 2536 | GDS_NEIGHBOURS_send_trail_setup (&(trail_setup->source_peer), |
2367 | trail_setup->destination_finger, | 2537 | trail_setup->destination_finger, |
2368 | current_destination, target_friend, trail_length, | 2538 | current_destination, target_friend, trail_length, |
2369 | peer_list, finger_map_index, peer_type); | 2539 | peer_list, finger_map_index, current_dest_type); |
2370 | 2540 | ||
2371 | return GNUNET_YES; | 2541 | return GNUNET_YES; |
2542 | } | ||
2543 | return GNUNET_SYSERR; | ||
2372 | } | 2544 | } |
2373 | 2545 | ||
2374 | 2546 | ||
@@ -2385,7 +2557,7 @@ handle_dht_p2p_trail_setup_result(void *cls, const struct GNUNET_PeerIdentity *p | |||
2385 | { | 2557 | { |
2386 | struct PeerTrailSetupResultMessage *trail_result; | 2558 | struct PeerTrailSetupResultMessage *trail_result; |
2387 | struct GNUNET_PeerIdentity *trail_peer_list; | 2559 | struct GNUNET_PeerIdentity *trail_peer_list; |
2388 | struct GNUNET_PeerIdentity *next_peer; | 2560 | struct GNUNET_PeerIdentity *next_hop; |
2389 | struct FriendInfo *target_friend; | 2561 | struct FriendInfo *target_friend; |
2390 | unsigned int current_trail_index; | 2562 | unsigned int current_trail_index; |
2391 | unsigned int finger_map_index; | 2563 | unsigned int finger_map_index; |
@@ -2418,45 +2590,44 @@ handle_dht_p2p_trail_setup_result(void *cls, const struct GNUNET_PeerIdentity *p | |||
2418 | trail_peer_list = (struct GNUNET_PeerIdentity *) &trail_result[1]; | 2590 | trail_peer_list = (struct GNUNET_PeerIdentity *) &trail_result[1]; |
2419 | 2591 | ||
2420 | if ( 0 == (GNUNET_CRYPTO_cmp_peer_identity (&(trail_result->destination_peer), | 2592 | if ( 0 == (GNUNET_CRYPTO_cmp_peer_identity (&(trail_result->destination_peer), |
2421 | &my_identity))) | 2593 | &my_identity))) |
2422 | { | 2594 | { |
2423 | #if 0 | 2595 | #if 0 |
2424 | /* SUPU: Here I have removed myself from the trail before storing it in | 2596 | /* I don't remember why I have written this code. */ |
2425 | th finger table - to save space, but in case of verify successor result | 2597 | if (finger_map_index == 1) |
2426 | the result trail does not contain me, and I will never get the message back. | 2598 | { |
2427 | So, keeping myself in the trail list. Think of better solution.*/ | 2599 | struct GNUNET_PeerIdentity *new_trail_list; |
2428 | struct GNUNET_PeerIdentity *finger_trail; | 2600 | new_trail_list = invert_trail_list (&(trail_result->finger_identity), |
2429 | finger_trail = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * (trail_length - 1)); | 2601 | trail_peer_list, trail_length); |
2430 | 2602 | finger_table_add (&(trail_result->finger_identity), new_trail_list, trail_length, | |
2431 | /* Copy the whole trail_peer_list except the first element into trail */ | 2603 | finger_map_index); |
2432 | unsigned int i; | 2604 | return GNUNET_YES; |
2433 | i = trail_length - 1; | 2605 | } |
2434 | while (i > 0) | 2606 | else |
2435 | { | 2607 | { |
2436 | memcpy (&finger_trail[i], &trail_peer_list[i], sizeof (struct GNUNET_PeerIdentity)); | 2608 | #endif |
2437 | i--; | 2609 | finger_table_add (&(trail_result->finger_identity), trail_peer_list, trail_length, |
2438 | } | 2610 | finger_map_index); |
2439 | trail_length = trail_length -1 ; SUPU: As you removed yourself from the trail.*/ | 2611 | |
2440 | #endif | 2612 | return GNUNET_YES; |
2441 | 2613 | //} | |
2442 | finger_table_add (&(trail_result->finger_identity), trail_peer_list, trail_length, | ||
2443 | finger_map_index); | ||
2444 | |||
2445 | return GNUNET_YES; | ||
2446 | } | 2614 | } |
2447 | else | 2615 | else |
2448 | { | 2616 | { |
2449 | next_peer = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); | 2617 | next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); |
2450 | memcpy (next_peer, &(trail_peer_list[current_trail_index]), | 2618 | |
2451 | sizeof (struct GNUNET_PeerIdentity)); | 2619 | current_trail_index = current_trail_index - 1; |
2452 | /* SUPU: here current trail index will always be greater than 0. | 2620 | if (current_trail_index == 0) |
2453 | so no need for this check here. trail index = 0, contains the final | 2621 | { |
2454 | destination, and if we are in this loop we have not yet reached the | 2622 | memcpy (next_hop, &(trail_result->destination_peer),sizeof (struct GNUNET_PeerIdentity)); |
2455 | final destination. */ | 2623 | } |
2456 | current_trail_index = current_trail_index - 1; | 2624 | else |
2625 | { | ||
2626 | memcpy (next_hop, &(trail_peer_list[current_trail_index-1]),sizeof (struct GNUNET_PeerIdentity)); | ||
2627 | } | ||
2457 | 2628 | ||
2458 | target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_peer); | 2629 | target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop); |
2459 | GNUNET_free (next_peer); | 2630 | GNUNET_free (next_hop); |
2460 | 2631 | ||
2461 | GDS_NEIGHBOURS_send_trail_setup_result (&(trail_result->destination_peer), | 2632 | GDS_NEIGHBOURS_send_trail_setup_result (&(trail_result->destination_peer), |
2462 | &(trail_result->finger_identity), | 2633 | &(trail_result->finger_identity), |
@@ -2471,6 +2642,38 @@ handle_dht_p2p_trail_setup_result(void *cls, const struct GNUNET_PeerIdentity *p | |||
2471 | 2642 | ||
2472 | 2643 | ||
2473 | /** | 2644 | /** |
2645 | * FIXME: Use flag in the case finger peer map does not contain predcessor | ||
2646 | * then its NULL. Ideally it should never happen. | ||
2647 | * Get my current predecessor from the finger peer map | ||
2648 | * @return Current predecessor. | ||
2649 | */ | ||
2650 | static struct FingerInfo * | ||
2651 | get_predecessor() | ||
2652 | { | ||
2653 | struct GNUNET_CONTAINER_MultiPeerMapIterator *finger_iter; | ||
2654 | struct GNUNET_PeerIdentity key_ret; | ||
2655 | unsigned int finger_index; | ||
2656 | struct FingerInfo *my_predecessor; | ||
2657 | |||
2658 | /* Iterate over finger peer map and extract your predecessor. */ | ||
2659 | finger_iter = GNUNET_CONTAINER_multipeermap_iterator_create (finger_peermap); | ||
2660 | for (finger_index = 0; finger_index < GNUNET_CONTAINER_multipeermap_size (finger_peermap); finger_index++) | ||
2661 | { | ||
2662 | if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next | ||
2663 | (finger_iter,&key_ret,(const void **)&my_predecessor)) | ||
2664 | { | ||
2665 | if(1 == my_predecessor->finger_map_index) | ||
2666 | { | ||
2667 | break; | ||
2668 | } | ||
2669 | } | ||
2670 | } | ||
2671 | GNUNET_CONTAINER_multipeermap_iterator_destroy (finger_iter); | ||
2672 | return my_predecessor; | ||
2673 | } | ||
2674 | |||
2675 | |||
2676 | /** | ||
2474 | * Core handle for p2p verify successor messages. | 2677 | * Core handle for p2p verify successor messages. |
2475 | * @param cls closure | 2678 | * @param cls closure |
2476 | * @param message message | 2679 | * @param message message |
@@ -2500,15 +2703,13 @@ handle_dht_p2p_verify_successor(void *cls, const struct GNUNET_PeerIdentity *pee | |||
2500 | vsm = (struct PeerVerifySuccessorMessage *) message; | 2703 | vsm = (struct PeerVerifySuccessorMessage *) message; |
2501 | trail_length = ntohl (vsm->trail_length); | 2704 | trail_length = ntohl (vsm->trail_length); |
2502 | 2705 | ||
2503 | if ((msize < | 2706 | if ((msize < sizeof (struct PeerVerifySuccessorMessage) + |
2504 | sizeof (struct PeerVerifySuccessorMessage) + | 2707 | trail_length * sizeof (struct GNUNET_PeerIdentity)) || |
2505 | trail_length * sizeof (struct GNUNET_PeerIdentity)) || | 2708 | (trail_length > GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity))) |
2506 | (trail_length > | 2709 | { |
2507 | GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity))) | 2710 | GNUNET_break_op (0); |
2508 | { | 2711 | return GNUNET_YES; |
2509 | GNUNET_break_op (0); | 2712 | } |
2510 | return GNUNET_YES; | ||
2511 | } | ||
2512 | 2713 | ||
2513 | current_trail_index = ntohl (vsm->current_trail_index); | 2714 | current_trail_index = ntohl (vsm->current_trail_index); |
2514 | trail_peer_list = (struct GNUNET_PeerIdentity *) &vsm[1]; | 2715 | trail_peer_list = (struct GNUNET_PeerIdentity *) &vsm[1]; |
@@ -2517,80 +2718,29 @@ handle_dht_p2p_verify_successor(void *cls, const struct GNUNET_PeerIdentity *pee | |||
2517 | 2718 | ||
2518 | next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); | 2719 | next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); |
2519 | 2720 | ||
2520 | /* SUPU: If I am the destination. */ | 2721 | if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&(vsm->successor),&my_identity))) |
2521 | if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&(vsm->successor), | ||
2522 | &my_identity))) | ||
2523 | { | 2722 | { |
2524 | struct GNUNET_CONTAINER_MultiPeerMapIterator *finger_iter; | ||
2525 | struct GNUNET_PeerIdentity key_ret; | ||
2526 | unsigned int finger_index; | ||
2527 | struct FingerInfo *my_predecessor; | 2723 | struct FingerInfo *my_predecessor; |
2528 | struct GNUNET_PeerIdentity *destination_peer; | 2724 | current_trail_index = trail_length - 1; |
2529 | 2725 | if (current_trail_index == 0) | |
2530 | /* Iterate over finger peer map and extract your predecessor. */ | 2726 | memcpy (next_hop, source_peer, sizeof (struct GNUNET_PeerIdentity)); |
2531 | finger_iter = GNUNET_CONTAINER_multipeermap_iterator_create (finger_peermap); | 2727 | else |
2532 | for (finger_index = 0; finger_index < GNUNET_CONTAINER_multipeermap_size (finger_peermap); finger_index++) | 2728 | memcpy (next_hop, &trail_peer_list[current_trail_index-1], sizeof (struct GNUNET_PeerIdentity)); |
2533 | { | ||
2534 | if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next | ||
2535 | (finger_iter,&key_ret,(const void **)&my_predecessor)) | ||
2536 | { | ||
2537 | if(1 == my_predecessor->finger_map_index) | ||
2538 | { | ||
2539 | break; | ||
2540 | } | ||
2541 | } | ||
2542 | } | ||
2543 | GNUNET_CONTAINER_multipeermap_iterator_destroy (finger_iter); | ||
2544 | 2729 | ||
2545 | destination_peer = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); | ||
2546 | memcpy (destination_peer, source_peer, sizeof (struct GNUNET_PeerIdentity)); | ||
2547 | current_trail_index = trail_length - 2; | ||
2548 | memcpy (next_hop, &trail_peer_list[current_trail_index], sizeof (struct GNUNET_PeerIdentity)); | ||
2549 | target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop); | 2730 | target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop); |
2550 | GNUNET_free (next_hop); | 2731 | GNUNET_free (next_hop); |
2551 | 2732 | ||
2552 | if (current_trail_index != 0) | 2733 | my_predecessor = get_predecessor(); |
2553 | current_trail_index = current_trail_index - 1; | 2734 | if (0 == (GNUNET_CRYPTO_cmp_peer_identity (source_peer, |
2554 | 2735 | &(my_predecessor->finger_identity)))) | |
2555 | /*SUPU: Remove this later*/ | ||
2556 | struct GNUNET_PeerIdentity *predecessor; | ||
2557 | predecessor = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); | ||
2558 | if (NULL == my_predecessor) | ||
2559 | { | 2736 | { |
2560 | /* FIXME: Ideally my_predecessor should not be NULL. If some one sent | 2737 | GDS_NEIGHBOURS_send_verify_successor_result (source_peer, |
2561 | me a request to verify it I am the successor or not, then I would have | ||
2562 | added that peer to my_predecessor list. Check trail setup and see if | ||
2563 | you are adding predecessor when you get the request for successor. */ | ||
2564 | #if 0 | ||
2565 | update_predecessor (source_peer, trail_peer_list, trail_length); | ||
2566 | |||
2567 | GDS_NEIGHBOURS_send_verify_successor_result (destination_peer, | ||
2568 | &(my_identity), | 2738 | &(my_identity), |
2569 | source_peer, | 2739 | &(my_predecessor->finger_identity), |
2570 | target_friend, | 2740 | target_friend, |
2571 | trail_peer_list, | 2741 | trail_peer_list, |
2572 | trail_length, | 2742 | trail_length, |
2573 | current_trail_index); | 2743 | current_trail_index); |
2574 | #endif | ||
2575 | } | ||
2576 | else | ||
2577 | { | ||
2578 | /* FIXME: some times my_predecssor->finger_identity has no valid value. | ||
2579 | Check why?*/ | ||
2580 | memcpy (predecessor, &(my_predecessor->finger_identity), sizeof (struct GNUNET_PeerIdentity)); | ||
2581 | } | ||
2582 | |||
2583 | if (0 == (GNUNET_CRYPTO_cmp_peer_identity (source_peer, | ||
2584 | &(my_predecessor->finger_identity)))) | ||
2585 | { | ||
2586 | /* SUPU: If source peer is my predecessor .*/ | ||
2587 | GDS_NEIGHBOURS_send_verify_successor_result (destination_peer, | ||
2588 | &(my_identity), | ||
2589 | &(my_predecessor->finger_identity), | ||
2590 | target_friend, | ||
2591 | trail_peer_list, | ||
2592 | trail_length, | ||
2593 | current_trail_index); | ||
2594 | } | 2744 | } |
2595 | else | 2745 | else |
2596 | { | 2746 | { |
@@ -2598,18 +2748,12 @@ handle_dht_p2p_verify_successor(void *cls, const struct GNUNET_PeerIdentity *pee | |||
2598 | int new_trail_length; | 2748 | int new_trail_length; |
2599 | int i; | 2749 | int i; |
2600 | 2750 | ||
2601 | new_trail_length = trail_length + my_predecessor->trail_length - 1; | 2751 | new_trail_length = trail_length + my_predecessor->trail_length; |
2602 | new_successor_trail = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) | 2752 | new_successor_trail = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * new_trail_length); |
2603 | * new_trail_length); | 2753 | memcpy (new_successor_trail, trail_peer_list, (trail_length) * sizeof (struct GNUNET_PeerIdentity)); |
2604 | |||
2605 | /* Copy the trail from source peer to me. */ | ||
2606 | memcpy (new_successor_trail, trail_peer_list, | ||
2607 | (trail_length) * sizeof (struct GNUNET_PeerIdentity)); | ||
2608 | |||
2609 | /* Copy the trail from me to my predecessor excluding me. */ | ||
2610 | struct TrailPeerList *iterator; | 2754 | struct TrailPeerList *iterator; |
2611 | iterator = GNUNET_malloc (sizeof (struct TrailPeerList)); | 2755 | iterator = GNUNET_malloc (sizeof (struct TrailPeerList)); |
2612 | iterator = my_predecessor->head->next; | 2756 | iterator = my_predecessor->head; |
2613 | i = trail_length; | 2757 | i = trail_length; |
2614 | while (i < new_trail_length) | 2758 | while (i < new_trail_length) |
2615 | { | 2759 | { |
@@ -2618,27 +2762,25 @@ handle_dht_p2p_verify_successor(void *cls, const struct GNUNET_PeerIdentity *pee | |||
2618 | i++; | 2762 | i++; |
2619 | } | 2763 | } |
2620 | 2764 | ||
2621 | GDS_NEIGHBOURS_send_verify_successor_result (destination_peer, | 2765 | GDS_NEIGHBOURS_send_verify_successor_result (source_peer, |
2622 | &(my_identity), | 2766 | &(my_identity), |
2623 | &(my_predecessor->finger_identity), | 2767 | &(my_predecessor->finger_identity), |
2624 | target_friend, | 2768 | target_friend, |
2625 | new_successor_trail, | 2769 | new_successor_trail, |
2626 | new_trail_length, | 2770 | new_trail_length, |
2627 | current_trail_index); | 2771 | current_trail_index); |
2628 | } | 2772 | } |
2629 | 2773 | ||
2630 | } | 2774 | } |
2631 | else | 2775 | else |
2632 | { | 2776 | { |
2633 | /* If I am not the destination. */ | 2777 | current_trail_index = current_trail_index + 1; |
2634 | memcpy (next_hop, &trail_peer_list[current_trail_index], sizeof (struct GNUNET_PeerIdentity)); | 2778 | memcpy (next_hop, &trail_peer_list[current_trail_index], sizeof (struct GNUNET_PeerIdentity)); |
2635 | target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop); | 2779 | target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop); |
2636 | GNUNET_free (next_hop); | 2780 | GNUNET_free (next_hop); |
2637 | 2781 | ||
2638 | current_trail_index = current_trail_index + 1; | 2782 | GDS_NEIGHBOURS_send_verify_successor (source_peer, &(vsm->successor),target_friend, |
2639 | 2783 | trail_peer_list, trail_length, current_trail_index); | |
2640 | GDS_NEIGHBOURS_send_verify_successor(source_peer, &(vsm->successor),target_friend, | ||
2641 | trail_peer_list, trail_length, current_trail_index); | ||
2642 | } | 2784 | } |
2643 | return GNUNET_YES; | 2785 | return GNUNET_YES; |
2644 | } | 2786 | } |
@@ -2671,10 +2813,9 @@ handle_dht_p2p_notify_new_successor(void *cls, const struct GNUNET_PeerIdentity | |||
2671 | nsm = (struct PeerNotifyNewSuccessorMessage *) message; | 2813 | nsm = (struct PeerNotifyNewSuccessorMessage *) message; |
2672 | trail_length = ntohl (nsm->trail_length); | 2814 | trail_length = ntohl (nsm->trail_length); |
2673 | 2815 | ||
2674 | if ((msize < | 2816 | if ((msize < sizeof (struct PeerNotifyNewSuccessorMessage) + |
2675 | sizeof (struct PeerNotifyNewSuccessorMessage) + | 2817 | trail_length * sizeof (struct GNUNET_PeerIdentity)) || |
2676 | trail_length * sizeof (struct GNUNET_PeerIdentity)) || | 2818 | (trail_length > |
2677 | (trail_length > | ||
2678 | GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity))) | 2819 | GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity))) |
2679 | { | 2820 | { |
2680 | GNUNET_break_op (0); | 2821 | GNUNET_break_op (0); |
@@ -2684,38 +2825,25 @@ handle_dht_p2p_notify_new_successor(void *cls, const struct GNUNET_PeerIdentity | |||
2684 | current_trail_index = ntohl (nsm->current_index); | 2825 | current_trail_index = ntohl (nsm->current_index); |
2685 | trail_peer_list = (struct GNUNET_PeerIdentity *) &nsm[1]; | 2826 | trail_peer_list = (struct GNUNET_PeerIdentity *) &nsm[1]; |
2686 | 2827 | ||
2687 | if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&(nsm->destination_peer), | 2828 | if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&(nsm->destination_peer), &my_identity))) |
2688 | &my_identity))) | ||
2689 | { | 2829 | { |
2690 | struct GNUNET_PeerIdentity *new_trail; | 2830 | struct GNUNET_PeerIdentity *new_trail; |
2691 | int i; | 2831 | new_trail = invert_trail_list (&(nsm->source_peer), trail_peer_list, trail_length); |
2692 | int j; | 2832 | finger_table_add (&(nsm->source_peer), new_trail, trail_length, 1); |
2693 | |||
2694 | i = trail_length - 1; | ||
2695 | j = 0; | ||
2696 | new_trail = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * | ||
2697 | trail_length); | ||
2698 | while (i > 0) | ||
2699 | { | ||
2700 | memcpy( &new_trail[j], &trail_peer_list[i], sizeof (struct GNUNET_PeerIdentity)); | ||
2701 | i--; | ||
2702 | j++; | ||
2703 | } | ||
2704 | memcpy (&new_trail[j], &trail_peer_list[i], sizeof(struct GNUNET_PeerIdentity)); | ||
2705 | finger_table_add (&(nsm->source_peer), new_trail, trail_length, 1); | ||
2706 | |||
2707 | return GNUNET_YES; | 2833 | return GNUNET_YES; |
2708 | } | 2834 | } |
2709 | else | 2835 | else |
2710 | { | 2836 | { |
2711 | struct FriendInfo *target_friend; | 2837 | struct FriendInfo *target_friend; |
2712 | target_friend = GNUNET_malloc (sizeof (struct FriendInfo)); | ||
2713 | struct GNUNET_PeerIdentity *next_hop; | 2838 | struct GNUNET_PeerIdentity *next_hop; |
2839 | |||
2840 | target_friend = GNUNET_malloc (sizeof (struct FriendInfo)); | ||
2714 | next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); | 2841 | next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); |
2842 | |||
2843 | current_trail_index = current_trail_index + 1; | ||
2715 | memcpy (next_hop, &trail_peer_list[current_trail_index], sizeof (struct GNUNET_PeerIdentity)); | 2844 | memcpy (next_hop, &trail_peer_list[current_trail_index], sizeof (struct GNUNET_PeerIdentity)); |
2716 | target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop); | 2845 | target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop); |
2717 | GNUNET_free (next_hop); | 2846 | GNUNET_free (next_hop); |
2718 | current_trail_index = current_trail_index + 1; | ||
2719 | 2847 | ||
2720 | GDS_NEIGHBOURS_send_notify_new_successor (&(nsm->source_peer), | 2848 | GDS_NEIGHBOURS_send_notify_new_successor (&(nsm->source_peer), |
2721 | &(nsm->destination_peer), | 2849 | &(nsm->destination_peer), |
@@ -2768,17 +2896,15 @@ handle_dht_p2p_verify_successor_result(void *cls, const struct GNUNET_PeerIdenti | |||
2768 | current_trail_index = ntohl (vsrm->current_index); | 2896 | current_trail_index = ntohl (vsrm->current_index); |
2769 | trail_peer_list = (struct GNUNET_PeerIdentity *) &vsrm[1]; | 2897 | trail_peer_list = (struct GNUNET_PeerIdentity *) &vsrm[1]; |
2770 | 2898 | ||
2771 | if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&(vsrm->destination_peer), | 2899 | if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&(vsrm->destination_peer), &(my_identity)))) |
2772 | &(my_identity)))) | ||
2773 | { | 2900 | { |
2774 | if(0 != (GNUNET_CRYPTO_cmp_peer_identity (&(vsrm->my_predecessor), | 2901 | if(0 != (GNUNET_CRYPTO_cmp_peer_identity (&(vsrm->my_predecessor), &(my_identity)))) |
2775 | &(my_identity)))) | ||
2776 | { | 2902 | { |
2777 | finger_table_add (&(vsrm->my_predecessor), trail_peer_list, trail_length, 0); | 2903 | finger_table_add (&(vsrm->my_predecessor), trail_peer_list, trail_length, 0); |
2778 | next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); | 2904 | next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); |
2779 | memcpy (next_hop, &trail_peer_list[1], sizeof (struct GNUNET_PeerIdentity)); | 2905 | memcpy (next_hop, &trail_peer_list[0], sizeof (struct GNUNET_PeerIdentity)); |
2780 | target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop); | 2906 | target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop); |
2781 | current_trail_index = 2; | 2907 | current_trail_index = 0; |
2782 | GNUNET_free (next_hop); | 2908 | GNUNET_free (next_hop); |
2783 | 2909 | ||
2784 | GDS_NEIGHBOURS_send_notify_new_successor (&my_identity, &(vsrm->my_predecessor), | 2910 | GDS_NEIGHBOURS_send_notify_new_successor (&my_identity, &(vsrm->my_predecessor), |
@@ -2789,10 +2915,13 @@ handle_dht_p2p_verify_successor_result(void *cls, const struct GNUNET_PeerIdenti | |||
2789 | else | 2915 | else |
2790 | { | 2916 | { |
2791 | next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); | 2917 | next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); |
2792 | memcpy (next_hop, &trail_peer_list[current_trail_index], sizeof (struct GNUNET_PeerIdentity)); | 2918 | current_trail_index = current_trail_index - 1; |
2919 | if (current_trail_index == 0) | ||
2920 | memcpy (next_hop, &(vsrm->destination_peer), sizeof (struct GNUNET_PeerIdentity)); | ||
2921 | else | ||
2922 | memcpy (next_hop, &trail_peer_list[current_trail_index-1], sizeof (struct GNUNET_PeerIdentity)); | ||
2793 | target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop); | 2923 | target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop); |
2794 | GNUNET_free (next_hop); | 2924 | GNUNET_free (next_hop); |
2795 | current_trail_index = current_trail_index - 1; | ||
2796 | 2925 | ||
2797 | GDS_NEIGHBOURS_send_verify_successor_result (&(vsrm->destination_peer), | 2926 | GDS_NEIGHBOURS_send_verify_successor_result (&(vsrm->destination_peer), |
2798 | &(vsrm->source_successor), | 2927 | &(vsrm->source_successor), |
@@ -2825,9 +2954,6 @@ GDS_NEIGHBOURS_init() | |||
2825 | {NULL, 0, 0} | 2954 | {NULL, 0, 0} |
2826 | }; | 2955 | }; |
2827 | 2956 | ||
2828 | |||
2829 | /*TODO: What is ATS? Why do we need it? */ | ||
2830 | atsAPI = GNUNET_ATS_performance_init (GDS_cfg, NULL, NULL); | ||
2831 | core_api = | 2957 | core_api = |
2832 | GNUNET_CORE_connect (GDS_cfg, NULL, &core_init, &handle_core_connect, | 2958 | GNUNET_CORE_connect (GDS_cfg, NULL, &core_init, &handle_core_connect, |
2833 | &handle_core_disconnect, NULL, GNUNET_NO, NULL, | 2959 | &handle_core_disconnect, NULL, GNUNET_NO, NULL, |
@@ -2853,14 +2979,11 @@ GDS_NEIGHBOURS_done () | |||
2853 | 2979 | ||
2854 | GNUNET_CORE_disconnect (core_api); | 2980 | GNUNET_CORE_disconnect (core_api); |
2855 | core_api = NULL; | 2981 | core_api = NULL; |
2856 | GNUNET_ATS_performance_done (atsAPI); | 2982 | |
2857 | atsAPI = NULL; | ||
2858 | |||
2859 | GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (friend_peermap)); | 2983 | GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (friend_peermap)); |
2860 | GNUNET_CONTAINER_multipeermap_destroy (friend_peermap); | 2984 | GNUNET_CONTAINER_multipeermap_destroy (friend_peermap); |
2861 | friend_peermap = NULL; | 2985 | friend_peermap = NULL; |
2862 | 2986 | ||
2863 | |||
2864 | GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (finger_peermap)); | 2987 | GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (finger_peermap)); |
2865 | GNUNET_CONTAINER_multipeermap_destroy (finger_peermap); | 2988 | GNUNET_CONTAINER_multipeermap_destroy (finger_peermap); |
2866 | finger_peermap = NULL; | 2989 | finger_peermap = NULL; |
@@ -2870,8 +2993,7 @@ GDS_NEIGHBOURS_done () | |||
2870 | GNUNET_SCHEDULER_cancel (find_finger_trail_task); | 2993 | GNUNET_SCHEDULER_cancel (find_finger_trail_task); |
2871 | find_finger_trail_task = GNUNET_SCHEDULER_NO_TASK; | 2994 | find_finger_trail_task = GNUNET_SCHEDULER_NO_TASK; |
2872 | } | 2995 | } |
2873 | 2996 | ||
2874 | |||
2875 | if (GNUNET_SCHEDULER_NO_TASK != verify_successor) | 2997 | if (GNUNET_SCHEDULER_NO_TASK != verify_successor) |
2876 | { | 2998 | { |
2877 | GNUNET_SCHEDULER_cancel (verify_successor); | 2999 | GNUNET_SCHEDULER_cancel (verify_successor); |
diff --git a/src/dht/gnunet-service-xdht_neighbours.h b/src/dht/gnunet-service-xdht_neighbours.h index da5629ffb..8e0fce225 100644 --- a/src/dht/gnunet-service-xdht_neighbours.h +++ b/src/dht/gnunet-service-xdht_neighbours.h | |||
@@ -68,12 +68,12 @@ GDS_NEIGHBOURS_handle_put (enum GNUNET_BLOCK_Type type, | |||
68 | uint32_t desired_replication_level, | 68 | uint32_t desired_replication_level, |
69 | struct GNUNET_TIME_Absolute expiration_time, | 69 | struct GNUNET_TIME_Absolute expiration_time, |
70 | uint32_t hop_count, | 70 | uint32_t hop_count, |
71 | struct GNUNET_HashCode * key, | 71 | const struct GNUNET_HashCode * key, |
72 | unsigned int put_path_length, | 72 | unsigned int put_path_length, |
73 | struct GNUNET_PeerIdentity *put_path, | 73 | struct GNUNET_PeerIdentity *put_path, |
74 | const void *data, size_t data_size, | 74 | const void *data, size_t data_size, |
75 | struct GNUNET_PeerIdentity *current_destination, | 75 | struct GNUNET_PeerIdentity *current_destination, |
76 | enum current_destination_type *dest_type, | 76 | enum current_destination_type dest_type, |
77 | struct GNUNET_PeerIdentity *target_peer_id); | 77 | struct GNUNET_PeerIdentity *target_peer_id); |
78 | 78 | ||
79 | 79 | ||
@@ -94,18 +94,25 @@ GDS_NEIGHBOURS_handle_get (struct GNUNET_PeerIdentity *source_peer, | |||
94 | enum current_destination_type *type); | 94 | enum current_destination_type *type); |
95 | 95 | ||
96 | /** | 96 | /** |
97 | * | 97 | * Send get result back to requesting client. |
98 | * @param source_peer | 98 | * @param source_peer |
99 | * @param get_path | 99 | * @param get_path |
100 | * @param get_path_length | 100 | * @param get_path_length |
101 | * @param key | ||
101 | * @param destination_peer | 102 | * @param destination_peer |
103 | * @param current_path_index | ||
104 | * @param data | ||
105 | * @param data_size | ||
102 | */ | 106 | */ |
103 | void | 107 | void |
104 | GDS_NEIGHBOURS_send_get_result (struct GNUNET_PeerIdentity *source_peer, | 108 | GDS_NEIGHBOURS_send_get_result (struct GNUNET_PeerIdentity *source_peer, |
105 | struct GNUNET_PeerIdentity *get_path, | 109 | struct GNUNET_PeerIdentity *get_path, |
106 | unsigned int get_path_length, | 110 | unsigned int get_path_length, |
111 | struct GNUNET_HashCode *key, | ||
107 | struct GNUNET_PeerIdentity *destination_peer, | 112 | struct GNUNET_PeerIdentity *destination_peer, |
108 | unsigned int current_path_index); | 113 | unsigned int current_path_index, |
114 | const void *data, size_t data_size, | ||
115 | struct GNUNET_PeerIdentity *next_peer); | ||
109 | 116 | ||
110 | 117 | ||
111 | /** | 118 | /** |
diff --git a/src/dht/gnunet-service-xdht_routing.c b/src/dht/gnunet-service-xdht_routing.c index 55ef1f4b2..f7e56c115 100644 --- a/src/dht/gnunet-service-xdht_routing.c +++ b/src/dht/gnunet-service-xdht_routing.c | |||
@@ -34,9 +34,12 @@ | |||
34 | */ | 34 | */ |
35 | #define DHT_MAX_RECENT (1024 * 16) | 35 | #define DHT_MAX_RECENT (1024 * 16) |
36 | 36 | ||
37 | /** | ||
38 | * Maximum number of entries in routing table. | ||
39 | */ | ||
40 | #define ROUTING_TABLE_THRESHOLD 64 | ||
37 | 41 | ||
38 | /** | 42 | /** |
39 | * FIXME: Do we need a field prev_hop | ||
40 | * Routing table entry . | 43 | * Routing table entry . |
41 | */ | 44 | */ |
42 | struct RoutingTrail | 45 | struct RoutingTrail |
@@ -56,6 +59,11 @@ struct RoutingTrail | |||
56 | */ | 59 | */ |
57 | struct GNUNET_PeerIdentity next_hop; | 60 | struct GNUNET_PeerIdentity next_hop; |
58 | 61 | ||
62 | /** | ||
63 | * Peer just before next hop in the trail. | ||
64 | */ | ||
65 | struct GNUNET_PeerIdentity prev_hop; | ||
66 | |||
59 | }; | 67 | }; |
60 | 68 | ||
61 | 69 | ||
@@ -66,56 +74,91 @@ static struct GNUNET_CONTAINER_MultiPeerMap *routing_table; | |||
66 | 74 | ||
67 | 75 | ||
68 | /** | 76 | /** |
69 | * FIXME: Change the name of variable. | ||
70 | * Ensure that everywhere in this file you are using destination as the key. | ||
71 | * Do we need prev field in routing table? | ||
72 | * Add a new entry to our routing table. | 77 | * Add a new entry to our routing table. |
73 | * @param source peer | 78 | * @param source peer Source of the trail. |
74 | * @param destintation | 79 | * @param destintation Destination of the trail. |
75 | * @param next_hop | 80 | * @param next_hop Next peer to forward the message to reach the destination. |
81 | * @return GNUNET_YES | ||
82 | * GNUNET_SYSERR If the number of routing entries crossed thershold. | ||
76 | */ | 83 | */ |
77 | void | 84 | int |
78 | GDS_ROUTING_add (struct GNUNET_PeerIdentity *source, | 85 | GDS_ROUTING_add (struct GNUNET_PeerIdentity *source, |
79 | struct GNUNET_PeerIdentity *dest, | 86 | struct GNUNET_PeerIdentity *dest, |
80 | struct GNUNET_PeerIdentity *next_hop) | 87 | struct GNUNET_PeerIdentity *next_hop, |
88 | const struct GNUNET_PeerIdentity *prev_hop) | ||
81 | { | 89 | { |
82 | struct RoutingTrail *new_routing_entry; | 90 | struct RoutingTrail *new_routing_entry; |
83 | 91 | ||
84 | /* If dest is already present in the routing table, then exit.*/ | 92 | if (GNUNET_CONTAINER_multipeermap_size(routing_table) > ROUTING_TABLE_THRESHOLD) |
85 | if (GNUNET_YES == | 93 | return GNUNET_SYSERR; |
86 | GNUNET_CONTAINER_multipeermap_contains (routing_table, dest)) | 94 | //FPRINTF (stderr,_("\nSUPU ROUTING ADD %s, %s, %d"),__FILE__, __func__,__LINE__); |
87 | { | ||
88 | GNUNET_break (0); | ||
89 | return; | ||
90 | } | ||
91 | |||
92 | new_routing_entry = GNUNET_malloc (sizeof (struct RoutingTrail)); | 95 | new_routing_entry = GNUNET_malloc (sizeof (struct RoutingTrail)); |
93 | memcpy (&(new_routing_entry->source) , source, sizeof (struct GNUNET_PeerIdentity)); | 96 | memcpy (&(new_routing_entry->source) , source, sizeof (struct GNUNET_PeerIdentity)); |
94 | memcpy (&(new_routing_entry->next_hop), next_hop, sizeof (struct GNUNET_PeerIdentity)); | 97 | memcpy (&(new_routing_entry->next_hop), next_hop, sizeof (struct GNUNET_PeerIdentity)); |
95 | memcpy (&(new_routing_entry->destination), dest, sizeof (struct GNUNET_PeerIdentity)); | 98 | memcpy (&(new_routing_entry->destination), dest, sizeof (struct GNUNET_PeerIdentity)); |
99 | memcpy (&(new_routing_entry->prev_hop), prev_hop, sizeof (struct GNUNET_PeerIdentity)); | ||
96 | 100 | ||
97 | GNUNET_assert (GNUNET_OK == | 101 | GNUNET_assert (GNUNET_OK == |
98 | GNUNET_CONTAINER_multipeermap_put (routing_table, | 102 | GNUNET_CONTAINER_multipeermap_put (routing_table, |
99 | dest, new_routing_entry, | 103 | dest, new_routing_entry, |
100 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | 104 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); |
105 | return GNUNET_YES; | ||
101 | } | 106 | } |
102 | 107 | ||
103 | 108 | ||
104 | /**FIXME: Test if its correct or not. | 109 | /** |
105 | * Find the next hop to send packet to . | 110 | * Iterate over multiple entries for same destinational value and get |
106 | * @return next hop peer id | 111 | * the correct next hop. |
112 | * @param cls struct RoutingTrail | ||
113 | * @param key Destination identity | ||
114 | * @param value struct RoutingTrail | ||
115 | * @return #GNUNET_YES to continue looking, #GNUNET_NO if we found the next hop | ||
116 | */ | ||
117 | int | ||
118 | get_next_hop (void *cls, const struct GNUNET_PeerIdentity *key, void *value) | ||
119 | { | ||
120 | /* Here you should match if source, prev hop matches if yes then send | ||
121 | GNUNET_NO as you don't need to check more entries. */ | ||
122 | struct RoutingTrail *request = cls; | ||
123 | struct RoutingTrail *existing_entry = (struct RoutingTrail *)value; | ||
124 | |||
125 | if (0 == GNUNET_CRYPTO_cmp_peer_identity (&(request->source), &(existing_entry->source))) | ||
126 | { | ||
127 | if (0 == GNUNET_CRYPTO_cmp_peer_identity (&(request->prev_hop), &(existing_entry->prev_hop))) | ||
128 | { | ||
129 | memcpy (&(request->next_hop), &(existing_entry->next_hop), sizeof (struct GNUNET_PeerIdentity)); | ||
130 | return GNUNET_YES; | ||
131 | } | ||
132 | } | ||
133 | return GNUNET_NO; | ||
134 | } | ||
135 | |||
136 | |||
137 | /** | ||
138 | * Find the next hop to send packet to. | ||
139 | * @param source_peer Source of the trail. | ||
140 | * @param destination_peer Destination of the trail. | ||
141 | * @param prev_hop Previous hop in the trail. | ||
142 | * @return Next hop in the trail from source to destination. | ||
107 | */ | 143 | */ |
108 | struct GNUNET_PeerIdentity * | 144 | struct GNUNET_PeerIdentity * |
109 | GDS_ROUTING_search(struct GNUNET_PeerIdentity *source_peer, | 145 | GDS_ROUTING_search(struct GNUNET_PeerIdentity *source_peer, |
110 | struct GNUNET_PeerIdentity *destination_peer) | 146 | struct GNUNET_PeerIdentity *destination_peer, |
147 | const struct GNUNET_PeerIdentity *prev_hop) | ||
111 | { | 148 | { |
112 | struct RoutingTrail *trail; | 149 | struct RoutingTrail *trail; |
113 | trail = (struct RoutingTrail *)(GNUNET_CONTAINER_multipeermap_get(routing_table,destination_peer)); | 150 | trail = GNUNET_malloc (sizeof (struct RoutingTrail)); |
114 | 151 | memcpy (&(trail->destination), destination_peer, sizeof (struct GNUNET_PeerIdentity)); | |
115 | if(trail == NULL) | 152 | memcpy (&(trail->source), source_peer, sizeof (struct GNUNET_PeerIdentity)); |
116 | return NULL; | 153 | memcpy (&(trail->prev_hop), prev_hop, sizeof (struct GNUNET_PeerIdentity)); |
117 | 154 | //trail->next_hop = NULL; | |
118 | return &(trail->next_hop); | 155 | //FPRINTF (stderr,_("\nSUPU ROUTING SEARCH %s, %s, %d"),__FILE__, __func__,__LINE__); |
156 | GNUNET_CONTAINER_multipeermap_get_multiple (routing_table, destination_peer, | ||
157 | get_next_hop, trail); | ||
158 | if(trail != NULL) | ||
159 | return &(trail->next_hop); | ||
160 | else | ||
161 | return NULL; | ||
119 | } | 162 | } |
120 | 163 | ||
121 | 164 | ||
diff --git a/src/dht/gnunet-service-xdht_routing.h b/src/dht/gnunet-service-xdht_routing.h index 44cb07389..92ca5f4f4 100644 --- a/src/dht/gnunet-service-xdht_routing.h +++ b/src/dht/gnunet-service-xdht_routing.h | |||
@@ -34,10 +34,11 @@ | |||
34 | /** | 34 | /** |
35 | * Add a new entry to our routing table. | 35 | * Add a new entry to our routing table. |
36 | */ | 36 | */ |
37 | void | 37 | int |
38 | GDS_ROUTING_add (struct GNUNET_PeerIdentity *source, | 38 | GDS_ROUTING_add (struct GNUNET_PeerIdentity *source, |
39 | struct GNUNET_PeerIdentity *destination_peer, | 39 | struct GNUNET_PeerIdentity *destination_peer, |
40 | struct GNUNET_PeerIdentity *next_hop); | 40 | struct GNUNET_PeerIdentity *next_hop, |
41 | const struct GNUNET_PeerIdentity *prev_hop); | ||
41 | 42 | ||
42 | 43 | ||
43 | /** | 44 | /** |
@@ -46,7 +47,8 @@ GDS_ROUTING_add (struct GNUNET_PeerIdentity *source, | |||
46 | */ | 47 | */ |
47 | struct GNUNET_PeerIdentity * | 48 | struct GNUNET_PeerIdentity * |
48 | GDS_ROUTING_search(struct GNUNET_PeerIdentity *source_peer, | 49 | GDS_ROUTING_search(struct GNUNET_PeerIdentity *source_peer, |
49 | struct GNUNET_PeerIdentity *destination_peer); | 50 | struct GNUNET_PeerIdentity *destination_peer, |
51 | const struct GNUNET_PeerIdentity *prev_hop); | ||
50 | 52 | ||
51 | /** | 53 | /** |
52 | * Handle a reply (route to origin). Only forwards the reply back to | 54 | * Handle a reply (route to origin). Only forwards the reply back to |