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