fix
[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 TransportPlugin *tp;
2172   struct ValidationEntry *va;
2173   struct NeighbourList *neighbour;
2174   struct TransportPingMessage ping;
2175   struct CheckAddressExistsClosure caec;
2176   char * message_buf;
2177   uint16_t hello_size;
2178   size_t tsize;
2179
2180   peer_address->revalidate_task = GNUNET_SCHEDULER_NO_TASK;
2181   if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
2182     return; 
2183   tp = peer_address->ready_list->plugin;
2184   neighbour = peer_address->ready_list->neighbour;
2185   if (GNUNET_YES != neighbour->public_key_valid)
2186     {
2187       /* no public key yet, try again later */
2188       schedule_next_ping (peer_address);     
2189       return;
2190     }
2191   caec.addr = peer_address->addr;
2192   caec.addrlen = peer_address->addrlen;
2193   caec.tname = tp->short_name;
2194   caec.exists = GNUNET_NO;
2195   GNUNET_CONTAINER_multihashmap_iterate (validation_map,
2196                                          &check_address_exists,
2197                                          &caec);
2198   if (caec.exists == GNUNET_YES)
2199     {
2200       /* During validation attempts we will likely trigger the other
2201          peer trying to validate our address which in turn will cause
2202          it to send us its HELLO, so we expect to hit this case rather
2203          frequently.  Only print something if we are very verbose. */
2204 #if DEBUG_TRANSPORT > 1
2205       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2206                   "Some validation of address `%s' via `%s' for peer `%4s' already in progress.\n",
2207                   GNUNET_a2s (peer_address->addr,
2208                               peer_address->addrlen),
2209                   tp->short_name,
2210                   GNUNET_i2s (&neighbour->id));
2211 #endif
2212       schedule_next_ping (peer_address);     
2213       return;
2214     }
2215   va = GNUNET_malloc (sizeof (struct ValidationEntry) + peer_address->addrlen);
2216   va->transport_name = GNUNET_strdup (tp->short_name);
2217   va->challenge = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2218                                             (unsigned int) -1);
2219   va->send_time = GNUNET_TIME_absolute_get();
2220   va->addr = (const void*) &va[1];
2221   memcpy (&va[1], peer_address->addr, peer_address->addrlen);
2222   va->addrlen = peer_address->addrlen;
2223
2224   memcpy(&va->publicKey,
2225          &neighbour->publicKey, 
2226          sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
2227
2228   va->timeout_task = GNUNET_SCHEDULER_add_delayed (sched,
2229                                                    HELLO_VERIFICATION_TIMEOUT,
2230                                                    &timeout_hello_validation,
2231                                                    va);
2232   GNUNET_CONTAINER_multihashmap_put (validation_map,
2233                                      &neighbour->id.hashPubKey,
2234                                      va,
2235                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
2236   hello_size = GNUNET_HELLO_size(our_hello);
2237   tsize = sizeof(struct TransportPingMessage) + hello_size;
2238   message_buf = GNUNET_malloc(tsize);
2239   ping.challenge = htonl(va->challenge);
2240   ping.header.size = htons(sizeof(struct TransportPingMessage));
2241   ping.header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_PING);
2242   memcpy(&ping.target, &neighbour->id, sizeof(struct GNUNET_PeerIdentity));
2243   memcpy(message_buf, our_hello, hello_size);
2244   memcpy(&message_buf[hello_size],
2245          &ping,
2246          sizeof(struct TransportPingMessage));
2247 #if DEBUG_TRANSPORT_REVALIDATION
2248   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2249               "Performing re-validation of address `%s' via `%s' for peer `%4s' sending `%s' (%u bytes) and `%s' (%u bytes)\n",
2250               GNUNET_a2s (peer_address->addr,
2251                           peer_address->addrlen),
2252               tp->short_name,
2253               GNUNET_i2s (&neighbour->id),
2254               "HELLO", hello_size,
2255               "PING", sizeof (struct TransportPingMessage));
2256 #endif
2257   GNUNET_STATISTICS_update (stats,
2258                             gettext_noop ("# PING messages sent for re-validation"),
2259                             1,
2260                             GNUNET_NO);
2261   transmit_to_peer (NULL, peer_address,
2262                     GNUNET_SCHEDULER_PRIORITY_DEFAULT,
2263                     HELLO_VERIFICATION_TIMEOUT,
2264                     message_buf, tsize,
2265                     GNUNET_YES, neighbour);
2266   GNUNET_free(message_buf);
2267   schedule_next_ping (peer_address);
2268 }
2269
2270
2271 /**
2272  * Schedule the job that will cause us to send a PING to the
2273  * foreign address to evaluate its validity and latency.
2274  *
2275  * @param fal address to PING
2276  */
2277 static void
2278 schedule_next_ping (struct ForeignAddressList *fal)
2279 {
2280   struct GNUNET_TIME_Relative delay;
2281
2282   if (fal->revalidate_task != GNUNET_SCHEDULER_NO_TASK)
2283     return;
2284   delay = GNUNET_TIME_absolute_get_remaining (fal->expires);
2285   delay.value /= 2; /* do before expiration */
2286   delay = GNUNET_TIME_relative_min (delay,
2287                                     LATENCY_EVALUATION_MAX_DELAY);
2288   if (GNUNET_YES != fal->estimated)
2289     {
2290       delay = GNUNET_TIME_UNIT_ZERO;
2291       fal->estimated = GNUNET_YES;
2292     }                               
2293   if (GNUNET_YES == fal->connected)
2294     {
2295       delay = GNUNET_TIME_relative_min (delay,
2296                                         CONNECTED_LATENCY_EVALUATION_MAX_DELAY);
2297     }  
2298   /* FIXME: also adjust delay based on how close the last
2299      observed latency is to the latency of the best alternative */
2300   /* bound how fast we can go */
2301   delay = GNUNET_TIME_relative_max (delay,
2302                                     GNUNET_TIME_UNIT_SECONDS);
2303   /* randomize a bit (to avoid doing all at the same time) */
2304   delay.value += GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 1000);
2305   fal->revalidate_task = GNUNET_SCHEDULER_add_delayed(sched, 
2306                                                       delay,
2307                                                       &send_periodic_ping, 
2308                                                       fal);
2309 }
2310
2311
2312 /**
2313  * Iterator over hash map entries.  Checks if the given validation
2314  * entry is for the same challenge as what is given in the PONG.
2315  *
2316  * @param cls the 'struct TransportPongMessage*'
2317  * @param key peer identity
2318  * @param value value in the hash map ('struct ValidationEntry')
2319  * @return GNUNET_YES if we should continue to
2320  *         iterate (mismatch), GNUNET_NO if not (entry matched)
2321  */
2322 static int
2323 check_pending_validation (void *cls,
2324                           const GNUNET_HashCode * key,
2325                           void *value)
2326 {
2327   const struct TransportPongMessage *pong = cls;
2328   struct ValidationEntry *ve = value;
2329   struct AddValidatedAddressContext avac;
2330   unsigned int challenge = ntohl(pong->challenge);
2331   struct GNUNET_HELLO_Message *hello;
2332   struct GNUNET_PeerIdentity target;
2333   struct NeighbourList *n;
2334   struct ForeignAddressList *fal;
2335
2336   if (ve->challenge != challenge)
2337     return GNUNET_YES;
2338
2339 #if DEBUG_TRANSPORT
2340   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2341               "Confirmed validity of address, peer `%4s' has address `%s' (%s).\n",
2342               GNUNET_h2s (key),
2343               GNUNET_a2s ((const struct sockaddr *) ve->addr,
2344                           ve->addrlen),
2345               ve->transport_name);
2346 #endif
2347   GNUNET_STATISTICS_update (stats,
2348                             gettext_noop ("# address validation successes"),
2349                             1,
2350                             GNUNET_NO);
2351   /* create the updated HELLO */
2352   GNUNET_CRYPTO_hash (&ve->publicKey,
2353                       sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
2354                       &target.hashPubKey);
2355   avac.done = GNUNET_NO;
2356   avac.ve = ve;
2357   hello = GNUNET_HELLO_create (&ve->publicKey,
2358                                &add_validated_address,
2359                                &avac);
2360   GNUNET_PEERINFO_add_peer (cfg, sched,
2361                             &target,
2362                             hello);
2363   GNUNET_free (hello);
2364   n = find_neighbour (&target);
2365   if (n != NULL)
2366     {
2367       n->publicKey = ve->publicKey;
2368       n->public_key_valid = GNUNET_YES;
2369       fal = add_peer_address (n,
2370                               ve->transport_name,
2371                               ve->addr,
2372                               ve->addrlen);
2373       GNUNET_assert (fal != NULL);
2374       fal->expires = GNUNET_TIME_relative_to_absolute (HELLO_ADDRESS_EXPIRATION);
2375       fal->validated = GNUNET_YES;
2376       GNUNET_STATISTICS_update (stats,
2377                                 gettext_noop ("# peer addresses considered valid"),
2378                                 1,
2379                                 GNUNET_NO);      
2380       fal->latency = GNUNET_TIME_absolute_get_duration (ve->send_time);
2381       schedule_next_ping (fal);
2382       if (n->latency.value == GNUNET_TIME_UNIT_FOREVER_REL.value)
2383         n->latency = fal->latency;
2384       else
2385         n->latency.value = (fal->latency.value + n->latency.value) / 2;
2386       n->distance = fal->distance;
2387       if (GNUNET_NO == n->received_pong)
2388         {
2389           notify_clients_connect (&target, n->latency, n->distance);
2390           n->received_pong = GNUNET_YES;
2391         }
2392       if (n->retry_task != GNUNET_SCHEDULER_NO_TASK)
2393         {
2394           GNUNET_SCHEDULER_cancel (sched,
2395                                    n->retry_task);
2396           n->retry_task = GNUNET_SCHEDULER_NO_TASK;
2397           try_transmission_to_peer (n);
2398         }
2399     }
2400
2401   /* clean up validation entry */
2402   GNUNET_assert (GNUNET_YES ==
2403                  GNUNET_CONTAINER_multihashmap_remove (validation_map,
2404                                                        key,
2405                                                        ve));
2406   GNUNET_SCHEDULER_cancel (sched,
2407                            ve->timeout_task);
2408   GNUNET_free (ve->transport_name);
2409   GNUNET_free (ve);
2410   return GNUNET_NO;
2411 }
2412
2413
2414 /**
2415  * Function that will be called if we receive a validation
2416  * of an address challenge that we transmitted to another
2417  * peer.  Note that the validation should only be considered
2418  * acceptable if the challenge matches AND if the sender
2419  * address is at least a plausible address for this peer
2420  * (otherwise we may be seeing a MiM attack).
2421  *
2422  * @param cls closure
2423  * @param message the pong message
2424  * @param peer who responded to our challenge
2425  * @param sender_address string describing our sender address (as observed
2426  *         by the other peer in binary format)
2427  * @param sender_address_len number of bytes in 'sender_address'
2428  */
2429 static void
2430 handle_pong (void *cls, const struct GNUNET_MessageHeader *message,
2431              const struct GNUNET_PeerIdentity *peer,
2432              const char *sender_address,
2433              size_t sender_address_len)
2434 {
2435 #if DEBUG_TRANSPORT > 1
2436   /* we get tons of these that just get discarded, only log
2437      if we are quite verbose */
2438   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2439               "Receiving `%s' message from `%4s'.\n", "PONG",
2440               GNUNET_i2s (peer));
2441 #endif
2442   GNUNET_STATISTICS_update (stats,
2443                             gettext_noop ("# PONG messages received"),
2444                             1,
2445                             GNUNET_NO);
2446   if (GNUNET_SYSERR !=
2447       GNUNET_CONTAINER_multihashmap_get_multiple (validation_map,
2448                                                   &peer->hashPubKey,
2449                                                   &check_pending_validation,
2450                                                   (void*) message))
2451     {
2452       /* This is *expected* to happen a lot since we send
2453          PONGs to *all* known addresses of the sender of
2454          the PING, so most likely we get multiple PONGs
2455          per PING, and all but the first PONG will end up
2456          here. So really we should not print anything here
2457          unless we want to be very, very verbose... */
2458 #if DEBUG_TRANSPORT > 2
2459       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2460                   "Received `%s' message from `%4s' but have no record of a matching `%s' message. Ignoring.\n",
2461                   "PONG",
2462                   GNUNET_i2s (peer),
2463                   "PING");
2464 #endif
2465       return;
2466     }
2467
2468 #if 0
2469   /* FIXME: add given address to potential pool of our addresses
2470      (for voting) */
2471   GNUNET_log (GNUNET_ERROR_TYPE_INFO | GNUNET_ERROR_TYPE_BULK,
2472               _("Another peer saw us using the address `%s' via `%s'.\n"),
2473               GNUNET_a2s ((const struct sockaddr *) &pong[1],
2474                           ntohs(pong->addrlen)),
2475               va->transport_name);
2476 #endif
2477 }
2478
2479
2480 /**
2481  * Check if the given address is already being validated; if not,
2482  * append the given address to the list of entries that are being be
2483  * validated and initiate validation.
2484  *
2485  * @param cls closure ('struct CheckHelloValidatedContext *')
2486  * @param tname name of the transport
2487  * @param expiration expiration time
2488  * @param addr the address
2489  * @param addrlen length of the address
2490  * @return GNUNET_OK (always)
2491  */
2492 static int
2493 run_validation (void *cls,
2494                 const char *tname,
2495                 struct GNUNET_TIME_Absolute expiration,
2496                 const void *addr, size_t addrlen)
2497 {
2498   struct CheckHelloValidatedContext *chvc = cls;
2499   struct GNUNET_PeerIdentity id;
2500   struct TransportPlugin *tp;
2501   struct ValidationEntry *va;
2502   struct NeighbourList *neighbour;
2503   struct ForeignAddressList *peer_address;
2504   struct TransportPingMessage ping;
2505   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pk;
2506   struct CheckAddressExistsClosure caec;
2507   char * message_buf;
2508   uint16_t hello_size;
2509   size_t tsize;
2510
2511   GNUNET_STATISTICS_update (stats,
2512                             gettext_noop ("# peer addresses scheduled for validation"),
2513                             1,
2514                             GNUNET_NO);      
2515   tp = find_transport (tname);
2516   if (tp == NULL)
2517     {
2518       GNUNET_log (GNUNET_ERROR_TYPE_INFO |
2519                   GNUNET_ERROR_TYPE_BULK,
2520                   _
2521                   ("Transport `%s' not loaded, will not try to validate peer address using this transport.\n"),
2522                   tname);
2523       GNUNET_STATISTICS_update (stats,
2524                                 gettext_noop ("# peer addresses not validated (no applicable transport plugin available)"),
2525                                 1,
2526                                 GNUNET_NO);      
2527       return GNUNET_OK;
2528     }
2529   GNUNET_HELLO_get_key (chvc->hello, &pk);
2530   GNUNET_CRYPTO_hash (&pk,
2531                       sizeof (struct
2532                               GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
2533                       &id.hashPubKey);
2534   caec.addr = addr;
2535   caec.addrlen = addrlen;
2536   caec.tname = tname;
2537   caec.exists = GNUNET_NO;
2538   GNUNET_CONTAINER_multihashmap_iterate (validation_map,
2539                                          &check_address_exists,
2540                                          &caec);
2541   if (caec.exists == GNUNET_YES)
2542     {
2543       /* During validation attempts we will likely trigger the other
2544          peer trying to validate our address which in turn will cause
2545          it to send us its HELLO, so we expect to hit this case rather
2546          frequently.  Only print something if we are very verbose. */
2547 #if DEBUG_TRANSPORT > 1
2548       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2549                   "Validation of address `%s' via `%s' for peer `%4s' already in progress.\n",
2550                   GNUNET_a2s (addr, addrlen),
2551                   tname,
2552                   GNUNET_i2s (&id));
2553 #endif
2554       GNUNET_STATISTICS_update (stats,
2555                                 gettext_noop ("# peer addresses not validated (in progress)"),
2556                                 1,
2557                                 GNUNET_NO);      
2558       return GNUNET_OK;
2559     }
2560   va = GNUNET_malloc (sizeof (struct ValidationEntry) + addrlen);
2561   va->transport_name = GNUNET_strdup (tname);
2562   va->challenge = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2563                                             (unsigned int) -1);
2564   va->send_time = GNUNET_TIME_absolute_get();
2565   va->addr = (const void*) &va[1];
2566   memcpy (&va[1], addr, addrlen);
2567   va->addrlen = addrlen;
2568   GNUNET_HELLO_get_key (chvc->hello,
2569                         &va->publicKey);
2570   va->timeout_task = GNUNET_SCHEDULER_add_delayed (sched,
2571                                                    HELLO_VERIFICATION_TIMEOUT,
2572                                                    &timeout_hello_validation,
2573                                                    va);
2574   GNUNET_CONTAINER_multihashmap_put (validation_map,
2575                                      &id.hashPubKey,
2576                                      va,
2577                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
2578   neighbour = find_neighbour(&id);
2579   if (neighbour == NULL)
2580     neighbour = setup_new_neighbour(&id);
2581   neighbour->publicKey = va->publicKey;
2582   neighbour->public_key_valid = GNUNET_YES;
2583   peer_address = add_peer_address(neighbour, tname, addr, addrlen);
2584   GNUNET_assert(peer_address != NULL);
2585   hello_size = GNUNET_HELLO_size(our_hello);
2586   tsize = sizeof(struct TransportPingMessage) + hello_size;
2587   message_buf = GNUNET_malloc(tsize);
2588   ping.challenge = htonl(va->challenge);
2589   ping.header.size = htons(sizeof(struct TransportPingMessage));
2590   ping.header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_PING);
2591   memcpy(&ping.target, &id, sizeof(struct GNUNET_PeerIdentity));
2592   memcpy(message_buf, our_hello, hello_size);
2593   memcpy(&message_buf[hello_size],
2594          &ping,
2595          sizeof(struct TransportPingMessage));
2596 #if DEBUG_TRANSPORT
2597   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2598               "Performing validation of address `%s' via `%s' for peer `%4s' sending `%s' (%u bytes) and `%s' (%u bytes)\n",
2599               GNUNET_a2s (addr, addrlen),
2600               tname,
2601               GNUNET_i2s (&id),
2602               "HELLO", hello_size,
2603               "PING", sizeof (struct TransportPingMessage));
2604 #endif
2605   GNUNET_STATISTICS_update (stats,
2606                             gettext_noop ("# PING messages sent for initial validation"),
2607                             1,
2608                             GNUNET_NO);      
2609   transmit_to_peer (NULL, peer_address,
2610                     GNUNET_SCHEDULER_PRIORITY_DEFAULT,
2611                     HELLO_VERIFICATION_TIMEOUT,
2612                     message_buf, tsize,
2613                     GNUNET_YES, neighbour);
2614   GNUNET_free(message_buf);
2615   return GNUNET_OK;
2616 }
2617
2618
2619 /**
2620  * Check if addresses in validated hello "h" overlap with
2621  * those in "chvc->hello" and validate the rest.
2622  *
2623  * @param cls closure
2624  * @param peer id of the peer, NULL for last call
2625  * @param h hello message for the peer (can be NULL)
2626  * @param trust amount of trust we have in the peer (not used)
2627  */
2628 static void
2629 check_hello_validated (void *cls,
2630                        const struct GNUNET_PeerIdentity *peer,
2631                        const struct GNUNET_HELLO_Message *h, 
2632                        uint32_t trust)
2633 {
2634   struct CheckHelloValidatedContext *chvc = cls;
2635   struct GNUNET_HELLO_Message *plain_hello;
2636   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pk;
2637   struct GNUNET_PeerIdentity target;
2638   struct NeighbourList *n;
2639
2640   if (peer == NULL)
2641     {
2642       chvc->piter = NULL;
2643       GNUNET_CONTAINER_DLL_remove (chvc_head,
2644                                    chvc_tail,
2645                                    chvc);
2646       if (GNUNET_NO == chvc->hello_known)
2647         {
2648           /* notify PEERINFO about the peer now, so that we at least
2649              have the public key if some other component needs it */
2650           GNUNET_HELLO_get_key (chvc->hello, &pk);
2651           GNUNET_CRYPTO_hash (&pk,
2652                               sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
2653                               &target.hashPubKey);
2654           plain_hello = GNUNET_HELLO_create (&pk,
2655                                              NULL, 
2656                                              NULL);
2657           GNUNET_PEERINFO_add_peer (cfg, sched, &target, plain_hello);
2658           GNUNET_free (plain_hello);
2659 #if DEBUG_TRANSPORT
2660           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2661                       "Peerinfo had no `%s' message for peer `%4s', full validation needed.\n",
2662                       "HELLO",
2663                       GNUNET_i2s (&target));
2664 #endif
2665           GNUNET_STATISTICS_update (stats,
2666                                     gettext_noop ("# new HELLOs requiring full validation"),
2667                                     1,
2668                                     GNUNET_NO);      
2669           GNUNET_HELLO_iterate_addresses (chvc->hello,
2670                                           GNUNET_NO, 
2671                                           &run_validation, 
2672                                           chvc);
2673         }
2674       else
2675         {
2676           GNUNET_STATISTICS_update (stats,
2677                                     gettext_noop ("# duplicate HELLO (peer known)"),
2678                                     1,
2679                                     GNUNET_NO);      
2680         }
2681       GNUNET_free (chvc);
2682       return;
2683     } 
2684   if (h == NULL)
2685     return;
2686 #if DEBUG_TRANSPORT
2687   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2688               "Peerinfo had `%s' message for peer `%4s', validating only new addresses.\n",
2689               "HELLO",
2690               GNUNET_i2s (peer));
2691 #endif
2692   chvc->hello_known = GNUNET_YES;
2693   n = find_neighbour (peer);
2694   if (n != NULL)
2695     {
2696       GNUNET_HELLO_iterate_addresses (h,
2697                                       GNUNET_NO,
2698                                       &add_to_foreign_address_list,
2699                                       n);
2700       try_transmission_to_peer (n);
2701     }
2702   else
2703     {
2704       GNUNET_STATISTICS_update (stats,
2705                                 gettext_noop ("# no existing neighbour record (validating HELLO)"),
2706                                 1,
2707                                 GNUNET_NO);      
2708     }
2709   GNUNET_STATISTICS_update (stats,
2710                             gettext_noop ("# HELLO validations (update case)"),
2711                             1,
2712                             GNUNET_NO);      
2713   GNUNET_HELLO_iterate_new_addresses (chvc->hello,
2714                                       h,
2715                                       GNUNET_TIME_relative_to_absolute (HELLO_REVALIDATION_START_TIME),
2716                                       &run_validation, 
2717                                       chvc);
2718 }
2719
2720 /**
2721  * Process HELLO-message.
2722  *
2723  * @param plugin transport involved, may be NULL
2724  * @param message the actual message
2725  * @return GNUNET_OK if the HELLO was well-formed, GNUNET_SYSERR otherwise
2726  */
2727 static int
2728 process_hello (struct TransportPlugin *plugin,
2729                const struct GNUNET_MessageHeader *message)
2730 {
2731   uint16_t hsize;
2732   struct GNUNET_PeerIdentity target;
2733   const struct GNUNET_HELLO_Message *hello;
2734   struct CheckHelloValidatedContext *chvc;
2735   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded publicKey;
2736
2737   hsize = ntohs (message->size);
2738   if ((ntohs (message->type) != GNUNET_MESSAGE_TYPE_HELLO) ||
2739       (hsize < sizeof (struct GNUNET_MessageHeader)))
2740     {
2741       GNUNET_break (0);
2742       return GNUNET_SYSERR;
2743     }
2744   GNUNET_STATISTICS_update (stats,
2745                             gettext_noop ("# HELLOs received for validation"),
2746                             1,
2747                             GNUNET_NO);      
2748   /* first, check if load is too high */
2749   if (GNUNET_SCHEDULER_get_load (sched,
2750                                  GNUNET_SCHEDULER_PRIORITY_BACKGROUND) > MAX_HELLO_LOAD)
2751     {
2752       GNUNET_STATISTICS_update (stats,
2753                                 gettext_noop ("# HELLOs ignored due to high load"),
2754                                 1,
2755                                 GNUNET_NO);      
2756       return GNUNET_OK;
2757     }
2758   hello = (const struct GNUNET_HELLO_Message *) message;
2759   if (GNUNET_OK != GNUNET_HELLO_get_key (hello, &publicKey))
2760     {
2761       GNUNET_break_op (0);
2762       return GNUNET_SYSERR;
2763     }
2764   GNUNET_CRYPTO_hash (&publicKey,
2765                       sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
2766                       &target.hashPubKey);
2767   if (0 == memcmp (&my_identity,
2768                    &target,
2769                    sizeof (struct GNUNET_PeerIdentity)))
2770     {
2771       GNUNET_STATISTICS_update (stats,
2772                                 gettext_noop ("# HELLOs ignored for validation (is my own HELLO)"),
2773                                 1,
2774                                 GNUNET_NO);      
2775       return GNUNET_OK;      
2776     }
2777 #if DEBUG_TRANSPORT > 1
2778   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2779               "Processing `%s' message for `%4s' of size %u\n",
2780               "HELLO", 
2781               GNUNET_i2s (&target), 
2782               GNUNET_HELLO_size(hello));
2783 #endif
2784   chvc = GNUNET_malloc (sizeof (struct CheckHelloValidatedContext) + hsize);
2785   chvc->hello = (const struct GNUNET_HELLO_Message *) &chvc[1];
2786   memcpy (&chvc[1], hello, hsize);
2787   GNUNET_CONTAINER_DLL_insert (chvc_head,
2788                                chvc_tail,
2789                                chvc);
2790   /* finally, check if HELLO was previously validated
2791      (continuation will then schedule actual validation) */
2792   chvc->piter = GNUNET_PEERINFO_iterate (cfg,
2793                                          sched,
2794                                          &target,
2795                                          0,
2796                                          HELLO_VERIFICATION_TIMEOUT,
2797                                          &check_hello_validated, chvc);
2798   return GNUNET_OK;
2799 }
2800
2801
2802 /**
2803  * The peer specified by the given neighbour has timed-out or a plugin
2804  * has disconnected.  We may either need to do nothing (other plugins
2805  * still up), or trigger a full disconnect and clean up.  This
2806  * function updates our state and does the necessary notifications.
2807  * Also notifies our clients that the neighbour is now officially
2808  * gone.
2809  *
2810  * @param n the neighbour list entry for the peer
2811  * @param check should we just check if all plugins
2812  *        disconnected or must we ask all plugins to
2813  *        disconnect?
2814  */
2815 static void
2816 disconnect_neighbour (struct NeighbourList *n, int check)
2817 {
2818   struct ReadyList *rpos;
2819   struct NeighbourList *npos;
2820   struct NeighbourList *nprev;
2821   struct MessageQueue *mq;
2822   struct ForeignAddressList *peer_addresses;
2823   struct ForeignAddressList *peer_pos;
2824
2825   if (GNUNET_YES == check)
2826     {
2827       rpos = n->plugins;
2828       while (NULL != rpos)
2829         {
2830           peer_addresses = rpos->addresses;
2831           while (peer_addresses != NULL)
2832             {
2833               if (GNUNET_YES == peer_addresses->connected)
2834                 return;             /* still connected */
2835               peer_addresses = peer_addresses->next;
2836             }
2837           rpos = rpos->next;
2838         }
2839     }
2840 #if DEBUG_TRANSPORT
2841   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2842               "Disconnecting from `%4s'\n",
2843               GNUNET_i2s (&n->id));
2844 #endif
2845   /* remove n from neighbours list */
2846   nprev = NULL;
2847   npos = neighbours;
2848   while ((npos != NULL) && (npos != n))
2849     {
2850       nprev = npos;
2851       npos = npos->next;
2852     }
2853   GNUNET_assert (npos != NULL);
2854   if (nprev == NULL)
2855     neighbours = n->next;
2856   else
2857     nprev->next = n->next;
2858
2859   /* notify all clients about disconnect */
2860   if (GNUNET_YES == n->received_pong)
2861     notify_clients_disconnect (&n->id);
2862
2863   /* clean up all plugins, cancel connections and pending transmissions */
2864   while (NULL != (rpos = n->plugins))
2865     {
2866       n->plugins = rpos->next;
2867       rpos->plugin->api->disconnect (rpos->plugin->api->cls, &n->id);
2868       while (rpos->addresses != NULL)
2869         {
2870           peer_pos = rpos->addresses;
2871           rpos->addresses = peer_pos->next;
2872           if (peer_pos->connected == GNUNET_YES)
2873             GNUNET_STATISTICS_update (stats,
2874                                       gettext_noop ("# connected addresses"),
2875                                       -1,
2876                                       GNUNET_NO); 
2877           if (GNUNET_YES == peer_pos->validated)
2878             GNUNET_STATISTICS_update (stats,
2879                                       gettext_noop ("# peer addresses considered valid"),
2880                                       -1,
2881                                       GNUNET_NO);      
2882           if (GNUNET_SCHEDULER_NO_TASK != peer_pos->revalidate_task)
2883             {
2884               GNUNET_SCHEDULER_cancel (sched,
2885                                        peer_pos->revalidate_task);
2886               peer_pos->revalidate_task = GNUNET_SCHEDULER_NO_TASK;
2887             }
2888           GNUNET_free(peer_pos);
2889         }
2890       GNUNET_free (rpos);
2891     }
2892
2893   /* free all messages on the queue */
2894   while (NULL != (mq = n->messages_head))
2895     {
2896       GNUNET_STATISTICS_update (stats,
2897                                 gettext_noop ("# bytes in message queue for other peers"),
2898                                 -mq->message_buf_size,
2899                                 GNUNET_NO);
2900       GNUNET_STATISTICS_update (stats,
2901                                 gettext_noop ("# bytes discarded due to disconnect"),
2902                                 mq->message_buf_size,
2903                                 GNUNET_NO);
2904       GNUNET_CONTAINER_DLL_remove (n->messages_head,
2905                                    n->messages_tail,
2906                                    mq);
2907       GNUNET_assert (0 == memcmp(&mq->neighbour_id, 
2908                                  &n->id,
2909                                  sizeof(struct GNUNET_PeerIdentity)));
2910       GNUNET_free (mq);
2911     }
2912   if (n->timeout_task != GNUNET_SCHEDULER_NO_TASK)
2913     {
2914       GNUNET_SCHEDULER_cancel (sched, n->timeout_task);
2915       n->timeout_task = GNUNET_SCHEDULER_NO_TASK;
2916     }
2917   if (n->retry_task != GNUNET_SCHEDULER_NO_TASK)
2918     {
2919       GNUNET_SCHEDULER_cancel (sched, n->retry_task);
2920       n->retry_task = GNUNET_SCHEDULER_NO_TASK;
2921     }
2922   if (n->piter != NULL)
2923     {
2924       GNUNET_PEERINFO_iterate_cancel (n->piter);
2925       n->piter = NULL;
2926     }
2927   /* finally, free n itself */
2928   GNUNET_STATISTICS_update (stats,
2929                             gettext_noop ("# active neighbours"),
2930                             -1,
2931                             GNUNET_NO);
2932   GNUNET_free (n);
2933 }
2934
2935
2936 /**
2937  * We have received a PING message from someone.  Need to send a PONG message
2938  * in response to the peer by any means necessary. 
2939  *
2940  * FIXME: With something like TCP where a connection exists, we may
2941  * want to send it that way.  But the current API does not seem to
2942  * allow us to do so (can't tell this to the transport!)
2943  */
2944 static int 
2945 handle_ping(void *cls, const struct GNUNET_MessageHeader *message,
2946             const struct GNUNET_PeerIdentity *peer,
2947             const char *sender_address,
2948             size_t sender_address_len)
2949 {
2950   struct TransportPlugin *plugin = cls;
2951   struct TransportPingMessage *ping;
2952   struct TransportPongMessage *pong;
2953   struct NeighbourList *n;
2954   struct ReadyList *rl;
2955   struct ForeignAddressList *fal;
2956
2957   if (ntohs (message->size) != sizeof (struct TransportPingMessage))
2958     {
2959       GNUNET_break_op (0);
2960       return GNUNET_SYSERR;
2961     }
2962   ping = (struct TransportPingMessage *) message;
2963   if (0 != memcmp (&ping->target,
2964                    plugin->env.my_identity,
2965                    sizeof (struct GNUNET_PeerIdentity)))
2966     {
2967       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2968                   _("Received `%s' message not destined for me!\n"), 
2969                   "PING");
2970       return GNUNET_SYSERR;
2971     }
2972 #if DEBUG_TRANSPORT
2973   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2974               "Processing `%s' from `%s'\n",
2975               "PING", 
2976               GNUNET_a2s ((const struct sockaddr *)sender_address, 
2977                           sender_address_len));
2978 #endif
2979   GNUNET_STATISTICS_update (stats,
2980                             gettext_noop ("# PING messages received"),
2981                             1,
2982                             GNUNET_NO);
2983   pong = GNUNET_malloc (sizeof (struct TransportPongMessage) + sender_address_len);
2984   pong->header.size = htons (sizeof (struct TransportPongMessage) + sender_address_len);
2985   pong->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_PONG);
2986   pong->purpose.size =
2987     htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) +
2988            sizeof (uint32_t) +
2989            sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) + sender_address_len);
2990   pong->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_TCP_PING);
2991   pong->challenge = ping->challenge;
2992   pong->addrlen = htons(sender_address_len);
2993   memcpy(&pong->signer, 
2994          &my_public_key, 
2995          sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
2996   memcpy (&pong[1], sender_address, sender_address_len);
2997   GNUNET_assert (GNUNET_OK ==
2998                  GNUNET_CRYPTO_rsa_sign (my_private_key,
2999                                          &pong->purpose, &pong->signature));
3000
3001   n = find_neighbour(peer);
3002   if (n == NULL)
3003     n = setup_new_neighbour(peer);
3004   /* broadcast 'PONG' to all available addresses */
3005   rl = n->plugins;
3006   while (rl != NULL)
3007     {
3008       fal = rl->addresses;
3009       while (fal != NULL)
3010         {
3011           transmit_to_peer(NULL, fal,
3012                            TRANSPORT_PONG_PRIORITY, 
3013                            HELLO_VERIFICATION_TIMEOUT,
3014                            (const char *)pong, 
3015                            ntohs(pong->header.size), 
3016                            GNUNET_YES, 
3017                            n);
3018           fal = fal->next;
3019         }
3020       rl = rl->next;
3021     }
3022   GNUNET_free(pong);
3023   return GNUNET_OK;
3024 }
3025
3026
3027 /**
3028  * Function called by the plugin for each received message.
3029  * Update data volumes, possibly notify plugins about
3030  * reducing the rate at which they read from the socket
3031  * and generally forward to our receive callback.
3032  *
3033  * @param cls the "struct TransportPlugin *" we gave to the plugin
3034  * @param peer (claimed) identity of the other peer
3035  * @param message the message, NULL if we only care about
3036  *                learning about the delay until we should receive again
3037  * @param distance in overlay hops; use 1 unless DV (or 0 if message == NULL)
3038  * @param sender_address binary address of the sender (if observed)
3039  * @param sender_address_len number of bytes in sender_address
3040  * @return how long the plugin should wait until receiving more data
3041  *         (plugins that do not support this, can ignore the return value)
3042  */
3043 static struct GNUNET_TIME_Relative
3044 plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
3045                     const struct GNUNET_MessageHeader *message,
3046                     unsigned int distance, const char *sender_address,
3047                     size_t sender_address_len)
3048 {
3049   struct ReadyList *service_context;
3050   struct TransportPlugin *plugin = cls;
3051   struct TransportClient *cpos;
3052   struct InboundMessage *im;
3053   struct ForeignAddressList *peer_address;
3054   uint16_t msize;
3055   struct NeighbourList *n;
3056   struct GNUNET_TIME_Relative ret;
3057
3058   n = find_neighbour (peer);
3059   if (n == NULL)
3060     n = setup_new_neighbour (peer);    
3061   service_context = n->plugins;
3062   while ((service_context != NULL) && (plugin != service_context->plugin))
3063     service_context = service_context->next;
3064   GNUNET_assert ((plugin->api->send == NULL) || (service_context != NULL));
3065   if (message != NULL)
3066     {
3067       peer_address = add_peer_address(n, 
3068                                       plugin->short_name,
3069                                       sender_address, 
3070                                       sender_address_len);  
3071       if (peer_address != NULL)
3072         {
3073           peer_address->distance = distance;
3074           if (peer_address->connected == GNUNET_NO)
3075             {
3076               /* FIXME: be careful here to not mark
3077                  MULTIPLE addresses as connected! */
3078               peer_address->connected = GNUNET_YES;
3079               GNUNET_STATISTICS_update (stats,
3080                                         gettext_noop ("# connected addresses"),
3081                                         1,
3082                                         GNUNET_NO);
3083             }
3084           peer_address->timeout
3085             =
3086             GNUNET_TIME_relative_to_absolute
3087             (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
3088           schedule_next_ping (peer_address);
3089         }
3090       /* update traffic received amount ... */
3091       msize = ntohs (message->size);      
3092       GNUNET_STATISTICS_update (stats,
3093                                 gettext_noop ("# bytes received from other peers"),
3094                                 msize,
3095                                 GNUNET_NO);
3096       n->distance = distance;
3097       n->peer_timeout =
3098         GNUNET_TIME_relative_to_absolute
3099         (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
3100       GNUNET_SCHEDULER_cancel (sched,
3101                                n->timeout_task);
3102       n->timeout_task =
3103         GNUNET_SCHEDULER_add_delayed (sched,
3104                                       GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
3105                                       &neighbour_timeout_task, n);
3106       if (n->quota_violation_count > QUOTA_VIOLATION_DROP_THRESHOLD)
3107         {
3108           /* dropping message due to frequent inbound volume violations! */
3109           GNUNET_log (GNUNET_ERROR_TYPE_WARNING |
3110                       GNUNET_ERROR_TYPE_BULK,
3111                       _
3112                       ("Dropping incoming message due to repeated bandwidth quota (%u b/s) violations (total of %u).\n"), 
3113                       n->in_tracker.available_bytes_per_s__,
3114                       n->quota_violation_count);
3115           GNUNET_STATISTICS_update (stats,
3116                                     gettext_noop ("# bandwidth quota violations by other peers"),
3117                                     1,
3118                                     GNUNET_NO);
3119           return GNUNET_TIME_UNIT_MINUTES; /* minimum penalty, likely ignored (UDP...) */
3120         }
3121       switch (ntohs (message->type))
3122         {
3123         case GNUNET_MESSAGE_TYPE_HELLO:
3124           GNUNET_STATISTICS_update (stats,
3125                                     gettext_noop ("# HELLO messages received from other peers"),
3126                                     1,
3127                                     GNUNET_NO);
3128           process_hello (plugin, message);
3129           break;
3130         case GNUNET_MESSAGE_TYPE_TRANSPORT_PING:
3131           handle_ping(plugin, message, peer, sender_address, sender_address_len);
3132           break;
3133         case GNUNET_MESSAGE_TYPE_TRANSPORT_PONG:
3134           handle_pong(plugin, message, peer, sender_address, sender_address_len);
3135           break;
3136         default:
3137 #if DEBUG_TRANSPORT
3138           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3139                       "Received message of type %u from `%4s', sending to all clients.\n",
3140                       ntohs (message->type), GNUNET_i2s (peer));
3141 #endif
3142           if (GNUNET_YES == GNUNET_BANDWIDTH_tracker_consume (&n->in_tracker,
3143                                                               msize))
3144             n->quota_violation_count++;
3145           else 
3146             n->quota_violation_count = 0; /* back within limits */
3147           GNUNET_STATISTICS_update (stats,
3148                                     gettext_noop ("# payload received from other peers"),
3149                                     msize,
3150                                     GNUNET_NO);
3151           /* transmit message to all clients */
3152           im = GNUNET_malloc (sizeof (struct InboundMessage) + msize);
3153           im->header.size = htons (sizeof (struct InboundMessage) + msize);
3154           im->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RECV);
3155           im->latency = GNUNET_TIME_relative_hton (n->latency);
3156           im->peer = *peer;
3157           memcpy (&im[1], message, msize);
3158           cpos = clients;
3159           while (cpos != NULL)
3160             {
3161               transmit_to_client (cpos, &im->header, GNUNET_YES);
3162               cpos = cpos->next;
3163             }
3164           GNUNET_free (im);
3165         }
3166     }  
3167   ret = GNUNET_BANDWIDTH_tracker_get_delay (&n->in_tracker, 0);
3168   if (ret.value > 0)
3169     {
3170       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3171                   "Throttling read (%llu bytes excess at %u b/s), waiting %llums before reading more.\n",
3172                   (unsigned long long) n->in_tracker.consumption_since_last_update__,
3173                   (unsigned int) n->in_tracker.available_bytes_per_s__,
3174                   (unsigned long long) ret.value);
3175       GNUNET_STATISTICS_update (stats,
3176                                 gettext_noop ("# ms throttling suggested"),
3177                                 (int64_t) ret.value,
3178                                 GNUNET_NO);      
3179     }
3180   return ret;
3181 }
3182
3183
3184 /**
3185  * Handle START-message.  This is the first message sent to us
3186  * by any client which causes us to add it to our list.
3187  *
3188  * @param cls closure (always NULL)
3189  * @param client identification of the client
3190  * @param message the actual message
3191  */
3192 static void
3193 handle_start (void *cls,
3194               struct GNUNET_SERVER_Client *client,
3195               const struct GNUNET_MessageHeader *message)
3196 {
3197   struct TransportClient *c;
3198   struct ConnectInfoMessage cim;
3199   struct NeighbourList *n;
3200
3201 #if DEBUG_TRANSPORT
3202   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3203               "Received `%s' request from client\n", "START");
3204 #endif
3205   c = clients;
3206   while (c != NULL)
3207     {
3208       if (c->client == client)
3209         {
3210           /* client already on our list! */
3211           GNUNET_break (0);
3212           GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3213           return;
3214         }
3215       c = c->next;
3216     }
3217   c = GNUNET_malloc (sizeof (struct TransportClient));
3218   c->next = clients;
3219   clients = c;
3220   c->client = client;
3221   if (our_hello != NULL)
3222     {
3223 #if DEBUG_TRANSPORT
3224       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3225                   "Sending our own `%s' to new client\n", "HELLO");
3226 #endif
3227       transmit_to_client (c,
3228                           (const struct GNUNET_MessageHeader *) our_hello,
3229                           GNUNET_NO);
3230       /* tell new client about all existing connections */
3231       cim.header.size = htons (sizeof (struct ConnectInfoMessage));
3232       cim.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
3233       n = neighbours; 
3234       while (n != NULL)
3235         {
3236           if (GNUNET_YES == n->received_pong)
3237             {
3238               cim.id = n->id;
3239               cim.latency = GNUNET_TIME_relative_hton (n->latency);
3240               cim.distance = htonl (n->distance);
3241               transmit_to_client (c, &cim.header, GNUNET_NO);
3242             }
3243             n = n->next;
3244         }
3245     }
3246   GNUNET_SERVER_receive_done (client, GNUNET_OK);
3247 }
3248
3249
3250 /**
3251  * Handle HELLO-message.
3252  *
3253  * @param cls closure (always NULL)
3254  * @param client identification of the client
3255  * @param message the actual message
3256  */
3257 static void
3258 handle_hello (void *cls,
3259               struct GNUNET_SERVER_Client *client,
3260               const struct GNUNET_MessageHeader *message)
3261 {
3262   int ret;
3263
3264   GNUNET_STATISTICS_update (stats,
3265                             gettext_noop ("# HELLOs received from clients"),
3266                             1,
3267                             GNUNET_NO);      
3268   ret = process_hello (NULL, message);
3269   GNUNET_SERVER_receive_done (client, ret);
3270 }
3271
3272
3273 /**
3274  * Handle SEND-message.
3275  *
3276  * @param cls closure (always NULL)
3277  * @param client identification of the client
3278  * @param message the actual message
3279  */
3280 static void
3281 handle_send (void *cls,
3282              struct GNUNET_SERVER_Client *client,
3283              const struct GNUNET_MessageHeader *message)
3284 {
3285   struct TransportClient *tc;
3286   struct NeighbourList *n;
3287   const struct OutboundMessage *obm;
3288   const struct GNUNET_MessageHeader *obmm;
3289   uint16_t size;
3290   uint16_t msize;
3291
3292   size = ntohs (message->size);
3293   if (size <
3294       sizeof (struct OutboundMessage) + sizeof (struct GNUNET_MessageHeader))
3295     {
3296       GNUNET_break (0);
3297       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3298       return;
3299     }
3300   GNUNET_STATISTICS_update (stats,
3301                             gettext_noop ("# payload received for other peers"),
3302                             size,
3303                             GNUNET_NO);      
3304   obm = (const struct OutboundMessage *) message;
3305 #if DEBUG_TRANSPORT
3306   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3307               "Received `%s' request from client with target `%4s'\n",
3308               "SEND", GNUNET_i2s (&obm->peer));
3309 #endif
3310   obmm = (const struct GNUNET_MessageHeader *) &obm[1];
3311   msize = ntohs (obmm->size);
3312   if (size != msize + sizeof (struct OutboundMessage))
3313     {
3314       GNUNET_break (0);
3315       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3316       return;
3317     }
3318   n = find_neighbour (&obm->peer);
3319   if (n == NULL)
3320     n = setup_new_neighbour (&obm->peer);
3321   tc = clients;
3322   while ((tc != NULL) && (tc->client != client))
3323     tc = tc->next;
3324
3325 #if DEBUG_TRANSPORT
3326   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3327               "Client asked to transmit %u-byte message of type %u to `%4s'\n",
3328               ntohs (obmm->size),
3329               ntohs (obmm->type), GNUNET_i2s (&obm->peer));
3330 #endif
3331   transmit_to_peer (tc, NULL, ntohl (obm->priority), 
3332                     GNUNET_TIME_relative_ntoh (obm->timeout),
3333                     (char *)obmm, 
3334                     ntohs (obmm->size), GNUNET_NO, n);
3335   GNUNET_SERVER_receive_done (client, GNUNET_OK);
3336 }
3337
3338
3339 /**
3340  * Handle SET_QUOTA-message.
3341  *
3342  * @param cls closure (always NULL)
3343  * @param client identification of the client
3344  * @param message the actual message
3345  */
3346 static void
3347 handle_set_quota (void *cls,
3348                   struct GNUNET_SERVER_Client *client,
3349                   const struct GNUNET_MessageHeader *message)
3350 {
3351   const struct QuotaSetMessage *qsm =
3352     (const struct QuotaSetMessage *) message;
3353   struct NeighbourList *n;
3354   
3355   GNUNET_STATISTICS_update (stats,
3356                             gettext_noop ("# SET QUOTA messages received"),
3357                             1,
3358                             GNUNET_NO);      
3359   n = find_neighbour (&qsm->peer);
3360   if (n == NULL)
3361     {
3362       GNUNET_SERVER_receive_done (client, GNUNET_OK);
3363       GNUNET_STATISTICS_update (stats,
3364                                 gettext_noop ("# SET QUOTA messages ignored (no such peer)"),
3365                                 1,
3366                                 GNUNET_NO);      
3367       return;
3368     }
3369 #if DEBUG_TRANSPORT
3370   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3371               "Received `%s' request (new quota %u, old quota %u) from client for peer `%4s'\n",
3372               "SET_QUOTA", 
3373               (unsigned int) ntohl (qsm->quota.value__),
3374               (unsigned int) n->in_tracker.available_bytes_per_s__,
3375               GNUNET_i2s (&qsm->peer));
3376 #endif
3377   GNUNET_BANDWIDTH_tracker_update_quota (&n->in_tracker,
3378                                          qsm->quota);
3379   if (0 == ntohl (qsm->quota.value__)) 
3380     disconnect_neighbour (n, GNUNET_NO);    
3381   GNUNET_SERVER_receive_done (client, GNUNET_OK);
3382 }
3383
3384
3385 static void
3386 transmit_address_to_client (void *cls, const char *address)
3387 {
3388   struct GNUNET_SERVER_TransmitContext *tc = cls;
3389   size_t slen;
3390
3391   if (NULL == address)
3392     slen = 0;
3393   else
3394     slen = strlen (address) + 1;
3395   GNUNET_SERVER_transmit_context_append_data (tc, address, slen,
3396                                               GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_REPLY);
3397   if (NULL == address)
3398     GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
3399 }
3400
3401
3402 /**
3403  * Handle AddressLookup-message.
3404  *
3405  * @param cls closure (always NULL)
3406  * @param client identification of the client
3407  * @param message the actual message
3408  */
3409 static void
3410 handle_address_lookup (void *cls,
3411                        struct GNUNET_SERVER_Client *client,
3412                        const struct GNUNET_MessageHeader *message)
3413 {
3414   const struct AddressLookupMessage *alum;
3415   struct TransportPlugin *lsPlugin;
3416   const char *nameTransport;
3417   const char *address;
3418   uint16_t size;
3419   struct GNUNET_SERVER_TransmitContext *tc;
3420
3421   size = ntohs (message->size);
3422   if (size < sizeof (struct AddressLookupMessage))
3423     {
3424       GNUNET_break_op (0);
3425       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3426       return;
3427     }
3428   alum = (const struct AddressLookupMessage *) message;
3429   uint32_t addressLen = ntohl (alum->addrlen);
3430   if (size <= sizeof (struct AddressLookupMessage) + addressLen)
3431     {
3432       GNUNET_break_op (0);
3433       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3434       return;
3435     }
3436   address = (const char *) &alum[1];
3437   nameTransport = (const char *) &address[addressLen];
3438   if (nameTransport
3439       [size - sizeof (struct AddressLookupMessage) - addressLen - 1] != '\0')
3440     {
3441       GNUNET_break_op (0);
3442       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3443       return;
3444     }
3445   struct GNUNET_TIME_Absolute timeout =
3446     GNUNET_TIME_absolute_ntoh (alum->timeout);
3447   struct GNUNET_TIME_Relative rtimeout =
3448     GNUNET_TIME_absolute_get_remaining (timeout);
3449   lsPlugin = find_transport (nameTransport);
3450   if (NULL == lsPlugin)
3451     {
3452       tc = GNUNET_SERVER_transmit_context_create (client);
3453       GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
3454                                                   GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_REPLY);
3455       GNUNET_SERVER_transmit_context_run (tc, rtimeout);
3456       return;
3457     }
3458   tc = GNUNET_SERVER_transmit_context_create (client);
3459   lsPlugin->api->address_pretty_printer (cls, nameTransport,
3460                                          address, addressLen, GNUNET_YES,
3461                                          rtimeout,
3462                                          &transmit_address_to_client, tc);
3463 }
3464
3465 /**
3466  * List of handlers for the messages understood by this
3467  * service.
3468  */
3469 static struct GNUNET_SERVER_MessageHandler handlers[] = {
3470   {&handle_start, NULL,
3471    GNUNET_MESSAGE_TYPE_TRANSPORT_START, 0},
3472   {&handle_hello, NULL,
3473    GNUNET_MESSAGE_TYPE_HELLO, 0},
3474   {&handle_send, NULL,
3475    GNUNET_MESSAGE_TYPE_TRANSPORT_SEND, 0},
3476   {&handle_set_quota, NULL,
3477    GNUNET_MESSAGE_TYPE_TRANSPORT_SET_QUOTA, sizeof (struct QuotaSetMessage)},
3478   {&handle_address_lookup, NULL,
3479    GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_LOOKUP,
3480    0},
3481   {NULL, NULL, 0, 0}
3482 };
3483
3484
3485 /**
3486  * Setup the environment for this plugin.
3487  */
3488 static void
3489 create_environment (struct TransportPlugin *plug)
3490 {
3491   plug->env.cfg = cfg;
3492   plug->env.sched = sched;
3493   plug->env.my_identity = &my_identity;
3494   plug->env.cls = plug;
3495   plug->env.receive = &plugin_env_receive;
3496   plug->env.notify_address = &plugin_env_notify_address;
3497   plug->env.max_connections = max_connect_per_transport;
3498   plug->env.stats = stats;
3499 }
3500
3501
3502 /**
3503  * Start the specified transport (load the plugin).
3504  */
3505 static void
3506 start_transport (struct GNUNET_SERVER_Handle *server, const char *name)
3507 {
3508   struct TransportPlugin *plug;
3509   char *libname;
3510
3511   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3512               _("Loading `%s' transport plugin\n"), name);
3513   GNUNET_asprintf (&libname, "libgnunet_plugin_transport_%s", name);
3514   plug = GNUNET_malloc (sizeof (struct TransportPlugin));
3515   create_environment (plug);
3516   plug->short_name = GNUNET_strdup (name);
3517   plug->lib_name = libname;
3518   plug->next = plugins;
3519   plugins = plug;
3520   plug->api = GNUNET_PLUGIN_load (libname, &plug->env);
3521   if (plug->api == NULL)
3522     {
3523       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3524                   _("Failed to load transport plugin for `%s'\n"), name);
3525       GNUNET_free (plug->short_name);
3526       plugins = plug->next;
3527       GNUNET_free (libname);
3528       GNUNET_free (plug);
3529     }
3530 }
3531
3532
3533 /**
3534  * Called whenever a client is disconnected.  Frees our
3535  * resources associated with that client.
3536  *
3537  * @param cls closure
3538  * @param client identification of the client
3539  */
3540 static void
3541 client_disconnect_notification (void *cls,
3542                                 struct GNUNET_SERVER_Client *client)
3543 {
3544   struct TransportClient *pos;
3545   struct TransportClient *prev;
3546   struct ClientMessageQueueEntry *mqe;
3547
3548   if (client == NULL)
3549     return;
3550 #if DEBUG_TRANSPORT
3551   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
3552               "Client disconnected, cleaning up.\n");
3553 #endif
3554   prev = NULL;
3555   pos = clients;
3556   while ((pos != NULL) && (pos->client != client))
3557     {
3558       prev = pos;
3559       pos = pos->next;
3560     }
3561   if (pos == NULL)
3562     return;
3563   while (NULL != (mqe = pos->message_queue_head))
3564     {
3565       GNUNET_CONTAINER_DLL_remove (pos->message_queue_head,
3566                                    pos->message_queue_tail,
3567                                    mqe);
3568       pos->message_count--;
3569       GNUNET_free (mqe);
3570     }
3571   if (prev == NULL)
3572     clients = pos->next;
3573   else
3574     prev->next = pos->next;
3575   if (GNUNET_YES == pos->tcs_pending)
3576     {
3577       pos->client = NULL;
3578       return;
3579     }
3580   if (pos->th != NULL)
3581     {
3582       GNUNET_CONNECTION_notify_transmit_ready_cancel (pos->th);
3583       pos->th = NULL;
3584     }
3585   GNUNET_break (0 == pos->message_count);
3586   GNUNET_free (pos);
3587 }
3588
3589
3590 /**
3591  * Iterator to free entries in the validation_map.
3592  *
3593  * @param cls closure (unused)
3594  * @param key current key code
3595  * @param value value in the hash map (validation to abort)
3596  * @return GNUNET_YES (always)
3597  */
3598 static int 
3599 abort_validation (void *cls,
3600                   const GNUNET_HashCode * key,
3601                   void *value)
3602 {
3603   struct ValidationEntry *va = value;
3604
3605   GNUNET_SCHEDULER_cancel (sched, va->timeout_task);
3606   GNUNET_free (va->transport_name);
3607   GNUNET_free (va);
3608   return GNUNET_YES;
3609 }
3610
3611
3612 /**
3613  * Function called when the service shuts down.  Unloads our plugins
3614  * and cancels pending validations.
3615  *
3616  * @param cls closure, unused
3617  * @param tc task context (unused)
3618  */
3619 static void
3620 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
3621 {
3622   struct TransportPlugin *plug;
3623   struct OwnAddressList *al;
3624   struct CheckHelloValidatedContext *chvc;
3625
3626   while (neighbours != NULL)
3627     disconnect_neighbour (neighbours, GNUNET_NO);
3628 #if DEBUG_TRANSPORT
3629   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3630               "Transport service is unloading plugins...\n");
3631 #endif
3632   while (NULL != (plug = plugins))
3633     {
3634       plugins = plug->next;
3635       GNUNET_break (NULL == GNUNET_PLUGIN_unload (plug->lib_name, plug->api));
3636       GNUNET_free (plug->lib_name);
3637       GNUNET_free (plug->short_name);
3638       while (NULL != (al = plug->addresses))
3639         {
3640           plug->addresses = al->next;
3641           GNUNET_free (al);
3642         }
3643       GNUNET_free (plug);
3644     }
3645   if (my_private_key != NULL)
3646     GNUNET_CRYPTO_rsa_key_free (my_private_key);
3647   GNUNET_free_non_null (our_hello);
3648
3649   /* free 'chvc' data structure */
3650   while (NULL != (chvc = chvc_head))
3651     {
3652       chvc_head = chvc->next;
3653       GNUNET_PEERINFO_iterate_cancel (chvc->piter);
3654       GNUNET_free (chvc);
3655     }
3656   chvc_tail = NULL;
3657
3658   GNUNET_CONTAINER_multihashmap_iterate (validation_map,
3659                                          &abort_validation,
3660                                          NULL);
3661   GNUNET_CONTAINER_multihashmap_destroy (validation_map);
3662   validation_map = NULL;
3663   if (stats != NULL)
3664     {
3665       GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
3666       stats = NULL;
3667     }
3668 }
3669
3670
3671 /**
3672  * Initiate transport service.
3673  *
3674  * @param cls closure
3675  * @param s scheduler to use
3676  * @param serv the initialized server
3677  * @param c configuration to use
3678  */
3679 static void
3680 run (void *cls,
3681      struct GNUNET_SCHEDULER_Handle *s,
3682      struct GNUNET_SERVER_Handle *serv,
3683      const struct GNUNET_CONFIGURATION_Handle *c)
3684 {
3685   char *plugs;
3686   char *pos;
3687   int no_transports;
3688   unsigned long long tneigh;
3689   char *keyfile;
3690
3691   sched = s;
3692   cfg = c;
3693   stats = GNUNET_STATISTICS_create (sched, "transport", cfg);
3694   validation_map = GNUNET_CONTAINER_multihashmap_create (64);
3695   /* parse configuration */
3696   if ((GNUNET_OK !=
3697        GNUNET_CONFIGURATION_get_value_number (c,
3698                                               "TRANSPORT",
3699                                               "NEIGHBOUR_LIMIT",
3700                                               &tneigh)) ||
3701       (GNUNET_OK !=
3702        GNUNET_CONFIGURATION_get_value_filename (c,
3703                                                 "GNUNETD",
3704                                                 "HOSTKEY", &keyfile)))
3705     {
3706       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3707                   _
3708                   ("Transport service is lacking key configuration settings.  Exiting.\n"));
3709       GNUNET_SCHEDULER_shutdown (s);
3710       if (stats != NULL)
3711         {
3712           GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
3713           stats = NULL;
3714         }
3715       GNUNET_CONTAINER_multihashmap_destroy (validation_map);
3716       validation_map = NULL;
3717       return;
3718     }
3719   max_connect_per_transport = (uint32_t) tneigh;
3720   my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
3721   GNUNET_free (keyfile);
3722   if (my_private_key == NULL)
3723     {
3724       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3725                   _
3726                   ("Transport service could not access hostkey.  Exiting.\n"));
3727       GNUNET_SCHEDULER_shutdown (s);
3728       if (stats != NULL)
3729         {
3730           GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
3731           stats = NULL;
3732         }
3733       GNUNET_CONTAINER_multihashmap_destroy (validation_map);
3734       validation_map = NULL;
3735       return;
3736     }
3737   GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key);
3738   GNUNET_CRYPTO_hash (&my_public_key,
3739                       sizeof (my_public_key), &my_identity.hashPubKey);
3740   /* setup notification */
3741   server = serv;
3742   GNUNET_SERVER_disconnect_notify (server,
3743                                    &client_disconnect_notification, NULL);
3744   /* load plugins... */
3745   no_transports = 1;
3746   if (GNUNET_OK ==
3747       GNUNET_CONFIGURATION_get_value_string (c,
3748                                              "TRANSPORT", "PLUGINS", &plugs))
3749     {
3750       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3751                   _("Starting transport plugins `%s'\n"), plugs);
3752       pos = strtok (plugs, " ");
3753       while (pos != NULL)
3754         {
3755           start_transport (server, pos);
3756           no_transports = 0;
3757           pos = strtok (NULL, " ");
3758         }
3759       GNUNET_free (plugs);
3760     }
3761   GNUNET_SCHEDULER_add_delayed (sched,
3762                                 GNUNET_TIME_UNIT_FOREVER_REL,
3763                                 &shutdown_task, NULL);
3764   if (no_transports)
3765     refresh_hello ();
3766
3767 #if DEBUG_TRANSPORT
3768   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Transport service ready.\n"));
3769 #endif
3770   /* process client requests */
3771   GNUNET_SERVER_add_handlers (server, handlers);
3772 }
3773
3774
3775 /**
3776  * The main function for the transport service.
3777  *
3778  * @param argc number of arguments from the command line
3779  * @param argv command line arguments
3780  * @return 0 ok, 1 on error
3781  */
3782 int
3783 main (int argc, char *const *argv)
3784 {
3785   return (GNUNET_OK ==
3786           GNUNET_SERVICE_run (argc,
3787                               argv,
3788                               "transport",
3789                               GNUNET_SERVICE_OPTION_NONE,
3790                               &run, NULL)) ? 0 : 1;
3791 }
3792
3793 /* end of gnunet-service-transport.c */