f375887edee86f0ba9ace179df2afa85162849c7
[oweals/gnunet.git] / src / transport / gnunet-service-transport.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 transport/gnunet-service-transport.c
23  * @brief low-level P2P messaging
24  * @author Christian Grothoff
25  *
26  * NOTE:
27  * - This code uses 'GNUNET_a2s' for debug printing in many places,
28  *   which is technically wrong since it assumes we have IP+Port 
29  *   (v4/v6) addresses.  Once we add transports like http or smtp
30  *   this will have to be changed!
31  */
32 #include "platform.h"
33 #include "gnunet_client_lib.h"
34 #include "gnunet_container_lib.h"
35 #include "gnunet_constants.h"
36 #include "gnunet_getopt_lib.h"
37 #include "gnunet_hello_lib.h"
38 #include "gnunet_os_lib.h"
39 #include "gnunet_peerinfo_service.h"
40 #include "gnunet_plugin_lib.h"
41 #include "gnunet_protocols.h"
42 #include "gnunet_service_lib.h"
43 #include "gnunet_signatures.h"
44 #include "plugin_transport.h"
45 #include "transport.h"
46
47 /**
48  * How many messages can we have pending for a given client process
49  * before we start to drop incoming messages?  We typically should
50  * have only one client and so this would be the primary buffer for
51  * messages, so the number should be chosen rather generously.
52  *
53  * The expectation here is that most of the time the queue is large
54  * enough so that a drop is virtually never required.
55  */
56 #define MAX_PENDING 128
57
58 /**
59  * How often should we try to reconnect to a peer using a particular
60  * transport plugin before giving up?  Note that the plugin may be
61  * added back to the list after PLUGIN_RETRY_FREQUENCY expires.
62  */
63 #define MAX_CONNECT_RETRY 3
64
65 /**
66  * Limit on the number of ready-to-run tasks when validating 
67  * HELLOs.  If more tasks are ready to run, we will drop 
68  * HELLOs instead of validating them.
69  */
70 #define MAX_HELLO_LOAD 4
71
72 /**
73  * How often must a peer violate bandwidth quotas before we start
74  * to simply drop its messages?
75  */
76 #define QUOTA_VIOLATION_DROP_THRESHOLD 100
77
78 /**
79  * How long until a HELLO verification attempt should time out?
80  * Must be rather small, otherwise a partially successful HELLO
81  * validation (some addresses working) might not be available
82  * before a client's request for a connection fails for good.
83  * Besides, if a single request to an address takes a long time,
84  * then the peer is unlikely worthwhile anyway.
85  */
86 #define HELLO_VERIFICATION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
87
88 /**
89  * How long will we allow sending of a ping to be delayed?
90  */
91 #define TRANSPORT_DEFAULT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15)
92
93 /**
94  * Priority to use for PONG messages.
95  */
96 #define TRANSPORT_PONG_PRIORITY 4
97
98 /**
99  * How often do we re-add (cheaper) plugins to our list of plugins
100  * to try for a given connected peer?
101  */
102 #define PLUGIN_RETRY_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15)
103
104 /**
105  * After how long do we expire an address in a HELLO that we just
106  * validated?  This value is also used for our own addresses when we
107  * create a HELLO.
108  */
109 #define HELLO_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 12)
110
111
112 /**
113  * How long before an existing address expires should we again try to
114  * validate it?  Must be (significantly) smaller than
115  * HELLO_ADDRESS_EXPIRATION.
116  */
117 #define HELLO_REVALIDATION_START_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 1)
118
119
120 /**
121  * List of addresses of other peers
122  */
123 struct ForeignAddressList
124 {
125   /**
126    * This is a linked list.
127    */
128   struct ForeignAddressList *next;
129
130   /**
131    * Which ready list does this entry belong to.
132    */
133   struct ReadyList *ready_list;
134
135   /**
136    * How long until we auto-expire this address (unless it is
137    * re-confirmed by the transport)?
138    */
139   struct GNUNET_TIME_Absolute expires;
140
141   /**
142    * Length of addr.
143    */
144   size_t addrlen;
145
146   /**
147    * The address.
148    */
149   const void *addr;
150
151   /**
152    * What was the last latency observed for this plugin
153    * and peer?  Invalid if connected is GNUNET_NO.
154    */
155   struct GNUNET_TIME_Relative latency;
156
157   /**
158    * If we did not successfully transmit a message to the given peer
159    * via this connection during the specified time, we should consider
160    * the connection to be dead.  This is used in the case that a TCP
161    * transport simply stalls writing to the stream but does not
162    * formerly get a signal that the other peer died.
163    */
164   /* FIXME: Do we need this? */
165   struct GNUNET_TIME_Absolute timeout;
166
167   /**
168    * Is this plugin currently connected?  The first time we transmit
169    * or send data to a peer via a particular plugin, we set this to
170    * GNUNET_YES.  If we later get an error (disconnect notification or
171    * transmission failure), we set it back to GNUNET_NO.  Each time
172    * the value is set to GNUNET_YES, we increment the
173    * "connect_attempts" counter.  If that one reaches a particular
174    * threshold, we consider the address to not be working properly at
175    * this time and remove it from the eligible list.
176    */
177   int connected;
178
179   /**
180    * Is this plugin ready to transmit to the specific target?
181    * GNUNET_NO if not.  Initially, all plugins are marked ready.  If a
182    * transmission is in progress, "transmit_ready" is set to
183    * GNUNET_NO.
184    */
185   int transmit_ready;
186
187   /**
188    * Has this address been validated yet?
189    */
190   int validated;
191
192   /**
193    * How often have we tried to connect using this plugin?
194    */
195   unsigned int connect_attempts;
196
197 };
198
199
200 /**
201  * Entry in linked list of network addresses for ourselves.
202  */
203 struct OwnAddressList
204 {
205   /**
206    * This is a linked list.
207    */
208   struct OwnAddressList *next;
209
210   /**
211    * The address, actually a pointer to the end
212    * of this struct.  Do not free!
213    */
214   const void *addr;
215   
216   /**
217    * How long until we auto-expire this address (unless it is
218    * re-confirmed by the transport)?
219    */
220   struct GNUNET_TIME_Absolute expires;
221
222   /**
223    * Length of addr.
224    */
225   size_t addrlen;
226
227 };
228
229
230 /**
231  * Entry in linked list of all of our plugins.
232  */
233 struct TransportPlugin
234 {
235
236   /**
237    * This is a linked list.
238    */
239   struct TransportPlugin *next;
240
241   /**
242    * API of the transport as returned by the plugin's
243    * initialization function.
244    */
245   struct GNUNET_TRANSPORT_PluginFunctions *api;
246
247   /**
248    * Short name for the plugin (i.e. "tcp").
249    */
250   char *short_name;
251
252   /**
253    * Name of the library (i.e. "gnunet_plugin_transport_tcp").
254    */
255   char *lib_name;
256
257   /**
258    * List of our known addresses for this transport.
259    */
260   struct OwnAddressList *addresses;
261
262   /**
263    * Environment this transport service is using
264    * for this plugin.
265    */
266   struct GNUNET_TRANSPORT_PluginEnvironment env;
267
268   /**
269    * ID of task that is used to clean up expired addresses.
270    */
271   GNUNET_SCHEDULER_TaskIdentifier address_update_task;
272
273   /**
274    * Set to GNUNET_YES if we need to scrap the existing
275    * list of "addresses" and start fresh when we receive
276    * the next address update from a transport.  Set to
277    * GNUNET_NO if we should just add the new address
278    * to the list and wait for the commit call.
279    */
280   int rebuild;
281
282 };
283
284 struct NeighborList;
285
286 /**
287  * For each neighbor we keep a list of messages
288  * that we still want to transmit to the neighbor.
289  */
290 struct MessageQueue
291 {
292
293   /**
294    * This is a linked list.
295    */
296   struct MessageQueue *next;
297
298   /**
299    * The message(s) we want to transmit, GNUNET_MessageHeader(s)
300    * stuck together in memory.  Allocated at the end of this struct.
301    */
302   const char *message_buf;
303
304   /**
305    * Size of the message buf
306    */
307   size_t message_buf_size;
308
309   /**
310    * Client responsible for queueing the message;
311    * used to check that a client has no two messages
312    * pending for the same target.  Can be NULL.
313    */
314   struct TransportClient *client;
315
316   /**
317    * Using which specific address should we send this message?
318    */
319   struct ForeignAddressList *specific_address;
320
321   /**
322    * Peer ID of the Neighbor this entry belongs to.
323    */
324   struct GNUNET_PeerIdentity neighbor_id;
325
326   /**
327    * Plugin that we used for the transmission.
328    * NULL until we scheduled a transmission.
329    */
330   struct TransportPlugin *plugin;
331
332   /**
333    * Internal message of the transport system that should not be
334    * included in the usual SEND-SEND_OK transmission confirmation
335    * traffic management scheme.  Typically, "internal_msg" will
336    * be set whenever "client" is NULL (but it is not strictly
337    * required).
338    */
339   int internal_msg;
340
341   /**
342    * How important is the message?
343    */
344   unsigned int priority;
345
346 };
347
348
349 /**
350  * For a given Neighbor, which plugins are available
351  * to talk to this peer and what are their costs?
352  */
353 struct ReadyList
354 {
355   /**
356    * This is a linked list.
357    */
358   struct ReadyList *next;
359
360   /**
361    * Which of our transport plugins does this entry
362    * represent?
363    */
364   struct TransportPlugin *plugin;
365
366   /**
367    * Transport addresses, latency, and readiness for
368    * this particular plugin.
369    */
370   struct ForeignAddressList *addresses;
371
372   /**
373    * Is this plugin ready to transmit to the specific target?
374    * GNUNET_NO if not.  Initially, all plugins are marked ready.  If a
375    * transmission is in progress, "transmit_ready" is set to
376    * GNUNET_NO.
377    */
378   // FIXME: is this dead?
379   int plugin_transmit_ready;
380
381   /**
382    * Is the plugin represented by this entry currently connected to
383    * the respective peer?
384    */
385   int connected;
386
387 };
388
389
390 /**
391  * Entry in linked list of all of our current neighbors.
392  */
393 struct NeighborList
394 {
395
396   /**
397    * This is a linked list.
398    */
399   struct NeighborList *next;
400
401   /**
402    * Which of our transports is connected to this peer
403    * and what is their status?
404    */
405   struct ReadyList *plugins;
406
407   /**
408    * List of messages we would like to send to this peer;
409    * must contain at most one message per client.
410    */
411   struct MessageQueue *messages;
412
413   /**
414    * Identity of this neighbor.
415    */
416   struct GNUNET_PeerIdentity id;
417
418   /**
419    * ID of task scheduled to run when this peer is about to
420    * time out (will free resources associated with the peer).
421    */
422   GNUNET_SCHEDULER_TaskIdentifier timeout_task;
423
424   /**
425    * How long until we should consider this peer dead
426    * (if we don't receive another message in the
427    * meantime)?
428    */
429   struct GNUNET_TIME_Absolute peer_timeout;
430
431   /**
432    * At what time did we reset last_received last?
433    */
434   struct GNUNET_TIME_Absolute last_quota_update;
435
436   /**
437    * The latency we have seen for this particular address for
438    * this particular peer.  This latency may have been calculated
439    * over multiple transports.  This value reflects how long it took
440    * us to receive a response when SENDING via this particular
441    * transport/neighbor/address combination!
442    * FIXME: why is this NBO?
443    */
444   struct GNUNET_TIME_RelativeNBO latency;
445
446   /**
447    * How many bytes have we received since the "last_quota_update"
448    * timestamp?
449    */
450   uint64_t last_received;
451
452   /**
453    * Global quota for inbound traffic for the neighbor in bytes/ms.
454    */
455   uint32_t quota_in;
456
457   /**
458    * How often has the other peer (recently) violated the
459    * inbound traffic limit?  Incremented by 10 per violation,
460    * decremented by 1 per non-violation (for each
461    * time interval).
462    */
463   unsigned int quota_violation_count;
464
465   /**
466    * Have we seen an ACK from this neighbor in the past?
467    * (used to make up a fake ACK for clients connecting after
468    * the neighbor connected to us).
469    */
470   int received_pong;
471
472 };
473
474 /**
475  * Message used to ask a peer to validate receipt (to check an address
476  * from a HELLO).  Followed by the address used.  Note that the
477  * recipients response does not affirm that he has this address,
478  * only that he got the challenge message.
479  */
480 struct TransportPingMessage
481 {
482
483   /**
484    * Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_PING
485    */
486   struct GNUNET_MessageHeader header;
487
488   /**
489    * Random challenge number (in network byte order).
490    */
491   uint32_t challenge GNUNET_PACKED;
492
493   /**
494    * Who is the intended recipient?
495    */
496   struct GNUNET_PeerIdentity target;
497
498 };
499
500
501 /**
502  * Message used to validate a HELLO.  The challenge is included in the
503  * confirmation to make matching of replies to requests possible.  The
504  * signature signs the original challenge number, our public key, the
505  * sender's address (so that the sender can check that the address we
506  * saw is plausible for him and possibly detect a MiM attack) and a
507  * timestamp (to limit replay).<p>
508  *
509  * This message is followed by the address of the
510  * client that we are observing (which is part of what
511  * is being signed).
512  */
513 struct TransportPongMessage
514 {
515
516   /**
517    * Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_PONG
518    */
519   struct GNUNET_MessageHeader header;
520
521   /**
522    * For padding, always zero.
523    */
524   uint32_t reserved GNUNET_PACKED;
525
526   /**
527    * Signature.
528    */
529   struct GNUNET_CRYPTO_RsaSignature signature;
530
531   /**
532    * What are we signing and why?
533    */
534   struct GNUNET_CRYPTO_RsaSignaturePurpose purpose;
535
536   /**
537    * Random challenge number (in network byte order).
538    */
539   uint32_t challenge GNUNET_PACKED;
540
541   /**
542    * Who signed this message?
543    */
544   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded signer;
545
546   /**
547    * Size of address appended to this message
548    */
549   size_t addrlen;
550
551 };
552
553 /**
554  * Linked list of messages to be transmitted to
555  * the client.  Each entry is followed by the
556  * actual message.
557  */
558 struct ClientMessageQueueEntry
559 {
560   /**
561    * This is a linked list.
562    */
563   struct ClientMessageQueueEntry *next;
564 };
565
566
567 /**
568  * Client connected to the transport service.
569  */
570 struct TransportClient
571 {
572
573   /**
574    * This is a linked list.
575    */
576   struct TransportClient *next;
577
578   /**
579    * Handle to the client.
580    */
581   struct GNUNET_SERVER_Client *client;
582
583   /**
584    * Linked list of messages yet to be transmitted to
585    * the client.
586    */
587   struct ClientMessageQueueEntry *message_queue_head;
588
589   /**
590    * Tail of linked list of messages yet to be transmitted to the
591    * client.
592    */
593   struct ClientMessageQueueEntry *message_queue_tail;
594
595   /**
596    * Is a call to "transmit_send_continuation" pending?  If so, we
597    * must not free this struct (even if the corresponding client
598    * disconnects) and instead only remove it from the linked list and
599    * set the "client" field to NULL.
600    */
601   int tcs_pending;
602
603   /**
604    * Length of the list of messages pending for this client.
605    */
606   unsigned int message_count;
607
608 };
609
610
611 /**
612  * Entry in map of all HELLOs awaiting validation.
613  */
614 struct ValidationEntry
615 {
616
617   /**
618    * The address, actually a pointer to the end
619    * of this struct.  Do not free!
620    */
621   const void *addr;
622
623   /**
624    * Name of the transport.
625    */
626   char *transport_name;
627
628   /**
629    * The public key of the peer.
630    */
631   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded publicKey;
632
633   /**
634    * ID of task that will clean up this entry if we don't succeed
635    * with the validation first.
636    */
637   GNUNET_SCHEDULER_TaskIdentifier timeout_task;
638
639   /**
640    * At what time did we send this validation?
641    */
642   struct GNUNET_TIME_Absolute send_time;
643
644   /**
645    * Length of addr.
646    */
647   size_t addrlen;
648
649   /**
650    * Challenge number we used.
651    */
652   uint32_t challenge;
653
654 };
655
656
657 /**
658  * Context of currently active requests to peerinfo
659  * for validation of HELLOs.
660  */
661 struct CheckHelloValidatedContext
662 {
663
664   /**
665    * This is a doubly-linked list.
666    */
667   struct CheckHelloValidatedContext *next;
668
669   /**
670    * This is a doubly-linked list.
671    */
672   struct CheckHelloValidatedContext *prev;
673
674   /**
675    * Hello that we are validating.
676    */
677   const struct GNUNET_HELLO_Message *hello;
678
679   /**
680    * Context for peerinfo iteration.
681    * NULL after we are done processing peerinfo's information.
682    */
683   struct GNUNET_PEERINFO_IteratorContext *piter;
684   
685   /**
686    * Was a HELLO known for this peer to peerinfo?
687    */
688   int hello_known;
689
690 };
691
692
693 /**
694  * Our HELLO message.
695  */
696 static struct GNUNET_HELLO_Message *our_hello;
697
698 /**
699  * "version" of "our_hello".  Used to see if a given neighbor has
700  * already been sent the latest version of our HELLO message.
701  */
702 static unsigned int our_hello_version;
703
704 /**
705  * Our public key.
706  */
707 static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded my_public_key;
708
709 /**
710  * Our identity.
711  */
712 static struct GNUNET_PeerIdentity my_identity;
713
714 /**
715  * Our private key.
716  */
717 static struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key;
718
719 /**
720  * Our scheduler.
721  */
722 struct GNUNET_SCHEDULER_Handle *sched;
723
724 /**
725  * Our configuration.
726  */
727 const struct GNUNET_CONFIGURATION_Handle *cfg;
728
729 /**
730  * Linked list of all clients to this service.
731  */
732 static struct TransportClient *clients;
733
734 /**
735  * All loaded plugins.
736  */
737 static struct TransportPlugin *plugins;
738
739 /**
740  * Our server.
741  */
742 static struct GNUNET_SERVER_Handle *server;
743
744 /**
745  * All known neighbors and their HELLOs.
746  */
747 static struct NeighborList *neighbors;
748
749 /**
750  * Number of neighbors we'd like to have.
751  */
752 static uint32_t max_connect_per_transport;
753
754 /**
755  * Head of linked list.
756  */
757 static struct CheckHelloValidatedContext *chvc_head;
758
759 /**
760  * Tail of linked list.
761  */
762 static struct CheckHelloValidatedContext *chvc_tail;
763
764
765 /**
766  * Map of PeerIdentities to 'struct ValidationEntry*'s (addresses
767  * of the given peer that we are currently validating).
768  */
769 static struct GNUNET_CONTAINER_MultiHashMap *validation_map;
770
771
772
773 /**
774  * The peer specified by the given neighbor has timed-out or a plugin
775  * has disconnected.  We may either need to do nothing (other plugins
776  * still up), or trigger a full disconnect and clean up.  This
777  * function updates our state and do the necessary notifications.
778  * Also notifies our clients that the neighbor is now officially
779  * gone.
780  *
781  * @param n the neighbor list entry for the peer
782  * @param check should we just check if all plugins
783  *        disconnected or must we ask all plugins to
784  *        disconnect?
785  */
786 static void disconnect_neighbor (struct NeighborList *n, int check);
787
788 /**
789  * Check the ready list for the given neighbor and if a plugin is
790  * ready for transmission (and if we have a message), do so!
791  *
792  * @param neighbor target peer for which to transmit
793  */
794 static void try_transmission_to_peer (struct NeighborList *neighbor);
795
796
797 /**
798  * Find an entry in the neighbor list for a particular peer.
799  * if sender_address is not specified (NULL) then return the
800  * first matching entry.  If sender_address is specified, then
801  * make sure that the address and address_len also matches.
802  *
803  * @return NULL if not found.
804  */
805 static struct NeighborList *
806 find_neighbor (const struct GNUNET_PeerIdentity *key)
807 {
808   struct NeighborList *head = neighbors;
809
810   while ((head != NULL) &&
811         (0 != memcmp (key, &head->id, sizeof (struct GNUNET_PeerIdentity))))
812     head = head->next;
813   return head;
814 }
815
816
817 /**
818  * Find an entry in the transport list for a particular transport.
819  *
820  * @return NULL if not found.
821  */
822 static struct TransportPlugin *
823 find_transport (const char *short_name)
824 {
825   struct TransportPlugin *head = plugins;
826   while ((head != NULL) && (0 != strcmp (short_name, head->short_name)))
827     head = head->next;
828   return head;
829 }
830
831
832 /**
833  * Update the quota values for the given neighbor now.
834  */
835 static void
836 update_quota (struct NeighborList *n)
837 {
838   struct GNUNET_TIME_Relative delta;
839   uint64_t allowed;
840   uint64_t remaining;
841
842   delta = GNUNET_TIME_absolute_get_duration (n->last_quota_update);
843   if (delta.value < MIN_QUOTA_REFRESH_TIME)
844     return;                     /* not enough time passed for doing quota update */
845   allowed = delta.value * n->quota_in;
846
847   if (n->last_received < allowed)
848     {
849       remaining = allowed - n->last_received;
850       if (n->quota_in > 0)
851         remaining /= n->quota_in;
852       else
853         remaining = 0;
854       if (remaining > MAX_BANDWIDTH_CARRY)
855         remaining = MAX_BANDWIDTH_CARRY;
856       n->last_received = 0;
857       n->last_quota_update = GNUNET_TIME_absolute_get ();
858       n->last_quota_update.value -= remaining;
859       if (n->quota_violation_count > 0)
860         n->quota_violation_count--;
861     }
862   else
863     {
864       n->last_received -= allowed;
865       n->last_quota_update = GNUNET_TIME_absolute_get ();
866       if (n->last_received > allowed)
867         {
868           /* more than twice the allowed rate! */
869           n->quota_violation_count += 10;
870         }
871     }
872 }
873
874
875 /**
876  * Function called to notify a client about the socket being ready to
877  * queue more data.  "buf" will be NULL and "size" zero if the socket
878  * was closed for writing in the meantime.
879  *
880  * @param cls closure
881  * @param size number of bytes available in buf
882  * @param buf where the callee should write the message
883  * @return number of bytes written to buf
884  */
885 static size_t
886 transmit_to_client_callback (void *cls, size_t size, void *buf)
887 {
888   struct TransportClient *client = cls;
889   struct ClientMessageQueueEntry *q;
890   uint16_t msize;
891   size_t tsize;
892   const struct GNUNET_MessageHeader *msg;
893   struct GNUNET_CONNECTION_TransmitHandle *th;
894   char *cbuf;
895
896   if (buf == NULL)
897     {
898       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
899                   "Transmission to client failed, closing connection.\n");
900       /* fatal error with client, free message queue! */
901       while (NULL != (q = client->message_queue_head))
902         {
903           client->message_queue_head = q->next;
904           GNUNET_free (q);
905         }
906       client->message_queue_tail = NULL;
907       client->message_count = 0;
908       return 0;
909     }
910   cbuf = buf;
911   tsize = 0;
912   while (NULL != (q = client->message_queue_head))
913     {
914       msg = (const struct GNUNET_MessageHeader *) &q[1];
915       msize = ntohs (msg->size);
916       if (msize + tsize > size)
917         break;
918 #if DEBUG_TRANSPORT
919       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
920                   "Transmitting message of type %u to client.\n",
921                   ntohs (msg->type));
922 #endif
923       client->message_queue_head = q->next;
924       if (q->next == NULL)
925         client->message_queue_tail = NULL;
926       memcpy (&cbuf[tsize], msg, msize);
927       tsize += msize;
928       GNUNET_free (q);
929       client->message_count--;
930     }
931   if (NULL != q)
932     {
933       GNUNET_assert (msize >= sizeof (struct GNUNET_MessageHeader));
934       th = GNUNET_SERVER_notify_transmit_ready (client->client,
935                                                 msize,
936                                                 GNUNET_TIME_UNIT_FOREVER_REL,
937                                                 &transmit_to_client_callback,
938                                                 client);
939       GNUNET_assert (th != NULL);
940     }
941   return tsize;
942 }
943
944
945 /**
946  * Send the specified message to the specified client.  Since multiple
947  * messages may be pending for the same client at a time, this code
948  * makes sure that no message is lost.
949  *
950  * @param client client to transmit the message to
951  * @param msg the message to send
952  * @param may_drop can this message be dropped if the
953  *        message queue for this client is getting far too large?
954  */
955 static void
956 transmit_to_client (struct TransportClient *client,
957                     const struct GNUNET_MessageHeader *msg, int may_drop)
958 {
959   struct ClientMessageQueueEntry *q;
960   uint16_t msize;
961   struct GNUNET_CONNECTION_TransmitHandle *th;
962
963   if ((client->message_count >= MAX_PENDING) && (GNUNET_YES == may_drop))
964     {
965       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
966                   _
967                   ("Dropping message, have %u messages pending (%u is the soft limit)\n"),
968                   client->message_count, MAX_PENDING);
969       /* TODO: call to statistics... */
970       return;
971     }
972   client->message_count++;
973   msize = ntohs (msg->size);
974   GNUNET_assert (msize >= sizeof (struct GNUNET_MessageHeader));
975   q = GNUNET_malloc (sizeof (struct ClientMessageQueueEntry) + msize);
976   memcpy (&q[1], msg, msize);
977   /* append to message queue */
978   if (client->message_queue_tail == NULL)
979     {
980       client->message_queue_tail = q;
981     }
982   else
983     {
984       client->message_queue_tail->next = q;
985       client->message_queue_tail = q;
986     }
987   if (client->message_queue_head == NULL)
988     {
989       client->message_queue_head = q;
990       th = GNUNET_SERVER_notify_transmit_ready (client->client,
991                                                 msize,
992                                                 GNUNET_TIME_UNIT_FOREVER_REL,
993                                                 &transmit_to_client_callback,
994                                                 client);
995       GNUNET_assert (th != NULL);
996     }
997 }
998
999
1000 /**
1001  * Function called by the GNUNET_TRANSPORT_TransmitFunction
1002  * upon "completion" of a send request.  This tells the API
1003  * that it is now legal to send another message to the given
1004  * peer.
1005  *
1006  * @param cls closure, identifies the entry on the
1007  *            message queue that was transmitted and the
1008  *            client responsible for queueing the message
1009  * @param target the peer receiving the message
1010  * @param result GNUNET_OK on success, if the transmission
1011  *           failed, we should not tell the client to transmit
1012  *           more messages
1013  */
1014 static void
1015 transmit_send_continuation (void *cls,
1016                             const struct GNUNET_PeerIdentity *target,
1017                             int result)
1018 {
1019   struct MessageQueue *mq = cls;
1020   /*struct ReadyList *rl;*/ /* We no longer use the ReadyList for anything here, safe to remove? */
1021   struct SendOkMessage send_ok_msg;
1022   struct NeighborList *n;
1023
1024   GNUNET_assert (mq != NULL);
1025   n = find_neighbor(&mq->neighbor_id);
1026   if (n == NULL) /* Neighbor must have been removed asynchronously! */
1027     return;
1028
1029   /* Otherwise, let's make sure we've got the right peer */
1030   GNUNET_assert (0 ==
1031                  memcmp (&n->id, target,
1032                          sizeof (struct GNUNET_PeerIdentity)));
1033
1034   if (result == GNUNET_OK)
1035     {
1036       mq->specific_address->timeout =
1037         GNUNET_TIME_relative_to_absolute
1038         (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
1039     }
1040   else
1041     {
1042       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1043                   "Transmission to peer `%s' failed, marking connection as down.\n",
1044                   GNUNET_i2s (target));
1045       mq->specific_address->connected = GNUNET_NO;
1046     }
1047   if (!mq->internal_msg)
1048     {
1049 #if DEBUG_TRANSPORT
1050       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1051                   "Setting transmit_ready on transport!\n");
1052 #endif
1053       mq->specific_address->transmit_ready = GNUNET_YES;
1054     }
1055
1056   if (mq->client != NULL)
1057     {
1058       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1059                   "Notifying client %p about transmission to peer `%4s'.\n",
1060                   mq->client, GNUNET_i2s (target));
1061       send_ok_msg.header.size = htons (sizeof (send_ok_msg));
1062       send_ok_msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK);
1063       send_ok_msg.success = htonl (result);
1064       send_ok_msg.peer = n->id;
1065       transmit_to_client (mq->client, &send_ok_msg.header, GNUNET_NO);
1066     }
1067   GNUNET_free (mq);
1068   /* one plugin just became ready again, try transmitting
1069      another message (if available) */
1070   if (result == GNUNET_OK)
1071     try_transmission_to_peer (n);
1072   else
1073     disconnect_neighbor (n, GNUNET_YES);
1074 }
1075
1076
1077 /**
1078  * Find an address in any of the available transports for
1079  * the given neighbor that would be good for message
1080  * transmission.  This is essentially the transport selection
1081  * routine.
1082  *
1083  * @param neighbor for whom to select an address
1084  * @return selected address, NULL if we have none
1085  */
1086 struct ForeignAddressList *
1087 find_ready_address(struct NeighborList *neighbor)
1088 {
1089   struct ReadyList *head = neighbor->plugins;
1090   struct ForeignAddressList *addresses;
1091   struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
1092   struct ForeignAddressList *best_address;
1093
1094   best_address = NULL;
1095   while (head != NULL)
1096     {
1097       addresses = head->addresses;
1098       while (addresses != NULL)
1099         {
1100           if ( (addresses->timeout.value < now.value) && 
1101                (addresses->connected == GNUNET_YES) )
1102             {
1103 #if DEBUG_TRANSPORT
1104               GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1105                           "Marking long-time inactive connection to `%4s' as down.\n",
1106                           GNUNET_i2s (&neighbor->id));
1107 #endif
1108               addresses->connected = GNUNET_NO;
1109             }
1110           addresses = addresses->next;
1111         }
1112
1113       addresses = head->addresses;
1114       while (addresses != NULL)
1115         {
1116           if ( ( (best_address == NULL) || 
1117                  (addresses->connected == GNUNET_YES) ||
1118                  (best_address->connected == GNUNET_NO) ) &&
1119                (addresses->transmit_ready == GNUNET_YES) &&
1120                ( (best_address == NULL) || 
1121                  (addresses->latency.value < best_address->latency.value)) )
1122             best_address = addresses;            
1123           /* FIXME: also give lower-latency addresses that are not
1124              connected a chance some times... */
1125           addresses = addresses->next;
1126         }
1127       head = head->next;
1128     }
1129 #if DEBUG_TRANSPORT
1130   if (best_address != NULL)
1131     {
1132       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1133                   "Best address found has latency of %llu ms.\n",
1134                   best_address->latency.value);
1135     }
1136 #endif
1137   return best_address;
1138
1139 }
1140
1141
1142 /**
1143  * Check the ready list for the given neighbor and if a plugin is
1144  * ready for transmission (and if we have a message), do so!
1145  *
1146  * @param neighbor target peer for which to transmit
1147  */
1148 static void
1149 try_transmission_to_peer (struct NeighborList *neighbor)
1150 {
1151   struct GNUNET_TIME_Relative min_latency;
1152   struct ReadyList *rl;
1153   struct MessageQueue *mq;
1154
1155   if (neighbor->messages == NULL)
1156     return;                     /* nothing to do */
1157   min_latency = GNUNET_TIME_UNIT_FOREVER_REL;
1158   rl = NULL;
1159   mq = neighbor->messages;
1160   if (mq->specific_address == NULL)
1161     mq->specific_address = find_ready_address(neighbor); 
1162   if (mq->specific_address == NULL)
1163     {
1164 #if DEBUG_TRANSPORT
1165       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1166                   "No destination address available to transmit message of size %u to peer `%4s'\n",
1167                   mq->message_buf_size,
1168                   GNUNET_i2s (&mq->neighbor_id));
1169 #endif
1170       return;                   /* nobody ready */
1171     }
1172   rl = mq->specific_address->ready_list;
1173   neighbor->messages = mq->next;
1174   mq->plugin = rl->plugin;
1175   if (!mq->internal_msg)
1176     mq->specific_address->transmit_ready = GNUNET_NO;
1177 #if DEBUG_TRANSPORT
1178   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1179               "Sending message of size %u for `%4s' to `%s' via plugin `%s'\n",
1180               mq->message_buf_size,
1181               GNUNET_i2s (&neighbor->id), 
1182               GNUNET_a2s (mq->specific_address->addr,
1183                           mq->specific_address->addrlen),
1184               rl->plugin->short_name);
1185 #endif
1186   rl->plugin->api->send (rl->plugin->api->cls,
1187                          &mq->neighbor_id,
1188                          mq->message_buf,
1189                          mq->message_buf_size,
1190                          mq->priority,
1191                          GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
1192                          mq->specific_address->addr,
1193                          mq->specific_address->addrlen,
1194                          GNUNET_YES /* FIXME: sometimes, we want to be more tolerant here! */,
1195                          &transmit_send_continuation, mq);
1196 }
1197
1198
1199 /**
1200  * Send the specified message to the specified peer.
1201  *
1202  * @param client source of the transmission request (can be NULL)
1203  * @param peer_address ForeignAddressList where we should send this message
1204  * @param priority how important is the message
1205  * @param message_buf message(s) to send GNUNET_MessageHeader(s)
1206  * @param message_buf_size total size of all messages in message_buf
1207  * @param is_internal is this an internal message
1208  * @param neighbor handle to the neighbor for transmission
1209  */
1210 static void
1211 transmit_to_peer (struct TransportClient *client,
1212                   struct ForeignAddressList *peer_address,
1213                   unsigned int priority,
1214                   const char *message_buf,
1215                   size_t message_buf_size,
1216                   int is_internal, struct NeighborList *neighbor)
1217 {
1218   struct MessageQueue *mq;
1219   struct MessageQueue *mqe;
1220
1221   if (client != NULL)
1222     {
1223       /* check for duplicate submission */
1224       mq = neighbor->messages;
1225       while (NULL != mq)
1226         {
1227           if (mq->client == client)
1228             {
1229               /* client transmitted to same peer twice
1230                  before getting SendOk! */
1231               GNUNET_break (0);
1232               return;
1233             }
1234           mq = mq->next;
1235         }
1236     }
1237   mq = GNUNET_malloc (sizeof (struct MessageQueue) + message_buf_size);
1238   mq->specific_address = peer_address;
1239   mq->client = client;
1240   memcpy (&mq[1], message_buf, message_buf_size);
1241   mq->message_buf = (const char*) &mq[1];
1242   mq->message_buf_size = message_buf_size;
1243   memcpy(&mq->neighbor_id, &neighbor->id, sizeof(struct GNUNET_PeerIdentity));
1244   mq->internal_msg = is_internal;
1245   mq->priority = priority;
1246
1247   if (is_internal)
1248     {
1249       /* append at head */
1250       mq->next = neighbor->messages;
1251       neighbor->messages = mq;
1252     }
1253   else
1254     {
1255       /* find tail */
1256       mqe = neighbor->messages;
1257       if (mqe != NULL)
1258         while (mqe->next != NULL)
1259           mqe = mqe->next;
1260       if (mqe == NULL)
1261         {
1262           /* new head */
1263           neighbor->messages = mq;
1264         }
1265       else
1266         {
1267           /* append */
1268           mqe->next = mq;
1269         }
1270     }
1271   try_transmission_to_peer (neighbor);
1272 }
1273
1274
1275 /**
1276  * FIXME: document.
1277  */
1278 struct GeneratorContext
1279 {
1280   struct TransportPlugin *plug_pos;
1281   struct OwnAddressList *addr_pos;
1282   struct GNUNET_TIME_Absolute expiration;
1283 };
1284
1285
1286 /**
1287  * FIXME: document.
1288  */
1289 static size_t
1290 address_generator (void *cls, size_t max, void *buf)
1291 {
1292   struct GeneratorContext *gc = cls;
1293   size_t ret;
1294
1295   while ((gc->addr_pos == NULL) && (gc->plug_pos != NULL))
1296     {
1297       gc->plug_pos = gc->plug_pos->next;
1298       gc->addr_pos = (gc->plug_pos != NULL) ? gc->plug_pos->addresses : NULL;
1299     }
1300   if (NULL == gc->plug_pos)
1301     {
1302
1303       return 0;
1304     }
1305   ret = GNUNET_HELLO_add_address (gc->plug_pos->short_name,
1306                                   gc->expiration,
1307                                   gc->addr_pos->addr,
1308                                   gc->addr_pos->addrlen, buf, max);
1309   gc->addr_pos = gc->addr_pos->next;
1310   return ret;
1311 }
1312
1313
1314 /**
1315  * Construct our HELLO message from all of the addresses of
1316  * all of the transports.
1317  */
1318 static void
1319 refresh_hello ()
1320 {
1321   struct GNUNET_HELLO_Message *hello;
1322   struct TransportClient *cpos;
1323   struct NeighborList *npos;
1324   struct GeneratorContext gc;
1325
1326   gc.plug_pos = plugins;
1327   gc.addr_pos = plugins != NULL ? plugins->addresses : NULL;
1328   gc.expiration = GNUNET_TIME_relative_to_absolute (HELLO_ADDRESS_EXPIRATION);
1329   hello = GNUNET_HELLO_create (&my_public_key, &address_generator, &gc);
1330 #if DEBUG_TRANSPORT
1331   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
1332               "Refreshed my `%s', new size is %d\n", "HELLO", GNUNET_HELLO_size(hello));
1333 #endif
1334   cpos = clients;
1335   while (cpos != NULL)
1336     {
1337       transmit_to_client (cpos,
1338                           (const struct GNUNET_MessageHeader *) hello,
1339                           GNUNET_NO);
1340       cpos = cpos->next;
1341     }
1342
1343   GNUNET_free_non_null (our_hello);
1344   our_hello = hello;
1345   our_hello_version++;
1346   GNUNET_PEERINFO_add_peer (cfg, sched, &my_identity, our_hello);
1347   npos = neighbors;
1348   while (npos != NULL)
1349     {
1350 #if DEBUG_TRANSPORT
1351       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
1352                   "Transmitting updated `%s' to neighbor `%4s'\n",
1353                   "HELLO", GNUNET_i2s (&npos->id));
1354 #endif
1355       transmit_to_peer (NULL, NULL, 0,
1356                         (const char *) our_hello, 
1357                         GNUNET_HELLO_size(our_hello),
1358                         GNUNET_NO, npos);
1359       npos = npos->next;
1360     }
1361 }
1362
1363
1364 /**
1365  * Task used to clean up expired addresses for a plugin.
1366  *
1367  * @param cls closure
1368  * @param tc context
1369  */
1370 static void
1371 expire_address_task (void *cls,
1372                      const struct GNUNET_SCHEDULER_TaskContext *tc);
1373
1374
1375 /**
1376  * Update the list of addresses for this plugin,
1377  * expiring those that are past their expiration date.
1378  *
1379  * @param plugin addresses of which plugin should be recomputed?
1380  * @param fresh set to GNUNET_YES if a new address was added
1381  *        and we need to regenerate the HELLO even if nobody
1382  *        expired
1383  */
1384 static void
1385 update_addresses (struct TransportPlugin *plugin, int fresh)
1386 {
1387   struct GNUNET_TIME_Relative min_remaining;
1388   struct GNUNET_TIME_Relative remaining;
1389   struct GNUNET_TIME_Absolute now;
1390   struct OwnAddressList *pos;
1391   struct OwnAddressList *prev;
1392   struct OwnAddressList *next;
1393   int expired;
1394
1395   if (plugin->address_update_task != GNUNET_SCHEDULER_NO_TASK)
1396     GNUNET_SCHEDULER_cancel (plugin->env.sched, plugin->address_update_task);
1397   plugin->address_update_task = GNUNET_SCHEDULER_NO_TASK;
1398   now = GNUNET_TIME_absolute_get ();
1399   min_remaining = GNUNET_TIME_UNIT_FOREVER_REL;
1400   expired = GNUNET_NO;
1401   prev = NULL;
1402   pos = plugin->addresses;
1403   while (pos != NULL)
1404     {
1405       next = pos->next;
1406       if (pos->expires.value < now.value)
1407         {
1408           expired = GNUNET_YES;
1409           if (prev == NULL)
1410             plugin->addresses = pos->next;
1411           else
1412             prev->next = pos->next;
1413           GNUNET_free (pos);
1414         }
1415       else
1416         {
1417           remaining = GNUNET_TIME_absolute_get_remaining (pos->expires);
1418           if (remaining.value < min_remaining.value)
1419             min_remaining = remaining;
1420           prev = pos;
1421         }
1422       pos = next;
1423     }
1424
1425   if (expired || fresh)
1426     refresh_hello ();
1427   if (min_remaining.value < GNUNET_TIME_UNIT_FOREVER_REL.value)
1428     plugin->address_update_task
1429       = GNUNET_SCHEDULER_add_delayed (plugin->env.sched,
1430                                       min_remaining,
1431                                       &expire_address_task, plugin);
1432
1433 }
1434
1435
1436 /**
1437  * Task used to clean up expired addresses for a plugin.
1438  *
1439  * @param cls closure
1440  * @param tc context
1441  */
1442 static void
1443 expire_address_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1444 {
1445   struct TransportPlugin *plugin = cls;
1446   plugin->address_update_task = GNUNET_SCHEDULER_NO_TASK;
1447   update_addresses (plugin, GNUNET_NO);
1448 }
1449
1450
1451 /**
1452  * Function that must be called by each plugin to notify the
1453  * transport service about the addresses under which the transport
1454  * provided by the plugin can be reached.
1455  *
1456  * @param cls closure
1457  * @param name name of the transport that generated the address
1458  * @param addr one of the addresses of the host, NULL for the last address
1459  *        the specific address format depends on the transport
1460  * @param addrlen length of the address
1461  * @param expires when should this address automatically expire?
1462  */
1463 static void
1464 plugin_env_notify_address (void *cls,
1465                            const char *name,
1466                            const void *addr,
1467                            size_t addrlen,
1468                            struct GNUNET_TIME_Relative expires)
1469 {
1470   struct TransportPlugin *p = cls;
1471   struct OwnAddressList *al;
1472   struct GNUNET_TIME_Absolute abex;
1473
1474   abex = GNUNET_TIME_relative_to_absolute (expires);
1475   GNUNET_assert (p == find_transport (name));
1476
1477   al = p->addresses;
1478   while (al != NULL)
1479     {
1480       if ((addrlen == al->addrlen) && (0 == memcmp (addr, &al[1], addrlen)))
1481         {
1482           if (al->expires.value < abex.value)
1483             al->expires = abex;
1484           return;
1485         }
1486       al = al->next;
1487     }
1488
1489   al = GNUNET_malloc (sizeof (struct OwnAddressList) + addrlen);
1490   al->addr = &al[1];
1491   al->next = p->addresses;
1492   p->addresses = al;
1493   al->expires = abex;
1494   al->addrlen = addrlen;
1495   memcpy (&al[1], addr, addrlen);
1496   update_addresses (p, GNUNET_YES);
1497 }
1498
1499
1500 /**
1501  * Notify all of our clients about a peer connecting.
1502  */
1503 static void
1504 notify_clients_connect (const struct GNUNET_PeerIdentity *peer,
1505                         struct GNUNET_TIME_Relative latency)
1506 {
1507   struct ConnectInfoMessage cim;
1508   struct TransportClient *cpos;
1509
1510   cim.header.size = htons (sizeof (struct ConnectInfoMessage));
1511   cim.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
1512   cim.quota_out = htonl (GNUNET_CONSTANTS_DEFAULT_BPM_IN_OUT / (60 * 1000));
1513   cim.latency = GNUNET_TIME_relative_hton (latency);
1514   memcpy (&cim.id, peer, sizeof (struct GNUNET_PeerIdentity));
1515   cpos = clients;
1516   while (cpos != NULL)
1517     {
1518       transmit_to_client (cpos, &cim.header, GNUNET_NO);
1519       cpos = cpos->next;
1520     }
1521 }
1522
1523
1524 /**
1525  * Notify all of our clients about a peer disconnecting.
1526  */
1527 static void
1528 notify_clients_disconnect (const struct GNUNET_PeerIdentity *peer)
1529 {
1530   struct DisconnectInfoMessage dim;
1531   struct TransportClient *cpos;
1532
1533   dim.header.size = htons (sizeof (struct DisconnectInfoMessage));
1534   dim.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT);
1535   dim.reserved = htonl (0);
1536   memcpy (&dim.peer, peer, sizeof (struct GNUNET_PeerIdentity));
1537   cpos = clients;
1538   while (cpos != NULL)
1539     {
1540       transmit_to_client (cpos, &dim.header, GNUNET_NO);
1541       cpos = cpos->next;
1542     }
1543 }
1544
1545
1546 /**
1547  * Find a ForeignAddressList entry for the given neighbour
1548  * that matches the given address and transport.
1549  *
1550  * @param neighbor which peer we care about
1551  * @param tname name of the transport plugin
1552  * @param addr binary address
1553  * @param addrlen length of addr
1554  * @return NULL if no such entry exists
1555  */
1556 static struct ForeignAddressList *
1557 find_peer_address(struct NeighborList *neighbor,
1558                   const char *tname,
1559                   const char *addr,
1560                   size_t addrlen)
1561 {
1562   struct ReadyList *head;
1563   struct ForeignAddressList *address_head;
1564
1565   head = neighbor->plugins;
1566   while (head != NULL)
1567     {
1568       if (0 == strcmp (tname, head->plugin->short_name))
1569         break;
1570       head = head->next;
1571     }
1572   if (head == NULL)
1573     return NULL;
1574
1575   address_head = head->addresses;
1576   while ( (address_head != NULL) &&
1577           ( (address_head->addrlen != addrlen) ||
1578             (memcmp(address_head->addr, addr, addrlen) != 0) ) )
1579     address_head = address_head->next;
1580   return address_head;
1581 }
1582
1583
1584 /**
1585  * Get the peer address struct for the given neighbor and
1586  * address.  If it doesn't yet exist, create it.
1587  *
1588  * @param neighbor which peer we care about
1589  * @param tname name of the transport plugin
1590  * @param addr binary address
1591  * @param addrlen length of addr
1592  * @return NULL if we do not have a transport plugin for 'tname'
1593  */
1594 static struct ForeignAddressList *
1595 add_peer_address(struct NeighborList *neighbor,
1596                  const char *tname,
1597                  const char *addr, 
1598                  size_t addrlen)
1599 {
1600   struct ReadyList *head;
1601   struct ForeignAddressList *ret;
1602
1603   ret = find_peer_address (neighbor, tname, addr, addrlen);
1604   if (ret != NULL)
1605     return ret;
1606   head = neighbor->plugins;
1607   while (head != NULL)
1608     {
1609       if (0 == strcmp (tname, head->plugin->short_name))
1610         break;
1611       head = head->next;
1612     }
1613   if (head == NULL)
1614     return NULL;
1615   ret = GNUNET_malloc(sizeof(struct ForeignAddressList) + addrlen);
1616   ret->addr = (const char*) &ret[1];
1617   memcpy (&ret[1], addr, addrlen);
1618   ret->addrlen = addrlen;
1619   ret->expires = GNUNET_TIME_relative_to_absolute
1620     (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
1621   ret->latency = GNUNET_TIME_relative_get_forever();
1622   ret->transmit_ready = GNUNET_YES;
1623   ret->timeout = GNUNET_TIME_relative_to_absolute
1624     (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT); 
1625   ret->ready_list = head;
1626   ret->next = head->addresses;
1627   head->addresses = ret;
1628   return ret;
1629 }
1630
1631
1632 /**
1633  * Closure for 'add_validated_address'.
1634  */
1635 struct AddValidatedAddressContext
1636 {
1637   /**
1638    * Entry that has been validated.
1639    */
1640   const struct ValidationEntry *ve;
1641
1642   /**
1643    * Flag set after we have added the address so
1644    * that we terminate the iteration next time.
1645    */
1646   int done;
1647 };
1648
1649
1650 /**
1651  * Callback function used to fill a buffer of max bytes with a list of
1652  * addresses in the format used by HELLOs.  Should use
1653  * "GNUNET_HELLO_add_address" as a helper function.
1654  *
1655  * @param cls the 'struct AddValidatedAddressContext' with the validated address
1656  * @param max maximum number of bytes that can be written to buf
1657  * @param buf where to write the address information
1658  * @return number of bytes written, 0 to signal the
1659  *         end of the iteration.
1660  */
1661 static size_t
1662 add_validated_address (void *cls,
1663                        size_t max, void *buf)
1664 {
1665   struct AddValidatedAddressContext *avac = cls;
1666   const struct ValidationEntry *ve = avac->ve;
1667
1668   if (GNUNET_YES == avac->done)
1669     return 0;
1670   avac->done = GNUNET_YES;
1671   return GNUNET_HELLO_add_address (ve->transport_name,
1672                                    GNUNET_TIME_relative_to_absolute (HELLO_ADDRESS_EXPIRATION),
1673                                    ve->addr,
1674                                    ve->addrlen,
1675                                    buf,
1676                                    max);
1677 }
1678
1679
1680 /**
1681  * Iterator over hash map entries.  Checks if the given
1682  * validation entry is for the same challenge as what
1683  * is given in the PONG.
1684  *
1685  * @param cls the 'struct TransportPongMessage*'
1686  * @param key peer identity 
1687  * @param value value in the hash map ('struct ValidationEntry')
1688  * @return GNUNET_YES if we should continue to
1689  *         iterate (mismatch), GNUNET_NO if not (entry matched)
1690  */
1691 static int
1692 check_pending_validation (void *cls,
1693                           const GNUNET_HashCode * key,
1694                           void *value)
1695 {
1696   const struct TransportPongMessage *pong = cls;
1697   struct ValidationEntry *ve = value;
1698   struct AddValidatedAddressContext avac;
1699   unsigned int challenge = ntohl(pong->challenge);
1700   struct GNUNET_HELLO_Message *hello;
1701   struct GNUNET_PeerIdentity target;
1702   struct NeighborList *n;
1703   struct ForeignAddressList *fal;
1704
1705   if (ve->challenge != challenge)
1706     return GNUNET_YES;
1707   
1708 #if DEBUG_TRANSPORT
1709   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1710               "Confirmed validity of address, peer `%4s' has address `%s' (%s).\n",
1711               GNUNET_h2s (key),
1712               GNUNET_a2s ((const struct sockaddr *) ve->addr,
1713                           ve->addrlen),
1714               ve->transport_name);
1715 #endif
1716   /* create the updated HELLO */
1717   GNUNET_CRYPTO_hash (&ve->publicKey,
1718                       sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1719                       &target.hashPubKey);
1720   avac.done = GNUNET_NO;
1721   avac.ve = ve;
1722   hello = GNUNET_HELLO_create (&ve->publicKey,
1723                                &add_validated_address,
1724                                &avac);
1725   GNUNET_PEERINFO_add_peer (cfg, sched,
1726                             &target, 
1727                             hello);
1728   GNUNET_free (hello);
1729   n = find_neighbor (&target);
1730   if (n != NULL)
1731     {
1732       fal = add_peer_address (n, ve->transport_name, 
1733                               ve->addr,
1734                               ve->addrlen);
1735       fal->expires = GNUNET_TIME_relative_to_absolute (HELLO_ADDRESS_EXPIRATION);
1736       fal->validated = GNUNET_YES;
1737       fal->latency = GNUNET_TIME_absolute_get_duration (ve->send_time);
1738     }
1739
1740   /* clean up validation entry */
1741   GNUNET_assert (GNUNET_YES ==
1742                  GNUNET_CONTAINER_multihashmap_remove (validation_map,
1743                                                        key,
1744                                                        ve));
1745   GNUNET_SCHEDULER_cancel (sched,
1746                            ve->timeout_task);
1747   GNUNET_free (ve->transport_name);
1748   GNUNET_free (ve);
1749   return GNUNET_NO;
1750 }
1751
1752
1753 /**
1754  * Function that will be called if we receive a validation
1755  * of an address challenge that we transmitted to another
1756  * peer.  Note that the validation should only be considered
1757  * acceptable if the challenge matches AND if the sender
1758  * address is at least a plausible address for this peer
1759  * (otherwise we may be seeing a MiM attack).
1760  *
1761  * @param cls closure
1762  * @param name name of the transport that generated the address
1763  * @param peer who responded to our challenge
1764  * @param challenge the challenge number we presumably used
1765  * @param sender_addr string describing our sender address (as observed
1766  *         by the other peer in human-readable format)
1767  */
1768 static void
1769 handle_pong (void *cls, const struct GNUNET_MessageHeader *message,
1770              const struct GNUNET_PeerIdentity *peer,
1771              const char *sender_address,
1772              size_t sender_address_len)
1773 {
1774 #if DEBUG_TRANSPORT > 1
1775   /* we get tons of these that just get discarded, only log
1776      if we are quite verbose */
1777   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1778               "Receiving `%s' message from `%4s'.\n", "PONG",
1779               GNUNET_i2s (peer));
1780 #endif
1781   if (GNUNET_SYSERR != 
1782       GNUNET_CONTAINER_multihashmap_get_multiple (validation_map,
1783                                                   &peer->hashPubKey,
1784                                                   &check_pending_validation,
1785                                                   (void*) message))
1786     {
1787       /* This is *expected* to happen a lot since we send
1788          PONGs to *all* known addresses of the sender of
1789          the PING, so most likely we get multiple PONGs
1790          per PING, and all but the first PONG will end up
1791          here. So really we should not print anything here
1792          unless we want to be very, very verbose... */
1793 #if DEBUG_TRANSPORT > 2
1794       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1795                   "Received `%s' message from `%4s' but have no record of a matching `%s' message. Ignoring.\n",
1796                   "PONG",
1797                   GNUNET_i2s (peer),
1798                   "PING");
1799 #endif
1800       return;
1801     }
1802 #if 0
1803   /* FIXME: add given address to potential pool of our addresses
1804      (for voting) */
1805   GNUNET_log (GNUNET_ERROR_TYPE_INFO | GNUNET_ERROR_TYPE_BULK,
1806               _("Another peer saw us using the address `%s' via `%s'.\n"),
1807               GNUNET_a2s ((const struct sockaddr *) &pong[1],
1808                           ntohs(pong->addrlen)), 
1809               va->transport_name);  
1810 #endif
1811 }
1812
1813
1814 static void
1815 neighbor_timeout_task (void *cls,
1816                         const struct GNUNET_SCHEDULER_TaskContext *tc)
1817 {
1818   struct NeighborList *n = cls;
1819
1820 #if DEBUG_TRANSPORT
1821   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
1822               "Neighbor `%4s' has timed out!\n", GNUNET_i2s (&n->id));
1823 #endif
1824   n->timeout_task = GNUNET_SCHEDULER_NO_TASK;
1825   disconnect_neighbor (n, GNUNET_NO);
1826 }
1827
1828
1829 /**
1830  * Create a fresh entry in our neighbor list for the given peer.
1831  * Will try to transmit our current HELLO to the new neighbor.  Also
1832  * notifies our clients about the new "connection".
1833  *
1834  * @param peer the peer for which we create the entry
1835  * @return the new neighbor list entry
1836  */
1837 static struct NeighborList *
1838 setup_new_neighbor (const struct GNUNET_PeerIdentity *peer)
1839 {
1840   struct NeighborList *n;
1841   struct TransportPlugin *tp;
1842   struct ReadyList *rl;
1843
1844   GNUNET_assert (our_hello != NULL);
1845   n = GNUNET_malloc (sizeof (struct NeighborList));
1846   n->next = neighbors;
1847   neighbors = n;
1848   n->id = *peer;
1849   n->last_quota_update = GNUNET_TIME_absolute_get ();
1850   n->peer_timeout =
1851     GNUNET_TIME_relative_to_absolute
1852     (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
1853   n->quota_in = (GNUNET_CONSTANTS_DEFAULT_BPM_IN_OUT + 59999) / (60 * 1000);
1854   tp = plugins;
1855   while (tp != NULL)
1856     {
1857       if (tp->api->send != NULL)
1858         {
1859           rl = GNUNET_malloc (sizeof (struct ReadyList));
1860           rl->next = n->plugins;
1861           n->plugins = rl;
1862           rl->plugin = tp;
1863           rl->addresses = NULL;
1864         }
1865       tp = tp->next;
1866     }
1867   n->timeout_task = GNUNET_SCHEDULER_add_delayed (sched,
1868                                                   GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
1869                                                   &neighbor_timeout_task, n);
1870   transmit_to_peer (NULL, NULL, 0,
1871                     (const char *) our_hello, GNUNET_HELLO_size(our_hello),
1872                     GNUNET_NO, n);
1873   notify_clients_connect (peer, GNUNET_TIME_UNIT_FOREVER_REL);
1874   return n;
1875 }
1876
1877
1878 /**
1879  * Closure for 'check_address_exists'.
1880  */
1881 struct CheckAddressExistsClosure
1882 {
1883   /**
1884    * Address to check for.
1885    */
1886   const void *addr;
1887
1888   /**
1889    * Name of the transport.
1890    */
1891   const char *tname;
1892
1893   /**
1894    * Length of addr.
1895    */
1896   size_t addrlen;
1897
1898   /**
1899    * Set to GNUNET_YES if the address exists.
1900    */
1901   int exists;
1902 };
1903
1904
1905 /**
1906  * Iterator over hash map entries.  Checks if the given
1907  * validation entry is for the same address as what is given
1908  * in the closure.
1909  *
1910  * @param cls the 'struct CheckAddressExistsClosure*'
1911  * @param key current key code (ignored)
1912  * @param value value in the hash map ('struct ValidationEntry')
1913  * @return GNUNET_YES if we should continue to
1914  *         iterate (mismatch), GNUNET_NO if not (entry matched)
1915  */
1916 static int
1917 check_address_exists (void *cls,
1918                       const GNUNET_HashCode * key,
1919                       void *value)
1920 {
1921   struct CheckAddressExistsClosure *caec = cls;
1922   struct ValidationEntry *ve = value;
1923   if ( (0 == strcmp (caec->tname,
1924                      ve->transport_name)) &&
1925        (caec->addrlen == ve->addrlen) &&
1926        (0 == memcmp (caec->addr,
1927                      ve->addr,
1928                      caec->addrlen)) )
1929     {
1930       caec->exists = GNUNET_YES;
1931       return GNUNET_NO;
1932     }
1933   return GNUNET_YES;
1934 }
1935
1936
1937 /**
1938  * HELLO validation cleanup task (validation failed).
1939  *
1940  * @param cls the 'struct ValidationEntry' that failed
1941  * @param tc scheduler context (unused)
1942  */
1943 static void
1944 timeout_hello_validation (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1945 {
1946   struct ValidationEntry *va = cls;
1947   struct GNUNET_PeerIdentity pid;
1948
1949   GNUNET_CRYPTO_hash (&va->publicKey,
1950                       sizeof (struct
1951                               GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1952                       &pid.hashPubKey);
1953   GNUNET_CONTAINER_multihashmap_remove (validation_map,
1954                                         &pid.hashPubKey,
1955                                         va);
1956   GNUNET_free (va->transport_name);
1957   GNUNET_free (va);
1958 }
1959
1960
1961 /**
1962  * Check if the given address is already being validated; if not,
1963  * append the given address to the list of entries that are being be
1964  * validated and initiate validation.
1965  *
1966  * @param cls closure ('struct CheckHelloValidatedContext *')
1967  * @param tname name of the transport
1968  * @param expiration expiration time
1969  * @param addr the address
1970  * @param addrlen length of the address
1971  * @return GNUNET_OK (always)
1972  */
1973 static int
1974 run_validation (void *cls,
1975                 const char *tname,
1976                 struct GNUNET_TIME_Absolute expiration,
1977                 const void *addr, size_t addrlen)
1978 {
1979   struct CheckHelloValidatedContext *chvc = cls;
1980   struct GNUNET_PeerIdentity id;
1981   struct TransportPlugin *tp;
1982   struct ValidationEntry *va;
1983   struct NeighborList *neighbor;
1984   struct ForeignAddressList *peer_address;
1985   struct TransportPingMessage ping;
1986   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pk;
1987   struct CheckAddressExistsClosure caec;
1988   char * message_buf;
1989   uint16_t hello_size;
1990   size_t tsize;
1991
1992   tp = find_transport (tname);
1993   if (tp == NULL)
1994     {
1995       GNUNET_log (GNUNET_ERROR_TYPE_INFO |
1996                   GNUNET_ERROR_TYPE_BULK,
1997                   _
1998                   ("Transport `%s' not loaded, will not try to validate peer address using this transport.\n"),
1999                   tname);
2000       return GNUNET_OK;
2001     }
2002   GNUNET_HELLO_get_key (chvc->hello, &pk);
2003   GNUNET_CRYPTO_hash (&pk,
2004                       sizeof (struct
2005                               GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
2006                       &id.hashPubKey);
2007   caec.addr = addr;
2008   caec.addrlen = addrlen;
2009   caec.tname = tname;
2010   caec.exists = GNUNET_NO;
2011   GNUNET_CONTAINER_multihashmap_iterate (validation_map,
2012                                          &check_address_exists,
2013                                          &caec);
2014   if (caec.exists == GNUNET_YES)
2015     {
2016       /* During validation attempts we will likely trigger the other
2017          peer trying to validate our address which in turn will cause
2018          it to send us its HELLO, so we expect to hit this case rather
2019          frequently.  Only print something if we are very verbose. */
2020 #if DEBUG_TRANSPORT > 1
2021       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2022                   "Validation of address `%s' via `%s' for peer `%4s' already in progress.\n",
2023                   GNUNET_a2s (addr, addrlen), 
2024                   tname, 
2025                   GNUNET_i2s (&id));
2026 #endif
2027       return GNUNET_OK;
2028     } 
2029   va = GNUNET_malloc (sizeof (struct ValidationEntry) + addrlen);
2030   va->transport_name = GNUNET_strdup (tname);
2031   va->challenge = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2032                                             (unsigned int) -1);
2033   va->send_time = GNUNET_TIME_absolute_get();
2034   va->addr = (const void*) &va[1];
2035   memcpy (&va[1], addr, addrlen);
2036   va->addrlen = addrlen;
2037   GNUNET_HELLO_get_key (chvc->hello,
2038                         &va->publicKey);
2039   va->timeout_task = GNUNET_SCHEDULER_add_delayed (sched,
2040                                                    HELLO_VERIFICATION_TIMEOUT,
2041                                                    &timeout_hello_validation,
2042                                                    va);  
2043   GNUNET_CONTAINER_multihashmap_put (validation_map,
2044                                      &id.hashPubKey,
2045                                      va,
2046                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
2047   neighbor = find_neighbor(&id);  
2048   if (neighbor == NULL)
2049     neighbor = setup_new_neighbor(&id);
2050   peer_address = add_peer_address(neighbor, tname, addr, addrlen);    
2051   GNUNET_assert(peer_address != NULL);
2052   hello_size = GNUNET_HELLO_size(our_hello);
2053   tsize = sizeof(struct TransportPingMessage) + hello_size;
2054   message_buf = GNUNET_malloc(tsize);
2055   ping.challenge = htonl(va->challenge);
2056   ping.header.size = htons(sizeof(struct TransportPingMessage));
2057   ping.header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_PING);
2058   memcpy(&ping.target, &id, sizeof(struct GNUNET_PeerIdentity));
2059   memcpy(message_buf, our_hello, hello_size);
2060   memcpy(&message_buf[hello_size], 
2061          &ping, 
2062          sizeof(struct TransportPingMessage));
2063 #if DEBUG_TRANSPORT
2064   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2065               "Performing validation of address `%s' via `%s' for peer `%4s' sending `%s' (%u bytes) and `%s' (%u bytes)\n",
2066               GNUNET_a2s (addr, addrlen), 
2067               tname, 
2068               GNUNET_i2s (&id),
2069               "HELLO", hello_size,
2070               "PING", sizeof (struct TransportPingMessage));
2071 #endif
2072   transmit_to_peer(NULL, peer_address, 
2073                    GNUNET_SCHEDULER_PRIORITY_DEFAULT,
2074                    message_buf, tsize, 
2075                    GNUNET_YES, neighbor);
2076   GNUNET_free(message_buf);
2077   return GNUNET_OK;
2078 }
2079
2080
2081 /**
2082  * Add the given address to the list of foreign addresses
2083  * available for the given peer (check for duplicates).
2084  *
2085  * @param cls the respective 'struct NeighborList' to update
2086  * @param tname name of the transport
2087  * @param expiration expiration time
2088  * @param addr the address
2089  * @param addrlen length of the address
2090  * @return GNUNET_OK (always)
2091  */
2092 static int
2093 add_to_foreign_address_list (void *cls,
2094                              const char *tname,
2095                              struct GNUNET_TIME_Absolute expiration,
2096                              const void *addr, size_t addrlen)
2097 {
2098   struct NeighborList *n = cls;
2099   struct ForeignAddressList *fal;
2100
2101   fal = find_peer_address (n, tname, addr, addrlen);
2102   if (fal == NULL)
2103     {
2104 #if DEBUG_TRANSPORT
2105       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2106                   "Adding address `%s' (%s) for peer `%4s' due to peerinfo data.\n",
2107                   GNUNET_a2s (addr, addrlen),
2108                   tname,
2109                   GNUNET_i2s (&n->id));
2110 #endif
2111       fal = add_peer_address (n, tname, addr, addrlen);
2112     }
2113   fal->expires = GNUNET_TIME_absolute_max (expiration,
2114                                            fal->expires);
2115   fal->validated = GNUNET_YES;
2116   return GNUNET_OK;
2117 }
2118
2119
2120 /**
2121  * Check if addresses in validated hello "h" overlap with
2122  * those in "chvc->hello" and validate the rest.
2123  *
2124  * @param cls closure
2125  * @param peer id of the peer, NULL for last call
2126  * @param hello hello message for the peer (can be NULL)
2127  * @param trust amount of trust we have in the peer (not used)
2128  */
2129 static void
2130 check_hello_validated (void *cls,
2131                        const struct GNUNET_PeerIdentity *peer,
2132                        const struct GNUNET_HELLO_Message *h, 
2133                        uint32_t trust)
2134 {
2135   struct CheckHelloValidatedContext *chvc = cls;
2136   struct GNUNET_HELLO_Message *plain_hello;
2137   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pk;
2138   struct GNUNET_PeerIdentity target;
2139   struct NeighborList *n;
2140
2141   if (peer == NULL)
2142     {
2143       chvc->piter = NULL;
2144       GNUNET_CONTAINER_DLL_remove (chvc_head,
2145                                    chvc_tail,
2146                                    chvc);
2147       if (GNUNET_NO == chvc->hello_known)
2148         {
2149           /* notify PEERINFO about the peer now, so that we at least
2150              have the public key if some other component needs it */
2151           GNUNET_HELLO_get_key (chvc->hello, &pk);
2152           GNUNET_CRYPTO_hash (&pk,
2153                               sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
2154                               &target.hashPubKey);
2155           plain_hello = GNUNET_HELLO_create (&pk,
2156                                              NULL, 
2157                                              NULL);
2158           GNUNET_PEERINFO_add_peer (cfg, sched, &target, plain_hello);
2159           GNUNET_free (plain_hello);
2160 #if DEBUG_TRANSPORT
2161           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2162                       "Peerinfo had no `%s' message for peer `%4s', full validation needed.\n",
2163                       "HELLO",
2164                       GNUNET_i2s (&target));
2165 #endif
2166           GNUNET_HELLO_iterate_addresses (chvc->hello,
2167                                           GNUNET_NO, 
2168                                           &run_validation, 
2169                                           chvc);
2170         }
2171       GNUNET_free (chvc);
2172       return;
2173     }
2174   if (h == NULL)
2175     return;
2176   chvc->hello_known = GNUNET_YES;
2177   n = find_neighbor (peer);
2178   if (n != NULL)
2179     GNUNET_HELLO_iterate_addresses (h,
2180                                     GNUNET_NO,
2181                                     &add_to_foreign_address_list,
2182                                     n);
2183   GNUNET_HELLO_iterate_new_addresses (chvc->hello,
2184                                       h,
2185                                       GNUNET_TIME_relative_to_absolute (HELLO_REVALIDATION_START_TIME),
2186                                       &run_validation, 
2187                                       chvc);
2188 }
2189
2190 /**
2191  * Process HELLO-message.
2192  *
2193  * @param plugin transport involved, may be NULL
2194  * @param message the actual message
2195  * @return GNUNET_OK if the HELLO was well-formed, GNUNET_SYSERR otherwise
2196  */
2197 static int
2198 process_hello (struct TransportPlugin *plugin,
2199                const struct GNUNET_MessageHeader *message)
2200 {
2201   uint16_t hsize;
2202   struct GNUNET_PeerIdentity target;
2203   const struct GNUNET_HELLO_Message *hello;
2204   struct CheckHelloValidatedContext *chvc;
2205   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded publicKey;
2206
2207   hsize = ntohs (message->size);
2208   if ((ntohs (message->type) != GNUNET_MESSAGE_TYPE_HELLO) ||
2209       (hsize < sizeof (struct GNUNET_MessageHeader)))
2210     {
2211       GNUNET_break (0);
2212       return GNUNET_SYSERR;
2213     }
2214   /* first, check if load is too high */
2215   if (GNUNET_SCHEDULER_get_load (sched,
2216                                  GNUNET_SCHEDULER_PRIORITY_BACKGROUND) > MAX_HELLO_LOAD)
2217     {
2218       /* TODO: call to stats? */
2219       return GNUNET_OK;
2220     }
2221   hello = (const struct GNUNET_HELLO_Message *) message;
2222   if (GNUNET_OK != GNUNET_HELLO_get_key (hello, &publicKey))
2223     {
2224       GNUNET_break_op (0);
2225       return GNUNET_SYSERR;
2226     }
2227   GNUNET_CRYPTO_hash (&publicKey,
2228                       sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
2229                       &target.hashPubKey);
2230 #if DEBUG_TRANSPORT
2231   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2232               "Processing `%s' message for `%4s' of size %u\n",
2233               "HELLO", 
2234               GNUNET_i2s (&target), 
2235               GNUNET_HELLO_size(hello));
2236 #endif
2237
2238   chvc = GNUNET_malloc (sizeof (struct CheckHelloValidatedContext) + hsize);
2239   chvc->hello = (const struct GNUNET_HELLO_Message *) &chvc[1];
2240   memcpy (&chvc[1], hello, hsize);
2241   GNUNET_CONTAINER_DLL_insert (chvc_head,
2242                                chvc_tail,
2243                                chvc);
2244   /* finally, check if HELLO was previously validated
2245      (continuation will then schedule actual validation) */
2246   chvc->piter = GNUNET_PEERINFO_iterate (cfg,
2247                                          sched,
2248                                          &target,
2249                                          0,
2250                                          HELLO_VERIFICATION_TIMEOUT,
2251                                          &check_hello_validated, chvc);
2252   return GNUNET_OK;
2253 }
2254
2255
2256 /**
2257  * The peer specified by the given neighbor has timed-out or a plugin
2258  * has disconnected.  We may either need to do nothing (other plugins
2259  * still up), or trigger a full disconnect and clean up.  This
2260  * function updates our state and does the necessary notifications.
2261  * Also notifies our clients that the neighbor is now officially
2262  * gone.
2263  *
2264  * @param n the neighbor list entry for the peer
2265  * @param check should we just check if all plugins
2266  *        disconnected or must we ask all plugins to
2267  *        disconnect?
2268  */
2269 static void
2270 disconnect_neighbor (struct NeighborList *current_handle, int check)
2271 {
2272   struct ReadyList *rpos;
2273   struct NeighborList *npos;
2274   struct NeighborList *nprev;
2275   struct NeighborList *n;
2276   struct MessageQueue *mq;
2277   struct ForeignAddressList *peer_addresses;
2278   struct ForeignAddressList *peer_pos;
2279
2280   if (neighbors == NULL)
2281     return; /* We don't have any neighbors, so client has an already removed handle! */
2282
2283   npos = neighbors;
2284   while ((npos != NULL) && (current_handle != npos))
2285     npos = npos->next;
2286
2287   if (npos == NULL)
2288     return; /* Couldn't find neighbor in existing list, must have been already removed! */
2289   else
2290     n = npos;
2291
2292   if (GNUNET_YES == check)
2293     {
2294       rpos = n->plugins;
2295       while (NULL != rpos)
2296         {
2297           peer_addresses = rpos->addresses;
2298           while (peer_addresses != NULL)
2299             {
2300               if (GNUNET_YES == peer_addresses->connected)
2301                 return;             /* still connected */
2302               peer_addresses = peer_addresses->next;
2303             }
2304           rpos = rpos->next;
2305         }
2306     }
2307
2308 #if DEBUG_TRANSPORT
2309   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2310               "Disconnecting from `%4s'\n", GNUNET_i2s (&n->id));
2311 #endif
2312   /* remove n from neighbors list */
2313   nprev = NULL;
2314   npos = neighbors;
2315   while ((npos != NULL) && (npos != n))
2316     {
2317       nprev = npos;
2318       npos = npos->next;
2319     }
2320   GNUNET_assert (npos != NULL);
2321   if (nprev == NULL)
2322     neighbors = n->next;
2323   else
2324     nprev->next = n->next;
2325
2326   /* notify all clients about disconnect */
2327   notify_clients_disconnect (&n->id);
2328
2329   /* clean up all plugins, cancel connections and pending transmissions */
2330   while (NULL != (rpos = n->plugins))
2331     {
2332       n->plugins = rpos->next;
2333       if (GNUNET_YES == rpos->connected)
2334         rpos->plugin->api->disconnect (rpos->plugin->api->cls, &n->id);
2335
2336       while (rpos->addresses != NULL)
2337         {
2338           peer_pos = rpos->addresses;
2339           rpos->addresses = peer_pos->next;
2340           GNUNET_free(peer_pos);
2341         }
2342       GNUNET_free (rpos);
2343     }
2344
2345   /* free all messages on the queue */
2346   while (NULL != (mq = n->messages))
2347     {
2348       n->messages = mq->next;
2349       GNUNET_assert (0 == memcmp(&mq->neighbor_id, 
2350                                  &n->id,
2351                                  sizeof(struct GNUNET_PeerIdentity)));
2352       GNUNET_free (mq);
2353     }
2354   if (n->timeout_task != GNUNET_SCHEDULER_NO_TASK)
2355     GNUNET_SCHEDULER_cancel (sched, n->timeout_task);
2356   /* finally, free n itself */
2357   GNUNET_free (n);
2358 }
2359
2360
2361 /**
2362  * We have received a PING message from someone.  Need to send a PONG message
2363  * in response to the peer by any means necessary. 
2364  *
2365  * FIXME: With something like TCP where a connection exists, we may
2366  * want to send it that way.  But the current API does not seem to
2367  * allow us to do so (can't tell this to the transport!)
2368  */
2369 static int 
2370 handle_ping(void *cls, const struct GNUNET_MessageHeader *message,
2371             const struct GNUNET_PeerIdentity *peer,
2372             const char *sender_address,
2373             size_t sender_address_len)
2374 {
2375   struct TransportPlugin *plugin = cls;
2376   struct TransportPingMessage *ping;
2377   struct TransportPongMessage *pong;
2378   uint16_t msize;
2379   struct NeighborList *n;
2380   struct ReadyList *rl;
2381   struct ForeignAddressList *fal;
2382
2383   msize = ntohs (message->size);
2384   if (msize < sizeof (struct TransportPingMessage))
2385     {
2386       GNUNET_break_op (0);
2387       return GNUNET_SYSERR;
2388     }
2389   ping = (struct TransportPingMessage *) message;
2390   if (0 != memcmp (&ping->target,
2391                    plugin->env.my_identity,
2392                    sizeof (struct GNUNET_PeerIdentity)))
2393     {
2394       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2395                   _("Received `%s' message not destined for me!\n"), 
2396                   "PING");
2397       return GNUNET_SYSERR;
2398     }
2399 #if DEBUG_TRANSPORT
2400   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2401               "Processing `%s' from `%s'\n",
2402               "PING", 
2403               GNUNET_a2s ((const struct sockaddr *)sender_address, 
2404                           sender_address_len));
2405 #endif
2406   msize -= sizeof (struct TransportPingMessage);
2407   pong = GNUNET_malloc (sizeof (struct TransportPongMessage) + sender_address_len);
2408   pong->header.size = htons (sizeof (struct TransportPongMessage) + sender_address_len);
2409   pong->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_PONG);
2410   pong->purpose.size =
2411     htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) +
2412            sizeof (uint32_t) +
2413            sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) + sender_address_len);
2414   pong->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_TCP_PING);
2415   pong->challenge = ping->challenge;
2416   pong->addrlen = htons(sender_address_len);
2417   memcpy(&pong->signer, 
2418          &my_public_key, 
2419          sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
2420   memcpy (&pong[1], sender_address, sender_address_len);
2421   GNUNET_assert (GNUNET_OK ==
2422                  GNUNET_CRYPTO_rsa_sign (my_private_key,
2423                                          &pong->purpose, &pong->signature));
2424
2425   n = find_neighbor(peer);
2426   if (n == NULL)
2427     n = setup_new_neighbor(peer);
2428   /* broadcast 'PONG' to all available addresses */
2429   rl = n->plugins;
2430   while (rl != NULL)
2431     {
2432       fal = rl->addresses;
2433       while (fal != NULL)
2434         {
2435           transmit_to_peer(NULL, fal,
2436                            TRANSPORT_PONG_PRIORITY, 
2437                            (const char *)pong, 
2438                            ntohs(pong->header.size), 
2439                            GNUNET_YES, 
2440                            n);
2441           fal = fal->next;
2442         }
2443       rl = rl->next;
2444     }
2445   GNUNET_free(pong);
2446   return GNUNET_OK;
2447 }
2448
2449
2450 /**
2451  * Function called by the plugin for each received message.
2452  * Update data volumes, possibly notify plugins about
2453  * reducing the rate at which they read from the socket
2454  * and generally forward to our receive callback.
2455  *
2456  * @param cls the "struct TransportPlugin *" we gave to the plugin
2457  * @param message the message, NULL if peer was disconnected
2458  * @param distance the transport cost to this peer (not latency!)
2459  * @param sender_address the address that the sender reported
2460  *        (opaque to transport service)
2461  * @param sender_address_len the length of the sender address
2462  * @param peer (claimed) identity of the other peer
2463  * @return the new service_context that the plugin should use
2464  *         for future receive calls for messages from this
2465  *         particular peer
2466  *
2467  */
2468 static void
2469 plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
2470                     const struct GNUNET_MessageHeader *message,
2471                     unsigned int distance, const char *sender_address,
2472                     size_t sender_address_len)
2473 {
2474   struct ReadyList *service_context;
2475   struct TransportPlugin *plugin = cls;
2476   struct TransportClient *cpos;
2477   struct InboundMessage *im;
2478   struct ForeignAddressList *peer_address;
2479   uint16_t msize;
2480   struct NeighborList *n;
2481
2482   n = find_neighbor (peer);
2483   if (n == NULL)
2484     {
2485       if (message == NULL)
2486         return;                 /* disconnect of peer already marked down */
2487       n = setup_new_neighbor (peer);
2488
2489     }
2490   service_context = n->plugins;
2491   while ((service_context != NULL) && (plugin != service_context->plugin))
2492     service_context = service_context->next;
2493   GNUNET_assert ((plugin->api->send == NULL) || (service_context != NULL));
2494   if (message == NULL)
2495     {
2496 #if DEBUG_TRANSPORT
2497       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2498                   "Receive failed from `%4s', triggering disconnect\n",
2499                   GNUNET_i2s (&n->id));
2500 #endif
2501       /* TODO: call stats */
2502       if (service_context != NULL)
2503         service_context->connected = GNUNET_NO;
2504       disconnect_neighbor (n, GNUNET_YES);
2505       return;
2506     }
2507   peer_address = add_peer_address(n, 
2508                                   plugin->short_name,
2509                                   sender_address, 
2510                                   sender_address_len);
2511   if (service_context != NULL)
2512     {
2513       if (service_context->connected == GNUNET_NO)
2514         {
2515           service_context->connected = GNUNET_YES;
2516           /* FIXME: What to do here?  Should we use these as well, 
2517              to specify some Address in the AddressList should be
2518              available? */
2519           peer_address->transmit_ready = GNUNET_YES;
2520           peer_address->connect_attempts++;
2521         }
2522       peer_address->timeout
2523         =
2524         GNUNET_TIME_relative_to_absolute
2525         (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
2526     }
2527   /* update traffic received amount ... */
2528   msize = ntohs (message->size);
2529   n->last_received += msize;
2530   GNUNET_SCHEDULER_cancel (sched, n->timeout_task);
2531   n->peer_timeout =
2532     GNUNET_TIME_relative_to_absolute
2533     (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
2534   n->timeout_task =
2535     GNUNET_SCHEDULER_add_delayed (sched,
2536                                   GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
2537                                   &neighbor_timeout_task, n);
2538   update_quota (n);
2539   if (n->quota_violation_count > QUOTA_VIOLATION_DROP_THRESHOLD)
2540     {
2541       /* dropping message due to frequent inbound volume violations! */
2542       GNUNET_log (GNUNET_ERROR_TYPE_WARNING |
2543                   GNUNET_ERROR_TYPE_BULK,
2544                   _
2545                   ("Dropping incoming message due to repeated bandwidth quota violations (total of %u).\n"), n->quota_violation_count);
2546       /* TODO: call stats */
2547       return;
2548     }
2549   switch (ntohs (message->type))
2550     {
2551     case GNUNET_MESSAGE_TYPE_HELLO:
2552       process_hello (plugin, message);
2553       break;
2554     case GNUNET_MESSAGE_TYPE_TRANSPORT_PING:
2555       handle_ping(plugin, message, peer, sender_address, sender_address_len);
2556       break;
2557     case GNUNET_MESSAGE_TYPE_TRANSPORT_PONG:
2558       handle_pong(plugin, message, peer, sender_address, sender_address_len);
2559       break;
2560     default:
2561 #if DEBUG_TRANSPORT
2562       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2563                   "Received message of type %u from `%4s', sending to all clients.\n",
2564                   ntohs (message->type), GNUNET_i2s (peer));
2565 #endif
2566       /* transmit message to all clients */
2567       im = GNUNET_malloc (sizeof (struct InboundMessage) + msize);
2568       im->header.size = htons (sizeof (struct InboundMessage) + msize);
2569       im->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RECV);
2570       im->latency = n->latency;
2571       im->peer = *peer;
2572       memcpy (&im[1], message, msize);
2573
2574       cpos = clients;
2575       while (cpos != NULL)
2576         {
2577           transmit_to_client (cpos, &im->header, GNUNET_YES);
2578           cpos = cpos->next;
2579         }
2580       GNUNET_free (im);
2581     }
2582 }
2583
2584
2585 /**
2586  * Handle START-message.  This is the first message sent to us
2587  * by any client which causes us to add it to our list.
2588  *
2589  * @param cls closure (always NULL)
2590  * @param client identification of the client
2591  * @param message the actual message
2592  */
2593 static void
2594 handle_start (void *cls,
2595               struct GNUNET_SERVER_Client *client,
2596               const struct GNUNET_MessageHeader *message)
2597 {
2598   struct TransportClient *c;
2599   struct ConnectInfoMessage cim;
2600   struct NeighborList *n;
2601   struct InboundMessage *im;
2602   struct GNUNET_MessageHeader *ack;
2603
2604 #if DEBUG_TRANSPORT
2605   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2606               "Received `%s' request from client\n", "START");
2607 #endif
2608   c = clients;
2609   while (c != NULL)
2610     {
2611       if (c->client == client)
2612         {
2613           /* client already on our list! */
2614           GNUNET_break (0);
2615           GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2616           return;
2617         }
2618       c = c->next;
2619     }
2620   c = GNUNET_malloc (sizeof (struct TransportClient));
2621   c->next = clients;
2622   clients = c;
2623   c->client = client;
2624   if (our_hello != NULL)
2625     {
2626 #if DEBUG_TRANSPORT
2627       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2628                   "Sending our own `%s' to new client\n", "HELLO");
2629 #endif
2630       transmit_to_client (c,
2631                           (const struct GNUNET_MessageHeader *) our_hello,
2632                           GNUNET_NO);
2633       /* tell new client about all existing connections */
2634       cim.header.size = htons (sizeof (struct ConnectInfoMessage));
2635       cim.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
2636       cim.quota_out =
2637         htonl (GNUNET_CONSTANTS_DEFAULT_BPM_IN_OUT / (60 * 1000));
2638       cim.latency = GNUNET_TIME_relative_hton (GNUNET_TIME_UNIT_ZERO);  /* FIXME? */
2639       im = GNUNET_malloc (sizeof (struct InboundMessage) +
2640                           sizeof (struct GNUNET_MessageHeader));
2641       im->header.size = htons (sizeof (struct InboundMessage) +
2642                                sizeof (struct GNUNET_MessageHeader));
2643       im->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RECV);
2644       im->latency = GNUNET_TIME_relative_hton (GNUNET_TIME_UNIT_ZERO);  /* FIXME? */
2645       ack = (struct GNUNET_MessageHeader *) &im[1];
2646       ack->size = htons (sizeof (struct GNUNET_MessageHeader));
2647       ack->type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_ACK);
2648       for (n = neighbors; n != NULL; n = n->next)
2649         {
2650           cim.id = n->id;
2651           transmit_to_client (c, &cim.header, GNUNET_NO);
2652           if (n->received_pong)
2653             {
2654               im->peer = n->id;
2655               transmit_to_client (c, &im->header, GNUNET_NO);
2656             }
2657         }
2658       GNUNET_free (im);
2659     }
2660   else
2661     {
2662       fprintf(stderr, "Our hello is NULL!\n");
2663     }
2664   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2665 }
2666
2667
2668 /**
2669  * Handle HELLO-message.
2670  *
2671  * @param cls closure (always NULL)
2672  * @param client identification of the client
2673  * @param message the actual message
2674  */
2675 static void
2676 handle_hello (void *cls,
2677               struct GNUNET_SERVER_Client *client,
2678               const struct GNUNET_MessageHeader *message)
2679 {
2680   int ret;
2681
2682 #if DEBUG_TRANSPORT
2683   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2684               "Received `%s' request from client\n", "HELLO");
2685 #endif
2686   ret = process_hello (NULL, message);
2687   GNUNET_SERVER_receive_done (client, ret);
2688 }
2689
2690
2691 /**
2692  * Handle SEND-message.
2693  *
2694  * @param cls closure (always NULL)
2695  * @param client identification of the client
2696  * @param message the actual message
2697  */
2698 static void
2699 handle_send (void *cls,
2700              struct GNUNET_SERVER_Client *client,
2701              const struct GNUNET_MessageHeader *message)
2702 {
2703   struct TransportClient *tc;
2704   struct NeighborList *n;
2705   const struct OutboundMessage *obm;
2706   const struct GNUNET_MessageHeader *obmm;
2707   uint16_t size;
2708   uint16_t msize;
2709
2710   size = ntohs (message->size);
2711   if (size <
2712       sizeof (struct OutboundMessage) + sizeof (struct GNUNET_MessageHeader))
2713     {
2714       GNUNET_break (0);
2715       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2716       return;
2717     }
2718   obm = (const struct OutboundMessage *) message;
2719 #if DEBUG_TRANSPORT
2720   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2721               "Received `%s' request from client with target `%4s'\n",
2722               "SEND", GNUNET_i2s (&obm->peer));
2723 #endif
2724   obmm = (const struct GNUNET_MessageHeader *) &obm[1];
2725   msize = ntohs (obmm->size);
2726   if (size != msize + sizeof (struct OutboundMessage))
2727     {
2728       GNUNET_break (0);
2729       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2730       return;
2731     }
2732   n = find_neighbor (&obm->peer);
2733   if (n == NULL)
2734     n = setup_new_neighbor (&obm->peer); /* But won't ever add address, we have none! */
2735   tc = clients;
2736   while ((tc != NULL) && (tc->client != client))
2737     tc = tc->next;
2738
2739 #if DEBUG_TRANSPORT
2740   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2741               "Client asked to transmit %u-byte message of type %u to `%4s'\n",
2742               ntohs (obmm->size),
2743               ntohs (obmm->type), GNUNET_i2s (&obm->peer));
2744 #endif
2745   transmit_to_peer (tc, NULL, ntohl (obm->priority), (char *)obmm, 
2746                     ntohs (obmm->size), GNUNET_NO, n);
2747   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2748 }
2749
2750
2751 /**
2752  * Handle SET_QUOTA-message.
2753  *
2754  * @param cls closure (always NULL)
2755  * @param client identification of the client
2756  * @param message the actual message
2757  */
2758 static void
2759 handle_set_quota (void *cls,
2760                   struct GNUNET_SERVER_Client *client,
2761                   const struct GNUNET_MessageHeader *message)
2762 {
2763   const struct QuotaSetMessage *qsm =
2764     (const struct QuotaSetMessage *) message;
2765   struct NeighborList *n;
2766   struct TransportPlugin *p;
2767   struct ReadyList *rl;
2768
2769   n = find_neighbor (&qsm->peer);
2770   if (n == NULL)
2771     {
2772       GNUNET_SERVER_receive_done (client, GNUNET_OK);
2773       return;
2774     }
2775
2776 #if DEBUG_TRANSPORT
2777   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2778               "Received `%s' request (new quota %u, old quota %u) from client for peer `%4s'\n",
2779               "SET_QUOTA", ntohl(qsm->quota_in), n->quota_in, GNUNET_i2s (&qsm->peer));
2780 #endif
2781
2782   update_quota (n);
2783   if (n->quota_in < ntohl (qsm->quota_in))
2784     n->last_quota_update = GNUNET_TIME_absolute_get ();
2785   n->quota_in = ntohl (qsm->quota_in);
2786   rl = n->plugins;
2787   while (rl != NULL)
2788     {
2789       p = rl->plugin;
2790       p->api->set_receive_quota (p->api->cls,
2791                                  &qsm->peer, ntohl (qsm->quota_in));
2792       rl = rl->next;
2793     }
2794   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2795 }
2796
2797
2798 /**
2799  * Handle TRY_CONNECT-message.
2800  *
2801  * @param cls closure (always NULL)
2802  * @param client identification of the client
2803  * @param message the actual message
2804  */
2805 static void
2806 handle_try_connect (void *cls,
2807                     struct GNUNET_SERVER_Client *client,
2808                     const struct GNUNET_MessageHeader *message)
2809 {
2810   const struct TryConnectMessage *tcm;
2811   struct NeighborList *neighbor;
2812   tcm = (const struct TryConnectMessage *) message;
2813 #if DEBUG_TRANSPORT
2814   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2815               "Received `%s' request from client %p asking to connect to `%4s'\n",
2816               "TRY_CONNECT", client, GNUNET_i2s (&tcm->peer));
2817 #endif
2818   neighbor = find_neighbor(&tcm->peer);
2819   if (neighbor == NULL)
2820     setup_new_neighbor (&tcm->peer);
2821   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2822 }
2823
2824
2825 static void
2826 transmit_address_to_client (void *cls, const char *address)
2827 {
2828   struct GNUNET_SERVER_TransmitContext *tc = cls;
2829   size_t slen;
2830
2831   if (NULL == address)
2832     slen = 0;
2833   else
2834     slen = strlen (address) + 1;
2835   GNUNET_SERVER_transmit_context_append_data (tc, address, slen,
2836                                               GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_REPLY);
2837   if (NULL == address)
2838     GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
2839 }
2840
2841
2842 /**
2843  * Handle AddressLookup-message.
2844  *
2845  * @param cls closure (always NULL)
2846  * @param client identification of the client
2847  * @param message the actual message
2848  */
2849 static void
2850 handle_address_lookup (void *cls,
2851                        struct GNUNET_SERVER_Client *client,
2852                        const struct GNUNET_MessageHeader *message)
2853 {
2854   const struct AddressLookupMessage *alum;
2855   struct TransportPlugin *lsPlugin;
2856   const char *nameTransport;
2857   const char *address;
2858   uint16_t size;
2859   struct GNUNET_SERVER_TransmitContext *tc;
2860
2861   size = ntohs (message->size);
2862   if (size < sizeof (struct AddressLookupMessage))
2863     {
2864       GNUNET_break_op (0);
2865       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2866       return;
2867     }
2868   alum = (const struct AddressLookupMessage *) message;
2869   uint32_t addressLen = ntohl (alum->addrlen);
2870   if (size <= sizeof (struct AddressLookupMessage) + addressLen)
2871     {
2872       GNUNET_break_op (0);
2873       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2874       return;
2875     }
2876   address = (const char *) &alum[1];
2877   nameTransport = (const char *) &address[addressLen];
2878   if (nameTransport
2879       [size - sizeof (struct AddressLookupMessage) - addressLen - 1] != '\0')
2880     {
2881       GNUNET_break_op (0);
2882       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2883       return;
2884     }
2885   struct GNUNET_TIME_Absolute timeout =
2886     GNUNET_TIME_absolute_ntoh (alum->timeout);
2887   struct GNUNET_TIME_Relative rtimeout =
2888     GNUNET_TIME_absolute_get_remaining (timeout);
2889   lsPlugin = find_transport (nameTransport);
2890   if (NULL == lsPlugin)
2891     {
2892       tc = GNUNET_SERVER_transmit_context_create (client);
2893       GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
2894                                                   GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_REPLY);
2895       GNUNET_SERVER_transmit_context_run (tc, rtimeout);
2896       return;
2897     }
2898   tc = GNUNET_SERVER_transmit_context_create (client);
2899   lsPlugin->api->address_pretty_printer (cls, nameTransport,
2900                                          address, addressLen, GNUNET_YES,
2901                                          rtimeout,
2902                                          &transmit_address_to_client, tc);
2903 }
2904
2905 /**
2906  * List of handlers for the messages understood by this
2907  * service.
2908  */
2909 static struct GNUNET_SERVER_MessageHandler handlers[] = {
2910   {&handle_start, NULL,
2911    GNUNET_MESSAGE_TYPE_TRANSPORT_START, 0},
2912   {&handle_hello, NULL,
2913    GNUNET_MESSAGE_TYPE_HELLO, 0},
2914   {&handle_send, NULL,
2915    GNUNET_MESSAGE_TYPE_TRANSPORT_SEND, 0},
2916   {&handle_set_quota, NULL,
2917    GNUNET_MESSAGE_TYPE_TRANSPORT_SET_QUOTA, sizeof (struct QuotaSetMessage)},
2918   {&handle_try_connect, NULL,
2919    GNUNET_MESSAGE_TYPE_TRANSPORT_TRY_CONNECT,
2920    sizeof (struct TryConnectMessage)},
2921   {&handle_address_lookup, NULL,
2922    GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_LOOKUP,
2923    0},
2924   {NULL, NULL, 0, 0}
2925 };
2926
2927
2928 /**
2929  * Setup the environment for this plugin.
2930  */
2931 static void
2932 create_environment (struct TransportPlugin *plug)
2933 {
2934   plug->env.cfg = cfg;
2935   plug->env.sched = sched;
2936   plug->env.my_identity = &my_identity;
2937   plug->env.cls = plug;
2938   plug->env.receive = &plugin_env_receive;
2939   plug->env.notify_address = &plugin_env_notify_address;
2940   plug->env.default_quota_in =
2941     (GNUNET_CONSTANTS_DEFAULT_BPM_IN_OUT + 59999) / (60 * 1000);
2942   plug->env.max_connections = max_connect_per_transport;
2943 }
2944
2945
2946 /**
2947  * Start the specified transport (load the plugin).
2948  */
2949 static void
2950 start_transport (struct GNUNET_SERVER_Handle *server, const char *name)
2951 {
2952   struct TransportPlugin *plug;
2953   char *libname;
2954
2955   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2956               _("Loading `%s' transport plugin\n"), name);
2957   GNUNET_asprintf (&libname, "libgnunet_plugin_transport_%s", name);
2958   plug = GNUNET_malloc (sizeof (struct TransportPlugin));
2959   create_environment (plug);
2960   plug->short_name = GNUNET_strdup (name);
2961   plug->lib_name = libname;
2962   plug->next = plugins;
2963   plugins = plug;
2964   plug->api = GNUNET_PLUGIN_load (libname, &plug->env);
2965   if (plug->api == NULL)
2966     {
2967       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2968                   _("Failed to load transport plugin for `%s'\n"), name);
2969       GNUNET_free (plug->short_name);
2970       plugins = plug->next;
2971       GNUNET_free (libname);
2972       GNUNET_free (plug);
2973     }
2974 }
2975
2976
2977 /**
2978  * Called whenever a client is disconnected.  Frees our
2979  * resources associated with that client.
2980  *
2981  * @param cls closure
2982  * @param client identification of the client
2983  */
2984 static void
2985 client_disconnect_notification (void *cls,
2986                                 struct GNUNET_SERVER_Client *client)
2987 {
2988   struct TransportClient *pos;
2989   struct TransportClient *prev;
2990   struct ClientMessageQueueEntry *mqe;
2991
2992   if (client == NULL)
2993     return;
2994 #if DEBUG_TRANSPORT
2995   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2996               "Client disconnected, cleaning up.\n");
2997 #endif
2998   prev = NULL;
2999   pos = clients;
3000   while ((pos != NULL) && (pos->client != client))
3001     {
3002       prev = pos;
3003       pos = pos->next;
3004     }
3005   if (pos == NULL)
3006     return;
3007   while (NULL != (mqe = pos->message_queue_head))
3008     {
3009       pos->message_queue_head = mqe->next;
3010       GNUNET_free (mqe);
3011     }
3012   pos->message_queue_head = NULL;
3013   if (prev == NULL)
3014     clients = pos->next;
3015   else
3016     prev->next = pos->next;
3017   if (GNUNET_YES == pos->tcs_pending)
3018     {
3019       pos->client = NULL;
3020       return;
3021     }
3022   GNUNET_free (pos);
3023 }
3024
3025
3026 /**
3027  * Iterator to free entries in the validation_map.
3028  *
3029  * @param cls closure (unused)
3030  * @param key current key code
3031  * @param value value in the hash map (validation to abort)
3032  * @return GNUNET_YES (always)
3033  */
3034 static int 
3035 abort_validation (void *cls,
3036                   const GNUNET_HashCode * key,
3037                   void *value)
3038 {
3039   struct ValidationEntry *va = value;
3040
3041   GNUNET_SCHEDULER_cancel (sched, va->timeout_task);
3042   GNUNET_free (va->transport_name);
3043   GNUNET_free (va);
3044   return GNUNET_YES;
3045 }
3046
3047
3048 /**
3049  * Function called when the service shuts down.  Unloads our plugins
3050  * and cancels pending validations.
3051  *
3052  * @param cls closure, unused
3053  * @param tc task context (unused)
3054  */
3055 static void
3056 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
3057 {
3058   struct TransportPlugin *plug;
3059   struct OwnAddressList *al;
3060   struct CheckHelloValidatedContext *chvc;
3061
3062 #if DEBUG_TRANSPORT
3063   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3064               "Transport service is unloading plugins...\n");
3065 #endif
3066   while (NULL != (plug = plugins))
3067     {
3068       plugins = plug->next;
3069       GNUNET_break (NULL == GNUNET_PLUGIN_unload (plug->lib_name, plug->api));
3070       GNUNET_free (plug->lib_name);
3071       GNUNET_free (plug->short_name);
3072       while (NULL != (al = plug->addresses))
3073         {
3074           plug->addresses = al->next;
3075           GNUNET_free (al);
3076         }
3077       GNUNET_free (plug);
3078     }
3079   if (my_private_key != NULL)
3080     GNUNET_CRYPTO_rsa_key_free (my_private_key);
3081   GNUNET_free_non_null (our_hello);
3082
3083   /* free 'chvc' data structure */
3084   while (NULL != (chvc = chvc_head))
3085     {
3086       chvc_head = chvc->next;
3087       GNUNET_PEERINFO_iterate_cancel (chvc->piter);
3088       GNUNET_free (chvc);
3089     }
3090   chvc_tail = NULL;
3091
3092   GNUNET_CONTAINER_multihashmap_iterate (validation_map,
3093                                          &abort_validation,
3094                                          NULL);
3095   GNUNET_CONTAINER_multihashmap_destroy (validation_map);
3096 }
3097
3098
3099 /**
3100  * Initiate transport service.
3101  *
3102  * @param cls closure
3103  * @param s scheduler to use
3104  * @param serv the initialized server
3105  * @param c configuration to use
3106  */
3107 static void
3108 run (void *cls,
3109      struct GNUNET_SCHEDULER_Handle *s,
3110      struct GNUNET_SERVER_Handle *serv,
3111      const struct GNUNET_CONFIGURATION_Handle *c)
3112 {
3113   char *plugs;
3114   char *pos;
3115   int no_transports;
3116   unsigned long long tneigh;
3117   char *keyfile;
3118
3119   sched = s;
3120   cfg = c;
3121   validation_map = GNUNET_CONTAINER_multihashmap_create (64);
3122   /* parse configuration */
3123   if ((GNUNET_OK !=
3124        GNUNET_CONFIGURATION_get_value_number (c,
3125                                               "TRANSPORT",
3126                                               "NEIGHBOUR_LIMIT",
3127                                               &tneigh)) ||
3128       (GNUNET_OK !=
3129        GNUNET_CONFIGURATION_get_value_filename (c,
3130                                                 "GNUNETD",
3131                                                 "HOSTKEY", &keyfile)))
3132     {
3133       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3134                   _
3135                   ("Transport service is lacking key configuration settings.  Exiting.\n"));
3136       GNUNET_SCHEDULER_shutdown (s);
3137       return;
3138     }
3139   max_connect_per_transport = (uint32_t) tneigh;
3140   my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
3141   GNUNET_free (keyfile);
3142   if (my_private_key == NULL)
3143     {
3144       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3145                   _
3146                   ("Transport service could not access hostkey.  Exiting.\n"));
3147       GNUNET_SCHEDULER_shutdown (s);
3148       return;
3149     }
3150   GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key);
3151   GNUNET_CRYPTO_hash (&my_public_key,
3152                       sizeof (my_public_key), &my_identity.hashPubKey);
3153   /* setup notification */
3154   server = serv;
3155   GNUNET_SERVER_disconnect_notify (server,
3156                                    &client_disconnect_notification, NULL);
3157   /* load plugins... */
3158   no_transports = 1;
3159   if (GNUNET_OK ==
3160       GNUNET_CONFIGURATION_get_value_string (c,
3161                                              "TRANSPORT", "PLUGINS", &plugs))
3162     {
3163       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3164                   _("Starting transport plugins `%s'\n"), plugs);
3165       pos = strtok (plugs, " ");
3166       while (pos != NULL)
3167         {
3168           start_transport (server, pos);
3169           no_transports = 0;
3170           pos = strtok (NULL, " ");
3171         }
3172       GNUNET_free (plugs);
3173     }
3174   GNUNET_SCHEDULER_add_delayed (sched,
3175                                 GNUNET_TIME_UNIT_FOREVER_REL,
3176                                 &shutdown_task, NULL);
3177   if (no_transports)
3178     refresh_hello ();
3179
3180 #if DEBUG_TRANSPORT
3181   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Transport service ready.\n"));
3182 #endif
3183   /* process client requests */
3184   GNUNET_SERVER_add_handlers (server, handlers);
3185 }
3186
3187
3188 /**
3189  * The main function for the transport service.
3190  *
3191  * @param argc number of arguments from the command line
3192  * @param argv command line arguments
3193  * @return 0 ok, 1 on error
3194  */
3195 int
3196 main (int argc, char *const *argv)
3197 {
3198   return (GNUNET_OK ==
3199           GNUNET_SERVICE_run (argc,
3200                               argv,
3201                               "transport",
3202                               GNUNET_SERVICE_OPTION_NONE,
3203                               &run, NULL)) ? 0 : 1;
3204 }
3205
3206 /* end of gnunet-service-transport.c */