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