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