ce8338b1d78f14548d18672ef8be0babc048f087
[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 /**
578  * Linked list of messages to be transmitted to the client.  Each
579  * entry is followed by the actual message.
580  */
581 struct ClientMessageQueueEntry
582 {
583   /**
584    * This is a doubly-linked list.
585    */
586   struct ClientMessageQueueEntry *next;
587
588   /**
589    * This is a doubly-linked list.
590    */
591   struct ClientMessageQueueEntry *prev;
592 };
593
594
595 /**
596  * Client connected to the transport service.
597  */
598 struct TransportClient
599 {
600
601   /**
602    * This is a linked list.
603    */
604   struct TransportClient *next;
605
606   /**
607    * Handle to the client.
608    */
609   struct GNUNET_SERVER_Client *client;
610
611   /**
612    * Linked list of messages yet to be transmitted to
613    * the client.
614    */
615   struct ClientMessageQueueEntry *message_queue_head;
616
617   /**
618    * Tail of linked list of messages yet to be transmitted to the
619    * client.
620    */
621   struct ClientMessageQueueEntry *message_queue_tail;
622
623   /**
624    * Current transmit request handle.
625    */ 
626   struct GNUNET_CONNECTION_TransmitHandle *th;
627
628   /**
629    * Is a call to "transmit_send_continuation" pending?  If so, we
630    * must not free this struct (even if the corresponding client
631    * disconnects) and instead only remove it from the linked list and
632    * set the "client" field to NULL.
633    */
634   int tcs_pending;
635
636   /**
637    * Length of the list of messages pending for this client.
638    */
639   unsigned int message_count;
640
641 };
642
643
644 /**
645  * Entry in map of all HELLOs awaiting validation.
646  */
647 struct ValidationEntry
648 {
649
650   /**
651    * The address, actually a pointer to the end
652    * of this struct.  Do not free!
653    */
654   const void *addr;
655
656   /**
657    * Name of the transport.
658    */
659   char *transport_name;
660
661   /**
662    * The public key of the peer.
663    */
664   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded publicKey;
665
666   /**
667    * ID of task that will clean up this entry if we don't succeed
668    * with the validation first.
669    */
670   GNUNET_SCHEDULER_TaskIdentifier timeout_task;
671
672   /**
673    * At what time did we send this validation?
674    */
675   struct GNUNET_TIME_Absolute send_time;
676
677   /**
678    * Length of addr.
679    */
680   size_t addrlen;
681
682   /**
683    * Challenge number we used.
684    */
685   uint32_t challenge;
686
687 };
688
689
690 /**
691  * Context of currently active requests to peerinfo
692  * for validation of HELLOs.
693  */
694 struct CheckHelloValidatedContext
695 {
696
697   /**
698    * This is a doubly-linked list.
699    */
700   struct CheckHelloValidatedContext *next;
701
702   /**
703    * This is a doubly-linked list.
704    */
705   struct CheckHelloValidatedContext *prev;
706
707   /**
708    * Hello that we are validating.
709    */
710   const struct GNUNET_HELLO_Message *hello;
711
712   /**
713    * Context for peerinfo iteration.
714    * NULL after we are done processing peerinfo's information.
715    */
716   struct GNUNET_PEERINFO_IteratorContext *piter;
717   
718   /**
719    * Was a HELLO known for this peer to peerinfo?
720    */
721   int hello_known;
722
723 };
724
725
726 /**
727  * Our HELLO message.
728  */
729 static struct GNUNET_HELLO_Message *our_hello;
730
731 /**
732  * "version" of "our_hello".  Used to see if a given neighbour has
733  * already been sent the latest version of our HELLO message.
734  */
735 static unsigned int our_hello_version;
736
737 /**
738  * Our public key.
739  */
740 static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded my_public_key;
741
742 /**
743  * Our identity.
744  */
745 static struct GNUNET_PeerIdentity my_identity;
746
747 /**
748  * Our private key.
749  */
750 static struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key;
751
752 /**
753  * Our scheduler.
754  */
755 struct GNUNET_SCHEDULER_Handle *sched;
756
757 /**
758  * Our configuration.
759  */
760 const struct GNUNET_CONFIGURATION_Handle *cfg;
761
762 /**
763  * Linked list of all clients to this service.
764  */
765 static struct TransportClient *clients;
766
767 /**
768  * All loaded plugins.
769  */
770 static struct TransportPlugin *plugins;
771
772 /**
773  * Our server.
774  */
775 static struct GNUNET_SERVER_Handle *server;
776
777 /**
778  * All known neighbours and their HELLOs.
779  */
780 static struct NeighbourList *neighbours;
781
782 /**
783  * Number of neighbours we'd like to have.
784  */
785 static uint32_t max_connect_per_transport;
786
787 /**
788  * Head of linked list.
789  */
790 static struct CheckHelloValidatedContext *chvc_head;
791
792 /**
793  * Tail of linked list.
794  */
795 static struct CheckHelloValidatedContext *chvc_tail;
796
797
798 /**
799  * Map of PeerIdentities to 'struct ValidationEntry*'s (addresses
800  * of the given peer that we are currently validating).
801  */
802 static struct GNUNET_CONTAINER_MultiHashMap *validation_map;
803
804
805 /**
806  * The peer specified by the given neighbour has timed-out or a plugin
807  * has disconnected.  We may either need to do nothing (other plugins
808  * still up), or trigger a full disconnect and clean up.  This
809  * function updates our state and do the necessary notifications.
810  * Also notifies our clients that the neighbour is now officially
811  * gone.
812  *
813  * @param n the neighbour list entry for the peer
814  * @param check should we just check if all plugins
815  *        disconnected or must we ask all plugins to
816  *        disconnect?
817  */
818 static void disconnect_neighbour (struct NeighbourList *n, int check);
819
820 /**
821  * Check the ready list for the given neighbour and if a plugin is
822  * ready for transmission (and if we have a message), do so!
823  *
824  * @param neighbour target peer for which to transmit
825  */
826 static void try_transmission_to_peer (struct NeighbourList *neighbour);
827
828
829 /**
830  * Find an entry in the neighbour list for a particular peer.
831  * if sender_address is not specified (NULL) then return the
832  * first matching entry.  If sender_address is specified, then
833  * make sure that the address and address_len also matches.
834  *
835  * @return NULL if not found.
836  */
837 static struct NeighbourList *
838 find_neighbour (const struct GNUNET_PeerIdentity *key)
839 {
840   struct NeighbourList *head = neighbours;
841
842   while ((head != NULL) &&
843         (0 != memcmp (key, &head->id, sizeof (struct GNUNET_PeerIdentity))))
844     head = head->next;
845   return head;
846 }
847
848
849 /**
850  * Find an entry in the transport list for a particular transport.
851  *
852  * @return NULL if not found.
853  */
854 static struct TransportPlugin *
855 find_transport (const char *short_name)
856 {
857   struct TransportPlugin *head = plugins;
858   while ((head != NULL) && (0 != strcmp (short_name, head->short_name)))
859     head = head->next;
860   return head;
861 }
862
863
864 /**
865  * Update the quota values for the given neighbour now.
866  */
867 static void
868 update_quota (struct NeighbourList *n)
869 {
870   struct GNUNET_TIME_Relative delta;
871   uint64_t allowed;
872   uint64_t remaining;
873
874   delta = GNUNET_TIME_absolute_get_duration (n->last_quota_update);
875   if (delta.value < MIN_QUOTA_REFRESH_TIME)
876     return;                     /* not enough time passed for doing quota update */
877   allowed = delta.value * n->quota_in;
878
879   if (n->last_received < allowed)
880     {
881       remaining = allowed - n->last_received;
882       if (n->quota_in > 0)
883         remaining /= n->quota_in;
884       else
885         remaining = 0;
886       if (remaining > MAX_BANDWIDTH_CARRY)
887         remaining = MAX_BANDWIDTH_CARRY;
888       n->last_received = 0;
889       n->last_quota_update = GNUNET_TIME_absolute_get ();
890       n->last_quota_update.value -= remaining;
891       if (n->quota_violation_count > 0)
892         n->quota_violation_count--;
893     }
894   else
895     {
896       n->last_received -= allowed;
897       n->last_quota_update = GNUNET_TIME_absolute_get ();
898       if (n->last_received > allowed)
899         {
900           /* more than twice the allowed rate! */
901           n->quota_violation_count += 10;
902         }
903     }
904 }
905
906
907 /**
908  * Function called to notify a client about the socket being ready to
909  * queue more data.  "buf" will be NULL and "size" zero if the socket
910  * was closed for writing in the meantime.
911  *
912  * @param cls closure
913  * @param size number of bytes available in buf
914  * @param buf where the callee should write the message
915  * @return number of bytes written to buf
916  */
917 static size_t
918 transmit_to_client_callback (void *cls, size_t size, void *buf)
919 {
920   struct TransportClient *client = cls;
921   struct ClientMessageQueueEntry *q;
922   uint16_t msize;
923   size_t tsize;
924   const struct GNUNET_MessageHeader *msg;
925   char *cbuf;
926
927   client->th = NULL;
928   if (buf == NULL)
929     {
930       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
931                   "Transmission to client failed, closing connection.\n");
932       /* fatal error with client, free message queue! */
933       while (NULL != (q = client->message_queue_head))
934         {
935           GNUNET_CONTAINER_DLL_remove (client->message_queue_head,
936                                        client->message_queue_tail,
937                                        q);
938           GNUNET_free (q);
939         }
940       client->message_count = 0;
941       return 0;
942     }
943   cbuf = buf;
944   tsize = 0;
945   while (NULL != (q = client->message_queue_head))
946     {
947       msg = (const struct GNUNET_MessageHeader *) &q[1];
948       msize = ntohs (msg->size);
949       if (msize + tsize > size)
950         break;
951 #if DEBUG_TRANSPORT
952       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
953                   "Transmitting message of type %u to client.\n",
954                   ntohs (msg->type));
955 #endif
956       GNUNET_CONTAINER_DLL_remove (client->message_queue_head,
957                                    client->message_queue_tail,
958                                    q);
959       memcpy (&cbuf[tsize], msg, msize);
960       tsize += msize;
961       GNUNET_free (q);
962       client->message_count--;
963     }
964   if (NULL != q)
965     {
966       GNUNET_assert (msize >= sizeof (struct GNUNET_MessageHeader));
967       client->th = GNUNET_SERVER_notify_transmit_ready (client->client,
968                                                         msize,
969                                                         GNUNET_TIME_UNIT_FOREVER_REL,
970                                                         &transmit_to_client_callback,
971                                                         client);
972       GNUNET_assert (client->th != NULL);
973     }
974   return tsize;
975 }
976
977
978 /**
979  * Send the specified message to the specified client.  Since multiple
980  * messages may be pending for the same client at a time, this code
981  * makes sure that no message is lost.
982  *
983  * @param client client to transmit the message to
984  * @param msg the message to send
985  * @param may_drop can this message be dropped if the
986  *        message queue for this client is getting far too large?
987  */
988 static void
989 transmit_to_client (struct TransportClient *client,
990                     const struct GNUNET_MessageHeader *msg, int may_drop)
991 {
992   struct ClientMessageQueueEntry *q;
993   uint16_t msize;
994
995   if ((client->message_count >= MAX_PENDING) && (GNUNET_YES == may_drop))
996     {
997       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
998                   _
999                   ("Dropping message, have %u messages pending (%u is the soft limit)\n"),
1000                   client->message_count, MAX_PENDING);
1001       /* TODO: call to statistics... */
1002       return;
1003     }
1004   msize = ntohs (msg->size);
1005   GNUNET_assert (msize >= sizeof (struct GNUNET_MessageHeader));
1006   q = GNUNET_malloc (sizeof (struct ClientMessageQueueEntry) + msize);
1007   memcpy (&q[1], msg, msize);
1008   GNUNET_CONTAINER_DLL_insert_after (client->message_queue_head,
1009                                      client->message_queue_tail,
1010                                      client->message_queue_tail,
1011                                      q);                                     
1012   client->message_count++;
1013   if (client->th == NULL)
1014     {
1015       client->th = GNUNET_SERVER_notify_transmit_ready (client->client,
1016                                                         msize,
1017                                                         GNUNET_TIME_UNIT_FOREVER_REL,
1018                                                         &transmit_to_client_callback,
1019                                                         client);
1020       GNUNET_assert (client->th != NULL);
1021     }
1022 }
1023
1024
1025 /**
1026  * Transmit a 'SEND_OK' notification to the given client for the
1027  * given neighbour.
1028  *
1029  * @param client who to notify
1030  * @param n neighbour to notify about
1031  * @param result status code for the transmission request
1032  */
1033 static void
1034 transmit_send_ok (struct TransportClient *client,
1035                   struct NeighbourList *n,
1036                   int result)
1037 {
1038   struct SendOkMessage send_ok_msg;
1039
1040   send_ok_msg.header.size = htons (sizeof (send_ok_msg));
1041   send_ok_msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK);
1042   send_ok_msg.success = htonl (result);
1043   send_ok_msg.latency = GNUNET_TIME_relative_hton (n->latency);
1044   send_ok_msg.peer = n->id;
1045   transmit_to_client (client, &send_ok_msg.header, GNUNET_NO); 
1046 }
1047
1048
1049 /**
1050  * Function called by the GNUNET_TRANSPORT_TransmitFunction
1051  * upon "completion" of a send request.  This tells the API
1052  * that it is now legal to send another message to the given
1053  * peer.
1054  *
1055  * @param cls closure, identifies the entry on the
1056  *            message queue that was transmitted and the
1057  *            client responsible for queueing the message
1058  * @param target the peer receiving the message
1059  * @param result GNUNET_OK on success, if the transmission
1060  *           failed, we should not tell the client to transmit
1061  *           more messages
1062  */
1063 static void
1064 transmit_send_continuation (void *cls,
1065                             const struct GNUNET_PeerIdentity *target,
1066                             int result)
1067 {
1068   struct MessageQueue *mq = cls;
1069   struct NeighbourList *n;
1070
1071   n = find_neighbour(&mq->neighbour_id);
1072   GNUNET_assert (n != NULL);
1073   if (mq->specific_address != NULL)
1074     {
1075       if (result == GNUNET_OK)    
1076         {
1077           mq->specific_address->timeout =
1078             GNUNET_TIME_relative_to_absolute
1079             (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
1080           mq->specific_address->connected = GNUNET_YES;
1081         }    
1082       else
1083         {
1084           mq->specific_address->connected = GNUNET_NO;
1085         }    
1086       if (! mq->internal_msg) 
1087         mq->specific_address->in_transmit = GNUNET_NO;
1088     }
1089   if (mq->client != NULL)
1090     transmit_send_ok (mq->client, n, result);
1091   GNUNET_free (mq);
1092   try_transmission_to_peer (n);
1093   if (result != GNUNET_OK)
1094     disconnect_neighbour (n, GNUNET_YES);    
1095 }
1096
1097
1098 /**
1099  * Find an address in any of the available transports for
1100  * the given neighbour that would be good for message
1101  * transmission.  This is essentially the transport selection
1102  * routine.
1103  *
1104  * @param neighbour for whom to select an address
1105  * @return selected address, NULL if we have none
1106  */
1107 struct ForeignAddressList *
1108 find_ready_address(struct NeighbourList *neighbour)
1109 {
1110   struct ReadyList *head = neighbour->plugins;
1111   struct ForeignAddressList *addresses;
1112   struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
1113   struct ForeignAddressList *best_address;
1114
1115   best_address = NULL;
1116   while (head != NULL)
1117     {
1118       addresses = head->addresses;
1119       while (addresses != NULL)
1120         {
1121           if ( (addresses->timeout.value < now.value) && 
1122                (addresses->connected == GNUNET_YES) )
1123             {
1124 #if DEBUG_TRANSPORT
1125               GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1126                           "Marking long-time inactive connection to `%4s' as down.\n",
1127                           GNUNET_i2s (&neighbour->id));
1128 #endif
1129               addresses->connected = GNUNET_NO;
1130             }
1131           addresses = addresses->next;
1132         }
1133
1134       addresses = head->addresses;
1135       while (addresses != NULL)
1136         {
1137           if ( ( (best_address == NULL) || 
1138                  (addresses->connected == GNUNET_YES) ||
1139                  (best_address->connected == GNUNET_NO) ) &&
1140                (addresses->in_transmit == GNUNET_NO) &&
1141                ( (best_address == NULL) || 
1142                  (addresses->latency.value < best_address->latency.value)) )
1143             best_address = addresses;            
1144           /* FIXME: also give lower-latency addresses that are not
1145              connected a chance some times... */
1146           addresses = addresses->next;
1147         }
1148       head = head->next;
1149     }
1150 #if DEBUG_TRANSPORT
1151   if (best_address != NULL)
1152     {
1153       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1154                   "Best address found has latency of %llu ms.\n",
1155                   best_address->latency.value);
1156     }
1157 #endif
1158   return best_address;
1159
1160 }
1161
1162
1163 /**
1164  * We should re-try transmitting to the given peer,
1165  * hopefully we've learned something in the meantime.
1166  */
1167 static void
1168 retry_transmission_task (void *cls,
1169                          const struct GNUNET_SCHEDULER_TaskContext *tc)
1170 {
1171   struct NeighbourList *n = cls;
1172
1173   n->retry_task = GNUNET_SCHEDULER_NO_TASK;
1174   try_transmission_to_peer (n);
1175 }
1176
1177
1178 /**
1179  * Check the ready list for the given neighbour and if a plugin is
1180  * ready for transmission (and if we have a message), do so!
1181  *
1182  * @param neighbour target peer for which to transmit
1183  */
1184 static void
1185 try_transmission_to_peer (struct NeighbourList *neighbour)
1186 {
1187   struct ReadyList *rl;
1188   struct MessageQueue *mq;
1189   struct GNUNET_TIME_Relative timeout;
1190
1191   if (neighbour->messages_head == NULL)
1192     return;                     /* nothing to do */
1193   rl = NULL;
1194   mq = neighbour->messages_head;
1195   /* FIXME: support bi-directional use of TCP */
1196   if (mq->specific_address == NULL)
1197     mq->specific_address = find_ready_address(neighbour); 
1198   if (mq->specific_address == NULL)
1199     {
1200       timeout = GNUNET_TIME_absolute_get_remaining (mq->timeout);
1201       if (timeout.value == 0)
1202         {
1203 #if DEBUG_TRANSPORT
1204           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1205                       "No destination address available to transmit message of size %u to peer `%4s'\n",
1206                       mq->message_buf_size,
1207                       GNUNET_i2s (&mq->neighbour_id));
1208 #endif
1209           if (mq->client != NULL)
1210             transmit_send_ok (mq->client, neighbour, GNUNET_NO);
1211           GNUNET_CONTAINER_DLL_remove (neighbour->messages_head,
1212                                        neighbour->messages_tail,
1213                                        mq);
1214           GNUNET_free (mq);
1215           return;               /* nobody ready */ 
1216         }
1217       if (neighbour->retry_task != GNUNET_SCHEDULER_NO_TASK)
1218         GNUNET_SCHEDULER_cancel (sched,
1219                                  neighbour->retry_task);
1220       neighbour->retry_task = GNUNET_SCHEDULER_add_delayed (sched,
1221                                                             timeout,
1222                                                             &retry_transmission_task,
1223                                                             neighbour);
1224 #if DEBUG_TRANSPORT
1225       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1226                   "No validated destination address available to transmit message of size %u to peer `%4s', will wait %llums to find an address.\n",
1227                   mq->message_buf_size,
1228                   GNUNET_i2s (&mq->neighbour_id),
1229                   timeout.value);
1230 #endif
1231       return;    
1232     }
1233   GNUNET_CONTAINER_DLL_remove (neighbour->messages_head,
1234                                neighbour->messages_tail,
1235                                mq);
1236   if (mq->specific_address->connected == GNUNET_NO)
1237     mq->specific_address->connect_attempts++;
1238   rl = mq->specific_address->ready_list;
1239   mq->plugin = rl->plugin;
1240   if (!mq->internal_msg)
1241     mq->specific_address->in_transmit = GNUNET_YES;
1242 #if DEBUG_TRANSPORT
1243   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1244               "Sending message of size %u for `%4s' to `%s' via plugin `%s'\n",
1245               mq->message_buf_size,
1246               GNUNET_i2s (&neighbour->id), 
1247               GNUNET_a2s (mq->specific_address->addr,
1248                           mq->specific_address->addrlen),
1249               rl->plugin->short_name);
1250 #endif
1251   rl->plugin->api->send (rl->plugin->api->cls,
1252                          &mq->neighbour_id,
1253                          mq->message_buf,
1254                          mq->message_buf_size,
1255                          mq->priority,
1256                          GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
1257                          mq->specific_address->addr,
1258                          mq->specific_address->addrlen,
1259                          GNUNET_YES /* FIXME: sometimes, we want to be more tolerant here! */,
1260                          &transmit_send_continuation, mq);
1261 }
1262
1263
1264 /**
1265  * Send the specified message to the specified peer.
1266  *
1267  * @param client source of the transmission request (can be NULL)
1268  * @param peer_address ForeignAddressList where we should send this message
1269  * @param priority how important is the message
1270  * @param timeout how long do we have to transmit?
1271  * @param message_buf message(s) to send GNUNET_MessageHeader(s)
1272  * @param message_buf_size total size of all messages in message_buf
1273  * @param is_internal is this an internal message; these are pre-pended and
1274  *                    also do not count for plugins being "ready" to transmit
1275  * @param neighbour handle to the neighbour for transmission
1276  */
1277 static void
1278 transmit_to_peer (struct TransportClient *client,
1279                   struct ForeignAddressList *peer_address,
1280                   unsigned int priority,
1281                   struct GNUNET_TIME_Relative timeout,
1282                   const char *message_buf,
1283                   size_t message_buf_size,
1284                   int is_internal, struct NeighbourList *neighbour)
1285 {
1286   struct MessageQueue *mq;
1287
1288 #if EXTRA_CHECKS
1289   if (client != NULL)
1290     {
1291       /* check for duplicate submission */
1292       mq = neighbour->messages_head;
1293       while (NULL != mq)
1294         {
1295           if (mq->client == client)
1296             {
1297               /* client transmitted to same peer twice
1298                  before getting SendOk! */
1299               GNUNET_break (0);
1300               return;
1301             }
1302           mq = mq->next;
1303         }
1304     }
1305 #endif
1306   mq = GNUNET_malloc (sizeof (struct MessageQueue) + message_buf_size);
1307   mq->specific_address = peer_address;
1308   mq->client = client;
1309   memcpy (&mq[1], message_buf, message_buf_size);
1310   mq->message_buf = (const char*) &mq[1];
1311   mq->message_buf_size = message_buf_size;
1312   memcpy(&mq->neighbour_id, &neighbour->id, sizeof(struct GNUNET_PeerIdentity));
1313   mq->internal_msg = is_internal;
1314   mq->priority = priority;
1315   mq->timeout = GNUNET_TIME_relative_to_absolute (timeout);
1316   if (is_internal)    
1317     GNUNET_CONTAINER_DLL_insert (neighbour->messages_head,
1318                                  neighbour->messages_tail,
1319                                  mq);
1320   else
1321     GNUNET_CONTAINER_DLL_insert_after (neighbour->messages_head,
1322                                        neighbour->messages_tail,
1323                                        neighbour->messages_tail,
1324                                        mq);
1325   try_transmission_to_peer (neighbour);
1326 }
1327
1328
1329 /**
1330  * FIXME: document.
1331  */
1332 struct GeneratorContext
1333 {
1334   struct TransportPlugin *plug_pos;
1335   struct OwnAddressList *addr_pos;
1336   struct GNUNET_TIME_Absolute expiration;
1337 };
1338
1339
1340 /**
1341  * FIXME: document.
1342  */
1343 static size_t
1344 address_generator (void *cls, size_t max, void *buf)
1345 {
1346   struct GeneratorContext *gc = cls;
1347   size_t ret;
1348
1349   while ((gc->addr_pos == NULL) && (gc->plug_pos != NULL))
1350     {
1351       gc->plug_pos = gc->plug_pos->next;
1352       gc->addr_pos = (gc->plug_pos != NULL) ? gc->plug_pos->addresses : NULL;
1353     }
1354   if (NULL == gc->plug_pos)
1355     {
1356
1357       return 0;
1358     }
1359   ret = GNUNET_HELLO_add_address (gc->plug_pos->short_name,
1360                                   gc->expiration,
1361                                   gc->addr_pos->addr,
1362                                   gc->addr_pos->addrlen, buf, max);
1363   gc->addr_pos = gc->addr_pos->next;
1364   return ret;
1365 }
1366
1367
1368 /**
1369  * Construct our HELLO message from all of the addresses of
1370  * all of the transports.
1371  */
1372 static void
1373 refresh_hello ()
1374 {
1375   struct GNUNET_HELLO_Message *hello;
1376   struct TransportClient *cpos;
1377   struct NeighbourList *npos;
1378   struct GeneratorContext gc;
1379
1380   gc.plug_pos = plugins;
1381   gc.addr_pos = plugins != NULL ? plugins->addresses : NULL;
1382   gc.expiration = GNUNET_TIME_relative_to_absolute (HELLO_ADDRESS_EXPIRATION);
1383   hello = GNUNET_HELLO_create (&my_public_key, &address_generator, &gc);
1384 #if DEBUG_TRANSPORT
1385   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
1386               "Refreshed my `%s', new size is %d\n", "HELLO", GNUNET_HELLO_size(hello));
1387 #endif
1388   cpos = clients;
1389   while (cpos != NULL)
1390     {
1391       transmit_to_client (cpos,
1392                           (const struct GNUNET_MessageHeader *) hello,
1393                           GNUNET_NO);
1394       cpos = cpos->next;
1395     }
1396
1397   GNUNET_free_non_null (our_hello);
1398   our_hello = hello;
1399   our_hello_version++;
1400   GNUNET_PEERINFO_add_peer (cfg, sched, &my_identity, our_hello);
1401   npos = neighbours;
1402   while (npos != NULL)
1403     {
1404 #if DEBUG_TRANSPORT
1405       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
1406                   "Transmitting updated `%s' to neighbour `%4s'\n",
1407                   "HELLO", GNUNET_i2s (&npos->id));
1408 #endif
1409       transmit_to_peer (NULL, NULL, 0,
1410                         HELLO_ADDRESS_EXPIRATION,
1411                         (const char *) our_hello, 
1412                         GNUNET_HELLO_size(our_hello),
1413                         GNUNET_NO, npos);
1414       npos = npos->next;
1415     }
1416 }
1417
1418
1419 /**
1420  * Task used to clean up expired addresses for a plugin.
1421  *
1422  * @param cls closure
1423  * @param tc context
1424  */
1425 static void
1426 expire_address_task (void *cls,
1427                      const struct GNUNET_SCHEDULER_TaskContext *tc);
1428
1429
1430 /**
1431  * Update the list of addresses for this plugin,
1432  * expiring those that are past their expiration date.
1433  *
1434  * @param plugin addresses of which plugin should be recomputed?
1435  * @param fresh set to GNUNET_YES if a new address was added
1436  *        and we need to regenerate the HELLO even if nobody
1437  *        expired
1438  */
1439 static void
1440 update_addresses (struct TransportPlugin *plugin, int fresh)
1441 {
1442   struct GNUNET_TIME_Relative min_remaining;
1443   struct GNUNET_TIME_Relative remaining;
1444   struct GNUNET_TIME_Absolute now;
1445   struct OwnAddressList *pos;
1446   struct OwnAddressList *prev;
1447   struct OwnAddressList *next;
1448   int expired;
1449
1450   if (plugin->address_update_task != GNUNET_SCHEDULER_NO_TASK)
1451     GNUNET_SCHEDULER_cancel (plugin->env.sched, plugin->address_update_task);
1452   plugin->address_update_task = GNUNET_SCHEDULER_NO_TASK;
1453   now = GNUNET_TIME_absolute_get ();
1454   min_remaining = GNUNET_TIME_UNIT_FOREVER_REL;
1455   expired = GNUNET_NO;
1456   prev = NULL;
1457   pos = plugin->addresses;
1458   while (pos != NULL)
1459     {
1460       next = pos->next;
1461       if (pos->expires.value < now.value)
1462         {
1463           expired = GNUNET_YES;
1464           if (prev == NULL)
1465             plugin->addresses = pos->next;
1466           else
1467             prev->next = pos->next;
1468           GNUNET_free (pos);
1469         }
1470       else
1471         {
1472           remaining = GNUNET_TIME_absolute_get_remaining (pos->expires);
1473           if (remaining.value < min_remaining.value)
1474             min_remaining = remaining;
1475           prev = pos;
1476         }
1477       pos = next;
1478     }
1479
1480   if (expired || fresh)
1481     refresh_hello ();
1482   if (min_remaining.value < GNUNET_TIME_UNIT_FOREVER_REL.value)
1483     plugin->address_update_task
1484       = GNUNET_SCHEDULER_add_delayed (plugin->env.sched,
1485                                       min_remaining,
1486                                       &expire_address_task, plugin);
1487
1488 }
1489
1490
1491 /**
1492  * Task used to clean up expired addresses for a plugin.
1493  *
1494  * @param cls closure
1495  * @param tc context
1496  */
1497 static void
1498 expire_address_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1499 {
1500   struct TransportPlugin *plugin = cls;
1501   plugin->address_update_task = GNUNET_SCHEDULER_NO_TASK;
1502   update_addresses (plugin, GNUNET_NO);
1503 }
1504
1505
1506 /**
1507  * Function that must be called by each plugin to notify the
1508  * transport service about the addresses under which the transport
1509  * provided by the plugin can be reached.
1510  *
1511  * @param cls closure
1512  * @param name name of the transport that generated the address
1513  * @param addr one of the addresses of the host, NULL for the last address
1514  *        the specific address format depends on the transport
1515  * @param addrlen length of the address
1516  * @param expires when should this address automatically expire?
1517  */
1518 static void
1519 plugin_env_notify_address (void *cls,
1520                            const char *name,
1521                            const void *addr,
1522                            size_t addrlen,
1523                            struct GNUNET_TIME_Relative expires)
1524 {
1525   struct TransportPlugin *p = cls;
1526   struct OwnAddressList *al;
1527   struct GNUNET_TIME_Absolute abex;
1528
1529   abex = GNUNET_TIME_relative_to_absolute (expires);
1530   GNUNET_assert (p == find_transport (name));
1531
1532   al = p->addresses;
1533   while (al != NULL)
1534     {
1535       if ((addrlen == al->addrlen) && (0 == memcmp (addr, &al[1], addrlen)))
1536         {
1537           if (al->expires.value < abex.value)
1538             al->expires = abex;
1539           return;
1540         }
1541       al = al->next;
1542     }
1543
1544   al = GNUNET_malloc (sizeof (struct OwnAddressList) + addrlen);
1545   al->addr = &al[1];
1546   al->next = p->addresses;
1547   p->addresses = al;
1548   al->expires = abex;
1549   al->addrlen = addrlen;
1550   memcpy (&al[1], addr, addrlen);
1551   update_addresses (p, GNUNET_YES);
1552 }
1553
1554
1555 /**
1556  * Notify all of our clients about a peer connecting.
1557  */
1558 static void
1559 notify_clients_connect (const struct GNUNET_PeerIdentity *peer,
1560                         struct GNUNET_TIME_Relative latency,
1561                         uint32_t distance)
1562 {
1563   struct ConnectInfoMessage cim;
1564   struct TransportClient *cpos;
1565
1566 #if DEBUG_TRANSPORT
1567   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1568               "Notifying clients about connection from `%s'\n",
1569               GNUNET_i2s (peer));
1570 #endif
1571   cim.header.size = htons (sizeof (struct ConnectInfoMessage));
1572   cim.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
1573   cim.distance = htonl (distance);
1574   cim.latency = GNUNET_TIME_relative_hton (latency);
1575   memcpy (&cim.id, peer, sizeof (struct GNUNET_PeerIdentity));
1576   cpos = clients;
1577   while (cpos != NULL)
1578     {
1579       transmit_to_client (cpos, &cim.header, GNUNET_NO);
1580       cpos = cpos->next;
1581     }
1582 }
1583
1584
1585 /**
1586  * Notify all of our clients about a peer disconnecting.
1587  */
1588 static void
1589 notify_clients_disconnect (const struct GNUNET_PeerIdentity *peer)
1590 {
1591   struct DisconnectInfoMessage dim;
1592   struct TransportClient *cpos;
1593
1594 #if DEBUG_TRANSPORT
1595   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1596               "Notifying clients about lost connection to `%s'\n",
1597               GNUNET_i2s (peer));
1598 #endif
1599   dim.header.size = htons (sizeof (struct DisconnectInfoMessage));
1600   dim.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT);
1601   dim.reserved = htonl (0);
1602   memcpy (&dim.peer, peer, sizeof (struct GNUNET_PeerIdentity));
1603   cpos = clients;
1604   while (cpos != NULL)
1605     {
1606       transmit_to_client (cpos, &dim.header, GNUNET_NO);
1607       cpos = cpos->next;
1608     }
1609 }
1610
1611
1612 /**
1613  * Find a ForeignAddressList entry for the given neighbour
1614  * that matches the given address and transport.
1615  *
1616  * @param neighbour which peer we care about
1617  * @param tname name of the transport plugin
1618  * @param addr binary address
1619  * @param addrlen length of addr
1620  * @return NULL if no such entry exists
1621  */
1622 static struct ForeignAddressList *
1623 find_peer_address(struct NeighbourList *neighbour,
1624                   const char *tname,
1625                   const char *addr,
1626                   size_t addrlen)
1627 {
1628   struct ReadyList *head;
1629   struct ForeignAddressList *address_head;
1630
1631   head = neighbour->plugins;
1632   while (head != NULL)
1633     {
1634       if (0 == strcmp (tname, head->plugin->short_name))
1635         break;
1636       head = head->next;
1637     }
1638   if (head == NULL)
1639     return NULL;
1640
1641   address_head = head->addresses;
1642   while ( (address_head != NULL) &&
1643           ( (address_head->addrlen != addrlen) ||
1644             (memcmp(address_head->addr, addr, addrlen) != 0) ) )
1645     address_head = address_head->next;
1646   return address_head;
1647 }
1648
1649
1650 /**
1651  * Get the peer address struct for the given neighbour and
1652  * address.  If it doesn't yet exist, create it.
1653  *
1654  * @param neighbour which peer we care about
1655  * @param tname name of the transport plugin
1656  * @param addr binary address
1657  * @param addrlen length of addr
1658  * @return NULL if we do not have a transport plugin for 'tname'
1659  */
1660 static struct ForeignAddressList *
1661 add_peer_address(struct NeighbourList *neighbour,
1662                  const char *tname,
1663                  const char *addr, 
1664                  size_t addrlen)
1665 {
1666   struct ReadyList *head;
1667   struct ForeignAddressList *ret;
1668
1669   ret = find_peer_address (neighbour, tname, addr, addrlen);
1670   if (ret != NULL)
1671     return ret;
1672   head = neighbour->plugins;
1673   while (head != NULL)
1674     {
1675       if (0 == strcmp (tname, head->plugin->short_name))
1676         break;
1677       head = head->next;
1678     }
1679   if (head == NULL)
1680     return NULL;
1681   ret = GNUNET_malloc(sizeof(struct ForeignAddressList) + addrlen);
1682   ret->addr = (const char*) &ret[1];
1683   memcpy (&ret[1], addr, addrlen);
1684   ret->addrlen = addrlen;
1685   ret->expires = GNUNET_TIME_relative_to_absolute
1686     (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
1687   ret->latency = GNUNET_TIME_relative_get_forever();
1688   ret->distance = -1;
1689   ret->timeout = GNUNET_TIME_relative_to_absolute
1690     (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT); 
1691   ret->ready_list = head;
1692   ret->next = head->addresses;
1693   head->addresses = ret;
1694   return ret;
1695 }
1696
1697
1698 /**
1699  * Closure for 'add_validated_address'.
1700  */
1701 struct AddValidatedAddressContext
1702 {
1703   /**
1704    * Entry that has been validated.
1705    */
1706   const struct ValidationEntry *ve;
1707
1708   /**
1709    * Flag set after we have added the address so
1710    * that we terminate the iteration next time.
1711    */
1712   int done;
1713 };
1714
1715
1716 /**
1717  * Callback function used to fill a buffer of max bytes with a list of
1718  * addresses in the format used by HELLOs.  Should use
1719  * "GNUNET_HELLO_add_address" as a helper function.
1720  *
1721  * @param cls the 'struct AddValidatedAddressContext' with the validated address
1722  * @param max maximum number of bytes that can be written to buf
1723  * @param buf where to write the address information
1724  * @return number of bytes written, 0 to signal the
1725  *         end of the iteration.
1726  */
1727 static size_t
1728 add_validated_address (void *cls,
1729                        size_t max, void *buf)
1730 {
1731   struct AddValidatedAddressContext *avac = cls;
1732   const struct ValidationEntry *ve = avac->ve;
1733
1734   if (GNUNET_YES == avac->done)
1735     return 0;
1736   avac->done = GNUNET_YES;
1737   return GNUNET_HELLO_add_address (ve->transport_name,
1738                                    GNUNET_TIME_relative_to_absolute (HELLO_ADDRESS_EXPIRATION),
1739                                    ve->addr,
1740                                    ve->addrlen,
1741                                    buf,
1742                                    max);
1743 }
1744
1745
1746 /**
1747  * Iterator over hash map entries.  Checks if the given
1748  * validation entry is for the same challenge as what
1749  * is given in the PONG.
1750  *
1751  * @param cls the 'struct TransportPongMessage*'
1752  * @param key peer identity 
1753  * @param value value in the hash map ('struct ValidationEntry')
1754  * @return GNUNET_YES if we should continue to
1755  *         iterate (mismatch), GNUNET_NO if not (entry matched)
1756  */
1757 static int
1758 check_pending_validation (void *cls,
1759                           const GNUNET_HashCode * key,
1760                           void *value)
1761 {
1762   const struct TransportPongMessage *pong = cls;
1763   struct ValidationEntry *ve = value;
1764   struct AddValidatedAddressContext avac;
1765   unsigned int challenge = ntohl(pong->challenge);
1766   struct GNUNET_HELLO_Message *hello;
1767   struct GNUNET_PeerIdentity target;
1768   struct NeighbourList *n;
1769   struct ForeignAddressList *fal;
1770
1771   if (ve->challenge != challenge)
1772     return GNUNET_YES;
1773   
1774 #if DEBUG_TRANSPORT
1775   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1776               "Confirmed validity of address, peer `%4s' has address `%s' (%s).\n",
1777               GNUNET_h2s (key),
1778               GNUNET_a2s ((const struct sockaddr *) ve->addr,
1779                           ve->addrlen),
1780               ve->transport_name);
1781 #endif
1782   /* create the updated HELLO */
1783   GNUNET_CRYPTO_hash (&ve->publicKey,
1784                       sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1785                       &target.hashPubKey);
1786   avac.done = GNUNET_NO;
1787   avac.ve = ve;
1788   hello = GNUNET_HELLO_create (&ve->publicKey,
1789                                &add_validated_address,
1790                                &avac);
1791   GNUNET_PEERINFO_add_peer (cfg, sched,
1792                             &target, 
1793                             hello);
1794   GNUNET_free (hello);
1795   n = find_neighbour (&target);
1796   if (n != NULL)
1797     {
1798       fal = add_peer_address (n, ve->transport_name, 
1799                               ve->addr,
1800                               ve->addrlen);
1801       fal->expires = GNUNET_TIME_relative_to_absolute (HELLO_ADDRESS_EXPIRATION);
1802       fal->validated = GNUNET_YES;
1803       fal->latency = GNUNET_TIME_absolute_get_duration (ve->send_time);
1804       if (n->latency.value == GNUNET_TIME_UNIT_FOREVER_REL.value)
1805         n->latency = fal->latency;
1806       else
1807         n->latency.value = (fal->latency.value + n->latency.value) / 2;
1808       n->distance = fal->distance;
1809       if (GNUNET_NO == n->received_pong)
1810         {
1811           notify_clients_connect (&target, n->latency, n->distance);
1812           n->received_pong = GNUNET_YES;
1813         }
1814       if (n->retry_task != GNUNET_SCHEDULER_NO_TASK)
1815         {
1816           GNUNET_SCHEDULER_cancel (sched,
1817                                    n->retry_task);
1818           n->retry_task = GNUNET_SCHEDULER_NO_TASK;     
1819           try_transmission_to_peer (n);
1820         }
1821     }
1822
1823   /* clean up validation entry */
1824   GNUNET_assert (GNUNET_YES ==
1825                  GNUNET_CONTAINER_multihashmap_remove (validation_map,
1826                                                        key,
1827                                                        ve));
1828   GNUNET_SCHEDULER_cancel (sched,
1829                            ve->timeout_task);
1830   GNUNET_free (ve->transport_name);
1831   GNUNET_free (ve);
1832   return GNUNET_NO;
1833 }
1834
1835
1836 /**
1837  * Function that will be called if we receive a validation
1838  * of an address challenge that we transmitted to another
1839  * peer.  Note that the validation should only be considered
1840  * acceptable if the challenge matches AND if the sender
1841  * address is at least a plausible address for this peer
1842  * (otherwise we may be seeing a MiM attack).
1843  *
1844  * @param cls closure
1845  * @param message the pong message
1846  * @param peer who responded to our challenge
1847  * @param sender_addr string describing our sender address (as observed
1848  *         by the other peer in binary format)
1849  * @param sender_address_len number of bytes in 'sender_address'
1850  */
1851 static void
1852 handle_pong (void *cls, const struct GNUNET_MessageHeader *message,
1853              const struct GNUNET_PeerIdentity *peer,
1854              const char *sender_address,
1855              size_t sender_address_len)
1856 {
1857 #if DEBUG_TRANSPORT > 1
1858   /* we get tons of these that just get discarded, only log
1859      if we are quite verbose */
1860   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1861               "Receiving `%s' message from `%4s'.\n", "PONG",
1862               GNUNET_i2s (peer));
1863 #endif
1864   if (GNUNET_SYSERR != 
1865       GNUNET_CONTAINER_multihashmap_get_multiple (validation_map,
1866                                                   &peer->hashPubKey,
1867                                                   &check_pending_validation,
1868                                                   (void*) message))
1869     {
1870       /* This is *expected* to happen a lot since we send
1871          PONGs to *all* known addresses of the sender of
1872          the PING, so most likely we get multiple PONGs
1873          per PING, and all but the first PONG will end up
1874          here. So really we should not print anything here
1875          unless we want to be very, very verbose... */
1876 #if DEBUG_TRANSPORT > 2
1877       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1878                   "Received `%s' message from `%4s' but have no record of a matching `%s' message. Ignoring.\n",
1879                   "PONG",
1880                   GNUNET_i2s (peer),
1881                   "PING");
1882 #endif
1883       return;
1884     }
1885   
1886 #if 0
1887   /* FIXME: add given address to potential pool of our addresses
1888      (for voting) */
1889   GNUNET_log (GNUNET_ERROR_TYPE_INFO | GNUNET_ERROR_TYPE_BULK,
1890               _("Another peer saw us using the address `%s' via `%s'.\n"),
1891               GNUNET_a2s ((const struct sockaddr *) &pong[1],
1892                           ntohs(pong->addrlen)), 
1893               va->transport_name);  
1894 #endif
1895 }
1896
1897
1898 static void
1899 neighbour_timeout_task (void *cls,
1900                        const struct GNUNET_SCHEDULER_TaskContext *tc)
1901 {
1902   struct NeighbourList *n = cls;
1903
1904 #if DEBUG_TRANSPORT
1905   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
1906               "Neighbour `%4s' has timed out!\n", GNUNET_i2s (&n->id));
1907 #endif
1908   n->timeout_task = GNUNET_SCHEDULER_NO_TASK;
1909   disconnect_neighbour (n, GNUNET_NO);
1910 }
1911
1912
1913 /**
1914  * Create a fresh entry in our neighbour list for the given peer.
1915  * Will try to transmit our current HELLO to the new neighbour.  Also
1916  * notifies our clients about the new "connection".
1917  *
1918  * @param peer the peer for which we create the entry
1919  * @return the new neighbour list entry
1920  */
1921 static struct NeighbourList *
1922 setup_new_neighbour (const struct GNUNET_PeerIdentity *peer)
1923 {
1924   struct NeighbourList *n;
1925   struct TransportPlugin *tp;
1926   struct ReadyList *rl;
1927
1928   GNUNET_assert (our_hello != NULL);
1929   n = GNUNET_malloc (sizeof (struct NeighbourList));
1930   n->next = neighbours;
1931   neighbours = n;
1932   n->id = *peer;
1933   n->last_quota_update = GNUNET_TIME_absolute_get ();
1934   n->peer_timeout =
1935     GNUNET_TIME_relative_to_absolute
1936     (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
1937   n->quota_in = (GNUNET_CONSTANTS_DEFAULT_BPM_IN_OUT + 59999) / (60 * 1000);
1938   tp = plugins;
1939   while (tp != NULL)
1940     {
1941       if (tp->api->send != NULL)
1942         {
1943           rl = GNUNET_malloc (sizeof (struct ReadyList));
1944           rl->next = n->plugins;
1945           n->plugins = rl;
1946           rl->plugin = tp;
1947           rl->addresses = NULL;
1948         }
1949       tp = tp->next;
1950     }
1951   n->latency = GNUNET_TIME_UNIT_FOREVER_REL;
1952   n->distance = -1;
1953   n->timeout_task = GNUNET_SCHEDULER_add_delayed (sched,
1954                                                   GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
1955                                                   &neighbour_timeout_task, n);
1956   transmit_to_peer (NULL, NULL, 0,
1957                     HELLO_ADDRESS_EXPIRATION,
1958                     (const char *) our_hello, GNUNET_HELLO_size(our_hello),
1959                     GNUNET_NO, n);
1960   return n;
1961 }
1962
1963
1964 /**
1965  * Closure for 'check_address_exists'.
1966  */
1967 struct CheckAddressExistsClosure
1968 {
1969   /**
1970    * Address to check for.
1971    */
1972   const void *addr;
1973
1974   /**
1975    * Name of the transport.
1976    */
1977   const char *tname;
1978
1979   /**
1980    * Length of addr.
1981    */
1982   size_t addrlen;
1983
1984   /**
1985    * Set to GNUNET_YES if the address exists.
1986    */
1987   int exists;
1988 };
1989
1990
1991 /**
1992  * Iterator over hash map entries.  Checks if the given
1993  * validation entry is for the same address as what is given
1994  * in the closure.
1995  *
1996  * @param cls the 'struct CheckAddressExistsClosure*'
1997  * @param key current key code (ignored)
1998  * @param value value in the hash map ('struct ValidationEntry')
1999  * @return GNUNET_YES if we should continue to
2000  *         iterate (mismatch), GNUNET_NO if not (entry matched)
2001  */
2002 static int
2003 check_address_exists (void *cls,
2004                       const GNUNET_HashCode * key,
2005                       void *value)
2006 {
2007   struct CheckAddressExistsClosure *caec = cls;
2008   struct ValidationEntry *ve = value;
2009   if ( (0 == strcmp (caec->tname,
2010                      ve->transport_name)) &&
2011        (caec->addrlen == ve->addrlen) &&
2012        (0 == memcmp (caec->addr,
2013                      ve->addr,
2014                      caec->addrlen)) )
2015     {
2016       caec->exists = GNUNET_YES;
2017       return GNUNET_NO;
2018     }
2019   return GNUNET_YES;
2020 }
2021
2022
2023 /**
2024  * HELLO validation cleanup task (validation failed).
2025  *
2026  * @param cls the 'struct ValidationEntry' that failed
2027  * @param tc scheduler context (unused)
2028  */
2029 static void
2030 timeout_hello_validation (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2031 {
2032   struct ValidationEntry *va = cls;
2033   struct GNUNET_PeerIdentity pid;
2034
2035   GNUNET_CRYPTO_hash (&va->publicKey,
2036                       sizeof (struct
2037                               GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
2038                       &pid.hashPubKey);
2039   GNUNET_CONTAINER_multihashmap_remove (validation_map,
2040                                         &pid.hashPubKey,
2041                                         va);
2042   GNUNET_free (va->transport_name);
2043   GNUNET_free (va);
2044 }
2045
2046
2047 /**
2048  * Check if the given address is already being validated; if not,
2049  * append the given address to the list of entries that are being be
2050  * validated and initiate validation.
2051  *
2052  * @param cls closure ('struct CheckHelloValidatedContext *')
2053  * @param tname name of the transport
2054  * @param expiration expiration time
2055  * @param addr the address
2056  * @param addrlen length of the address
2057  * @return GNUNET_OK (always)
2058  */
2059 static int
2060 run_validation (void *cls,
2061                 const char *tname,
2062                 struct GNUNET_TIME_Absolute expiration,
2063                 const void *addr, size_t addrlen)
2064 {
2065   struct CheckHelloValidatedContext *chvc = cls;
2066   struct GNUNET_PeerIdentity id;
2067   struct TransportPlugin *tp;
2068   struct ValidationEntry *va;
2069   struct NeighbourList *neighbour;
2070   struct ForeignAddressList *peer_address;
2071   struct TransportPingMessage ping;
2072   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pk;
2073   struct CheckAddressExistsClosure caec;
2074   char * message_buf;
2075   uint16_t hello_size;
2076   size_t tsize;
2077
2078   tp = find_transport (tname);
2079   if (tp == NULL)
2080     {
2081       GNUNET_log (GNUNET_ERROR_TYPE_INFO |
2082                   GNUNET_ERROR_TYPE_BULK,
2083                   _
2084                   ("Transport `%s' not loaded, will not try to validate peer address using this transport.\n"),
2085                   tname);
2086       return GNUNET_OK;
2087     }
2088   GNUNET_HELLO_get_key (chvc->hello, &pk);
2089   GNUNET_CRYPTO_hash (&pk,
2090                       sizeof (struct
2091                               GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
2092                       &id.hashPubKey);
2093   caec.addr = addr;
2094   caec.addrlen = addrlen;
2095   caec.tname = tname;
2096   caec.exists = GNUNET_NO;
2097   GNUNET_CONTAINER_multihashmap_iterate (validation_map,
2098                                          &check_address_exists,
2099                                          &caec);
2100   if (caec.exists == GNUNET_YES)
2101     {
2102       /* During validation attempts we will likely trigger the other
2103          peer trying to validate our address which in turn will cause
2104          it to send us its HELLO, so we expect to hit this case rather
2105          frequently.  Only print something if we are very verbose. */
2106 #if DEBUG_TRANSPORT > 1
2107       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2108                   "Validation of address `%s' via `%s' for peer `%4s' already in progress.\n",
2109                   GNUNET_a2s (addr, addrlen), 
2110                   tname, 
2111                   GNUNET_i2s (&id));
2112 #endif
2113       return GNUNET_OK;
2114     } 
2115   va = GNUNET_malloc (sizeof (struct ValidationEntry) + addrlen);
2116   va->transport_name = GNUNET_strdup (tname);
2117   va->challenge = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2118                                             (unsigned int) -1);
2119   va->send_time = GNUNET_TIME_absolute_get();
2120   va->addr = (const void*) &va[1];
2121   memcpy (&va[1], addr, addrlen);
2122   va->addrlen = addrlen;
2123   GNUNET_HELLO_get_key (chvc->hello,
2124                         &va->publicKey);
2125   va->timeout_task = GNUNET_SCHEDULER_add_delayed (sched,
2126                                                    HELLO_VERIFICATION_TIMEOUT,
2127                                                    &timeout_hello_validation,
2128                                                    va);  
2129   GNUNET_CONTAINER_multihashmap_put (validation_map,
2130                                      &id.hashPubKey,
2131                                      va,
2132                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
2133   neighbour = find_neighbour(&id);  
2134   if (neighbour == NULL)
2135     neighbour = setup_new_neighbour(&id);
2136   peer_address = add_peer_address(neighbour, tname, addr, addrlen);    
2137   GNUNET_assert(peer_address != NULL);
2138   hello_size = GNUNET_HELLO_size(our_hello);
2139   tsize = sizeof(struct TransportPingMessage) + hello_size;
2140   message_buf = GNUNET_malloc(tsize);
2141   ping.challenge = htonl(va->challenge);
2142   ping.header.size = htons(sizeof(struct TransportPingMessage));
2143   ping.header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_PING);
2144   memcpy(&ping.target, &id, sizeof(struct GNUNET_PeerIdentity));
2145   memcpy(message_buf, our_hello, hello_size);
2146   memcpy(&message_buf[hello_size], 
2147          &ping, 
2148          sizeof(struct TransportPingMessage));
2149 #if DEBUG_TRANSPORT
2150   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2151               "Performing validation of address `%s' via `%s' for peer `%4s' sending `%s' (%u bytes) and `%s' (%u bytes)\n",
2152               GNUNET_a2s (addr, addrlen), 
2153               tname, 
2154               GNUNET_i2s (&id),
2155               "HELLO", hello_size,
2156               "PING", sizeof (struct TransportPingMessage));
2157 #endif
2158   transmit_to_peer (NULL, peer_address, 
2159                     GNUNET_SCHEDULER_PRIORITY_DEFAULT,
2160                     HELLO_VERIFICATION_TIMEOUT,
2161                     message_buf, tsize, 
2162                     GNUNET_YES, neighbour);
2163   GNUNET_free(message_buf);
2164   return GNUNET_OK;
2165 }
2166
2167
2168 /**
2169  * Add the given address to the list of foreign addresses
2170  * available for the given peer (check for duplicates).
2171  *
2172  * @param cls the respective 'struct NeighbourList' to update
2173  * @param tname name of the transport
2174  * @param expiration expiration time
2175  * @param addr the address
2176  * @param addrlen length of the address
2177  * @return GNUNET_OK (always)
2178  */
2179 static int
2180 add_to_foreign_address_list (void *cls,
2181                              const char *tname,
2182                              struct GNUNET_TIME_Absolute expiration,
2183                              const void *addr, size_t addrlen)
2184 {
2185   struct NeighbourList *n = cls;
2186   struct ForeignAddressList *fal;
2187
2188   fal = find_peer_address (n, tname, addr, addrlen);
2189   if (fal == NULL)
2190     {
2191 #if DEBUG_TRANSPORT
2192       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2193                   "Adding address `%s' (%s) for peer `%4s' due to peerinfo data for %llums.\n",
2194                   GNUNET_a2s (addr, addrlen),
2195                   tname,
2196                   GNUNET_i2s (&n->id),
2197                   expiration.value);
2198 #endif
2199       fal = add_peer_address (n, tname, addr, addrlen);
2200     }
2201   if (fal == NULL)
2202     return GNUNET_OK;
2203   fal->expires = GNUNET_TIME_absolute_max (expiration,
2204                                            fal->expires);
2205   fal->validated = GNUNET_YES;
2206   return GNUNET_OK;
2207 }
2208
2209
2210 /**
2211  * Check if addresses in validated hello "h" overlap with
2212  * those in "chvc->hello" and validate the rest.
2213  *
2214  * @param cls closure
2215  * @param peer id of the peer, NULL for last call
2216  * @param h hello message for the peer (can be NULL)
2217  * @param trust amount of trust we have in the peer (not used)
2218  */
2219 static void
2220 check_hello_validated (void *cls,
2221                        const struct GNUNET_PeerIdentity *peer,
2222                        const struct GNUNET_HELLO_Message *h, 
2223                        uint32_t trust)
2224 {
2225   struct CheckHelloValidatedContext *chvc = cls;
2226   struct GNUNET_HELLO_Message *plain_hello;
2227   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pk;
2228   struct GNUNET_PeerIdentity target;
2229   struct NeighbourList *n;
2230
2231   if (peer == NULL)
2232     {
2233       chvc->piter = NULL;
2234       GNUNET_CONTAINER_DLL_remove (chvc_head,
2235                                    chvc_tail,
2236                                    chvc);
2237       if (GNUNET_NO == chvc->hello_known)
2238         {
2239           /* notify PEERINFO about the peer now, so that we at least
2240              have the public key if some other component needs it */
2241           GNUNET_HELLO_get_key (chvc->hello, &pk);
2242           GNUNET_CRYPTO_hash (&pk,
2243                               sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
2244                               &target.hashPubKey);
2245           plain_hello = GNUNET_HELLO_create (&pk,
2246                                              NULL, 
2247                                              NULL);
2248           GNUNET_PEERINFO_add_peer (cfg, sched, &target, plain_hello);
2249           GNUNET_free (plain_hello);
2250 #if DEBUG_TRANSPORT
2251           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2252                       "Peerinfo had no `%s' message for peer `%4s', full validation needed.\n",
2253                       "HELLO",
2254                       GNUNET_i2s (&target));
2255 #endif
2256           GNUNET_HELLO_iterate_addresses (chvc->hello,
2257                                           GNUNET_NO, 
2258                                           &run_validation, 
2259                                           chvc);
2260         }
2261       GNUNET_free (chvc);
2262       return;
2263     }
2264   if (h == NULL)
2265     return;
2266   chvc->hello_known = GNUNET_YES;
2267   n = find_neighbour (peer);
2268   if (n != NULL)
2269     {
2270       GNUNET_HELLO_iterate_addresses (h,
2271                                       GNUNET_NO,
2272                                       &add_to_foreign_address_list,
2273                                       n);
2274       try_transmission_to_peer (n);
2275     }
2276   GNUNET_HELLO_iterate_new_addresses (chvc->hello,
2277                                       h,
2278                                       GNUNET_TIME_relative_to_absolute (HELLO_REVALIDATION_START_TIME),
2279                                       &run_validation, 
2280                                       chvc);
2281 }
2282
2283 /**
2284  * Process HELLO-message.
2285  *
2286  * @param plugin transport involved, may be NULL
2287  * @param message the actual message
2288  * @return GNUNET_OK if the HELLO was well-formed, GNUNET_SYSERR otherwise
2289  */
2290 static int
2291 process_hello (struct TransportPlugin *plugin,
2292                const struct GNUNET_MessageHeader *message)
2293 {
2294   uint16_t hsize;
2295   struct GNUNET_PeerIdentity target;
2296   const struct GNUNET_HELLO_Message *hello;
2297   struct CheckHelloValidatedContext *chvc;
2298   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded publicKey;
2299
2300   hsize = ntohs (message->size);
2301   if ((ntohs (message->type) != GNUNET_MESSAGE_TYPE_HELLO) ||
2302       (hsize < sizeof (struct GNUNET_MessageHeader)))
2303     {
2304       GNUNET_break (0);
2305       return GNUNET_SYSERR;
2306     }
2307   /* first, check if load is too high */
2308   if (GNUNET_SCHEDULER_get_load (sched,
2309                                  GNUNET_SCHEDULER_PRIORITY_BACKGROUND) > MAX_HELLO_LOAD)
2310     {
2311       /* TODO: call to stats? */
2312       return GNUNET_OK;
2313     }
2314   hello = (const struct GNUNET_HELLO_Message *) message;
2315   if (GNUNET_OK != GNUNET_HELLO_get_key (hello, &publicKey))
2316     {
2317       GNUNET_break_op (0);
2318       return GNUNET_SYSERR;
2319     }
2320   GNUNET_CRYPTO_hash (&publicKey,
2321                       sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
2322                       &target.hashPubKey);
2323 #if DEBUG_TRANSPORT
2324   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2325               "Processing `%s' message for `%4s' of size %u\n",
2326               "HELLO", 
2327               GNUNET_i2s (&target), 
2328               GNUNET_HELLO_size(hello));
2329 #endif
2330
2331   chvc = GNUNET_malloc (sizeof (struct CheckHelloValidatedContext) + hsize);
2332   chvc->hello = (const struct GNUNET_HELLO_Message *) &chvc[1];
2333   memcpy (&chvc[1], hello, hsize);
2334   GNUNET_CONTAINER_DLL_insert (chvc_head,
2335                                chvc_tail,
2336                                chvc);
2337   /* finally, check if HELLO was previously validated
2338      (continuation will then schedule actual validation) */
2339   chvc->piter = GNUNET_PEERINFO_iterate (cfg,
2340                                          sched,
2341                                          &target,
2342                                          0,
2343                                          HELLO_VERIFICATION_TIMEOUT,
2344                                          &check_hello_validated, chvc);
2345   return GNUNET_OK;
2346 }
2347
2348
2349 /**
2350  * The peer specified by the given neighbour has timed-out or a plugin
2351  * has disconnected.  We may either need to do nothing (other plugins
2352  * still up), or trigger a full disconnect and clean up.  This
2353  * function updates our state and does the necessary notifications.
2354  * Also notifies our clients that the neighbour is now officially
2355  * gone.
2356  *
2357  * @param n the neighbour list entry for the peer
2358  * @param check should we just check if all plugins
2359  *        disconnected or must we ask all plugins to
2360  *        disconnect?
2361  */
2362 static void
2363 disconnect_neighbour (struct NeighbourList *n, int check)
2364 {
2365   struct ReadyList *rpos;
2366   struct NeighbourList *npos;
2367   struct NeighbourList *nprev;
2368   struct MessageQueue *mq;
2369   struct ForeignAddressList *peer_addresses;
2370   struct ForeignAddressList *peer_pos;
2371
2372   if (GNUNET_YES == check)
2373     {
2374       rpos = n->plugins;
2375       while (NULL != rpos)
2376         {
2377           peer_addresses = rpos->addresses;
2378           while (peer_addresses != NULL)
2379             {
2380               if (GNUNET_YES == peer_addresses->connected)
2381                 return;             /* still connected */
2382               peer_addresses = peer_addresses->next;
2383             }
2384           rpos = rpos->next;
2385         }
2386     }
2387 #if DEBUG_TRANSPORT
2388   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2389               "Disconnecting from `%4s'\n",
2390               GNUNET_i2s (&n->id));
2391 #endif
2392   /* remove n from neighbours list */
2393   nprev = NULL;
2394   npos = neighbours;
2395   while ((npos != NULL) && (npos != n))
2396     {
2397       nprev = npos;
2398       npos = npos->next;
2399     }
2400   GNUNET_assert (npos != NULL);
2401   if (nprev == NULL)
2402     neighbours = n->next;
2403   else
2404     nprev->next = n->next;
2405
2406   /* notify all clients about disconnect */
2407   if (GNUNET_YES == n->received_pong)
2408     notify_clients_disconnect (&n->id);
2409
2410   /* clean up all plugins, cancel connections and pending transmissions */
2411   while (NULL != (rpos = n->plugins))
2412     {
2413       n->plugins = rpos->next;
2414       rpos->plugin->api->disconnect (rpos->plugin->api->cls, &n->id);
2415
2416       while (rpos->addresses != NULL)
2417         {
2418           peer_pos = rpos->addresses;
2419           rpos->addresses = peer_pos->next;
2420           GNUNET_free(peer_pos);
2421         }
2422       GNUNET_free (rpos);
2423     }
2424
2425   /* free all messages on the queue */
2426   while (NULL != (mq = n->messages_head))
2427     {
2428       GNUNET_CONTAINER_DLL_remove (n->messages_head,
2429                                    n->messages_tail,
2430                                    mq);
2431       GNUNET_assert (0 == memcmp(&mq->neighbour_id, 
2432                                  &n->id,
2433                                  sizeof(struct GNUNET_PeerIdentity)));
2434       GNUNET_free (mq);
2435     }
2436   if (n->timeout_task != GNUNET_SCHEDULER_NO_TASK)
2437     {
2438       GNUNET_SCHEDULER_cancel (sched, n->timeout_task);
2439       n->timeout_task = GNUNET_SCHEDULER_NO_TASK;
2440     }
2441   if (n->retry_task != GNUNET_SCHEDULER_NO_TASK)
2442     {
2443       GNUNET_SCHEDULER_cancel (sched, n->retry_task);
2444       n->retry_task = GNUNET_SCHEDULER_NO_TASK;
2445     }
2446   /* finally, free n itself */
2447   GNUNET_free (n);
2448 }
2449
2450
2451 /**
2452  * We have received a PING message from someone.  Need to send a PONG message
2453  * in response to the peer by any means necessary. 
2454  *
2455  * FIXME: With something like TCP where a connection exists, we may
2456  * want to send it that way.  But the current API does not seem to
2457  * allow us to do so (can't tell this to the transport!)
2458  */
2459 static int 
2460 handle_ping(void *cls, const struct GNUNET_MessageHeader *message,
2461             const struct GNUNET_PeerIdentity *peer,
2462             const char *sender_address,
2463             size_t sender_address_len)
2464 {
2465   struct TransportPlugin *plugin = cls;
2466   struct TransportPingMessage *ping;
2467   struct TransportPongMessage *pong;
2468   uint16_t msize;
2469   struct NeighbourList *n;
2470   struct ReadyList *rl;
2471   struct ForeignAddressList *fal;
2472
2473   msize = ntohs (message->size);
2474   if (msize < sizeof (struct TransportPingMessage))
2475     {
2476       GNUNET_break_op (0);
2477       return GNUNET_SYSERR;
2478     }
2479   ping = (struct TransportPingMessage *) message;
2480   if (0 != memcmp (&ping->target,
2481                    plugin->env.my_identity,
2482                    sizeof (struct GNUNET_PeerIdentity)))
2483     {
2484       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2485                   _("Received `%s' message not destined for me!\n"), 
2486                   "PING");
2487       return GNUNET_SYSERR;
2488     }
2489 #if DEBUG_TRANSPORT
2490   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2491               "Processing `%s' from `%s'\n",
2492               "PING", 
2493               GNUNET_a2s ((const struct sockaddr *)sender_address, 
2494                           sender_address_len));
2495 #endif
2496   msize -= sizeof (struct TransportPingMessage);
2497   pong = GNUNET_malloc (sizeof (struct TransportPongMessage) + sender_address_len);
2498   pong->header.size = htons (sizeof (struct TransportPongMessage) + sender_address_len);
2499   pong->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_PONG);
2500   pong->purpose.size =
2501     htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) +
2502            sizeof (uint32_t) +
2503            sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) + sender_address_len);
2504   pong->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_TCP_PING);
2505   pong->challenge = ping->challenge;
2506   pong->addrlen = htons(sender_address_len);
2507   memcpy(&pong->signer, 
2508          &my_public_key, 
2509          sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
2510   memcpy (&pong[1], sender_address, sender_address_len);
2511   GNUNET_assert (GNUNET_OK ==
2512                  GNUNET_CRYPTO_rsa_sign (my_private_key,
2513                                          &pong->purpose, &pong->signature));
2514
2515   n = find_neighbour(peer);
2516   if (n == NULL)
2517     n = setup_new_neighbour(peer);
2518   /* broadcast 'PONG' to all available addresses */
2519   rl = n->plugins;
2520   while (rl != NULL)
2521     {
2522       fal = rl->addresses;
2523       while (fal != NULL)
2524         {
2525           transmit_to_peer(NULL, fal,
2526                            TRANSPORT_PONG_PRIORITY, 
2527                            HELLO_VERIFICATION_TIMEOUT,
2528                            (const char *)pong, 
2529                            ntohs(pong->header.size), 
2530                            GNUNET_YES, 
2531                            n);
2532           fal = fal->next;
2533         }
2534       rl = rl->next;
2535     }
2536   GNUNET_free(pong);
2537   return GNUNET_OK;
2538 }
2539
2540
2541 /**
2542  * Function called by the plugin for each received message.
2543  * Update data volumes, possibly notify plugins about
2544  * reducing the rate at which they read from the socket
2545  * and generally forward to our receive callback.
2546  *
2547  * @param cls the "struct TransportPlugin *" we gave to the plugin
2548  * @param message the message, NULL if peer was disconnected
2549  * @param distance the transport cost to this peer (not latency!)
2550  * @param sender_address the address that the sender reported
2551  *        (opaque to transport service)
2552  * @param sender_address_len the length of the sender address
2553  * @param peer (claimed) identity of the other peer
2554  * @return the new service_context that the plugin should use
2555  *         for future receive calls for messages from this
2556  *         particular peer
2557  *
2558  */
2559 static void
2560 plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
2561                     const struct GNUNET_MessageHeader *message,
2562                     unsigned int distance, const char *sender_address,
2563                     size_t sender_address_len)
2564 {
2565   struct ReadyList *service_context;
2566   struct TransportPlugin *plugin = cls;
2567   struct TransportClient *cpos;
2568   struct InboundMessage *im;
2569   struct ForeignAddressList *peer_address;
2570   uint16_t msize;
2571   struct NeighbourList *n;
2572
2573   n = find_neighbour (peer);
2574   if (n == NULL)
2575     {
2576       if (message == NULL)
2577         return;                 /* disconnect of peer already marked down */
2578       n = setup_new_neighbour (peer);
2579     }
2580   service_context = n->plugins;
2581   while ((service_context != NULL) && (plugin != service_context->plugin))
2582     service_context = service_context->next;
2583   GNUNET_assert ((plugin->api->send == NULL) || (service_context != NULL));
2584   if (message == NULL)
2585     {
2586 #if DEBUG_TRANSPORT
2587       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2588                   "Receive failed from `%4s', triggering disconnect\n",
2589                   GNUNET_i2s (&n->id));
2590 #endif
2591       /* TODO: call stats */
2592       disconnect_neighbour (n, GNUNET_YES);
2593       return;
2594     }
2595   peer_address = add_peer_address(n, 
2596                                   plugin->short_name,
2597                                   sender_address, 
2598                                   sender_address_len);  
2599   if (peer_address != NULL)
2600     {
2601       peer_address->distance = distance;
2602       if (peer_address->connected == GNUNET_NO)
2603         {
2604           peer_address->connected = GNUNET_YES;
2605           peer_address->connect_attempts++;
2606         }
2607       peer_address->timeout
2608         =
2609         GNUNET_TIME_relative_to_absolute
2610         (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
2611     }
2612   /* update traffic received amount ... */
2613   msize = ntohs (message->size);
2614   n->last_received += msize;
2615   n->distance = distance;
2616   n->peer_timeout =
2617     GNUNET_TIME_relative_to_absolute
2618     (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
2619   GNUNET_SCHEDULER_cancel (sched,
2620                            n->timeout_task);
2621   n->timeout_task =
2622     GNUNET_SCHEDULER_add_delayed (sched,
2623                                   GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
2624                                   &neighbour_timeout_task, n);
2625   update_quota (n);
2626   if (n->quota_violation_count > QUOTA_VIOLATION_DROP_THRESHOLD)
2627     {
2628       /* dropping message due to frequent inbound volume violations! */
2629       GNUNET_log (GNUNET_ERROR_TYPE_WARNING |
2630                   GNUNET_ERROR_TYPE_BULK,
2631                   _
2632                   ("Dropping incoming message due to repeated bandwidth quota violations (total of %u).\n"), n->quota_violation_count);
2633       /* TODO: call stats */
2634       return;
2635     }
2636   switch (ntohs (message->type))
2637     {
2638     case GNUNET_MESSAGE_TYPE_HELLO:
2639       process_hello (plugin, message);
2640       break;
2641     case GNUNET_MESSAGE_TYPE_TRANSPORT_PING:
2642       handle_ping(plugin, message, peer, sender_address, sender_address_len);
2643       break;
2644     case GNUNET_MESSAGE_TYPE_TRANSPORT_PONG:
2645       handle_pong(plugin, message, peer, sender_address, sender_address_len);
2646       break;
2647     default:
2648 #if DEBUG_TRANSPORT
2649       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2650                   "Received message of type %u from `%4s', sending to all clients.\n",
2651                   ntohs (message->type), GNUNET_i2s (peer));
2652 #endif
2653       /* transmit message to all clients */
2654       im = GNUNET_malloc (sizeof (struct InboundMessage) + msize);
2655       im->header.size = htons (sizeof (struct InboundMessage) + msize);
2656       im->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RECV);
2657       im->latency = GNUNET_TIME_relative_hton (n->latency);
2658       im->peer = *peer;
2659       memcpy (&im[1], message, msize);
2660       cpos = clients;
2661       while (cpos != NULL)
2662         {
2663           transmit_to_client (cpos, &im->header, GNUNET_YES);
2664           cpos = cpos->next;
2665         }
2666       GNUNET_free (im);
2667     }
2668 }
2669
2670
2671 /**
2672  * Handle START-message.  This is the first message sent to us
2673  * by any client which causes us to add it to our list.
2674  *
2675  * @param cls closure (always NULL)
2676  * @param client identification of the client
2677  * @param message the actual message
2678  */
2679 static void
2680 handle_start (void *cls,
2681               struct GNUNET_SERVER_Client *client,
2682               const struct GNUNET_MessageHeader *message)
2683 {
2684   struct TransportClient *c;
2685   struct ConnectInfoMessage cim;
2686   struct NeighbourList *n;
2687
2688 #if DEBUG_TRANSPORT
2689   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2690               "Received `%s' request from client\n", "START");
2691 #endif
2692   c = clients;
2693   while (c != NULL)
2694     {
2695       if (c->client == client)
2696         {
2697           /* client already on our list! */
2698           GNUNET_break (0);
2699           GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2700           return;
2701         }
2702       c = c->next;
2703     }
2704   c = GNUNET_malloc (sizeof (struct TransportClient));
2705   c->next = clients;
2706   clients = c;
2707   c->client = client;
2708   if (our_hello != NULL)
2709     {
2710 #if DEBUG_TRANSPORT
2711       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2712                   "Sending our own `%s' to new client\n", "HELLO");
2713 #endif
2714       transmit_to_client (c,
2715                           (const struct GNUNET_MessageHeader *) our_hello,
2716                           GNUNET_NO);
2717       /* tell new client about all existing connections */
2718       cim.header.size = htons (sizeof (struct ConnectInfoMessage));
2719       cim.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
2720       n = neighbours; 
2721       while (n != NULL)
2722         {
2723           if (GNUNET_YES == n->received_pong)
2724             {
2725               cim.id = n->id;
2726               cim.latency = GNUNET_TIME_relative_hton (n->latency);
2727               cim.distance = htonl (n->distance);
2728               transmit_to_client (c, &cim.header, GNUNET_NO);
2729             }
2730             n = n->next;
2731         }
2732     }
2733   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2734 }
2735
2736
2737 /**
2738  * Handle HELLO-message.
2739  *
2740  * @param cls closure (always NULL)
2741  * @param client identification of the client
2742  * @param message the actual message
2743  */
2744 static void
2745 handle_hello (void *cls,
2746               struct GNUNET_SERVER_Client *client,
2747               const struct GNUNET_MessageHeader *message)
2748 {
2749   int ret;
2750
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       GNUNET_CONTAINER_DLL_remove (pos->message_queue_head,
3047                                    pos->message_queue_tail,
3048                                    mqe);
3049       pos->message_count--;
3050       GNUNET_free (mqe);
3051     }
3052   if (prev == NULL)
3053     clients = pos->next;
3054   else
3055     prev->next = pos->next;
3056   if (GNUNET_YES == pos->tcs_pending)
3057     {
3058       pos->client = NULL;
3059       return;
3060     }
3061   if (pos->th != NULL)
3062     {
3063       GNUNET_CONNECTION_notify_transmit_ready_cancel (pos->th);
3064       pos->th = NULL;
3065     }
3066   GNUNET_break (0 == pos->message_count);
3067   GNUNET_free (pos);
3068 }
3069
3070
3071 /**
3072  * Iterator to free entries in the validation_map.
3073  *
3074  * @param cls closure (unused)
3075  * @param key current key code
3076  * @param value value in the hash map (validation to abort)
3077  * @return GNUNET_YES (always)
3078  */
3079 static int 
3080 abort_validation (void *cls,
3081                   const GNUNET_HashCode * key,
3082                   void *value)
3083 {
3084   struct ValidationEntry *va = value;
3085
3086   GNUNET_SCHEDULER_cancel (sched, va->timeout_task);
3087   GNUNET_free (va->transport_name);
3088   GNUNET_free (va);
3089   return GNUNET_YES;
3090 }
3091
3092
3093 /**
3094  * Function called when the service shuts down.  Unloads our plugins
3095  * and cancels pending validations.
3096  *
3097  * @param cls closure, unused
3098  * @param tc task context (unused)
3099  */
3100 static void
3101 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
3102 {
3103   struct TransportPlugin *plug;
3104   struct OwnAddressList *al;
3105   struct CheckHelloValidatedContext *chvc;
3106
3107   while (neighbours != NULL)
3108     disconnect_neighbour (neighbours, GNUNET_NO);
3109 #if DEBUG_TRANSPORT
3110   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3111               "Transport service is unloading plugins...\n");
3112 #endif
3113   while (NULL != (plug = plugins))
3114     {
3115       plugins = plug->next;
3116       GNUNET_break (NULL == GNUNET_PLUGIN_unload (plug->lib_name, plug->api));
3117       GNUNET_free (plug->lib_name);
3118       GNUNET_free (plug->short_name);
3119       while (NULL != (al = plug->addresses))
3120         {
3121           plug->addresses = al->next;
3122           GNUNET_free (al);
3123         }
3124       GNUNET_free (plug);
3125     }
3126   if (my_private_key != NULL)
3127     GNUNET_CRYPTO_rsa_key_free (my_private_key);
3128   GNUNET_free_non_null (our_hello);
3129
3130   /* free 'chvc' data structure */
3131   while (NULL != (chvc = chvc_head))
3132     {
3133       chvc_head = chvc->next;
3134       GNUNET_PEERINFO_iterate_cancel (chvc->piter);
3135       GNUNET_free (chvc);
3136     }
3137   chvc_tail = NULL;
3138
3139   GNUNET_CONTAINER_multihashmap_iterate (validation_map,
3140                                          &abort_validation,
3141                                          NULL);
3142   GNUNET_CONTAINER_multihashmap_destroy (validation_map);
3143 }
3144
3145
3146 /**
3147  * Initiate transport service.
3148  *
3149  * @param cls closure
3150  * @param s scheduler to use
3151  * @param serv the initialized server
3152  * @param c configuration to use
3153  */
3154 static void
3155 run (void *cls,
3156      struct GNUNET_SCHEDULER_Handle *s,
3157      struct GNUNET_SERVER_Handle *serv,
3158      const struct GNUNET_CONFIGURATION_Handle *c)
3159 {
3160   char *plugs;
3161   char *pos;
3162   int no_transports;
3163   unsigned long long tneigh;
3164   char *keyfile;
3165
3166   sched = s;
3167   cfg = c;
3168   validation_map = GNUNET_CONTAINER_multihashmap_create (64);
3169   /* parse configuration */
3170   if ((GNUNET_OK !=
3171        GNUNET_CONFIGURATION_get_value_number (c,
3172                                               "TRANSPORT",
3173                                               "NEIGHBOUR_LIMIT",
3174                                               &tneigh)) ||
3175       (GNUNET_OK !=
3176        GNUNET_CONFIGURATION_get_value_filename (c,
3177                                                 "GNUNETD",
3178                                                 "HOSTKEY", &keyfile)))
3179     {
3180       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3181                   _
3182                   ("Transport service is lacking key configuration settings.  Exiting.\n"));
3183       GNUNET_SCHEDULER_shutdown (s);
3184       return;
3185     }
3186   max_connect_per_transport = (uint32_t) tneigh;
3187   my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
3188   GNUNET_free (keyfile);
3189   if (my_private_key == NULL)
3190     {
3191       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3192                   _
3193                   ("Transport service could not access hostkey.  Exiting.\n"));
3194       GNUNET_SCHEDULER_shutdown (s);
3195       return;
3196     }
3197   GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key);
3198   GNUNET_CRYPTO_hash (&my_public_key,
3199                       sizeof (my_public_key), &my_identity.hashPubKey);
3200   /* setup notification */
3201   server = serv;
3202   GNUNET_SERVER_disconnect_notify (server,
3203                                    &client_disconnect_notification, NULL);
3204   /* load plugins... */
3205   no_transports = 1;
3206   if (GNUNET_OK ==
3207       GNUNET_CONFIGURATION_get_value_string (c,
3208                                              "TRANSPORT", "PLUGINS", &plugs))
3209     {
3210       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3211                   _("Starting transport plugins `%s'\n"), plugs);
3212       pos = strtok (plugs, " ");
3213       while (pos != NULL)
3214         {
3215           start_transport (server, pos);
3216           no_transports = 0;
3217           pos = strtok (NULL, " ");
3218         }
3219       GNUNET_free (plugs);
3220     }
3221   GNUNET_SCHEDULER_add_delayed (sched,
3222                                 GNUNET_TIME_UNIT_FOREVER_REL,
3223                                 &shutdown_task, NULL);
3224   if (no_transports)
3225     refresh_hello ();
3226
3227 #if DEBUG_TRANSPORT
3228   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Transport service ready.\n"));
3229 #endif
3230   /* process client requests */
3231   GNUNET_SERVER_add_handlers (server, handlers);
3232 }
3233
3234
3235 /**
3236  * The main function for the transport service.
3237  *
3238  * @param argc number of arguments from the command line
3239  * @param argv command line arguments
3240  * @return 0 ok, 1 on error
3241  */
3242 int
3243 main (int argc, char *const *argv)
3244 {
3245   return (GNUNET_OK ==
3246           GNUNET_SERVICE_run (argc,
3247                               argv,
3248                               "transport",
3249                               GNUNET_SERVICE_OPTION_NONE,
3250                               &run, NULL)) ? 0 : 1;
3251 }
3252
3253 /* end of gnunet-service-transport.c */