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