fix recursive message sending (last first causes issues)
[oweals/gnunet.git] / src / dv / gnunet-service-dv.c
1 /*
2      This file is part of GNUnet.
3      (C) 2009 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 2, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * @file dv/gnunet-service-dv.c
23  * @brief the distance vector service, primarily handles gossip of nearby
24  * peers and sending/receiving DV messages from core and decapsulating
25  * them
26  *
27  * @author Christian Grothoff
28  * @author Nathan Evans
29  *
30  * TODO: The gossip rates need to be worked out.  Probably many other things
31  * as well.
32  *
33  */
34 #include "platform.h"
35 #include "gnunet_client_lib.h"
36 #include "gnunet_getopt_lib.h"
37 #include "gnunet_os_lib.h"
38 #include "gnunet_protocols.h"
39 #include "gnunet_service_lib.h"
40 #include "gnunet_core_service.h"
41 #include "gnunet_signal_lib.h"
42 #include "gnunet_util_lib.h"
43 #include "gnunet_hello_lib.h"
44 #include "gnunet_peerinfo_service.h"
45 #include "gnunet_crypto_lib.h"
46 #include "dv.h"
47
48 /**
49  * For testing mostly, remember only the
50  * shortest path to a distant neighbor.
51  */
52 #define AT_MOST_ONE GNUNET_NO
53
54 #define USE_PEER_ID GNUNET_YES
55
56 /**
57  * How often do we check about sending out more peer information (if
58  * we are connected to no peers previously).
59  */
60 #define GNUNET_DV_DEFAULT_SEND_INTERVAL GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 500000)
61
62 /**
63  * How long do we wait at most between sending out information?
64  */
65 #define GNUNET_DV_MAX_SEND_INTERVAL GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 500000)
66
67 /**
68  * How long can we have not heard from a peer and
69  * still have it in our tables?
70  */
71 #define GNUNET_DV_PEER_EXPIRATION_TIME GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 1000))
72
73 /**
74  * Priority for gossip.
75  */
76 #define GNUNET_DV_DHT_GOSSIP_PRIORITY (GNUNET_EXTREME_PRIORITY / 10)
77
78 /**
79  * How often should we check if expiration time has elapsed for
80  * some peer?
81  */
82 #define GNUNET_DV_MAINTAIN_FREQUENCY GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5))
83
84 /**
85  * How long to allow a message to be delayed?
86  */
87 #define DV_DELAY GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5))
88
89 /**
90  * Priority to use for DV data messages.
91  */
92 #define DV_PRIORITY 0
93
94 /**
95  * The cost to a direct neighbor.  We used to use 0, but 1 makes more sense.
96  */
97 #define DIRECT_NEIGHBOR_COST 1
98
99 /**
100  * The default number of direct connections to store in DV (max)
101  */
102 #define DEFAULT_DIRECT_CONNECTIONS 50
103
104 /**
105  * The default size of direct + extended peers in DV (max)
106  */
107 #define DEFAULT_DV_SIZE 100
108
109 /**
110  * The default fisheye depth, from how many hops away will
111  * we keep peers?
112  */
113 #define DEFAULT_FISHEYE_DEPTH 4
114
115 /**
116  * Linked list of messages to send to clients.
117  */
118 struct PendingMessage
119 {
120   /**
121    * Pointer to next item in the list
122    */
123   struct PendingMessage *next;
124
125   /**
126    * Pointer to previous item in the list
127    */
128   struct PendingMessage *prev;
129
130   /**
131    * The PeerIdentity to send to
132    */
133   struct GNUNET_PeerIdentity recipient;
134
135   /**
136    * The result of message sending.
137    */
138   struct GNUNET_DV_SendResultMessage *send_result;
139
140   /**
141    * Message importance level.
142    */
143   unsigned int importance;
144
145   /**
146    * Size of message.
147    */
148   unsigned int msg_size;
149
150   /**
151    * How long to wait before sending message.
152    */
153   struct GNUNET_TIME_Relative timeout;
154
155   /**
156    * Actual message to be sent; // avoid allocation
157    */
158   const struct GNUNET_MessageHeader *msg; // msg = (cast) &pm[1]; // memcpy (&pm[1], data, len);
159
160 };
161
162 struct FastGossipNeighborList
163 {
164   /**
165    * Next element of DLL
166    */
167   struct FastGossipNeighborList *next;
168
169   /**
170    * Prev element of DLL
171    */
172   struct FastGossipNeighborList *prev;
173
174   /**
175    * The neighbor to gossip about
176    */
177   struct DistantNeighbor *about;
178 };
179
180 /**
181  * Context created whenever a direct peer connects to us,
182  * used to gossip other peers to it.
183  */
184 struct NeighborSendContext
185 {
186   /**
187    * The peer we will gossip to.
188    */
189   struct DirectNeighbor *toNeighbor;
190
191   /**
192    * The task associated with this context.
193    */
194   GNUNET_SCHEDULER_TaskIdentifier task;
195
196   /**
197    * Head of DLL of peers to gossip about
198    * as fast as possible to this peer, for initial
199    * set up.
200    */
201   struct FastGossipNeighborList *fast_gossip_list_head;
202
203   /**
204    * Tail of DLL of peers to gossip about
205    * as fast as possible to this peer, for initial
206    * set up.
207    */
208   struct FastGossipNeighborList *fast_gossip_list_tail;
209
210 };
211
212
213 /**
214  * Struct to hold information for updating existing neighbors
215  */
216 struct NeighborUpdateInfo
217 {
218   /**
219    * Cost
220    */
221   unsigned int cost;
222
223   /**
224    * The existing neighbor
225    */
226   struct DistantNeighbor *neighbor;
227
228   /**
229    * The referrer of the possibly existing peer
230    */
231   struct DirectNeighbor *referrer;
232
233   /**
234    * The time we heard about this peer
235    */
236   struct GNUNET_TIME_Absolute now;
237
238   /**
239    * Peer id this peer uses to refer to neighbor.
240    */
241   unsigned int referrer_peer_id;
242
243 };
244
245 /**
246  * Struct where actual neighbor information is stored,
247  * referenced by min_heap and max_heap.  Freeing dealt
248  * with when items removed from hashmap.
249  */
250 struct DirectNeighbor
251 {
252   /**
253    * Identity of neighbor.
254    */
255   struct GNUNET_PeerIdentity identity;
256
257   /**
258    * PublicKey of neighbor.
259    */
260   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
261
262   /**
263    * Head of DLL of nodes that this direct neighbor referred to us.
264    */
265   struct DistantNeighbor *referee_head;
266
267   /**
268    * Tail of DLL of nodes that this direct neighbor referred to us.
269    */
270   struct DistantNeighbor *referee_tail;
271
272   /**
273    * The sending context for gossiping peers to this neighbor.
274    */
275   struct NeighborSendContext *send_context;
276
277   /**
278    * Is this one of the direct neighbors that we are "hiding"
279    * from DV?
280    */
281   int hidden;
282 };
283
284
285 /**
286  * Struct where actual neighbor information is stored,
287  * referenced by min_heap and max_heap.  Freeing dealt
288  * with when items removed from hashmap.
289  */
290 struct DistantNeighbor
291 {
292   /**
293    * We keep distant neighbor's of the same referrer in a DLL.
294    */
295   struct DistantNeighbor *next;
296
297   /**
298    * We keep distant neighbor's of the same referrer in a DLL.
299    */
300   struct DistantNeighbor *prev;
301
302   /**
303    * Node in min heap
304    */
305   struct GNUNET_CONTAINER_HeapNode *min_loc;
306
307   /**
308    * Node in max heap
309    */
310   struct GNUNET_CONTAINER_HeapNode *max_loc;
311
312   /**
313    * Identity of referrer (next hop towards 'neighbor').
314    */
315   struct DirectNeighbor *referrer;
316
317   /**
318    * Identity of neighbor.
319    */
320   struct GNUNET_PeerIdentity identity;
321
322   /**
323    * PublicKey of neighbor.
324    */
325   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pkey;
326
327   /**
328    * Last time we received routing information from this peer
329    */
330   struct GNUNET_TIME_Absolute last_activity;
331
332   /**
333    * Cost to neighbor, used for actual distance vector computations
334    */
335   unsigned int cost;
336
337   /**
338    * Random identifier *we* use for this peer, to be used as shortcut
339    * instead of sending full peer id for each message
340    */
341   unsigned int our_id;
342
343   /**
344    * Random identifier the *referrer* uses for this peer.
345    */
346   unsigned int referrer_id;
347
348   /**
349    * Is this one of the direct neighbors that we are "hiding"
350    * from DV?
351    */
352   int hidden;
353
354 };
355
356 struct PeerIteratorContext
357 {
358   /**
359    * The actual context, to be freed later.
360    */
361   struct GNUNET_PEERINFO_IteratorContext *ic;
362
363   /**
364    * The neighbor about which we are concerned.
365    */
366   struct DirectNeighbor *neighbor;
367
368   /**
369    * The distant neighbor entry for this direct neighbor.
370    */
371   struct DistantNeighbor *distant;
372
373 };
374
375 /**
376  * Context used for creating hello messages when
377  * gossips are received.
378  */
379 struct HelloContext
380 {
381   /**
382    * Identity of distant neighbor.
383    */
384   struct GNUNET_PeerIdentity distant_peer;
385
386   /**
387    * Identity of direct neighbor, via which we send this message.
388    */
389   const struct GNUNET_PeerIdentity *direct_peer;
390
391   /**
392    * How many addresses do we need to add (always starts at 1, then set to 0)
393    */
394   int addresses_to_add;
395
396 };
397
398 struct DV_SendContext
399 {
400   /**
401    * The distant peer (should always match)
402    */
403   struct GNUNET_PeerIdentity *distant_peer;
404
405   /**
406    * The direct peer, we need to verify the referrer of.
407    */
408   struct GNUNET_PeerIdentity *direct_peer;
409
410   /**
411    * The message to be sent
412    */
413   struct GNUNET_MessageHeader *message;
414
415   /**
416    * The pre-built send result message.  Simply needs to be queued
417    * and freed once send has been called!
418    */
419   struct GNUNET_DV_SendResultMessage *send_result;
420
421   /**
422    * The size of the message being sent, may be larger
423    * than message->header.size because it's multiple
424    * messages packed into one!
425    */
426   size_t message_size;
427
428   /**
429    * How important is this message?
430    */
431   unsigned int importance;
432
433   /**
434    * Timeout for this message
435    */
436   struct GNUNET_TIME_Relative timeout;
437
438   /**
439    * Unique ID for DV message
440    */
441   unsigned int uid;
442 };
443
444 struct FindDestinationContext
445 {
446   unsigned int tid;
447   struct DistantNeighbor *dest;
448 };
449
450 struct FindIDContext
451 {
452   unsigned int tid;
453   struct GNUNET_PeerIdentity *dest;
454   const struct GNUNET_PeerIdentity *via;
455 };
456
457 struct DisconnectContext
458 {
459   /**
460    * Distant neighbor to get pid from.
461    */
462   struct DistantNeighbor *distant;
463
464   /**
465    * Direct neighbor that disconnected.
466    */
467   struct DirectNeighbor *direct;
468 };
469
470 struct TokenizedMessageContext
471 {
472   /**
473    * Immediate sender of this message
474    */
475   const struct GNUNET_PeerIdentity *peer;
476
477   /**
478    * Distant sender of the message
479    */
480   struct DistantNeighbor *distant;
481
482   /**
483    * Uid for this set of messages
484    */
485   uint32_t uid;
486 };
487
488 /**
489  * Context for finding the least cost peer to send to.
490  * Transport selection can only go so far.
491  */
492 struct FindLeastCostContext
493 {
494   struct DistantNeighbor *target;
495   unsigned int least_cost;
496 };
497
498 /**
499  * Handle to the core service api.
500  */
501 static struct GNUNET_CORE_Handle *coreAPI;
502
503 /**
504  * Stream tokenizer to handle messages coming in from core.
505  */
506 static struct GNUNET_SERVER_MessageStreamTokenizer *coreMST;
507
508 /**
509  * The identity of our peer.
510  */
511 static struct GNUNET_PeerIdentity my_identity;
512
513 /**
514  * The configuration for this service.
515  */
516 static const struct GNUNET_CONFIGURATION_Handle *cfg;
517
518 /**
519  * The scheduler for this service.
520  */
521 static struct GNUNET_SCHEDULER_Handle *sched;
522
523 /**
524  * The client, the DV plugin connected to us.  Hopefully
525  * this client will never change, although if the plugin dies
526  * and returns for some reason it may happen.
527  */
528 static struct GNUNET_SERVER_Client * client_handle;
529
530 /**
531  * Task to run when we shut down, cleaning up all our trash
532  */
533 static GNUNET_SCHEDULER_TaskIdentifier cleanup_task;
534
535 static size_t default_dv_priority = 0;
536
537 static char *my_short_id;
538
539 /**
540  * Transmit handle to the plugin.
541  */
542 static struct GNUNET_CONNECTION_TransmitHandle * plugin_transmit_handle;
543
544 /**
545  * Head of DLL for client messages
546  */
547 static struct PendingMessage *plugin_pending_head;
548
549 /**
550  * Tail of DLL for client messages
551  */
552 static struct PendingMessage *plugin_pending_tail;
553
554 /**
555  * Handle to the peerinfo service
556  */
557 static struct GNUNET_PEERINFO_Handle *peerinfo_handle;
558
559 /**
560  * Transmit handle to core service.
561  */
562 static struct GNUNET_CORE_TransmitHandle * core_transmit_handle;
563
564 /**
565  * Head of DLL for core messages
566  */
567 static struct PendingMessage *core_pending_head;
568
569 /**
570  * Tail of DLL for core messages
571  */
572 static struct PendingMessage *core_pending_tail;
573
574 /**
575  * Map of PeerIdentifiers to 'struct GNUNET_dv_neighbor*'s for all
576  * directly connected peers.
577  */
578 static struct GNUNET_CONTAINER_MultiHashMap *direct_neighbors;
579
580 /**
581  * Map of PeerIdentifiers to 'struct GNUNET_dv_neighbor*'s for
582  * peers connected via DV (extended neighborhood).  Does ALSO
583  * include any peers that are in 'direct_neighbors'; for those
584  * peers, the cost will be zero and the referrer all zeros.
585  */
586 static struct GNUNET_CONTAINER_MultiHashMap *extended_neighbors;
587
588 /**
589  * We use the min heap (min refers to cost) to prefer
590  * gossipping about peers with small costs.
591  */
592 static struct GNUNET_CONTAINER_Heap *neighbor_min_heap;
593
594 /**
595  * We use the max heap (max refers to cost) for general
596  * iterations over all peers and to remove the most costly
597  * connection if we have too many.
598  */
599 static struct GNUNET_CONTAINER_Heap *neighbor_max_heap;
600
601 /**
602  * How far out to keep peers we learn about.
603  */
604 static unsigned long long fisheye_depth;
605
606 /**
607  * How many peers to store at most.
608  */
609 static unsigned long long max_table_size;
610
611 /**
612  * We've been given a target ID based on the random numbers that
613  * we assigned to our DV-neighborhood.  Find the entry for the
614  * respective neighbor.
615  */
616 static int
617 find_destination (void *cls,
618                   struct GNUNET_CONTAINER_HeapNode *node,
619                   void *element, GNUNET_CONTAINER_HeapCostType cost)
620 {
621   struct FindDestinationContext *fdc = cls;
622   struct DistantNeighbor *dn = element;
623
624   if (fdc->tid != dn->our_id)
625     return GNUNET_YES;
626   fdc->dest = dn;
627   return GNUNET_NO;
628 }
629
630
631 /**
632  * We've been given a target ID based on the random numbers that
633  * we assigned to our DV-neighborhood.  Find the entry for the
634  * respective neighbor.
635  */
636 static int
637 find_specific_id (void *cls,
638                   const GNUNET_HashCode *key,
639                   void *value)
640 {
641   struct FindIDContext *fdc = cls;
642   struct DistantNeighbor *dn = value;
643
644   if (memcmp(&dn->referrer->identity, fdc->via, sizeof(struct GNUNET_PeerIdentity)) == 0)
645     {
646       fdc->tid = dn->referrer_id;
647       return GNUNET_NO;
648     }
649   return GNUNET_YES;
650 }
651
652 /**
653  * Find a distant peer whose referrer_id matches what we're
654  * looking for.  For looking up a peer we've gossipped about
655  * but is now disconnected.  Need to do this because we don't
656  * want to remove those that may be accessible via a different
657  * route.
658  */
659 static int find_distant_peer (void *cls,
660                               const GNUNET_HashCode * key,
661                               void *value)
662 {
663   struct FindDestinationContext *fdc = cls;
664   struct DistantNeighbor *distant = value;
665
666   if (fdc->tid == distant->referrer_id)
667     {
668       fdc->dest = distant;
669       return GNUNET_NO;
670     }
671   return GNUNET_YES;
672 }
673
674 /**
675  * Function called to notify a client about the socket
676  * begin ready to queue more data.  "buf" will be
677  * NULL and "size" zero if the socket was closed for
678  * writing in the meantime.
679  *
680  * @param cls closure
681  * @param size number of bytes available in buf
682  * @param buf where the callee should write the message
683  * @return number of bytes written to buf
684  */
685 size_t transmit_to_plugin (void *cls,
686                            size_t size, void *buf)
687 {
688   char *cbuf = buf;
689   struct PendingMessage *reply;
690   size_t off;
691   size_t msize;
692
693   if (buf == NULL)
694     {
695       /* client disconnected */
696 #if DEBUG_DV_MESSAGES
697       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s: %s buffer was NULL (client disconnect?)\n", my_short_id, "transmit_to_plugin");
698 #endif
699       return 0;
700     }
701   plugin_transmit_handle = NULL;
702   off = 0;
703   while ( (NULL != (reply = plugin_pending_head)) &&
704           (size >= off + (msize = ntohs (reply->msg->size))))
705     {
706       GNUNET_CONTAINER_DLL_remove (plugin_pending_head,
707                                    plugin_pending_tail,
708                                    reply);
709       memcpy (&cbuf[off], reply->msg, msize);
710       GNUNET_free (reply);
711       off += msize;
712     }
713
714   if (plugin_pending_head != NULL)
715     plugin_transmit_handle = GNUNET_SERVER_notify_transmit_ready (client_handle,
716                                                                   ntohs(plugin_pending_head->msg->size),
717                                                                   GNUNET_TIME_UNIT_FOREVER_REL,
718                                                                   &transmit_to_plugin, NULL);
719
720   return off;
721 }
722
723 /**
724  * Send a message to the dv plugin.
725  *
726  * @param sender the direct sender of the message
727  * @param message the message to send to the plugin
728  *        (may be an encapsulated type)
729  * @param message_size the size of the message to be sent
730  * @param distant_neighbor the original sender of the message
731  * @param cost the cost to the original sender of the message
732  */
733 void send_to_plugin(const struct GNUNET_PeerIdentity * sender,
734                     const struct GNUNET_MessageHeader *message,
735                     size_t message_size,
736                     struct GNUNET_PeerIdentity *distant_neighbor,
737                     size_t cost)
738 {
739   struct GNUNET_DV_MessageReceived *received_msg;
740   struct PendingMessage *pending_message;
741   char *sender_address;
742   size_t sender_address_len;
743   char *packed_msg_start;
744   int size;
745
746 #if DEBUG_DV
747   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "send_to_plugin called with peer %s as sender\n", GNUNET_i2s(distant_neighbor));
748 #endif
749
750   if (memcmp(sender, distant_neighbor, sizeof(struct GNUNET_PeerIdentity)) != 0)
751   {
752     sender_address_len = sizeof(struct GNUNET_PeerIdentity) * 2;
753     sender_address = GNUNET_malloc(sender_address_len);
754     memcpy(sender_address, distant_neighbor, sizeof(struct GNUNET_PeerIdentity));
755     memcpy(&sender_address[sizeof(struct GNUNET_PeerIdentity)], sender, sizeof(struct GNUNET_PeerIdentity));
756   }
757   else
758   {
759     sender_address_len = sizeof(struct GNUNET_PeerIdentity);
760     sender_address = GNUNET_malloc(sender_address_len);
761     memcpy(sender_address, sender, sizeof(struct GNUNET_PeerIdentity));
762   }
763
764   size = sizeof(struct GNUNET_DV_MessageReceived) + sender_address_len + message_size;
765   received_msg = GNUNET_malloc(size);
766   received_msg->header.size = htons(size);
767   received_msg->header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_DV_RECEIVE);
768   received_msg->sender_address_len = htonl(sender_address_len);
769   received_msg->distance = htonl(cost);
770   received_msg->msg_len = htonl(message_size);
771   /* Set the sender in this message to be the original sender! */
772   memcpy(&received_msg->sender, distant_neighbor, sizeof(struct GNUNET_PeerIdentity));
773   /* Copy the intermediate sender to the end of the message, this is how the transport identifies this peer */
774   memcpy(&received_msg[1], sender_address, sender_address_len);
775   GNUNET_free(sender_address);
776   /* Copy the actual message after the sender */
777   packed_msg_start = (char *)&received_msg[1];
778   packed_msg_start = &packed_msg_start[sender_address_len];
779   memcpy(packed_msg_start, message, message_size);
780   pending_message = GNUNET_malloc(sizeof(struct PendingMessage) + size);
781   pending_message->msg = (struct GNUNET_MessageHeader *)&pending_message[1];
782   memcpy(&pending_message[1], received_msg, size);
783   GNUNET_free(received_msg);
784
785   GNUNET_CONTAINER_DLL_insert_after(plugin_pending_head, plugin_pending_tail, plugin_pending_tail, pending_message);
786
787   if (client_handle != NULL)
788     {
789       if (plugin_transmit_handle == NULL)
790         {
791           plugin_transmit_handle = GNUNET_SERVER_notify_transmit_ready (client_handle,
792                                                                         size, GNUNET_TIME_UNIT_FOREVER_REL,
793                                                                         &transmit_to_plugin, NULL);
794         }
795     }
796   else
797     {
798       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to queue message for plugin, client_handle not yet set (how?)!\n");
799     }
800 }
801
802 /* Declare here so retry_core_send is aware of it */
803 size_t core_transmit_notify (void *cls,
804                              size_t size, void *buf);
805
806 /**
807  *  Try to send another message from our core sending list
808  */
809 static void
810 try_core_send (void *cls,
811                  const struct GNUNET_SCHEDULER_TaskContext *tc)
812 {
813   struct PendingMessage *pending;
814   pending = core_pending_head;
815
816   if (core_transmit_handle != NULL)
817     return; /* Message send already in progress */
818
819   if (pending != NULL)
820     core_transmit_handle = GNUNET_CORE_notify_transmit_ready(coreAPI, pending->importance, pending->timeout, &pending->recipient, pending->msg_size, &core_transmit_notify, NULL);
821 }
822
823 /**
824  * Function called to notify a client about the socket
825  * being ready to queue more data.  "buf" will be
826  * NULL and "size" zero if the socket was closed for
827  * writing in the meantime.
828  *
829  * @param cls closure (NULL)
830  * @param size number of bytes available in buf
831  * @param buf where the callee should write the message
832  * @return number of bytes written to buf
833  */
834 size_t core_transmit_notify (void *cls,
835                              size_t size, void *buf)
836 {
837   char *cbuf = buf;
838   struct PendingMessage *pending;
839   struct PendingMessage *client_reply;
840   size_t off;
841   size_t msize;
842
843   if (buf == NULL)
844     {
845       /* client disconnected */
846 #if DEBUG_DV
847       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "`%s': buffer was NULL\n", "DHT");
848 #endif
849       return 0;
850     }
851
852   core_transmit_handle = NULL;
853   off = 0;
854   pending = core_pending_head;
855   if ( (pending != NULL) &&
856           (size >= (msize = ntohs (pending->msg->size))))
857     {
858 #if DEBUG_DV
859       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "`%s' : transmit_notify (core) called with size %d\n", "dv service", msize);
860 #endif
861       GNUNET_CONTAINER_DLL_remove (core_pending_head,
862                                    core_pending_tail,
863                                    pending);
864       if (pending->send_result != NULL) /* Will only be non-null if a real client asked for this send */
865         {
866           client_reply = GNUNET_malloc(sizeof(struct PendingMessage) + sizeof(struct GNUNET_DV_SendResultMessage));
867           client_reply->msg = (struct GNUNET_MessageHeader *)&client_reply[1];
868           memcpy(&client_reply[1], pending->send_result, sizeof(struct GNUNET_DV_SendResultMessage));
869           GNUNET_free(pending->send_result);
870
871           GNUNET_CONTAINER_DLL_insert_after(plugin_pending_head, plugin_pending_tail, plugin_pending_tail, client_reply);
872           if (client_handle != NULL)
873             {
874               if (plugin_transmit_handle == NULL)
875                 {
876                   plugin_transmit_handle = GNUNET_SERVER_notify_transmit_ready (client_handle,
877                                                                                 sizeof(struct GNUNET_DV_SendResultMessage),
878                                                                                 GNUNET_TIME_UNIT_FOREVER_REL,
879                                                                                 &transmit_to_plugin, NULL);
880                 }
881               else
882                 {
883                   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to queue message for plugin, must be one in progress already!!\n");
884                 }
885             }
886         }
887       memcpy (&cbuf[off], pending->msg, msize);
888       GNUNET_free (pending);
889       off += msize;
890     }
891   /*reply = core_pending_head;*/
892
893   GNUNET_SCHEDULER_add_now(sched, &try_core_send, NULL);
894   /*if (reply != NULL)
895     core_transmit_handle = GNUNET_CORE_notify_transmit_ready(coreAPI, reply->importance, reply->timeout, &reply->recipient, reply->msg_size, &core_transmit_notify, NULL);*/
896
897   return off;
898 }
899
900
901 /**
902  * Send a DV data message via DV.
903  *
904  * @param sender the original sender of the message
905  * @param recipient the next hop recipient, may be our direct peer, maybe not
906  * @param send_context the send context
907  */
908 static int
909 send_message_via (const struct GNUNET_PeerIdentity *sender,
910                   const struct GNUNET_PeerIdentity *recipient,
911                   struct DV_SendContext *send_context)
912 {
913   p2p_dv_MESSAGE_Data *toSend;
914   unsigned int msg_size;
915   unsigned int recipient_id;
916   unsigned int sender_id;
917   struct DistantNeighbor *source;
918   struct PendingMessage *pending_message;
919   struct FindIDContext find_context;
920 #if DEBUG_DV
921   char shortname[5];
922 #endif
923
924   msg_size = send_context->message_size + sizeof (p2p_dv_MESSAGE_Data);
925
926   find_context.dest = send_context->distant_peer;
927   find_context.via = recipient;
928   find_context.tid = 0;
929   GNUNET_CONTAINER_multihashmap_get_multiple (extended_neighbors, &send_context->distant_peer->hashPubKey,
930                                               &find_specific_id, &find_context);
931
932   if (find_context.tid == 0)
933     {
934       GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "%s: find_specific_id failed to find peer!\n", my_short_id);
935       /* target unknown to us, drop! */
936       return GNUNET_SYSERR;
937     }
938   recipient_id = find_context.tid;
939
940   if (0 == (memcmp (&my_identity,
941                         sender, sizeof (struct GNUNET_PeerIdentity))))
942   {
943     sender_id = 0;
944     source = GNUNET_CONTAINER_multihashmap_get (extended_neighbors,
945                                                     &sender->hashPubKey);
946     if (source != NULL)
947       GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "%s: send_message_via found %s, myself in extended peer list???\n", my_short_id, GNUNET_i2s(&source->identity));
948   }
949   else
950   {
951     source = GNUNET_CONTAINER_multihashmap_get (extended_neighbors,
952                                                 &sender->hashPubKey);
953     if (source == NULL)
954       {
955               /* sender unknown to us, drop! */
956         return GNUNET_SYSERR;
957       }
958     sender_id = source->our_id;
959   }
960
961   pending_message = GNUNET_malloc(sizeof(struct PendingMessage) + msg_size);
962   pending_message->msg = (struct GNUNET_MessageHeader *)&pending_message[1];
963   pending_message->send_result = send_context->send_result;
964   memcpy(&pending_message->recipient, recipient, sizeof(struct GNUNET_PeerIdentity));
965   pending_message->msg_size = msg_size;
966   pending_message->importance = send_context->importance;
967   pending_message->timeout = send_context->timeout;
968   toSend = (p2p_dv_MESSAGE_Data *)pending_message->msg;
969   toSend->header.size = htons (msg_size);
970   toSend->header.type = htons (GNUNET_MESSAGE_TYPE_DV_DATA);
971   toSend->sender = htonl (sender_id);
972   toSend->recipient = htonl (recipient_id);
973 #if DEBUG_DV_MESSAGES
974   toSend->uid = send_context->uid; /* Still sent around in network byte order */
975 #else
976   toSend->uid = htonl(0);
977 #endif
978
979   memcpy (&toSend[1], send_context->message, send_context->message_size);
980
981 #if DEBUG_DV
982   memcpy(&shortname, GNUNET_i2s(send_context->distant_peer), 4);
983   shortname[4] = '\0';
984   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s: Notifying core of send to destination `%s' via `%s' size %u\n", "DV", &shortname, GNUNET_i2s(recipient), msg_size);
985 #endif
986
987   GNUNET_CONTAINER_DLL_insert_after (core_pending_head,
988                                      core_pending_tail,
989                                      core_pending_tail,
990                                      pending_message);
991
992   if (core_transmit_handle == NULL)
993     core_transmit_handle = GNUNET_CORE_notify_transmit_ready(coreAPI, send_context->importance, send_context->timeout, recipient, msg_size, &core_transmit_notify, NULL);
994   else
995     {
996 #if DEBUG_DV
997       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "`%s': Failed to schedule pending transmission (must be one in progress!)\n", "dv service");
998 #endif
999     }
1000   return GNUNET_YES;
1001 }
1002
1003 /**
1004  * Given a FindLeastCostContext, and a set
1005  * of peers that match the target, return the cheapest.
1006  *
1007  * @param cls closure, a struct FindLeastCostContext
1008  * @param key the key identifying the target peer
1009  * @param value the target peer
1010  *
1011  * @return GNUNET_YES to continue iteration, GNUNET_NO to stop
1012  */
1013 static int
1014 find_least_cost_peer (void *cls,
1015                   const GNUNET_HashCode *key,
1016                   void *value)
1017 {
1018   struct FindLeastCostContext *find_context = cls;
1019   struct DistantNeighbor *dn = value;
1020
1021   if (dn->cost < find_context->least_cost)
1022     {
1023       find_context->target = dn;
1024     }
1025   if (dn->cost == DIRECT_NEIGHBOR_COST)
1026     return GNUNET_NO;
1027   return GNUNET_YES;
1028 }
1029
1030 /**
1031  * Send a DV data message via DV.
1032  *
1033  * @param recipient the ultimate recipient of this message
1034  * @param sender the original sender of the message
1035  * @param specific_neighbor the specific neighbor to send this message via
1036  * @param message the packed message
1037  * @param message_size size of the message
1038  * @param importance what priority to send this message with
1039  * @param timeout how long to possibly delay sending this message
1040  */
1041 static int
1042 send_message (const struct GNUNET_PeerIdentity * recipient,
1043               const struct GNUNET_PeerIdentity * sender,
1044               const struct DistantNeighbor * specific_neighbor,
1045               const struct GNUNET_MessageHeader * message,
1046               size_t message_size,
1047               unsigned int importance,
1048               unsigned int uid,
1049               struct GNUNET_TIME_Relative timeout)
1050 {
1051   p2p_dv_MESSAGE_Data *toSend;
1052   unsigned int msg_size;
1053   unsigned int cost;
1054   unsigned int recipient_id;
1055   unsigned int sender_id;
1056   struct DistantNeighbor *target;
1057   struct DistantNeighbor *source;
1058   struct PendingMessage *pending_message;
1059   struct FindLeastCostContext find_least_ctx;
1060 #if DEBUG_DV_PEER_NUMBERS
1061   struct GNUNET_CRYPTO_HashAsciiEncoded encPeerFrom;
1062   struct GNUNET_CRYPTO_HashAsciiEncoded encPeerTo;
1063   struct GNUNET_CRYPTO_HashAsciiEncoded encPeerVia;
1064 #endif
1065   msg_size = message_size + sizeof (p2p_dv_MESSAGE_Data);
1066
1067   find_least_ctx.least_cost = -1;
1068   find_least_ctx.target = NULL;
1069   /*
1070    * Need to find the least cost peer, lest the transport selection keep
1071    * picking the same DV route for the same destination which results
1072    * in messages looping forever.  Relatively cheap, we don't iterate
1073    * over all known peers, just those that apply.
1074    */
1075   GNUNET_CONTAINER_multihashmap_get_multiple (extended_neighbors,
1076                                                        &recipient->hashPubKey,  &find_least_cost_peer, &find_least_ctx);
1077   target = find_least_ctx.target;
1078
1079   if (target == NULL)
1080     {
1081       /* target unknown to us, drop! */
1082       return GNUNET_SYSERR;
1083     }
1084   recipient_id = target->referrer_id;
1085
1086   source = GNUNET_CONTAINER_multihashmap_get (extended_neighbors,
1087                                               &sender->hashPubKey);
1088   if (source == NULL)
1089     {
1090       if (0 != (memcmp (&my_identity,
1091                         sender, sizeof (struct GNUNET_PeerIdentity))))
1092         {
1093           /* sender unknown to us, drop! */
1094           return GNUNET_SYSERR;
1095         }
1096       sender_id = 0;            /* 0 == us */
1097     }
1098   else
1099     {
1100       /* find out the number that we use when we gossip about
1101          the sender */
1102       sender_id = source->our_id;
1103     }
1104
1105 #if DEBUG_DV_PEER_NUMBERS
1106   GNUNET_CRYPTO_hash_to_enc (&source->identity.hashPubKey, &encPeerFrom);
1107   GNUNET_CRYPTO_hash_to_enc (&target->referrer->identity.hashPubKey, &encPeerVia);
1108   encPeerFrom.encoding[4] = '\0';
1109   encPeerVia.encoding[4] = '\0';
1110 #endif
1111   if ((sender_id != 0) && (0 == memcmp(&source->identity, &target->referrer->identity, sizeof(struct GNUNET_PeerIdentity))))
1112     {
1113       return 0;
1114     }
1115
1116   cost = target->cost;
1117   pending_message = GNUNET_malloc(sizeof(struct PendingMessage) + msg_size);
1118   pending_message->msg = (struct GNUNET_MessageHeader *)&pending_message[1];
1119   pending_message->send_result = NULL;
1120   pending_message->importance = importance;
1121   pending_message->timeout = timeout;
1122   memcpy(&pending_message->recipient, &target->referrer->identity, sizeof(struct GNUNET_PeerIdentity));
1123   pending_message->msg_size = msg_size;
1124   toSend = (p2p_dv_MESSAGE_Data *)pending_message->msg;
1125   toSend->header.size = htons (msg_size);
1126   toSend->header.type = htons (GNUNET_MESSAGE_TYPE_DV_DATA);
1127   toSend->sender = htonl (sender_id);
1128   toSend->recipient = htonl (recipient_id);
1129 #if DEBUG_DV_MESSAGES
1130   toSend->uid = htonl(uid);
1131 #else
1132   toSend->uid = htonl(0);
1133 #endif
1134
1135 #if DEBUG_DV_PEER_NUMBERS
1136   GNUNET_CRYPTO_hash_to_enc (&target->identity.hashPubKey, &encPeerTo);
1137   encPeerTo.encoding[4] = '\0';
1138   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s: Sending DATA message. Sender id %u, source %s, destination %s, via %s\n", GNUNET_i2s(&my_identity), sender_id, &encPeerFrom, &encPeerTo, &encPeerVia);
1139 #endif
1140   memcpy (&toSend[1], message, message_size);
1141   if (source->pkey == NULL) /* Test our hypothesis about message failures! */
1142     {
1143       GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "%s: Sending message, but anticipate recipient will not know sender!!!\n\n\n");
1144     }
1145   GNUNET_CONTAINER_DLL_insert_after (core_pending_head,
1146                                      core_pending_tail,
1147                                      core_pending_tail,
1148                                      pending_message);
1149 #if DEBUG_DV
1150   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s: Notifying core of send size %d to destination `%s'\n", "DV SEND MESSAGE", msg_size, GNUNET_i2s(recipient));
1151 #endif
1152   if (core_transmit_handle == NULL)
1153     core_transmit_handle = GNUNET_CORE_notify_transmit_ready(coreAPI, importance, timeout, &target->referrer->identity, msg_size, &core_transmit_notify, NULL);
1154   else
1155     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s: CORE ALREADY SENDING\n", "DV SEND MESSAGE", msg_size);
1156   return (int) cost;
1157 }
1158
1159 #if USE_PEER_ID
1160 struct CheckPeerContext
1161 {
1162   /**
1163    * Peer we found
1164    */
1165   struct DistantNeighbor *peer;
1166
1167   /**
1168    * Sender id to search for
1169    */
1170   unsigned int sender_id;
1171 };
1172
1173 /**
1174  * Iterator over hash map entries.
1175  *
1176  * @param cls closure
1177  * @param key current key code
1178  * @param value value in the hash map
1179  * @return GNUNET_YES if we should continue to
1180  *         iterate,
1181  *         GNUNET_NO if not.
1182  */
1183 int checkPeerID (void *cls,
1184                  const GNUNET_HashCode * key,
1185                  void *value)
1186 {
1187   struct CheckPeerContext *ctx = cls;
1188   struct DistantNeighbor *distant = value;
1189
1190   if (memcmp(key, &ctx->sender_id, sizeof(unsigned int)) == 0)
1191   {
1192     ctx->peer = distant;
1193     return GNUNET_NO;
1194   }
1195   return GNUNET_YES;
1196
1197 }
1198 #endif
1199
1200
1201 /**
1202  * Handler for messages parsed out by the tokenizer from
1203  * DV DATA received for this peer.
1204  *
1205  * @param cls NULL
1206  * @param client the TokenizedMessageContext which contains message information
1207  * @param message the actual message
1208  */
1209 void tokenized_message_handler (void *cls,
1210                                 void *client,
1211                                 const struct GNUNET_MessageHeader *message)
1212 {
1213   struct TokenizedMessageContext *ctx = client;
1214   GNUNET_break_op (ntohs (message->type) != GNUNET_MESSAGE_TYPE_DV_GOSSIP);
1215   GNUNET_break_op (ntohs (message->type) != GNUNET_MESSAGE_TYPE_DV_DATA);
1216   if ( (ntohs (message->type) != GNUNET_MESSAGE_TYPE_DV_GOSSIP) &&
1217       (ntohs (message->type) != GNUNET_MESSAGE_TYPE_DV_DATA) )
1218   {
1219 #if DEBUG_DV_MESSAGES
1220     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1221                 "%s: Receives %s message for me, uid %u, size %d, type %d cost %u from %s!\n", my_short_id, "DV DATA", ctx->uid, ntohs(message->size), ntohs(message->type), ctx->distant->cost, GNUNET_i2s(&ctx->distant->identity));
1222 #endif
1223     GNUNET_assert(memcmp(ctx->peer, &ctx->distant->identity, sizeof(struct GNUNET_PeerIdentity)) != 0);
1224     send_to_plugin(ctx->peer, message, ntohs(message->size), &ctx->distant->identity, ctx->distant->cost);
1225   }
1226 }
1227
1228 /**
1229  * Core handler for dv data messages.  Whatever this message
1230  * contains all we really have to do is rip it out of its
1231  * DV layering and give it to our pal the DV plugin to report
1232  * in with.
1233  *
1234  * @param cls closure
1235  * @param peer peer which sent the message (immediate sender)
1236  * @param message the message
1237  * @param latency the latency of the connection we received the message from
1238  * @param distance the distance to the immediate peer
1239  */
1240 static int handle_dv_data_message (void *cls,
1241                              const struct GNUNET_PeerIdentity * peer,
1242                              const struct GNUNET_MessageHeader * message,
1243                              struct GNUNET_TIME_Relative latency,
1244                              uint32_t distance)
1245 {
1246   const p2p_dv_MESSAGE_Data *incoming = (const p2p_dv_MESSAGE_Data *) message;
1247   const struct GNUNET_MessageHeader *packed_message;
1248   struct DirectNeighbor *dn;
1249   struct DistantNeighbor *pos;
1250   unsigned int sid;             /* Sender id */
1251   unsigned int tid;             /* Target id */
1252   struct GNUNET_PeerIdentity original_sender;
1253   struct GNUNET_PeerIdentity destination;
1254   struct FindDestinationContext fdc;
1255   struct TokenizedMessageContext tkm_ctx;
1256 #if USE_PEER_ID
1257   struct CheckPeerContext checkPeerCtx;
1258 #endif
1259   char *sender_id;
1260   char *direct_id;
1261   int ret;
1262   size_t packed_message_size;
1263   char *cbuf;
1264 #if NO_MST
1265   size_t offset;
1266 #endif
1267   packed_message_size = ntohs(incoming->header.size) - sizeof(p2p_dv_MESSAGE_Data);
1268
1269
1270 #if DEBUG_DV
1271   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1272               "%s: Receives DATA message from %s size %d, packed size %d!\n", my_short_id, GNUNET_i2s(peer) , ntohs(incoming->header.size), packed_message_size);
1273 #endif
1274
1275   if (ntohs (incoming->header.size) <  sizeof (p2p_dv_MESSAGE_Data) + sizeof (struct GNUNET_MessageHeader))
1276     {
1277
1278 #if DEBUG_DV
1279     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1280                 "`%s': Message sizes don't add up, total size %u, expected at least %u!\n", "dv service", ntohs(incoming->header.size), sizeof (p2p_dv_MESSAGE_Data) + sizeof (struct GNUNET_MessageHeader));
1281 #endif
1282       return GNUNET_SYSERR;
1283     }
1284
1285   dn = GNUNET_CONTAINER_multihashmap_get (direct_neighbors,
1286                                   &peer->hashPubKey);
1287   if (dn == NULL)
1288     {
1289 #if DEBUG_DV
1290       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1291                   "%s: dn NULL!\n", "dv");
1292 #endif
1293       return GNUNET_OK;
1294     }
1295   sid = ntohl (incoming->sender);
1296 #if USE_PEER_ID
1297   if (sid != 0)
1298   {
1299     checkPeerCtx.sender_id = sid;
1300     checkPeerCtx.peer = NULL;
1301     GNUNET_CONTAINER_multihashmap_iterate(extended_neighbors, &checkPeerID, &checkPeerCtx);
1302     pos = checkPeerCtx.peer;
1303   }
1304   else
1305   {
1306     pos = GNUNET_CONTAINER_multihashmap_get (extended_neighbors,
1307                                              &peer->hashPubKey);
1308   }
1309 #else
1310   pos = dn->referee_head;
1311   while ((NULL != pos) && (pos->referrer_id != sid))
1312     pos = pos->next;
1313 #endif
1314
1315   if (pos == NULL)
1316     {
1317       direct_id = GNUNET_strdup(GNUNET_i2s(&dn->identity));
1318 #if DEBUG_DV_MESSAGES
1319       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1320                   "%s: unknown sender (%u), Message uid %llu from %s!\n", GNUNET_i2s(&my_identity), ntohl(incoming->sender), ntohl(incoming->uid), direct_id);
1321 #endif
1322       GNUNET_free(direct_id);
1323       pos = dn->referee_head;
1324       while ((NULL != pos) && (pos->referrer_id != sid))
1325       {
1326         sender_id = strdup(GNUNET_i2s(&pos->identity));
1327         GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "I know sender %u %s\n", pos->referrer_id, sender_id);
1328         GNUNET_free(sender_id);
1329         pos = pos->next;
1330       }
1331
1332 #if DEBUG_MESSAGE_DROP
1333       direct_id = GNUNET_strdup(GNUNET_i2s(&dn->identity));
1334       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1335                   "%s: DROPPING MESSAGE type %d, unknown sender! Message immediately from %s!\n", GNUNET_i2s(&my_identity), ntohs(((struct GNUNET_MessageHeader *)&incoming[1])->type), direct_id);
1336       GNUNET_free(direct_id);
1337 #endif
1338       /* unknown sender */
1339       return GNUNET_OK;
1340     }
1341   original_sender = pos->identity;
1342   tid = ntohl (incoming->recipient);
1343   if (tid == 0)
1344     {
1345       /* 0 == us */
1346       cbuf = (char *)&incoming[1];
1347
1348       tkm_ctx.peer = peer;
1349       tkm_ctx.distant = pos;
1350       tkm_ctx.uid = ntohl(incoming->uid);
1351       if (GNUNET_OK != GNUNET_SERVER_mst_receive (coreMST,
1352                                                   &tkm_ctx,
1353                                                   cbuf,
1354                                                   packed_message_size,
1355                                                   GNUNET_NO,
1356                                                   GNUNET_NO))
1357         {
1358           GNUNET_break_op(0);
1359           GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "%s: %s Received corrupt data, discarding!", my_short_id, "DV SERVICE");
1360         }
1361 #if NO_MST
1362       offset = 0;
1363       while(offset < packed_message_size)
1364         {
1365           packed_message = (struct GNUNET_MessageHeader *)&cbuf[offset];
1366
1367           GNUNET_break_op (ntohs (packed_message->type) != GNUNET_MESSAGE_TYPE_DV_GOSSIP);
1368           GNUNET_break_op (ntohs (packed_message->type) != GNUNET_MESSAGE_TYPE_DV_DATA);
1369           if ( (ntohs (packed_message->type) != GNUNET_MESSAGE_TYPE_DV_GOSSIP) &&
1370               (ntohs (packed_message->type) != GNUNET_MESSAGE_TYPE_DV_DATA) )
1371           {
1372 #if DEBUG_DV_MESSAGES
1373             GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1374                         "%s: Receives %s message(s) for me, uid %u, total size %d cost %u from %s!\n", my_short_id, "DV DATA", ntohl(incoming->uid), ntohs(packed_message->size), pos->cost, GNUNET_i2s(&pos->identity));
1375 #endif
1376             GNUNET_assert(memcmp(peer, &pos->identity, sizeof(struct GNUNET_PeerIdentity)) != 0);
1377             send_to_plugin(peer, packed_message, ntohs(packed_message->size), &pos->identity, pos->cost);
1378           }
1379           offset += ntohs(packed_message->size);
1380         }
1381 #endif
1382       return GNUNET_OK;
1383     }
1384   else
1385     {
1386       packed_message = (struct GNUNET_MessageHeader *)&incoming[1];
1387     }
1388
1389   /* FIXME: this is the *only* per-request operation we have in DV
1390      that is O(n) in relation to the number of connected peers; a
1391      hash-table lookup could easily solve this (minor performance
1392      issue) */
1393   fdc.tid = tid;
1394   fdc.dest = NULL;
1395   GNUNET_CONTAINER_heap_iterate (neighbor_max_heap,
1396                                  &find_destination, &fdc);
1397
1398 #if DEBUG_DV
1399       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1400                   "%s: Receives %s message for someone else!\n", "dv", "DV DATA");
1401 #endif
1402
1403   if (fdc.dest == NULL)
1404     {
1405 #if DEBUG_DV_MESSAGES
1406       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1407                   "%s: Receives %s message uid %u for someone we don't know (id %u)!\n", my_short_id, "DV DATA", ntohl(incoming->uid), tid);
1408 #endif
1409     return GNUNET_OK;
1410     }
1411   destination = fdc.dest->identity;
1412
1413   if (0 == memcmp (&destination, peer, sizeof (struct GNUNET_PeerIdentity)))
1414     {
1415       /* FIXME: create stat: routing loop-discard! */
1416 #if DEBUG_DV_PEER_NUMBERS
1417       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "\n\n\nLoopy loo message\n\n\n");
1418 #endif
1419
1420 #if DEBUG_DV_MESSAGES
1421       direct_id = GNUNET_strdup(GNUNET_i2s(&dn->identity));
1422       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1423                   "%s: DROPPING MESSAGE uid %u type %d, routing loop! Message immediately from %s!\n", my_short_id, ntohl(incoming->uid), ntohs(packed_message->type), direct_id);
1424 #endif
1425       return GNUNET_OK;
1426     }
1427
1428   /* At this point we have a message, and we need to forward it on to the
1429    * next DV hop.
1430    */
1431   /* FIXME: Can't send message on, we have to behave.
1432    * We have to tell core we have a message for the next peer, and let
1433    * transport do transport selection on how to get this message to 'em */
1434   /*ret = send_message (&destination,
1435                       &original_sender,
1436                       packed_message, DV_PRIORITY, DV_DELAY);*/
1437
1438 #if DEBUG_DV_MESSAGES
1439   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1440               "%s: FORWARD %s message for %s, uid %u, size %d type %d, cost %u!\n", my_short_id, "DV DATA", GNUNET_i2s(&destination), ntohl(incoming->uid), ntohs(packed_message->size), ntohs(packed_message->type), pos->cost);
1441 #endif
1442
1443   ret = send_message(&destination,
1444                      &original_sender,
1445                      NULL,
1446                      packed_message,
1447                      packed_message_size,
1448                      default_dv_priority,
1449                      ntohl(incoming->uid),
1450                      GNUNET_TIME_relative_get_forever());
1451
1452   if (ret != GNUNET_SYSERR)
1453     return GNUNET_OK;
1454   else
1455     {
1456 #if DEBUG_MESSAGE_DROP
1457       direct_id = GNUNET_strdup(GNUNET_i2s(&dn->identity));
1458       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1459                   "%s: DROPPING MESSAGE type %d, forwarding failed! Message immediately from %s!\n", GNUNET_i2s(&my_identity), ntohs(((struct GNUNET_MessageHeader *)&incoming[1])->type), direct_id);
1460 #endif
1461       return GNUNET_SYSERR;
1462     }
1463 }
1464
1465 #if DEBUG_DV
1466 /**
1467  * Iterator over hash map entries.
1468  *
1469  * @param cls closure (NULL)
1470  * @param key current key code
1471  * @param value value in the hash map (DistantNeighbor)
1472  * @return GNUNET_YES if we should continue to
1473  *         iterate,
1474  *         GNUNET_NO if not.
1475  */
1476 int print_neighbors (void *cls,
1477                      const GNUNET_HashCode * key,
1478                      void *value)
1479 {
1480   struct DistantNeighbor *distant_neighbor = value;
1481   char my_shortname[5];
1482   char referrer_shortname[5];
1483   memcpy(&my_shortname, GNUNET_i2s(&my_identity), 4);
1484   my_shortname[4] = '\0';
1485   memcpy(&referrer_shortname, GNUNET_i2s(&distant_neighbor->referrer->identity), 4);
1486   referrer_shortname[4] = '\0';
1487
1488   GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "`%s' %s: Peer `%s', distance %d, referrer `%s' pkey: %s\n", &my_shortname, "DV", GNUNET_i2s(&distant_neighbor->identity), distant_neighbor->cost, &referrer_shortname, distant_neighbor->pkey == NULL ? "no" : "yes");
1489   return GNUNET_YES;
1490 }
1491 #endif
1492
1493 /**
1494  *  Scheduled task which gossips about known direct peers to other connected
1495  *  peers.  Will run until called with reason shutdown.
1496  */
1497 static void
1498 neighbor_send_task (void *cls,
1499                     const struct GNUNET_SCHEDULER_TaskContext *tc)
1500 {
1501   struct NeighborSendContext *send_context = cls;
1502 #if DEBUG_DV_GOSSIP_SEND
1503   char * encPeerAbout;
1504   char * encPeerTo;
1505 #endif
1506   struct DistantNeighbor *about;
1507   struct DirectNeighbor *to;
1508   struct FastGossipNeighborList *about_list;
1509
1510   p2p_dv_MESSAGE_NeighborInfo *message;
1511   struct PendingMessage *pending_message;
1512
1513   if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
1514   {
1515 #if DEBUG_DV_GOSSIP
1516   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1517               "%s: Called with reason shutdown, shutting down!\n",
1518               GNUNET_i2s(&my_identity));
1519 #endif
1520     return;
1521   }
1522
1523   if (send_context->fast_gossip_list_head != NULL)
1524     {
1525       about_list = send_context->fast_gossip_list_head;
1526       about = about_list->about;
1527       GNUNET_CONTAINER_DLL_remove(send_context->fast_gossip_list_head,
1528                                   send_context->fast_gossip_list_tail,
1529                                   about_list);
1530       GNUNET_free(about_list);
1531     }
1532   else
1533     {
1534       /* FIXME: this may become a problem, because the heap walk has only one internal "walker".  This means
1535        * that if two neighbor_send_tasks are operating in lockstep (which is quite possible, given default
1536        * values for all connected peers) there may be a serious bias as to which peers get gossiped about!
1537        * Probably the *best* way to fix would be to have an opaque pointer to the walk position passed as
1538        * part of the walk_get_next call.  Then the heap would have to keep a list of walks, or reset the walk
1539        * whenever a modification has been detected.  Yuck either way.  Perhaps we could iterate over the heap
1540        * once to get a list of peers to gossip about and gossip them over time... But then if one goes away
1541        * in the mean time that becomes nasty.  For now we'll just assume that the walking is done
1542        * asynchronously enough to avoid major problems (-;
1543        *
1544        * NOTE: probably fixed once we decided send rate based on allowed bandwidth.
1545        */
1546       about = GNUNET_CONTAINER_heap_walk_get_next (neighbor_min_heap);
1547     }
1548   to = send_context->toNeighbor;
1549
1550   if ((about != NULL) && (to != about->referrer /* split horizon */ ) &&
1551 #if SUPPORT_HIDING
1552       (about->hidden == GNUNET_NO) &&
1553 #endif
1554       (to != NULL) &&
1555       (0 != memcmp (&about->identity,
1556                         &to->identity, sizeof (struct GNUNET_PeerIdentity))) &&
1557       (about->pkey != NULL))
1558     {
1559 #if DEBUG_DV_GOSSIP_SEND
1560       encPeerAbout = GNUNET_strdup(GNUNET_i2s(&about->identity));
1561       encPeerTo = GNUNET_strdup(GNUNET_i2s(&to->identity));
1562       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1563                   "%s: Sending info about peer %s id %u to directly connected peer %s\n",
1564                   GNUNET_i2s(&my_identity),
1565                   encPeerAbout, about->our_id, encPeerTo);
1566       GNUNET_free(encPeerAbout);
1567       GNUNET_free(encPeerTo);
1568 #endif
1569       pending_message = GNUNET_malloc(sizeof(struct PendingMessage) + sizeof(p2p_dv_MESSAGE_NeighborInfo));
1570       pending_message->msg = (struct GNUNET_MessageHeader *)&pending_message[1];
1571       pending_message->importance = default_dv_priority;
1572       pending_message->timeout = GNUNET_TIME_relative_get_forever();
1573       memcpy(&pending_message->recipient, &to->identity, sizeof(struct GNUNET_PeerIdentity));
1574       pending_message->msg_size = sizeof(p2p_dv_MESSAGE_NeighborInfo);
1575       message = (p2p_dv_MESSAGE_NeighborInfo *)pending_message->msg;
1576       message->header.size = htons (sizeof (p2p_dv_MESSAGE_NeighborInfo));
1577       message->header.type = htons (GNUNET_MESSAGE_TYPE_DV_GOSSIP);
1578       message->cost = htonl (about->cost);
1579       message->neighbor_id = htonl (about->our_id);
1580
1581       memcpy (&message->pkey, about->pkey, sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
1582       memcpy (&message->neighbor,
1583               &about->identity, sizeof (struct GNUNET_PeerIdentity));
1584
1585       GNUNET_CONTAINER_DLL_insert_after (core_pending_head,
1586                                          core_pending_tail,
1587                                          core_pending_tail,
1588                                          pending_message);
1589
1590       if (core_transmit_handle == NULL)
1591         core_transmit_handle = GNUNET_CORE_notify_transmit_ready(coreAPI, default_dv_priority, GNUNET_TIME_relative_get_forever(), &to->identity, sizeof(p2p_dv_MESSAGE_NeighborInfo), &core_transmit_notify, NULL);
1592
1593     }
1594
1595   if (send_context->fast_gossip_list_head != NULL) /* If there are other peers in the fast list, schedule right away */
1596     {
1597 #if DEBUG_DV_PEER_NUMBERS
1598       GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "DV SERVICE: still in fast send mode\n");
1599 #endif
1600       send_context->task = GNUNET_SCHEDULER_add_now(sched, &neighbor_send_task, send_context);
1601     }
1602   else
1603     {
1604 #if DEBUG_DV_PEER_NUMBERS
1605       GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "DV SERVICE: entering slow send mode\n");
1606 #endif
1607       send_context->task = GNUNET_SCHEDULER_add_delayed(sched, GNUNET_DV_DEFAULT_SEND_INTERVAL, &neighbor_send_task, send_context);
1608     }
1609
1610   return;
1611 }
1612
1613
1614 /**
1615  * Handle START-message.  This is the first message sent to us
1616  * by the client (can only be one!).
1617  *
1618  * @param cls closure (always NULL)
1619  * @param client identification of the client
1620  * @param message the actual message
1621  */
1622 static void
1623 handle_start (void *cls,
1624               struct GNUNET_SERVER_Client *client,
1625               const struct GNUNET_MessageHeader *message)
1626 {
1627
1628 #if DEBUG_DV
1629   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1630               "Received `%s' request from client\n", "START");
1631 #endif
1632
1633   client_handle = client;
1634
1635   GNUNET_SERVER_client_keep(client_handle);
1636   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1637 }
1638
1639 #if UNSIMPLER
1640 /**
1641  * Iterate over hash map entries for a distant neighbor,
1642  * if direct neighbor matches context call send message
1643  *
1644  * @param cls closure, a DV_SendContext
1645  * @param key current key code
1646  * @param value value in the hash map
1647  * @return GNUNET_YES if we should continue to
1648  *         iterate,
1649  *         GNUNET_NO if not.
1650  */
1651 int send_iterator (void *cls,
1652                    const GNUNET_HashCode * key,
1653                    void *value)
1654 {
1655   struct DV_SendContext *send_context = cls;
1656   struct DistantNeighbor *distant_neighbor = value;
1657
1658   if (memcmp(distant_neighbor->referrer, send_context->direct_peer, sizeof(struct GNUNET_PeerIdentity)) == 0) /* They match, send and free */
1659     {
1660       send_message_via(&my_identity, distant_neighbor, send_context);
1661       return GNUNET_NO;
1662     }
1663   return GNUNET_YES;
1664 }
1665 #endif
1666
1667 /**
1668  * Service server's handler for message send requests (which come
1669  * bubbling up to us through the DV plugin).
1670  *
1671  * @param cls closure
1672  * @param client identification of the client
1673  * @param message the actual message
1674  */
1675 void handle_dv_send_message (void *cls,
1676                              struct GNUNET_SERVER_Client * client,
1677                              const struct GNUNET_MessageHeader * message)
1678 {
1679   struct GNUNET_DV_SendMessage *send_msg;
1680   struct GNUNET_DV_SendResultMessage *send_result_msg;
1681   struct PendingMessage *pending_message;
1682   size_t address_len;
1683   size_t message_size;
1684   struct GNUNET_PeerIdentity *destination;
1685   struct GNUNET_PeerIdentity *direct;
1686   struct GNUNET_MessageHeader *message_buf;
1687   char *temp_pos;
1688   int offset;
1689   static struct GNUNET_CRYPTO_HashAsciiEncoded dest_hash;
1690   struct DV_SendContext *send_context;
1691 #if DEBUG_DV_MESSAGES
1692   char *cbuf;
1693   struct GNUNET_MessageHeader *packed_message;
1694 #endif
1695
1696   if (client_handle == NULL)
1697   {
1698     client_handle = client;
1699     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1700               "%s: Setting initial client handle, never received `%s' message?\n", "dv", "START");
1701   }
1702   else if (client_handle != client)
1703   {
1704     client_handle = client;
1705     /* What should we do in this case, assert fail or just log the warning? */
1706 #if DEBUG_DV
1707     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1708                 "%s: Setting client handle (was a different client!)!\n", "dv");
1709 #endif
1710   }
1711
1712   GNUNET_assert(ntohs(message->size) > sizeof(struct GNUNET_DV_SendMessage));
1713   send_msg = (struct GNUNET_DV_SendMessage *)message;
1714
1715   address_len = ntohl(send_msg->addrlen);
1716   GNUNET_assert(address_len == sizeof(struct GNUNET_PeerIdentity) * 2);
1717   message_size = ntohs(message->size) - sizeof(struct GNUNET_DV_SendMessage) - address_len;
1718   destination = GNUNET_malloc(sizeof(struct GNUNET_PeerIdentity));
1719   direct = GNUNET_malloc(sizeof(struct GNUNET_PeerIdentity));
1720   message_buf = GNUNET_malloc(message_size);
1721
1722   temp_pos = (char *)&send_msg[1]; /* Set pointer to end of message */
1723   offset = 0; /* Offset starts at zero */
1724
1725   memcpy(destination, &temp_pos[offset], sizeof(struct GNUNET_PeerIdentity));
1726   offset += sizeof(struct GNUNET_PeerIdentity);
1727
1728   memcpy(direct, &temp_pos[offset], sizeof(struct GNUNET_PeerIdentity));
1729   offset += sizeof(struct GNUNET_PeerIdentity);
1730
1731
1732   memcpy(message_buf, &temp_pos[offset], message_size);
1733   if (memcmp(&send_msg->target, destination, sizeof(struct GNUNET_PeerIdentity)) != 0)
1734     {
1735       GNUNET_CRYPTO_hash_to_enc (&destination->hashPubKey, &dest_hash); /* GNUNET_i2s won't properly work, need to hash one ourselves */
1736       dest_hash.encoding[4] = '\0';
1737       GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "%s: asked to send message to `%s', but address is for `%s'!", "DV SERVICE", GNUNET_i2s(&send_msg->target), (const char *)&dest_hash.encoding);
1738     }
1739
1740 #if DEBUG_DV_MESSAGES
1741   cbuf = (char *)message_buf;
1742   offset = 0;
1743   while(offset < message_size)
1744     {
1745       packed_message = (struct GNUNET_MessageHeader *)&cbuf[offset];
1746       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s: DV PLUGIN SEND uid %u type %d to %s\n", my_short_id, ntohl(send_msg->uid), ntohs(packed_message->type), GNUNET_i2s(destination));
1747       offset += ntohs(packed_message->size);
1748     }
1749   /*GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s: DV PLUGIN SEND uid %u type %d to %s\n", my_short_id, ntohl(send_msg->uid), ntohs(message_buf->type), GNUNET_i2s(destination));*/
1750 #endif
1751   GNUNET_CRYPTO_hash_to_enc (&destination->hashPubKey, &dest_hash); /* GNUNET_i2s won't properly work, need to hash one ourselves */
1752   dest_hash.encoding[4] = '\0';
1753   send_context = GNUNET_malloc(sizeof(struct DV_SendContext));
1754
1755   send_result_msg = GNUNET_malloc(sizeof(struct GNUNET_DV_SendResultMessage));
1756   send_result_msg->header.size = htons(sizeof(struct GNUNET_DV_SendResultMessage));
1757   send_result_msg->header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_DV_SEND_RESULT);
1758   send_result_msg->uid = send_msg->uid; /* No need to ntohl->htonl this */
1759
1760   send_context->importance = ntohl(send_msg->priority);
1761   send_context->timeout = send_msg->timeout;
1762   send_context->direct_peer = direct;
1763   send_context->distant_peer = destination;
1764   send_context->message = message_buf;
1765   send_context->message_size = message_size;
1766   send_context->send_result = send_result_msg;
1767 #if DEBUG_DV_MESSAGES
1768   send_context->uid = send_msg->uid;
1769 #endif
1770
1771   if (send_message_via(&my_identity, direct, send_context) != GNUNET_YES)
1772     {
1773       send_result_msg->result = htons(1);
1774       pending_message = GNUNET_malloc(sizeof(struct PendingMessage) + sizeof(struct GNUNET_DV_SendResultMessage));
1775       pending_message->msg = (struct GNUNET_MessageHeader *)&pending_message[1];
1776       memcpy(&pending_message[1], send_result_msg, sizeof(struct GNUNET_DV_SendResultMessage));
1777       GNUNET_free(send_result_msg);
1778
1779       GNUNET_CONTAINER_DLL_insert_after(plugin_pending_head, plugin_pending_tail, plugin_pending_tail, pending_message);
1780
1781       if (client_handle != NULL)
1782         {
1783           if (plugin_transmit_handle == NULL)
1784             {
1785               plugin_transmit_handle = GNUNET_SERVER_notify_transmit_ready (client_handle,
1786                                                                             sizeof(struct GNUNET_DV_SendResultMessage),
1787                                                                             GNUNET_TIME_UNIT_FOREVER_REL,
1788                                                                             &transmit_to_plugin, NULL);
1789             }
1790           else
1791             {
1792               GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to queue message for plugin, must be one in progress already!!\n");
1793             }
1794         }
1795       GNUNET_CRYPTO_hash_to_enc (&destination->hashPubKey, &dest_hash); /* GNUNET_i2s won't properly work, need to hash one ourselves */
1796       dest_hash.encoding[4] = '\0';
1797       GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "%s DV SEND failed to send message to destination `%s' via `%s'\n", my_short_id, (const char *)&dest_hash.encoding, GNUNET_i2s(direct));
1798     }
1799
1800   /* In bizarro world GNUNET_SYSERR indicates that we succeeded */
1801 #if UNSIMPLER
1802   if (GNUNET_SYSERR != GNUNET_CONTAINER_multihashmap_get_multiple(extended_neighbors, &destination->hashPubKey, &send_iterator, send_context))
1803     {
1804       send_result_msg->result = htons(1);
1805       pending_message = GNUNET_malloc(sizeof(struct PendingMessage) + sizeof(struct GNUNET_DV_SendResultMessage));
1806       pending_message->msg = (struct GNUNET_MessageHeader *)&pending_message[1];
1807       memcpy(&pending_message[1], send_result_msg, sizeof(struct GNUNET_DV_SendResultMessage));
1808       GNUNET_free(send_result_msg);
1809
1810       GNUNET_CONTAINER_DLL_insert_after(plugin_pending_head, plugin_pending_tail, plugin_pending_tail, pending_message);
1811
1812       if (client_handle != NULL)
1813         {
1814           if (plugin_transmit_handle == NULL)
1815             {
1816               plugin_transmit_handle = GNUNET_SERVER_notify_transmit_ready (client_handle,
1817                                                                             sizeof(struct GNUNET_DV_SendResultMessage),
1818                                                                             GNUNET_TIME_UNIT_FOREVER_REL,
1819                                                                             &transmit_to_plugin, NULL);
1820             }
1821           else
1822             {
1823               GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to queue message for plugin, must be one in progress already!!\n");
1824             }
1825         }
1826       GNUNET_CRYPTO_hash_to_enc (&destination->hashPubKey, &dest_hash); /* GNUNET_i2s won't properly work, need to hash one ourselves */
1827       dest_hash.encoding[4] = '\0';
1828       GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "%s DV SEND failed to send message to destination `%s' via `%s'\n", my_short_id, (const char *)&dest_hash.encoding, GNUNET_i2s(direct));
1829     }
1830 #endif
1831   GNUNET_free(message_buf);
1832   GNUNET_free(send_context);
1833   GNUNET_free(direct);
1834   GNUNET_free(destination);
1835
1836   GNUNET_SERVER_receive_done(client, GNUNET_OK);
1837 }
1838
1839 /** Forward declarations **/
1840 static int handle_dv_gossip_message (void *cls,
1841                                      const struct GNUNET_PeerIdentity *peer,
1842                                      const struct GNUNET_MessageHeader *message,
1843                                      struct GNUNET_TIME_Relative latency,
1844                                      uint32_t distance);
1845
1846 static int handle_dv_disconnect_message (void *cls,
1847                                          const struct GNUNET_PeerIdentity *peer,
1848                                          const struct GNUNET_MessageHeader *message,
1849                                          struct GNUNET_TIME_Relative latency,
1850                                          uint32_t distance);
1851 /** End forward declarations **/
1852
1853
1854 /**
1855  * List of handlers for the messages understood by this
1856  * service.
1857  *
1858  * Hmm... will we need to register some handlers with core and
1859  * some handlers with our server here?  Because core should be
1860  * getting the incoming DV messages (from whichever lower level
1861  * transport) and then our server should be getting messages
1862  * from the dv_plugin, right?
1863  */
1864 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
1865   {&handle_dv_data_message, GNUNET_MESSAGE_TYPE_DV_DATA, 0},
1866   {&handle_dv_gossip_message, GNUNET_MESSAGE_TYPE_DV_GOSSIP, 0},
1867   {&handle_dv_disconnect_message, GNUNET_MESSAGE_TYPE_DV_DISCONNECT, 0},
1868   {NULL, 0, 0}
1869 };
1870
1871 static struct GNUNET_SERVER_MessageHandler plugin_handlers[] = {
1872   {&handle_dv_send_message, NULL, GNUNET_MESSAGE_TYPE_TRANSPORT_DV_SEND, 0},
1873   {&handle_start, NULL, GNUNET_MESSAGE_TYPE_DV_START, 0},
1874   {NULL, NULL, 0, 0}
1875 };
1876
1877 /**
1878  * Free a DistantNeighbor node, including removing it
1879  * from the referer's list.
1880  */
1881 static void
1882 distant_neighbor_free (struct DistantNeighbor *referee)
1883 {
1884   struct DirectNeighbor *referrer;
1885
1886   referrer = referee->referrer;
1887   if (referrer != NULL)
1888     {
1889       GNUNET_CONTAINER_DLL_remove (referrer->referee_head,
1890                          referrer->referee_tail, referee);
1891     }
1892   GNUNET_CONTAINER_heap_remove_node (neighbor_max_heap, referee->max_loc);
1893   GNUNET_CONTAINER_heap_remove_node (neighbor_min_heap, referee->min_loc);
1894   GNUNET_CONTAINER_multihashmap_remove_all (extended_neighbors,
1895                                     &referee->identity.hashPubKey);
1896   GNUNET_free_non_null (referee->pkey);
1897   GNUNET_free (referee);
1898 }
1899
1900 /**
1901  * Free a DirectNeighbor node, including removing it
1902  * from the referer's list.
1903  */
1904 static void
1905 direct_neighbor_free (struct DirectNeighbor *direct)
1906 {
1907   struct NeighborSendContext *send_context;
1908   struct FastGossipNeighborList *about_list;
1909   struct FastGossipNeighborList *prev_about;
1910
1911   send_context = direct->send_context;
1912
1913   if (send_context->task != GNUNET_SCHEDULER_NO_TASK)
1914     GNUNET_SCHEDULER_cancel(sched, send_context->task);
1915
1916   about_list = send_context->fast_gossip_list_head;
1917   while (about_list != NULL)
1918     {
1919       GNUNET_CONTAINER_DLL_remove(send_context->fast_gossip_list_head, send_context->fast_gossip_list_tail, about_list);
1920       prev_about = about_list;
1921       about_list = about_list->next;
1922       GNUNET_free(prev_about);
1923     }
1924   GNUNET_free(send_context);
1925   GNUNET_free(direct);
1926 }
1927
1928 /**
1929  * Multihashmap iterator for sending out disconnect messages
1930  * for a peer.
1931  *
1932  * @param cls the peer that was disconnected
1933  * @param key key value stored under
1934  * @param value the direct neighbor to send disconnect to
1935  *
1936  * @return GNUNET_YES to continue iteration, GNUNET_NO to stop
1937  */
1938 static int schedule_disconnect_messages (void *cls,
1939                                     const GNUNET_HashCode * key,
1940                                     void *value)
1941 {
1942   struct DisconnectContext *disconnect_context = cls;
1943   struct DirectNeighbor *disconnected = disconnect_context->direct;
1944   struct DirectNeighbor *notify = value;
1945   struct PendingMessage *pending_message;
1946   p2p_dv_MESSAGE_Disconnect *disconnect_message;
1947
1948   if (memcmp(&notify->identity, &disconnected->identity, sizeof(struct GNUNET_PeerIdentity)) == 0)
1949     return GNUNET_YES; /* Don't send disconnect message to peer that disconnected! */
1950
1951   pending_message = GNUNET_malloc(sizeof(struct PendingMessage) + sizeof(p2p_dv_MESSAGE_Disconnect));
1952   pending_message->msg = (struct GNUNET_MessageHeader *)&pending_message[1];
1953   pending_message->importance = default_dv_priority;
1954   pending_message->timeout = GNUNET_TIME_relative_get_forever();
1955   memcpy(&pending_message->recipient, &notify->identity, sizeof(struct GNUNET_PeerIdentity));
1956   pending_message->msg_size = sizeof(p2p_dv_MESSAGE_Disconnect);
1957   disconnect_message = (p2p_dv_MESSAGE_Disconnect *)pending_message->msg;
1958   disconnect_message->header.size = htons (sizeof (p2p_dv_MESSAGE_Disconnect));
1959   disconnect_message->header.type = htons (GNUNET_MESSAGE_TYPE_DV_DISCONNECT);
1960   disconnect_message->peer_id = htonl(disconnect_context->distant->our_id);
1961
1962   GNUNET_CONTAINER_DLL_insert_after (core_pending_head,
1963                                      core_pending_tail,
1964                                      core_pending_tail,
1965                                      pending_message);
1966
1967   if (core_transmit_handle == NULL)
1968     core_transmit_handle = GNUNET_CORE_notify_transmit_ready(coreAPI, default_dv_priority, GNUNET_TIME_relative_get_forever(), &notify->identity, sizeof(p2p_dv_MESSAGE_Disconnect), &core_transmit_notify, NULL);
1969
1970   return GNUNET_YES;
1971 }
1972
1973 /**
1974  * Multihashmap iterator for freeing extended neighbors.
1975  *
1976  * @param cls NULL
1977  * @param key key value stored under
1978  * @param value the distant neighbor to be freed
1979  *
1980  * @return GNUNET_YES to continue iteration, GNUNET_NO to stop
1981  */
1982 static int free_extended_neighbors (void *cls,
1983                                     const GNUNET_HashCode * key,
1984                                     void *value)
1985 {
1986   struct DistantNeighbor *distant = value;
1987   distant_neighbor_free(distant);
1988   return GNUNET_YES;
1989 }
1990
1991 /**
1992  * Multihashmap iterator for freeing direct neighbors.
1993  *
1994  * @param cls NULL
1995  * @param key key value stored under
1996  * @param value the direct neighbor to be freed
1997  *
1998  * @return GNUNET_YES to continue iteration, GNUNET_NO to stop
1999  */
2000 static int free_direct_neighbors (void *cls,
2001                                     const GNUNET_HashCode * key,
2002                                     void *value)
2003 {
2004   struct DirectNeighbor *direct = value;
2005   direct_neighbor_free(direct);
2006   return GNUNET_YES;
2007 }
2008
2009
2010 /**
2011  * Task run during shutdown.
2012  *
2013  * @param cls unused
2014  * @param tc unused
2015  */
2016 static void
2017 shutdown_task (void *cls,
2018                const struct GNUNET_SCHEDULER_TaskContext *tc)
2019 {
2020 #if DEBUG_DV
2021   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "calling CORE_DISCONNECT\n");
2022   GNUNET_CONTAINER_multihashmap_iterate(extended_neighbors, &print_neighbors, NULL);
2023 #endif
2024   GNUNET_CONTAINER_multihashmap_iterate(extended_neighbors, &free_extended_neighbors, NULL);
2025   GNUNET_CONTAINER_multihashmap_destroy(extended_neighbors);
2026   GNUNET_CONTAINER_multihashmap_iterate(direct_neighbors, &free_direct_neighbors, NULL);
2027   GNUNET_CONTAINER_multihashmap_destroy(direct_neighbors);
2028
2029   GNUNET_CONTAINER_heap_destroy(neighbor_max_heap);
2030   GNUNET_CONTAINER_heap_destroy(neighbor_min_heap);
2031
2032   GNUNET_CORE_disconnect (coreAPI);
2033   GNUNET_PEERINFO_disconnect(peerinfo_handle);
2034   GNUNET_SERVER_mst_destroy(coreMST);
2035   GNUNET_free_non_null(my_short_id);
2036 #if DEBUG_DV
2037   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "CORE_DISCONNECT completed\n");
2038 #endif
2039 }
2040
2041 /**
2042  * To be called on core init/fail.
2043  */
2044 void core_init (void *cls,
2045                 struct GNUNET_CORE_Handle * server,
2046                 const struct GNUNET_PeerIdentity *identity,
2047                 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded * publicKey)
2048 {
2049
2050   if (server == NULL)
2051     {
2052       GNUNET_SCHEDULER_cancel(sched, cleanup_task);
2053       GNUNET_SCHEDULER_add_now(sched, &shutdown_task, NULL);
2054       return;
2055     }
2056 #if DEBUG_DV
2057   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2058               "%s: Core connection initialized, I am peer: %s\n", "dv", GNUNET_i2s(identity));
2059 #endif
2060   memcpy(&my_identity, identity, sizeof(struct GNUNET_PeerIdentity));
2061   my_short_id = GNUNET_strdup(GNUNET_i2s(&my_identity));
2062   coreAPI = server;
2063 }
2064
2065
2066 #if PKEY_NO_NEIGHBOR_ON_ADD
2067 /**
2068  * Iterator over hash map entries.
2069  *
2070  * @param cls closure
2071  * @param key current key code
2072  * @param value value in the hash map
2073  * @return GNUNET_YES if we should continue to
2074  *         iterate,
2075  *         GNUNET_NO if not.
2076  */
2077 static int add_pkey_to_extended (void *cls,
2078                                  const GNUNET_HashCode * key,
2079                                  void *value)
2080 {
2081   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pkey = cls;
2082   struct DistantNeighbor *distant_neighbor = value;
2083
2084   if (distant_neighbor->pkey == NULL)
2085   {
2086     distant_neighbor->pkey = GNUNET_malloc(sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
2087     memcpy(distant_neighbor->pkey, pkey, sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
2088   }
2089
2090   return GNUNET_YES;
2091 }
2092 #endif
2093
2094 /**
2095  * Iterator over hash map entries.
2096  *
2097  * @param cls closure
2098  * @param key current key code
2099  * @param value value in the hash map
2100  * @return GNUNET_YES if we should continue to
2101  *         iterate,
2102  *         GNUNET_NO if not.
2103  */
2104 static int update_matching_neighbors (void *cls,
2105                                       const GNUNET_HashCode * key,
2106                                       void *value)
2107 {
2108   struct NeighborUpdateInfo * update_info = cls;
2109   struct DistantNeighbor *distant_neighbor = value;
2110
2111   if (update_info->referrer == distant_neighbor->referrer) /* Direct neighbor matches, update it's info and return GNUNET_NO */
2112   {
2113     /* same referrer, cost change! */
2114     GNUNET_CONTAINER_heap_update_cost (neighbor_max_heap,
2115                                        update_info->neighbor->max_loc, update_info->cost);
2116     GNUNET_CONTAINER_heap_update_cost (neighbor_min_heap,
2117                                        update_info->neighbor->min_loc, update_info->cost);
2118     update_info->neighbor->last_activity = update_info->now;
2119     update_info->neighbor->cost = update_info->cost;
2120     update_info->neighbor->referrer_id = update_info->referrer_peer_id;
2121     return GNUNET_NO;
2122   }
2123
2124   return GNUNET_YES;
2125 }
2126
2127
2128 /**
2129  * Iterate over all current direct peers, add DISTANT newly connected
2130  * peer to the fast gossip list for that peer so we get DV routing
2131  * information out as fast as possible!
2132  *
2133  * @param cls the newly connected neighbor we will gossip about
2134  * @param key the hashcode of the peer
2135  * @param value the direct neighbor we should gossip to
2136  *
2137  * @return GNUNET_YES to continue iteration, GNUNET_NO otherwise
2138  */
2139 static int add_distant_all_direct_neighbors (void *cls,
2140                                      const GNUNET_HashCode * key,
2141                                      void *value)
2142 {
2143   struct DirectNeighbor *direct = (struct DirectNeighbor *)value;
2144   struct DistantNeighbor *distant = (struct DistantNeighbor *)cls;
2145   struct NeighborSendContext *send_context = direct->send_context;
2146   struct FastGossipNeighborList *gossip_entry;
2147 #if DEBUG_DV
2148   char *encPeerAbout;
2149   char *encPeerTo;
2150 #endif
2151
2152   if (distant == NULL)
2153     {
2154       return GNUNET_YES;
2155     }
2156
2157   if (memcmp(&direct->identity, &distant->identity, sizeof(struct GNUNET_PeerIdentity)) == 0)
2158     {
2159       return GNUNET_YES; /* Don't gossip to a peer about itself! */
2160     }
2161
2162 #if SUPPORT_HIDING
2163   if (distant->hidden == GNUNET_YES)
2164     return GNUNET_YES; /* This peer should not be gossipped about (hidden) */
2165 #endif
2166   gossip_entry = GNUNET_malloc(sizeof(struct FastGossipNeighborList));
2167   gossip_entry->about = distant;
2168
2169   GNUNET_CONTAINER_DLL_insert_after(send_context->fast_gossip_list_head,
2170                                     send_context->fast_gossip_list_tail,
2171                                     send_context->fast_gossip_list_tail,
2172                                     gossip_entry);
2173 #if DEBUG_DV
2174   encPeerAbout = GNUNET_strdup(GNUNET_i2s(&distant->identity));
2175   encPeerTo = GNUNET_strdup(GNUNET_i2s(&direct->identity));
2176
2177   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s: Fast send info about peer %s id %u for directly connected peer %s\n",
2178              GNUNET_i2s(&my_identity),
2179              encPeerAbout, distant->our_id, encPeerTo);
2180   GNUNET_free(encPeerAbout);
2181   GNUNET_free(encPeerTo);
2182 #endif
2183   /*if (send_context->task != GNUNET_SCHEDULER_NO_TASK)
2184     GNUNET_SCHEDULER_cancel(sched, send_context->task);*/
2185
2186   send_context->task = GNUNET_SCHEDULER_add_now(sched, &neighbor_send_task, send_context);
2187   return GNUNET_YES;
2188 }
2189
2190 /**
2191  * Callback for hello address creation.
2192  *
2193  * @param cls closure, a struct HelloContext
2194  * @param max maximum number of bytes that can be written to buf
2195  * @param buf where to write the address information
2196  *
2197  * @return number of bytes written, 0 to signal the
2198  *         end of the iteration.
2199  */
2200 static size_t
2201 generate_hello_address (void *cls, size_t max, void *buf)
2202 {
2203   struct HelloContext *hello_context = cls;
2204   char *addr_buffer;
2205   size_t offset;
2206   size_t size;
2207   size_t ret;
2208
2209   if (hello_context->addresses_to_add == 0)
2210     return 0;
2211
2212   /* Hello "address" will be concatenation of distant peer and direct peer identities */
2213   size = 2 * sizeof(struct GNUNET_PeerIdentity);
2214   GNUNET_assert(max >= size);
2215
2216   addr_buffer = GNUNET_malloc(size);
2217   offset = 0;
2218   /* Copy the distant peer identity to buffer */
2219   memcpy(addr_buffer, &hello_context->distant_peer, sizeof(struct GNUNET_PeerIdentity));
2220   offset += sizeof(struct GNUNET_PeerIdentity);
2221   /* Copy the direct peer identity to buffer */
2222   memcpy(&addr_buffer[offset], hello_context->direct_peer, sizeof(struct GNUNET_PeerIdentity));
2223   ret = GNUNET_HELLO_add_address ("dv",
2224                                   GNUNET_TIME_relative_to_absolute
2225                                   (GNUNET_TIME_UNIT_HOURS), addr_buffer, size,
2226                                   buf, max);
2227
2228   hello_context->addresses_to_add--;
2229
2230   GNUNET_free(addr_buffer);
2231   return ret;
2232 }
2233
2234
2235 /**
2236  * Handles when a peer is either added due to being newly connected
2237  * or having been gossiped about, also called when the cost for a neighbor
2238  * needs to be updated.
2239  *
2240  * @param peer identity of the peer whose info is being added/updated
2241  * @param pkey public key of the peer whose info is being added/updated
2242  * @param referrer_peer_id id to use when sending to 'peer'
2243  * @param referrer if this is a gossiped peer, who did we hear it from?
2244  * @param cost the cost of communicating with this peer via 'referrer'
2245  *
2246  * @return the added neighbor, the updated neighbor or NULL (neighbor
2247  *         not added)
2248  */
2249 static struct DistantNeighbor *
2250 addUpdateNeighbor (const struct GNUNET_PeerIdentity * peer, struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pkey,
2251                    unsigned int referrer_peer_id,
2252                    struct DirectNeighbor *referrer, unsigned int cost)
2253 {
2254   struct DistantNeighbor *neighbor;
2255   struct DistantNeighbor *max;
2256   struct GNUNET_TIME_Absolute now;
2257   struct NeighborUpdateInfo *neighbor_update;
2258   struct HelloContext *hello_context;
2259   struct GNUNET_HELLO_Message *hello_msg;
2260   unsigned int our_id;
2261   char *addr1;
2262   char *addr2;
2263
2264 #if DEBUG_DV_PEER_NUMBERS
2265   char *encAbout;
2266   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2267               "%s Received sender id (%u)!\n", "DV SERVICE", referrer_peer_id);
2268 #endif
2269
2270   now = GNUNET_TIME_absolute_get ();
2271   neighbor = GNUNET_CONTAINER_multihashmap_get (extended_neighbors,
2272                                                 &peer->hashPubKey);
2273   neighbor_update = GNUNET_malloc(sizeof(struct NeighborUpdateInfo));
2274   neighbor_update->neighbor = neighbor;
2275   neighbor_update->cost = cost;
2276   neighbor_update->now = now;
2277   neighbor_update->referrer = referrer;
2278   neighbor_update->referrer_peer_id = referrer_peer_id;
2279
2280   if (neighbor != NULL)
2281     {
2282 #if USE_PEER_ID
2283       memcpy(&our_id, &neighbor->identity, sizeof(unsigned int));
2284 #else
2285       our_id = neighbor->our_id;
2286 #endif
2287     }
2288   else
2289     {
2290 #if USE_PEER_ID
2291       memcpy(&our_id, peer, sizeof(unsigned int));
2292 #else
2293       our_id = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, RAND_MAX - 1) + 1;
2294 #endif
2295     }
2296
2297   /* Either we do not know this peer, or we already do but via a different immediate peer */
2298   if ((neighbor == NULL) ||
2299       (GNUNET_CONTAINER_multihashmap_get_multiple(extended_neighbors,
2300                                                   &peer->hashPubKey,
2301                                                   &update_matching_neighbors,
2302                                                   neighbor_update) != GNUNET_SYSERR))
2303     {
2304
2305 #if AT_MOST_ONE
2306     if ((neighbor != NULL) && (cost < neighbor->cost)) /* New cost is less than old, remove old */
2307       {
2308         distant_neighbor_free(neighbor);
2309       }
2310     else if (neighbor != NULL) /* Only allow one DV connection to each peer */
2311       {
2312         return NULL;
2313       }
2314 #endif
2315       /* new neighbor! */
2316       if (cost > fisheye_depth)
2317         {
2318           /* too costly */
2319           GNUNET_free(neighbor_update);
2320           return NULL;
2321         }
2322
2323 #if DEBUG_DV_PEER_NUMBERS
2324       encAbout = GNUNET_strdup(GNUNET_i2s(peer));
2325       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2326                   "%s: %s Chose NEW id (%u) for peer %s!\n", GNUNET_i2s(&my_identity), "DV SERVICE", our_id, encAbout);
2327       GNUNET_free(encAbout);
2328 #endif
2329
2330       if (max_table_size <=
2331           GNUNET_CONTAINER_multihashmap_size (extended_neighbors))
2332         {
2333           /* remove most expensive entry */
2334           max = GNUNET_CONTAINER_heap_peek (neighbor_max_heap);
2335           GNUNET_assert(max != NULL);
2336           if (cost > max->cost)
2337             {
2338               /* new entry most expensive, don't create */
2339               GNUNET_free(neighbor_update);
2340               return NULL;
2341             }
2342           if (max->cost > 1)
2343             {
2344               /* only free if this is not a direct connection;
2345                  we could theoretically have more direct
2346                  connections than DV entries allowed total! */
2347               distant_neighbor_free (max);
2348             }
2349         }
2350
2351       neighbor = GNUNET_malloc (sizeof (struct DistantNeighbor));
2352       GNUNET_CONTAINER_DLL_insert (referrer->referee_head,
2353                          referrer->referee_tail, neighbor);
2354       neighbor->max_loc = GNUNET_CONTAINER_heap_insert (neighbor_max_heap,
2355                                                         neighbor, cost);
2356       neighbor->min_loc = GNUNET_CONTAINER_heap_insert (neighbor_min_heap,
2357                                                         neighbor, cost);
2358       neighbor->referrer = referrer;
2359       memcpy (&neighbor->identity, peer, sizeof (struct GNUNET_PeerIdentity));
2360       if (pkey != NULL) /* pkey will be null on direct neighbor addition */
2361       {
2362         neighbor->pkey = GNUNET_malloc(sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
2363         memcpy (neighbor->pkey, pkey, sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
2364       }
2365       else
2366         neighbor->pkey = pkey;
2367
2368       neighbor->last_activity = now;
2369       neighbor->cost = cost;
2370       neighbor->referrer_id = referrer_peer_id;
2371       neighbor->our_id = our_id;
2372       neighbor->hidden =
2373         (cost == DIRECT_NEIGHBOR_COST) ? (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 4) ==
2374                        0) : GNUNET_NO;
2375
2376       GNUNET_CONTAINER_multihashmap_put (extended_neighbors, &peer->hashPubKey,
2377                                  neighbor,
2378                                  GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
2379
2380       if (cost != DIRECT_NEIGHBOR_COST)
2381         {
2382           /* Added neighbor, now send HELLO to transport */
2383           hello_context = GNUNET_malloc(sizeof(struct HelloContext));
2384           hello_context->direct_peer = &referrer->identity;
2385           memcpy(&hello_context->distant_peer, peer, sizeof(struct GNUNET_PeerIdentity));
2386           hello_context->addresses_to_add = 1;
2387           hello_msg = GNUNET_HELLO_create(pkey, &generate_hello_address, hello_context);
2388           GNUNET_assert(memcmp(hello_context->direct_peer, &hello_context->distant_peer, sizeof(struct GNUNET_PeerIdentity)) != 0);
2389           addr1 = GNUNET_strdup(GNUNET_i2s(hello_context->direct_peer));
2390           addr2 = GNUNET_strdup(GNUNET_i2s(&hello_context->distant_peer));
2391           GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s: GIVING HELLO size %d for %s via %s to TRANSPORT\n", my_short_id, GNUNET_HELLO_size(hello_msg), addr2, addr1);
2392           GNUNET_free(addr1);
2393           GNUNET_free(addr2);
2394           send_to_plugin(hello_context->direct_peer, GNUNET_HELLO_get_header(hello_msg), GNUNET_HELLO_size(hello_msg), &hello_context->distant_peer, cost);
2395           GNUNET_free(hello_context);
2396           GNUNET_free(hello_msg);
2397         }
2398
2399     }
2400   else
2401     {
2402 #if DEBUG_DV_GOSSIP
2403       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2404                   "%s: Already know peer %s distance %d, referrer id %d!\n", "dv", GNUNET_i2s(peer), cost, referrer_peer_id);
2405 #endif
2406     }
2407 #if DEBUG_DV
2408     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2409                 "%s: Size of extended_neighbors is %d\n", "dv", GNUNET_CONTAINER_multihashmap_size(extended_neighbors));
2410 #endif
2411
2412   GNUNET_free(neighbor_update);
2413   return neighbor;
2414 }
2415
2416
2417 /**
2418  * Core handler for dv disconnect messages.  These will be used
2419  * by us to tell transport via the dv plugin that a peer can
2420  * no longer be contacted by us via a certain address.  We should
2421  * then propagate these messages on, given that the distance to
2422  * the peer indicates we would have gossiped about it to others.
2423  *
2424  * @param cls closure
2425  * @param peer peer which sent the message (immediate sender)
2426  * @param message the message
2427  * @param latency the latency of the connection we received the message from
2428  * @param distance the distance to the immediate peer
2429  */
2430 static int handle_dv_disconnect_message (void *cls,
2431                                          const struct GNUNET_PeerIdentity *peer,
2432                                          const struct GNUNET_MessageHeader *message,
2433                                          struct GNUNET_TIME_Relative latency,
2434                                          uint32_t distance)
2435 {
2436   struct DirectNeighbor *referrer;
2437   struct DistantNeighbor *distant;
2438   p2p_dv_MESSAGE_Disconnect *enc_message = (p2p_dv_MESSAGE_Disconnect *)message;
2439
2440   if (ntohs (message->size) < sizeof (p2p_dv_MESSAGE_Disconnect))
2441     {
2442       return GNUNET_SYSERR;     /* invalid message */
2443     }
2444
2445   referrer = GNUNET_CONTAINER_multihashmap_get (direct_neighbors,
2446                                                 &peer->hashPubKey);
2447   if (referrer == NULL)
2448     return GNUNET_OK;
2449
2450   distant = referrer->referee_head;
2451   while (distant != NULL)
2452     {
2453       if (distant->referrer_id == ntohl(enc_message->peer_id))
2454         {
2455           distant_neighbor_free(distant);
2456         }
2457       distant = referrer->referee_head;
2458     }
2459
2460   return GNUNET_OK;
2461 }
2462
2463
2464 /**
2465  * Core handler for dv gossip messages.  These will be used
2466  * by us to create a HELLO message for the newly peer containing
2467  * which direct peer we can connect through, and what the cost
2468  * is.  This HELLO will then be scheduled for validation by the
2469  * transport service so that it can be used by all others.
2470  *
2471  * @param cls closure
2472  * @param peer peer which sent the message (immediate sender)
2473  * @param message the message
2474  * @param latency the latency of the connection we received the message from
2475  * @param distance the distance to the immediate peer
2476  */
2477 static int handle_dv_gossip_message (void *cls,
2478                                      const struct GNUNET_PeerIdentity *peer,
2479                                      const struct GNUNET_MessageHeader *message,
2480                                      struct GNUNET_TIME_Relative latency,
2481                                      uint32_t distance)
2482 {
2483   struct DirectNeighbor *referrer;
2484   p2p_dv_MESSAGE_NeighborInfo *enc_message = (p2p_dv_MESSAGE_NeighborInfo *)message;
2485
2486   if (ntohs (message->size) < sizeof (p2p_dv_MESSAGE_NeighborInfo))
2487     {
2488       return GNUNET_SYSERR;     /* invalid message */
2489     }
2490
2491 #if DEBUG_DV_GOSSIP_RECEIPT
2492   char * encPeerAbout;
2493   char * encPeerFrom;
2494
2495   encPeerAbout = GNUNET_strdup(GNUNET_i2s(&enc_message->neighbor));
2496   encPeerFrom = GNUNET_strdup(GNUNET_i2s(peer));
2497   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2498               "%s: Received %s message from peer %s about peer %s id %u distance %d!\n", GNUNET_i2s(&my_identity), "DV GOSSIP", encPeerFrom, encPeerAbout, ntohl(enc_message->neighbor_id), ntohl (enc_message->cost) + 1);
2499   GNUNET_free(encPeerAbout);
2500   GNUNET_free(encPeerFrom);
2501 #endif
2502
2503   referrer = GNUNET_CONTAINER_multihashmap_get (direct_neighbors,
2504                                                 &peer->hashPubKey);
2505   if (referrer == NULL)
2506     return GNUNET_OK;
2507
2508   addUpdateNeighbor (&enc_message->neighbor, &enc_message->pkey,
2509                      ntohl (enc_message->neighbor_id),
2510                      referrer, ntohl (enc_message->cost) + 1);
2511
2512   return GNUNET_OK;
2513 }
2514
2515
2516 /**
2517  * Iterate over all currently known peers, add them to the
2518  * fast gossip list for this peer so we get DV routing information
2519  * out as fast as possible!
2520  *
2521  * @param cls the direct neighbor we will gossip to
2522  * @param key the hashcode of the peer
2523  * @param value the distant neighbor we should add to the list
2524  *
2525  * @return GNUNET_YES to continue iteration, GNUNET_NO otherwise
2526  */
2527 static int add_all_extended_peers (void *cls,
2528                                    const GNUNET_HashCode * key,
2529                                    void *value)
2530 {
2531   struct NeighborSendContext *send_context = (struct NeighborSendContext *)cls;
2532   struct DistantNeighbor *distant = (struct DistantNeighbor *)value;
2533   struct FastGossipNeighborList *gossip_entry;
2534
2535   if (memcmp(&send_context->toNeighbor->identity, &distant->identity, sizeof(struct GNUNET_PeerIdentity)) == 0)
2536     return GNUNET_YES; /* Don't gossip to a peer about itself! */
2537
2538 #if SUPPORT_HIDING
2539   if (distant->hidden == GNUNET_YES)
2540     return GNUNET_YES; /* This peer should not be gossipped about (hidden) */
2541 #endif
2542   gossip_entry = GNUNET_malloc(sizeof(struct FastGossipNeighborList));
2543   gossip_entry->about = distant;
2544
2545   GNUNET_CONTAINER_DLL_insert_after(send_context->fast_gossip_list_head,
2546                                     send_context->fast_gossip_list_tail,
2547                                     send_context->fast_gossip_list_tail,
2548                                     gossip_entry);
2549
2550   return GNUNET_YES;
2551 }
2552
2553 #if INSANE_GOSSIP
2554 /**
2555  * Iterator over hash map entries.
2556  *
2557  * @param cls closure
2558  * @param key current key code
2559  * @param value value in the hash map
2560  * @return GNUNET_YES if we should continue to
2561  *         iterate,
2562  *         GNUNET_NO if not.
2563  */
2564 static int gossip_all_to_all_iterator (void *cls,
2565                                       const GNUNET_HashCode * key,
2566                                       void *value)
2567 {
2568   struct DirectNeighbor *direct = value;
2569
2570   GNUNET_CONTAINER_multihashmap_iterate (extended_neighbors, &add_all_extended_peers, direct->send_context);
2571
2572   if (direct->send_context->task != GNUNET_SCHEDULER_NO_TASK)
2573     GNUNET_SCHEDULER_cancel(sched, direct->send_context->task);
2574
2575   direct->send_context->task = GNUNET_SCHEDULER_add_now(sched, &neighbor_send_task, direct->send_context);
2576   return GNUNET_YES;
2577 }
2578
2579 /**
2580  * Task run during shutdown.
2581  *
2582  * @param cls unused
2583  * @param tc unused
2584  */
2585 static void
2586 gossip_all_to_all (void *cls,
2587                    const struct GNUNET_SCHEDULER_TaskContext *tc)
2588 {
2589   GNUNET_CONTAINER_multihashmap_iterate (direct_neighbors, &gossip_all_to_all_iterator, NULL);
2590
2591   GNUNET_SCHEDULER_add_delayed (sched,
2592                                 GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5),
2593                                 &gossip_all_to_all,
2594                                 NULL);
2595
2596 }
2597 #endif
2598 /**
2599  * Iterate over all current direct peers, add newly connected peer
2600  * to the fast gossip list for that peer so we get DV routing
2601  * information out as fast as possible!
2602  *
2603  * @param cls the newly connected neighbor we will gossip about
2604  * @param key the hashcode of the peer
2605  * @param value the direct neighbor we should gossip to
2606  *
2607  * @return GNUNET_YES to continue iteration, GNUNET_NO otherwise
2608  */
2609 static int add_all_direct_neighbors (void *cls,
2610                                      const GNUNET_HashCode * key,
2611                                      void *value)
2612 {
2613   struct DirectNeighbor *direct = (struct DirectNeighbor *)value;
2614   struct DirectNeighbor *to = (struct DirectNeighbor *)cls;
2615   struct DistantNeighbor *distant;
2616   struct NeighborSendContext *send_context = direct->send_context;
2617   struct FastGossipNeighborList *gossip_entry;
2618   char *direct_id;
2619
2620
2621   distant = GNUNET_CONTAINER_multihashmap_get(extended_neighbors, &to->identity.hashPubKey);
2622   if (distant == NULL)
2623     {
2624       return GNUNET_YES;
2625     }
2626
2627   if (memcmp(&direct->identity, &to->identity, sizeof(struct GNUNET_PeerIdentity)) == 0)
2628     {
2629       return GNUNET_YES; /* Don't gossip to a peer about itself! */
2630     }
2631
2632 #if SUPPORT_HIDING
2633   if (distant->hidden == GNUNET_YES)
2634     return GNUNET_YES; /* This peer should not be gossipped about (hidden) */
2635 #endif
2636   direct_id = GNUNET_strdup(GNUNET_i2s(&direct->identity));
2637 #if DEBUG_DV_GOSSIP
2638   GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "%s: adding peer %s to fast send list for %s\n", my_short_id, GNUNET_i2s(&distant->identity), direct_id);
2639 #endif
2640   GNUNET_free(direct_id);
2641   gossip_entry = GNUNET_malloc(sizeof(struct FastGossipNeighborList));
2642   gossip_entry->about = distant;
2643
2644   GNUNET_CONTAINER_DLL_insert_after(send_context->fast_gossip_list_head,
2645                                     send_context->fast_gossip_list_tail,
2646                                     send_context->fast_gossip_list_tail,
2647                                     gossip_entry);
2648   if (send_context->task != GNUNET_SCHEDULER_NO_TASK)
2649     GNUNET_SCHEDULER_cancel(sched, send_context->task);
2650
2651   send_context->task = GNUNET_SCHEDULER_add_now(sched, &neighbor_send_task, send_context);
2652   //tc.reason = GNUNET_SCHEDULER_REASON_TIMEOUT;
2653   //neighbor_send_task(send_context, &tc);
2654   return GNUNET_YES;
2655 }
2656
2657 /**
2658  * Type of an iterator over the hosts.  Note that each
2659  * host will be called with each available protocol.
2660  *
2661  * @param cls closure
2662  * @param peer id of the peer, NULL for last call
2663  * @param hello hello message for the peer (can be NULL)
2664  * @param trust amount of trust we have in the peer
2665  */
2666 static void
2667 process_peerinfo (void *cls,
2668                   const struct GNUNET_PeerIdentity *peer,
2669                   const struct GNUNET_HELLO_Message *hello, uint32_t trust)
2670 {
2671   struct PeerIteratorContext *peerinfo_iterator = cls;
2672   struct DirectNeighbor *neighbor = peerinfo_iterator->neighbor;
2673   struct DistantNeighbor *distant = peerinfo_iterator->distant;
2674 #if DEBUG_DV_PEER_NUMBERS
2675   char *neighbor_pid;
2676 #endif
2677   int sent;
2678
2679   if (peer == NULL)
2680     {
2681       if (distant->pkey == NULL)
2682         {
2683 #if DEBUG_DV
2684           GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Failed to get peerinfo information for this peer, retrying!\n");
2685 #endif
2686           peerinfo_iterator->ic = GNUNET_PEERINFO_iterate(peerinfo_handle,
2687                                                           &peerinfo_iterator->neighbor->identity,
2688                                                           0,
2689                                                           GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3),
2690                                                           &process_peerinfo,
2691                                                           peerinfo_iterator);
2692         }
2693       else
2694         {
2695           GNUNET_free(peerinfo_iterator);
2696         }
2697       return;
2698     }
2699
2700   if (memcmp(&neighbor->identity, peer, sizeof(struct GNUNET_PeerIdentity) != 0))
2701     return;
2702
2703   if ((hello != NULL) && (GNUNET_HELLO_get_key (hello, &neighbor->pkey) == GNUNET_OK))
2704     {
2705       if (distant->pkey == NULL)
2706         {
2707           distant->pkey = GNUNET_malloc(sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
2708           memcpy(distant->pkey, &neighbor->pkey, sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
2709         }
2710
2711       sent = GNUNET_CONTAINER_multihashmap_iterate (extended_neighbors, &add_all_extended_peers, neighbor->send_context);
2712
2713 #if DEBUG_DV_PEER_NUMBERS
2714       neighbor_pid = GNUNET_strdup(GNUNET_i2s(&neighbor->identity));
2715       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s: Gossipped %d extended peers to %s\n", GNUNET_i2s(&my_identity), sent, neighbor_pid);
2716 #endif
2717       sent = GNUNET_CONTAINER_multihashmap_iterate (direct_neighbors, &add_all_direct_neighbors, neighbor);
2718 #if DEBUG_DV_PEER_NUMBERS
2719       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s: Gossipped about %s to %d direct peers\n", GNUNET_i2s(&my_identity), neighbor_pid, sent);
2720       GNUNET_free(neighbor_pid);
2721 #endif
2722       neighbor->send_context->task = GNUNET_SCHEDULER_add_now(sched, &neighbor_send_task, neighbor->send_context);
2723     }
2724 }
2725
2726
2727 /**
2728  * Method called whenever a peer connects.
2729  *
2730  * @param cls closure
2731  * @param peer peer identity this notification is about
2732  * @param latency reported latency of the connection with peer
2733  * @param distance reported distance (DV) to peer
2734  */
2735 void handle_core_connect (void *cls,
2736                           const struct GNUNET_PeerIdentity * peer,
2737                           struct GNUNET_TIME_Relative latency,
2738                           uint32_t distance)
2739 {
2740   struct DirectNeighbor *neighbor;
2741   struct DistantNeighbor *about;
2742   struct PeerIteratorContext *peerinfo_iterator;
2743   int sent;
2744 #if DEBUG_DV
2745   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2746               "%s: Receives core connect message for peer %s distance %d!\n", "dv", GNUNET_i2s(peer), distance);
2747 #endif
2748
2749   if ((distance == DIRECT_NEIGHBOR_COST) && (GNUNET_CONTAINER_multihashmap_get(direct_neighbors, &peer->hashPubKey) == NULL))
2750   {
2751     peerinfo_iterator = GNUNET_malloc(sizeof(struct PeerIteratorContext));
2752     neighbor = GNUNET_malloc (sizeof (struct DirectNeighbor));
2753     neighbor->send_context = GNUNET_malloc(sizeof(struct NeighborSendContext));
2754     neighbor->send_context->toNeighbor = neighbor;
2755     memcpy (&neighbor->identity, peer, sizeof (struct GNUNET_PeerIdentity));
2756
2757     GNUNET_assert(GNUNET_SYSERR != GNUNET_CONTAINER_multihashmap_put (direct_neighbors,
2758                                &peer->hashPubKey,
2759                                neighbor, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
2760     about = addUpdateNeighbor (peer, NULL, 0, neighbor, DIRECT_NEIGHBOR_COST);
2761     peerinfo_iterator->distant = about;
2762     peerinfo_iterator->neighbor = neighbor;
2763     peerinfo_iterator->ic = GNUNET_PEERINFO_iterate (peerinfo_handle,
2764                                                      peer,
2765                                                      0,
2766                                                      GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3),
2767                                                      &process_peerinfo,
2768                                                      peerinfo_iterator);
2769
2770     if ((about != NULL) && (about->pkey == NULL))
2771       {
2772 #if DEBUG_DV
2773         GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Newly added peer %s has NULL pkey!\n", GNUNET_i2s(peer));
2774 #endif
2775       }
2776     else if (about != NULL)
2777       {
2778         GNUNET_free(peerinfo_iterator);
2779       }
2780   }
2781   else
2782   {
2783     about = GNUNET_CONTAINER_multihashmap_get(extended_neighbors, &peer->hashPubKey);
2784     if ((GNUNET_CONTAINER_multihashmap_get(direct_neighbors, &peer->hashPubKey) == NULL) && (about != NULL))
2785       sent = GNUNET_CONTAINER_multihashmap_iterate(direct_neighbors, &add_distant_all_direct_neighbors, about);
2786 #if DEBUG_DV
2787     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2788                 "%s: Distance (%d) greater than %d or already know about peer (%s), not re-adding!\n", "dv", distance, DIRECT_NEIGHBOR_COST, GNUNET_i2s(peer));
2789 #endif
2790     return;
2791   }
2792 }
2793
2794 /**
2795  * Method called whenever a given peer disconnects.
2796  *
2797  * @param cls closure
2798  * @param peer peer identity this notification is about
2799  */
2800 void handle_core_disconnect (void *cls,
2801                              const struct GNUNET_PeerIdentity * peer)
2802 {
2803   struct DirectNeighbor *neighbor;
2804   struct DistantNeighbor *referee;
2805   struct FindDestinationContext fdc;
2806   struct DisconnectContext disconnect_context;
2807
2808 #if DEBUG_DV
2809   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2810               "%s: Receives core peer disconnect message!\n", "dv");
2811 #endif
2812
2813   neighbor =
2814     GNUNET_CONTAINER_multihashmap_get (direct_neighbors, &peer->hashPubKey);
2815   if (neighbor == NULL)
2816     {
2817       return;
2818     }
2819   while (NULL != (referee = neighbor->referee_head))
2820     distant_neighbor_free (referee);
2821
2822   fdc.dest = NULL;
2823   fdc.tid = 0;
2824
2825   GNUNET_CONTAINER_multihashmap_iterate (extended_neighbors, &find_distant_peer, &fdc);
2826
2827   if (fdc.dest != NULL)
2828     {
2829       disconnect_context.direct = neighbor;
2830       disconnect_context.distant = fdc.dest;
2831       GNUNET_CONTAINER_multihashmap_iterate (direct_neighbors, &schedule_disconnect_messages, &disconnect_context);
2832     }
2833
2834   GNUNET_assert (neighbor->referee_tail == NULL);
2835   if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_remove (direct_neighbors,
2836                                         &peer->hashPubKey, neighbor))
2837     {
2838       GNUNET_break(0);
2839     }
2840   if ((neighbor->send_context != NULL) && (neighbor->send_context->task != GNUNET_SCHEDULER_NO_TASK))
2841     GNUNET_SCHEDULER_cancel(sched, neighbor->send_context->task);
2842   GNUNET_free (neighbor);
2843 }
2844
2845
2846 /**
2847  * Process dv requests.
2848  *
2849  * @param cls closure
2850  * @param scheduler scheduler to use
2851  * @param server the initialized server
2852  * @param c configuration to use
2853  */
2854 static void
2855 run (void *cls,
2856      struct GNUNET_SCHEDULER_Handle *scheduler,
2857      struct GNUNET_SERVER_Handle *server,
2858      const struct GNUNET_CONFIGURATION_Handle *c)
2859 {
2860   unsigned long long max_hosts;
2861   sched = scheduler;
2862   cfg = c;
2863
2864   /* FIXME: Read from config, or calculate, or something other than this! */
2865   max_hosts = DEFAULT_DIRECT_CONNECTIONS;
2866   max_table_size = DEFAULT_DV_SIZE;
2867   fisheye_depth = DEFAULT_FISHEYE_DEPTH;
2868
2869   if (GNUNET_CONFIGURATION_have_value(cfg, "dv", "max_direct_connections"))
2870     GNUNET_assert(GNUNET_OK == GNUNET_CONFIGURATION_get_value_number(cfg, "dv", "max_direct_connections", &max_hosts));
2871
2872   if (GNUNET_CONFIGURATION_have_value(cfg, "dv", "max_total_connections"))
2873     GNUNET_assert(GNUNET_OK == GNUNET_CONFIGURATION_get_value_number(cfg, "dv", "max_total_connections", &max_table_size));
2874
2875
2876   if (GNUNET_CONFIGURATION_have_value(cfg, "dv", "fisheye_depth"))
2877     GNUNET_assert(GNUNET_OK == GNUNET_CONFIGURATION_get_value_number(cfg, "dv", "fisheye_depth", &fisheye_depth));
2878
2879   neighbor_min_heap =
2880     GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2881   neighbor_max_heap =
2882     GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MAX);
2883
2884   direct_neighbors = GNUNET_CONTAINER_multihashmap_create (max_hosts);
2885   extended_neighbors =
2886     GNUNET_CONTAINER_multihashmap_create (max_table_size * 3);
2887
2888   GNUNET_SERVER_add_handlers (server, plugin_handlers);
2889   coreAPI =
2890   GNUNET_CORE_connect (sched,
2891                        cfg,
2892                        GNUNET_TIME_relative_get_forever(),
2893                        NULL, /* FIXME: anything we want to pass around? */
2894                        &core_init,
2895                        &handle_core_connect,
2896                        &handle_core_disconnect,
2897                        NULL,
2898                        GNUNET_NO,
2899                        NULL,
2900                        GNUNET_NO,
2901                        core_handlers);
2902
2903   if (coreAPI == NULL)
2904     return;
2905
2906   coreMST = GNUNET_SERVER_mst_create (GNUNET_SERVER_MAX_MESSAGE_SIZE,
2907                                       &tokenized_message_handler,
2908                                       NULL);
2909
2910    peerinfo_handle = GNUNET_PEERINFO_connect(sched, cfg);
2911
2912    if (peerinfo_handle == NULL)
2913      {
2914        GNUNET_CORE_disconnect(coreAPI);
2915        return;
2916      }
2917
2918   /* Scheduled the task to clean up when shutdown is called */
2919   cleanup_task = GNUNET_SCHEDULER_add_delayed (sched,
2920                                 GNUNET_TIME_UNIT_FOREVER_REL,
2921                                 &shutdown_task,
2922                                 NULL);
2923 #if INSANE_GOSSIP
2924   GNUNET_SCHEDULER_add_delayed (sched,
2925                                 GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5),
2926                                 &gossip_all_to_all,
2927                                 NULL);
2928 #endif
2929 }
2930
2931
2932 /**
2933  * The main function for the dv service.
2934  *
2935  * @param argc number of arguments from the command line
2936  * @param argv command line arguments
2937  * @return 0 ok, 1 on error
2938  */
2939 int
2940 main (int argc, char *const *argv)
2941 {
2942   return (GNUNET_OK ==
2943           GNUNET_SERVICE_run (argc,
2944                               argv,
2945                               "dv",
2946                               GNUNET_SERVICE_OPTION_NONE,
2947                               &run, NULL)) ? 0 : 1;
2948 }