make compile
[oweals/gnunet.git] / src / transport / gnunet-service-transport.c
1 /*
2      This file is part of GNUnet.
3      (C) 2009, 2010 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 3, 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  */
27 #include "platform.h"
28 #include "gnunet_client_lib.h"
29 #include "gnunet_container_lib.h"
30 #include "gnunet_constants.h"
31 #include "gnunet_getopt_lib.h"
32 #include "gnunet_hello_lib.h"
33 #include "gnunet_os_lib.h"
34 #include "gnunet_peerinfo_service.h"
35 #include "gnunet_plugin_lib.h"
36 #include "gnunet_protocols.h"
37 #include "gnunet_service_lib.h"
38 #include "gnunet_signatures.h"
39 #include "gnunet_transport_plugin.h"
40 #include "transport.h"
41 #if HAVE_LIBGLPK
42 #include <glpk.h>
43 #endif
44
45 #define DEBUG_BLACKLIST GNUNET_YES
46
47 #define DEBUG_PING_PONG GNUNET_YES
48
49 #define DEBUG_TRANSPORT_HELLO GNUNET_YES
50
51 #define VERBOSE_ATS GNUNET_NO
52
53 /**
54  * Should we do some additional checks (to validate behavior
55  * of clients)?
56  */
57 #define EXTRA_CHECKS GNUNET_YES
58
59 /**
60  * How many messages can we have pending for a given client process
61  * before we start to drop incoming messages?  We typically should
62  * have only one client and so this would be the primary buffer for
63   * messages, so the number should be chosen rather generously.
64  *
65  * The expectation here is that most of the time the queue is large
66  * enough so that a drop is virtually never required.  Note that
67  * this value must be about as large as 'TOTAL_MSGS' in the
68  * 'test_transport_api_reliability.c', otherwise that testcase may
69  * fail.
70  */
71 #define MAX_PENDING (128 * 1024)
72
73 /**
74  * Size of the per-transport blacklist hash maps.
75  */
76 #define TRANSPORT_BLACKLIST_HT_SIZE 16
77
78 /**
79  * How often should we try to reconnect to a peer using a particular
80  * transport plugin before giving up?  Note that the plugin may be
81  * added back to the list after PLUGIN_RETRY_FREQUENCY expires.
82  */
83 #define MAX_CONNECT_RETRY 3
84
85 /**
86  * Limit on the number of ready-to-run tasks when validating
87  * HELLOs.  If more tasks are ready to run, we will drop
88  * HELLOs instead of validating them.
89  */
90 #define MAX_HELLO_LOAD 4
91
92 /**
93  * How often must a peer violate bandwidth quotas before we start
94  * to simply drop its messages?
95  */
96 #define QUOTA_VIOLATION_DROP_THRESHOLD 10
97
98 /**
99  * How long until a HELLO verification attempt should time out?
100  * Must be rather small, otherwise a partially successful HELLO
101  * validation (some addresses working) might not be available
102  * before a client's request for a connection fails for good.
103  * Besides, if a single request to an address takes a long time,
104  * then the peer is unlikely worthwhile anyway.
105  */
106 #define HELLO_VERIFICATION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15)
107
108 /**
109  * How long is a PONG signature valid?  We'll recycle a signature until
110  * 1/4 of this time is remaining.  PONGs should expire so that if our
111  * external addresses change an adversary cannot replay them indefinitely.
112  * OTOH, we don't want to spend too much time generating PONG signatures,
113  * so they must have some lifetime to reduce our CPU usage.
114  */
115 #define PONG_SIGNATURE_LIFETIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 1)
116
117 /**
118  * Priority to use for PONG messages.
119  */
120 #define TRANSPORT_PONG_PRIORITY 4
121
122 /**
123  * How often do we re-add (cheaper) plugins to our list of plugins
124  * to try for a given connected peer?
125  */
126 #define PLUGIN_RETRY_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15)
127
128 /**
129  * After how long do we expire an address in a HELLO that we just
130  * validated?  This value is also used for our own addresses when we
131  * create a HELLO.
132  */
133 #define HELLO_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 12)
134
135
136 /**
137  * How long before an existing address expires should we again try to
138  * validate it?  Must be (significantly) smaller than
139  * HELLO_ADDRESS_EXPIRATION.
140  */
141 #define HELLO_REVALIDATION_START_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 1)
142
143 /**
144  * Maximum frequency for re-evaluating latencies for all transport addresses.
145  */
146 #define LATENCY_EVALUATION_MAX_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 1)
147
148 /**
149  * Maximum frequency for re-evaluating latencies for connected addresses.
150  */
151 #define CONNECTED_LATENCY_EVALUATION_MAX_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 1)
152
153
154 /**
155  * List of addresses of other peers
156  */
157 struct ForeignAddressList
158 {
159   /**
160    * This is a linked list.
161    */
162   struct ForeignAddressList *next;
163
164   /**
165    * Which ready list does this entry belong to.
166    */
167   struct ReadyList *ready_list;
168
169   /**
170    * How long until we auto-expire this address (unless it is
171    * re-confirmed by the transport)?
172    */
173   struct GNUNET_TIME_Absolute expires;
174
175   /**
176    * Task used to re-validate addresses, updates latencies and
177    * verifies liveness.
178    */
179   GNUNET_SCHEDULER_TaskIdentifier revalidate_task;
180
181   /**
182    * The address.
183    */
184   const void *addr;
185
186   /**
187    * Session (or NULL if no valid session currently exists or if the
188    * plugin does not use sessions).
189    */
190   struct Session *session;
191
192   /**
193    * What was the last latency observed for this address, plugin and peer?
194    */
195   struct GNUNET_TIME_Relative latency;
196
197   /**
198    * If we did not successfully transmit a message to the given peer
199    * via this connection during the specified time, we should consider
200    * the connection to be dead.  This is used in the case that a TCP
201    * transport simply stalls writing to the stream but does not
202    * formerly get a signal that the other peer died.
203    */
204   struct GNUNET_TIME_Absolute timeout;
205
206   /**
207    * How often have we tried to connect using this plugin?  Used to
208    * discriminate against addresses that do not work well.
209    * FIXME: not yet used, but should be!
210    */
211   unsigned int connect_attempts;
212
213   /**
214    * DV distance to this peer (1 if no DV is used).
215    * FIXME: need to set this from transport plugins!
216    */
217   uint32_t distance;
218
219   /**
220    * Length of addr.
221    */
222   uint16_t addrlen;
223
224   /**
225    * Have we ever estimated the latency of this address?  Used to
226    * ensure that the first time we add an address, we immediately
227    * probe its latency.
228    */
229   int8_t estimated;
230
231   /**
232    * Are we currently connected via this address?  The first time we
233    * successfully transmit or receive data to a peer via a particular
234    * address, we set this to GNUNET_YES.  If we later get an error
235    * (disconnect notification, transmission failure, timeout), we set
236    * it back to GNUNET_NO.
237    */
238   int8_t connected;
239
240   /**
241    * Is this plugin currently busy transmitting to the specific target?
242    * GNUNET_NO if not (initial, default state is GNUNET_NO).   Internal
243    * messages do not count as 'in transmit'.
244    */
245   int8_t in_transmit;
246
247   /**
248    * Has this address been validated yet?
249    */
250   int8_t validated;
251
252 };
253
254
255 /**
256  * Entry in linked list of network addresses for ourselves.  Also
257  * includes a cached signature for 'struct TransportPongMessage's.
258  */
259 struct OwnAddressList
260 {
261   /**
262    * This is a linked list.
263    */
264   struct OwnAddressList *next;
265
266   /**
267    * How long until we actually auto-expire this address (unless it is
268    * re-confirmed by the transport)?
269    */
270   struct GNUNET_TIME_Absolute expires;
271
272   /**
273    * How long until the current signature expires? (ZERO if the
274    * signature was never created).
275    */
276   struct GNUNET_TIME_Absolute pong_sig_expires;
277
278   /**
279    * Signature for a 'struct TransportPongMessage' for this address.
280    */
281   struct GNUNET_CRYPTO_RsaSignature pong_signature;
282
283   /**
284    * Length of addr.
285    */
286   uint32_t addrlen;
287
288 };
289
290
291 /**
292  * Entry in linked list of all of our plugins.
293  */
294 struct TransportPlugin
295 {
296
297   /**
298    * This is a linked list.
299    */
300   struct TransportPlugin *next;
301
302   /**
303    * API of the transport as returned by the plugin's
304    * initialization function.
305    */
306   struct GNUNET_TRANSPORT_PluginFunctions *api;
307
308   /**
309    * Short name for the plugin (i.e. "tcp").
310    */
311   char *short_name;
312
313   /**
314    * Name of the library (i.e. "gnunet_plugin_transport_tcp").
315    */
316   char *lib_name;
317
318   /**
319    * List of our known addresses for this transport.
320    */
321   struct OwnAddressList *addresses;
322
323   /**
324    * Environment this transport service is using
325    * for this plugin.
326    */
327   struct GNUNET_TRANSPORT_PluginEnvironment env;
328
329   /**
330    * ID of task that is used to clean up expired addresses.
331    */
332   GNUNET_SCHEDULER_TaskIdentifier address_update_task;
333
334   /**
335    * Set to GNUNET_YES if we need to scrap the existing list of
336    * "addresses" and start fresh when we receive the next address
337    * update from a transport.  Set to GNUNET_NO if we should just add
338    * the new address to the list and wait for the commit call.
339    */
340   int rebuild;
341
342   /**
343    * Hashmap of blacklisted peers for this particular transport.
344    */
345   struct GNUNET_CONTAINER_MultiHashMap *blacklist;
346 };
347
348 struct NeighbourList;
349
350 /**
351  * For each neighbour we keep a list of messages
352  * that we still want to transmit to the neighbour.
353  */
354 struct MessageQueue
355 {
356
357   /**
358    * This is a doubly linked list.
359    */
360   struct MessageQueue *next;
361
362   /**
363    * This is a doubly linked list.
364    */
365   struct MessageQueue *prev;
366
367   /**
368    * The message(s) we want to transmit, GNUNET_MessageHeader(s)
369    * stuck together in memory.  Allocated at the end of this struct.
370    */
371   const char *message_buf;
372
373   /**
374    * Size of the message buf
375    */
376   size_t message_buf_size;
377
378   /**
379    * Client responsible for queueing the message;
380    * used to check that a client has no two messages
381    * pending for the same target.  Can be NULL.
382    */
383   struct TransportClient *client;
384
385   /**
386    * Using which specific address should we send this message?
387    */
388   struct ForeignAddressList *specific_address;
389
390   /**
391    * Peer ID of the Neighbour this entry belongs to.
392    */
393   struct GNUNET_PeerIdentity neighbour_id;
394
395   /**
396    * Plugin that we used for the transmission.
397    * NULL until we scheduled a transmission.
398    */
399   struct TransportPlugin *plugin;
400
401   /**
402    * At what time should we fail?
403    */
404   struct GNUNET_TIME_Absolute timeout;
405
406   /**
407    * Internal message of the transport system that should not be
408    * included in the usual SEND-SEND_OK transmission confirmation
409    * traffic management scheme.  Typically, "internal_msg" will
410    * be set whenever "client" is NULL (but it is not strictly
411    * required).
412    */
413   int internal_msg;
414
415   /**
416    * How important is the message?
417    */
418   unsigned int priority;
419
420 };
421
422
423 /**
424  * For a given Neighbour, which plugins are available
425  * to talk to this peer and what are their costs?
426  */
427 struct ReadyList
428 {
429   /**
430    * This is a linked list.
431    */
432   struct ReadyList *next;
433
434   /**
435    * Which of our transport plugins does this entry
436    * represent?
437    */
438   struct TransportPlugin *plugin;
439
440   /**
441    * Transport addresses, latency, and readiness for
442    * this particular plugin.
443    */
444   struct ForeignAddressList *addresses;
445
446   /**
447    * To which neighbour does this ready list belong to?
448    */
449   struct NeighbourList *neighbour;
450
451 };
452
453
454 /**
455  * Entry in linked list of all of our current neighbours.
456  */
457 struct NeighbourList
458 {
459
460   /**
461    * This is a linked list.
462    */
463   struct NeighbourList *next;
464
465   /**
466    * Which of our transports is connected to this peer
467    * and what is their status?
468    */
469   struct ReadyList *plugins;
470
471   /**
472    * Head of list of messages we would like to send to this peer;
473    * must contain at most one message per client.
474    */
475   struct MessageQueue *messages_head;
476
477   /**
478    * Tail of list of messages we would like to send to this peer; must
479    * contain at most one message per client.
480    */
481   struct MessageQueue *messages_tail;
482
483   /**
484    * Buffer for at most one payload message used when we receive
485    * payload data before our PING-PONG has succeeded.  We then
486    * store such messages in this intermediary buffer until the
487    * connection is fully up.
488    */
489   struct GNUNET_MessageHeader *pre_connect_message_buffer;
490
491   /**
492    * Context for peerinfo iteration.
493    * NULL after we are done processing peerinfo's information.
494    */
495   struct GNUNET_PEERINFO_IteratorContext *piter;
496
497   /**
498    * Public key for this peer.   Valid only if the respective flag is set below.
499    */
500   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded publicKey;
501
502   /**
503    * Identity of this neighbour.
504    */
505   struct GNUNET_PeerIdentity id;
506
507   /**
508    * ID of task scheduled to run when this peer is about to
509    * time out (will free resources associated with the peer).
510    */
511   GNUNET_SCHEDULER_TaskIdentifier timeout_task;
512
513   /**
514    * ID of task scheduled to run when we should retry transmitting
515    * the head of the message queue.  Actually triggered when the
516    * transmission is timing out (we trigger instantly when we have
517    * a chance of success).
518    */
519   GNUNET_SCHEDULER_TaskIdentifier retry_task;
520
521   /**
522    * How long until we should consider this peer dead
523    * (if we don't receive another message in the
524    * meantime)?
525    */
526   struct GNUNET_TIME_Absolute peer_timeout;
527
528   /**
529    * Tracker for inbound bandwidth.
530    */
531   struct GNUNET_BANDWIDTH_Tracker in_tracker;
532
533   /**
534    * The latency we have seen for this particular address for
535    * this particular peer.  This latency may have been calculated
536    * over multiple transports.  This value reflects how long it took
537    * us to receive a response when SENDING via this particular
538    * transport/neighbour/address combination!
539    *
540    * FIXME: we need to periodically send PINGs to update this
541    * latency (at least more often than the current "huge" (11h?)
542    * update interval).
543    */
544   struct GNUNET_TIME_Relative latency;
545
546   /**
547    * How often has the other peer (recently) violated the
548    * inbound traffic limit?  Incremented by 10 per violation,
549    * decremented by 1 per non-violation (for each
550    * time interval).
551    */
552   unsigned int quota_violation_count;
553
554   /**
555    * DV distance to this peer (1 if no DV is used).
556    */
557   uint32_t distance;
558
559   /**
560    * Have we seen an PONG from this neighbour in the past (and
561    * not had a disconnect since)?
562    */
563   int received_pong;
564
565   /**
566    * Do we have a valid public key for this neighbour?
567    */
568   int public_key_valid;
569
570   /**
571    * Performance data for the peer.
572    */
573   struct GNUNET_TRANSPORT_ATS_Information *ats;
574
575   /**
576    * Identity of the neighbour.
577    */
578   struct GNUNET_PeerIdentity peer;
579
580 };
581
582 /**
583  * Message used to ask a peer to validate receipt (to check an address
584  * from a HELLO).  Followed by the address we are trying to validate,
585  * or an empty address if we are just sending a PING to confirm that a
586  * connection which the receiver (of the PING) initiated is still valid.
587  */
588 struct TransportPingMessage
589 {
590
591   /**
592    * Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_PING
593    */
594   struct GNUNET_MessageHeader header;
595
596   /**
597    * Challenge code (to ensure fresh reply).
598    */
599   uint32_t challenge GNUNET_PACKED;
600
601   /**
602    * Who is the intended recipient?
603    */
604   struct GNUNET_PeerIdentity target;
605
606 };
607
608
609 /**
610  * Message used to validate a HELLO.  The challenge is included in the
611  * confirmation to make matching of replies to requests possible.  The
612  * signature signs our public key, an expiration time and our address.<p>
613  *
614  * This message is followed by our transport address that the PING tried
615  * to confirm (if we liked it).  The address can be empty (zero bytes)
616  * if the PING had not address either (and we received the request via
617  * a connection that we initiated).
618  */
619 struct TransportPongMessage
620 {
621
622   /**
623    * Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_PONG
624    */
625   struct GNUNET_MessageHeader header;
626
627   /**
628    * Challenge code from PING (showing freshness).  Not part of what
629    * is signed so that we can re-use signatures.
630    */
631   uint32_t challenge GNUNET_PACKED;
632
633   /**
634    * Signature.
635    */
636   struct GNUNET_CRYPTO_RsaSignature signature;
637
638   /**
639    * What are we signing and why?  Two possible reason codes can be here:
640    * GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN to confirm that this is a
641    * plausible address for this peer (pid is set to identity of signer); or
642    * GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_USING to confirm that this is
643    * an address we used to connect to the peer with the given pid.
644    */
645   struct GNUNET_CRYPTO_RsaSignaturePurpose purpose;
646
647   /**
648    * When does this signature expire?
649    */
650   struct GNUNET_TIME_AbsoluteNBO expiration;
651
652   /**
653    * Either the identity of the peer Who signed this message, or the
654    * identity of the peer that we're connected to using the given
655    * address (depending on purpose.type).
656    */
657   struct GNUNET_PeerIdentity pid;
658
659   /**
660    * Size of address appended to this message (part of what is
661    * being signed, hence not redundant).
662    */
663   uint32_t addrlen;
664
665 };
666
667
668 /**
669  * Linked list of messages to be transmitted to the client.  Each
670  * entry is followed by the actual message.
671  */
672 struct ClientMessageQueueEntry
673 {
674   /**
675    * This is a doubly-linked list.
676    */
677   struct ClientMessageQueueEntry *next;
678
679   /**
680    * This is a doubly-linked list.
681    */
682   struct ClientMessageQueueEntry *prev;
683 };
684
685
686 /**
687  * Client connected to the transport service.
688  */
689 struct TransportClient
690 {
691
692   /**
693    * This is a linked list.
694    */
695   struct TransportClient *next;
696
697   /**
698    * Handle to the client.
699    */
700   struct GNUNET_SERVER_Client *client;
701
702   /**
703    * Linked list of messages yet to be transmitted to
704    * the client.
705    */
706   struct ClientMessageQueueEntry *message_queue_head;
707
708   /**
709    * Tail of linked list of messages yet to be transmitted to the
710    * client.
711    */
712   struct ClientMessageQueueEntry *message_queue_tail;
713
714   /**
715    * Current transmit request handle.
716    */
717   struct GNUNET_CONNECTION_TransmitHandle *th;
718
719   /**
720    * Is a call to "transmit_send_continuation" pending?  If so, we
721    * must not free this struct (even if the corresponding client
722    * disconnects) and instead only remove it from the linked list and
723    * set the "client" field to NULL.
724    */
725   int tcs_pending;
726
727   /**
728    * Length of the list of messages pending for this client.
729    */
730   unsigned int message_count;
731
732 };
733
734
735 /**
736  * Context of currently active requests to peerinfo
737  * for validation of HELLOs.
738  */
739 struct CheckHelloValidatedContext;
740
741
742 /**
743  * Entry in map of all HELLOs awaiting validation.
744  */
745 struct ValidationEntry
746 {
747
748   /**
749    * NULL if this entry is not part of a larger HELLO validation.
750    */
751   struct CheckHelloValidatedContext *chvc;
752
753   /**
754    * The address, actually a pointer to the end
755    * of this struct.  Do not free!
756    */
757   const void *addr;
758
759   /**
760    * Name of the transport.
761    */
762   char *transport_name;
763
764   /**
765    * The public key of the peer.
766    */
767   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded publicKey;
768
769   /**
770    * ID of task that will clean up this entry if we don't succeed
771    * with the validation first.
772    */
773   GNUNET_SCHEDULER_TaskIdentifier timeout_task;
774
775   /**
776    * At what time did we send this validation?
777    */
778   struct GNUNET_TIME_Absolute send_time;
779
780   /**
781    * Session being validated (or NULL for none).
782    */
783   struct Session *session;
784
785   /**
786    * Challenge number we used.
787    */
788   uint32_t challenge;
789
790   /**
791    * Length of addr.
792    */
793   uint16_t addrlen;
794
795 };
796
797
798 /**
799  * Context of currently active requests to peerinfo
800  * for validation of HELLOs.
801  */
802 struct CheckHelloValidatedContext
803 {
804
805   /**
806    * This is a doubly-linked list.
807    */
808   struct CheckHelloValidatedContext *next;
809
810   /**
811    * This is a doubly-linked list.
812    */
813   struct CheckHelloValidatedContext *prev;
814
815   /**
816    * Hello that we are validating.
817    */
818   const struct GNUNET_HELLO_Message *hello;
819
820   /**
821    * Context for peerinfo iteration.
822    * NULL after we are done processing peerinfo's information.
823    */
824   struct GNUNET_PEERINFO_IteratorContext *piter;
825
826   /**
827    * Was a HELLO known for this peer to peerinfo?
828    */
829   int hello_known;
830
831   /**
832    * Number of validation entries currently referring to this
833    * CHVC.
834    */
835   unsigned int ve_count;
836 };
837
838
839
840 /**
841  * Our HELLO message.
842  */
843 static struct GNUNET_HELLO_Message *our_hello;
844
845 /**
846  * Our public key.
847  */
848 static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded my_public_key;
849
850 /**
851  * Our identity.
852  */
853 static struct GNUNET_PeerIdentity my_identity;
854
855 /**
856  * Our private key.
857  */
858 static struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key;
859
860 /**
861  * Our configuration.
862  */
863 const struct GNUNET_CONFIGURATION_Handle *cfg;
864
865 /**
866  * Linked list of all clients to this service.
867  */
868 static struct TransportClient *clients;
869
870 /**
871  * All loaded plugins.
872  */
873 static struct TransportPlugin *plugins;
874
875 /**
876  * Handle to peerinfo service.
877  */
878 static struct GNUNET_PEERINFO_Handle *peerinfo;
879
880 /**
881  * All known neighbours and their HELLOs.
882  */
883 static struct NeighbourList *neighbours;
884
885 /**
886  * Number of neighbours we'd like to have.
887  */
888 static uint32_t max_connect_per_transport;
889
890 /**
891  * Head of linked list.
892  */
893 static struct CheckHelloValidatedContext *chvc_head;
894
895 /**
896  * Tail of linked list.
897  */
898 static struct CheckHelloValidatedContext *chvc_tail;
899
900 /**
901  * Map of PeerIdentities to 'struct ValidationEntry*'s (addresses
902  * of the given peer that we are currently validating).
903  */
904 static struct GNUNET_CONTAINER_MultiHashMap *validation_map;
905
906 /**
907  * Handle for reporting statistics.
908  */
909 static struct GNUNET_STATISTICS_Handle *stats;
910
911 /**
912  * Handle for ats information
913  */
914 static struct ATS_info *ats;
915
916 /**
917  * The peer specified by the given neighbour has timed-out or a plugin
918  * has disconnected.  We may either need to do nothing (other plugins
919  * still up), or trigger a full disconnect and clean up.  This
920  * function updates our state and do the necessary notifications.
921  * Also notifies our clients that the neighbour is now officially
922  * gone.
923  *
924  * @param n the neighbour list entry for the peer
925  * @param check should we just check if all plugins
926  *        disconnected or must we ask all plugins to
927  *        disconnect?
928  */
929 static void disconnect_neighbour (struct NeighbourList *n, int check);
930
931 /**
932  * Check the ready list for the given neighbour and if a plugin is
933  * ready for transmission (and if we have a message), do so!
934  *
935  * @param neighbour target peer for which to transmit
936  */
937 static void try_transmission_to_peer (struct NeighbourList *n);
938
939
940 struct ATS_info * ats_init ();
941
942 void ats_shutdown ( );
943
944 void ats_notify_peer_connect (
945                 const struct GNUNET_PeerIdentity *peer,
946                 const struct GNUNET_TRANSPORT_ATS_Information *ats_data);
947
948 void ats_notify_peer_disconnect (
949                 const struct GNUNET_PeerIdentity *peer);
950
951 void ats_notify_ats_data (
952                 const struct GNUNET_PeerIdentity *peer,
953                 const struct GNUNET_TRANSPORT_ATS_Information *ats_data);
954
955 struct ForeignAddressList * ats_get_preferred_address (
956                 struct NeighbourList *n);
957
958 /**
959  * Find an entry in the neighbour list for a particular peer.
960  *
961  * @return NULL if not found.
962  */
963 static struct NeighbourList *
964 find_neighbour (const struct GNUNET_PeerIdentity *key)
965 {
966   struct NeighbourList *head = neighbours;
967
968   while ((head != NULL) &&
969         (0 != memcmp (key, &head->id, sizeof (struct GNUNET_PeerIdentity))))
970     head = head->next;
971   return head;
972 }
973
974
975 /**
976  * Find an entry in the transport list for a particular transport.
977  *
978  * @return NULL if not found.
979  */
980 static struct TransportPlugin *
981 find_transport (const char *short_name)
982 {
983   struct TransportPlugin *head = plugins;
984   while ((head != NULL) && (0 != strcmp (short_name, head->short_name)))
985     head = head->next;
986   return head;
987 }
988
989 /**
990  * Is a particular peer blacklisted for a particular transport?
991  *
992  * @param peer the peer to check for
993  * @param plugin the plugin used to connect to the peer
994  *
995  * @return GNUNET_YES if the peer is blacklisted, GNUNET_NO if not
996  */
997 static int
998 is_blacklisted (const struct GNUNET_PeerIdentity *peer, struct TransportPlugin *plugin)
999 {
1000
1001   if (plugin->blacklist != NULL)
1002     {
1003       if (GNUNET_CONTAINER_multihashmap_contains (plugin->blacklist, &peer->hashPubKey) == GNUNET_YES)
1004         {
1005 #if DEBUG_BLACKLIST
1006           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1007                       "Peer `%s:%s' is blacklisted!\n",
1008                       plugin->short_name, GNUNET_i2s (peer));
1009 #endif
1010           if (stats != NULL)
1011             GNUNET_STATISTICS_update (stats, "# blacklisted peers refused", 1, GNUNET_NO);
1012           return GNUNET_YES;
1013         }
1014     }
1015
1016   return GNUNET_NO;
1017 }
1018
1019
1020 static void
1021 add_peer_to_blacklist (struct GNUNET_PeerIdentity *peer, char *transport_name)
1022 {
1023   struct TransportPlugin *plugin;
1024
1025   plugin = find_transport(transport_name);
1026   if (plugin == NULL) /* Nothing to do */
1027     return;
1028   if (plugin->blacklist == NULL)
1029     plugin->blacklist = GNUNET_CONTAINER_multihashmap_create(TRANSPORT_BLACKLIST_HT_SIZE);
1030   GNUNET_assert(plugin->blacklist != NULL);
1031   GNUNET_CONTAINER_multihashmap_put(plugin->blacklist, &peer->hashPubKey,
1032                                     NULL,
1033                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
1034 }
1035
1036
1037 /**
1038  * Read the blacklist file, containing transport:peer entries.
1039  * Provided the transport is loaded, set up hashmap with these
1040  * entries to blacklist peers by transport.
1041  *
1042  */
1043 static void
1044 read_blacklist_file (const struct GNUNET_CONFIGURATION_Handle *cfg)
1045 {
1046   char *fn;
1047   char *data;
1048   size_t pos;
1049   size_t colon_pos;
1050   int tsize;
1051   struct GNUNET_PeerIdentity pid;
1052   struct stat frstat;
1053   struct GNUNET_CRYPTO_HashAsciiEncoded enc;
1054   unsigned int entries_found;
1055   char *transport_name;
1056
1057   if (GNUNET_OK !=
1058       GNUNET_CONFIGURATION_get_value_filename (cfg,
1059                                                "TRANSPORT",
1060                                                "BLACKLIST_FILE",
1061                                                &fn))
1062     {
1063 #if DEBUG_TRANSPORT
1064       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1065                   "Option `%s' in section `%s' not specified!\n",
1066                   "BLACKLIST_FILE",
1067                   "TRANSPORT");
1068 #endif
1069       return;
1070     }
1071   if (GNUNET_OK != GNUNET_DISK_file_test (fn))
1072     GNUNET_DISK_fn_write (fn, NULL, 0, GNUNET_DISK_PERM_USER_READ
1073         | GNUNET_DISK_PERM_USER_WRITE);
1074   if (0 != STAT (fn, &frstat))
1075     {
1076       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1077                   _("Could not read blacklist file `%s'\n"), fn);
1078       GNUNET_free (fn);
1079       return;
1080     }
1081   if (frstat.st_size == 0)
1082     {
1083 #if DEBUG_TRANSPORT
1084       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1085                   _("Blacklist file `%s' is empty.\n"),
1086                   fn);
1087 #endif
1088       GNUNET_free (fn);
1089       return;
1090     }
1091   /* FIXME: use mmap */
1092   data = GNUNET_malloc_large (frstat.st_size);
1093   GNUNET_assert(data != NULL);
1094   if (frstat.st_size !=
1095       GNUNET_DISK_fn_read (fn, data, frstat.st_size))
1096     {
1097       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1098                   _("Failed to read blacklist from `%s'\n"), fn);
1099       GNUNET_free (fn);
1100       GNUNET_free (data);
1101       return;
1102     }
1103   entries_found = 0;
1104   pos = 0;
1105   while ((pos < frstat.st_size) && isspace ( (unsigned char) data[pos]))
1106     pos++;
1107   while ((frstat.st_size >= sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)) &&
1108          (pos <= frstat.st_size - sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)))
1109     {
1110       colon_pos = pos;
1111       while ((colon_pos < frstat.st_size) && (data[colon_pos] != ':') && !isspace ( (unsigned char) data[colon_pos]))
1112         colon_pos++;
1113
1114       if (colon_pos >= frstat.st_size)
1115         {
1116           GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1117                       _("Syntax error in blacklist file at offset %llu, giving up!\n"),
1118                       (unsigned long long) colon_pos);
1119           GNUNET_free (fn);
1120           GNUNET_free (data);
1121           return;
1122         }
1123
1124       if (isspace( (unsigned char) data[colon_pos]))
1125       {
1126         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1127                     _("Syntax error in blacklist file at offset %llu, skipping bytes.\n"),
1128                     (unsigned long long) colon_pos);
1129         pos = colon_pos;
1130         while ((pos < frstat.st_size) && isspace ( (unsigned char) data[pos]))
1131           pos++;
1132         continue;
1133       }
1134       tsize = colon_pos - pos;
1135       if ((pos >= frstat.st_size) || (pos + tsize >= frstat.st_size) || (tsize == 0))
1136         {
1137           GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1138                       _("Syntax error in blacklist file at offset %llu, giving up!\n"),
1139                       (unsigned long long) colon_pos);
1140           GNUNET_free (fn);
1141           GNUNET_free (data);
1142           return;
1143         }
1144
1145       if (tsize < 1)
1146         continue;
1147
1148       transport_name = GNUNET_malloc(tsize + 1);
1149       memcpy(transport_name, &data[pos], tsize);
1150       pos = colon_pos + 1;
1151 #if DEBUG_TRANSPORT
1152       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1153                   "Read transport name %s in blacklist file.\n",
1154                   transport_name);
1155 #endif
1156       memcpy (&enc, &data[pos], sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded));
1157       if (!isspace ( (unsigned char) enc.encoding[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1]))
1158         {
1159           GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1160                       _("Syntax error in blacklist file at offset %llu, skipping bytes.\n"),
1161                       (unsigned long long) pos);
1162           pos++;
1163           while ((pos < frstat.st_size) && (!isspace ( (unsigned char) data[pos])))
1164             pos++;
1165           GNUNET_free_non_null(transport_name);
1166           continue;
1167         }
1168       enc.encoding[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] = '\0';
1169       if (GNUNET_OK != GNUNET_CRYPTO_hash_from_string ((char *) &enc, &pid.hashPubKey))
1170         {
1171           GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1172                       _("Syntax error in blacklist file at offset %llu, skipping bytes `%s'.\n"),
1173                       (unsigned long long) pos,
1174                       &enc);
1175         }
1176       else
1177         {
1178           if (0 != memcmp (&pid,
1179                            &my_identity,
1180                            sizeof (struct GNUNET_PeerIdentity)))
1181             {
1182               entries_found++;
1183               add_peer_to_blacklist (&pid,
1184                                      transport_name);
1185             }
1186           else
1187             {
1188               GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1189                           _("Found myself `%s' in blacklist (useless, ignored)\n"),
1190                           GNUNET_i2s (&pid));
1191             }
1192         }
1193       pos = pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded);
1194       GNUNET_free_non_null(transport_name);
1195       while ((pos < frstat.st_size) && isspace ( (unsigned char) data[pos]))
1196         pos++;
1197     }
1198   GNUNET_STATISTICS_update (stats, "# Transport entries blacklisted", entries_found, GNUNET_NO);
1199   GNUNET_free (data);
1200   GNUNET_free (fn);
1201 }
1202
1203
1204 /**
1205  * Function called to notify a client about the socket being ready to
1206  * queue more data.  "buf" will be NULL and "size" zero if the socket
1207  * was closed for writing in the meantime.
1208  *
1209  * @param cls closure
1210  * @param size number of bytes available in buf
1211  * @param buf where the callee should write the message
1212  * @return number of bytes written to buf
1213  */
1214 static size_t
1215 transmit_to_client_callback (void *cls, size_t size, void *buf)
1216 {
1217   struct TransportClient *client = cls;
1218   struct ClientMessageQueueEntry *q;
1219   uint16_t msize;
1220   size_t tsize;
1221   const struct GNUNET_MessageHeader *msg;
1222   char *cbuf;
1223
1224   client->th = NULL;
1225   if (buf == NULL)
1226     {
1227 #if DEBUG_TRANSPORT
1228       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1229                   "Transmission to client failed, closing connection.\n");
1230 #endif
1231       /* fatal error with client, free message queue! */
1232       while (NULL != (q = client->message_queue_head))
1233         {
1234           GNUNET_STATISTICS_update (stats,
1235                                     gettext_noop ("# bytes discarded (could not transmit to client)"),
1236                                     ntohs (((const struct GNUNET_MessageHeader*)&q[1])->size),
1237                                     GNUNET_NO);
1238           GNUNET_CONTAINER_DLL_remove (client->message_queue_head,
1239                                        client->message_queue_tail,
1240                                        q);
1241           GNUNET_free (q);
1242         }
1243       client->message_count = 0;
1244       return 0;
1245     }
1246   cbuf = buf;
1247   tsize = 0;
1248   while (NULL != (q = client->message_queue_head))
1249     {
1250       msg = (const struct GNUNET_MessageHeader *) &q[1];
1251       msize = ntohs (msg->size);
1252       if (msize + tsize > size)
1253         break;
1254 #if DEBUG_TRANSPORT
1255       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1256                   "Transmitting message of type %u to client.\n",
1257                   ntohs (msg->type));
1258 #endif
1259       GNUNET_CONTAINER_DLL_remove (client->message_queue_head,
1260                                    client->message_queue_tail,
1261                                    q);
1262       memcpy (&cbuf[tsize], msg, msize);
1263       tsize += msize;
1264       GNUNET_free (q);
1265       client->message_count--;
1266     }
1267   if (NULL != q)
1268     {
1269       GNUNET_assert (msize >= sizeof (struct GNUNET_MessageHeader));
1270       client->th = GNUNET_SERVER_notify_transmit_ready (client->client,
1271                                                         msize,
1272                                                         GNUNET_TIME_UNIT_FOREVER_REL,
1273                                                         &transmit_to_client_callback,
1274                                                         client);
1275       GNUNET_assert (client->th != NULL);
1276     }
1277   return tsize;
1278 }
1279
1280
1281 /**
1282  * Convert an address to a string.
1283  *
1284  * @param plugin name of the plugin responsible for the address
1285  * @param addr binary address
1286  * @param addr_len number of bytes in addr
1287  * @return NULL on error, otherwise address string
1288  */
1289 static const char*
1290 a2s (const char *plugin,
1291      const void *addr,
1292      uint16_t addr_len)
1293 {
1294   struct TransportPlugin *p;
1295
1296   if (plugin == NULL)
1297     return NULL;
1298   p = find_transport (plugin);
1299   if (p == NULL)
1300     return NULL;
1301   return p->api->address_to_string (p->api->cls,
1302                                     addr,
1303                                     addr_len);
1304 }
1305
1306
1307 /**
1308  * Mark the given FAL entry as 'connected' (and hence preferred for
1309  * sending); also mark all others for the same peer as 'not connected'
1310  * (since only one can be preferred).
1311  *
1312  * @param fal address to set to 'connected'
1313  */
1314 static void
1315 mark_address_connected (struct ForeignAddressList *fal)
1316 {
1317   struct ForeignAddressList *pos;
1318   int cnt;
1319
1320   GNUNET_assert (GNUNET_YES == fal->validated);
1321   if (fal->connected == GNUNET_YES)
1322     return; /* nothing to do */
1323   cnt = GNUNET_YES;
1324   pos = fal->ready_list->addresses;
1325   while (pos != NULL)
1326     {
1327       if (GNUNET_YES == pos->connected)
1328         {
1329 #if DEBUG_TRANSPORT
1330           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1331                       "Marking address `%s' as no longer connected (due to connect on other address)\n",
1332                       a2s (pos->ready_list->plugin->short_name,
1333                            pos->addr,
1334                            pos->addrlen));
1335 #endif
1336           GNUNET_break (cnt == GNUNET_YES);
1337           cnt = GNUNET_NO;
1338           pos->connected = GNUNET_NO;
1339           GNUNET_STATISTICS_update (stats,
1340                                     gettext_noop ("# connected addresses"),
1341                                     -1,
1342                                     GNUNET_NO);
1343         }
1344       pos = pos->next;
1345     }
1346   fal->connected = GNUNET_YES;
1347   if (GNUNET_YES == cnt)
1348     {
1349       GNUNET_STATISTICS_update (stats,
1350                                 gettext_noop ("# connected addresses"),
1351                                 1,
1352                                 GNUNET_NO);
1353     }
1354 }
1355
1356
1357 /**
1358  * Send the specified message to the specified client.  Since multiple
1359  * messages may be pending for the same client at a time, this code
1360  * makes sure that no message is lost.
1361  *
1362  * @param client client to transmit the message to
1363  * @param msg the message to send
1364  * @param may_drop can this message be dropped if the
1365  *        message queue for this client is getting far too large?
1366  */
1367 static void
1368 transmit_to_client (struct TransportClient *client,
1369                     const struct GNUNET_MessageHeader *msg, int may_drop)
1370 {
1371   struct ClientMessageQueueEntry *q;
1372   uint16_t msize;
1373
1374   if ((client->message_count >= MAX_PENDING) && (GNUNET_YES == may_drop))
1375     {
1376       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1377                   _
1378                   ("Dropping message of type %u and size %u, have %u messages pending (%u is the soft limit)\n"),
1379                   ntohs (msg->type),
1380                   ntohs (msg->size),
1381                   client->message_count,
1382                   MAX_PENDING);
1383       GNUNET_STATISTICS_update (stats,
1384                                 gettext_noop ("# messages dropped due to slow client"),
1385                                 1,
1386                                 GNUNET_NO);
1387       return;
1388     }
1389   msize = ntohs (msg->size);
1390   GNUNET_assert (msize >= sizeof (struct GNUNET_MessageHeader));
1391   q = GNUNET_malloc (sizeof (struct ClientMessageQueueEntry) + msize);
1392   memcpy (&q[1], msg, msize);
1393   GNUNET_CONTAINER_DLL_insert_after (client->message_queue_head,
1394                                      client->message_queue_tail,
1395                                      client->message_queue_tail,
1396                                      q);                                
1397   client->message_count++;
1398   if (client->th == NULL)
1399     {
1400       client->th = GNUNET_SERVER_notify_transmit_ready (client->client,
1401                                                         msize,
1402                                                         GNUNET_TIME_UNIT_FOREVER_REL,
1403                                                         &transmit_to_client_callback,
1404                                                         client);
1405       GNUNET_assert (client->th != NULL);
1406     }
1407 }
1408
1409
1410 /**
1411  * Transmit a 'SEND_OK' notification to the given client for the
1412  * given neighbour.
1413  *
1414  * @param client who to notify
1415  * @param n neighbour to notify about, can be NULL (on failure)
1416  * @param target target of the transmission
1417  * @param result status code for the transmission request
1418  */
1419 static void
1420 transmit_send_ok (struct TransportClient *client,
1421                   struct NeighbourList *n,
1422                   const struct GNUNET_PeerIdentity *target,
1423                   int result)
1424 {
1425   struct SendOkMessage send_ok_msg;
1426
1427   send_ok_msg.header.size = htons (sizeof (send_ok_msg));
1428   send_ok_msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK);
1429   send_ok_msg.success = htonl (result);
1430   if (n != NULL)
1431     send_ok_msg.latency = GNUNET_TIME_relative_hton (n->latency);
1432   else
1433     send_ok_msg.latency = GNUNET_TIME_relative_hton (GNUNET_TIME_UNIT_FOREVER_REL);
1434   send_ok_msg.peer = *target;
1435   transmit_to_client (client, &send_ok_msg.header, GNUNET_NO);
1436 }
1437
1438
1439 /**
1440  * Function called by the GNUNET_TRANSPORT_TransmitFunction
1441  * upon "completion" of a send request.  This tells the API
1442  * that it is now legal to send another message to the given
1443  * peer.
1444  *
1445  * @param cls closure, identifies the entry on the
1446  *            message queue that was transmitted and the
1447  *            client responsible for queuing the message
1448  * @param target the peer receiving the message
1449  * @param result GNUNET_OK on success, if the transmission
1450  *           failed, we should not tell the client to transmit
1451  *           more messages
1452  */
1453 static void
1454 transmit_send_continuation (void *cls,
1455                             const struct GNUNET_PeerIdentity *target,
1456                             int result)
1457 {
1458   struct MessageQueue *mq = cls;
1459   struct NeighbourList *n;
1460
1461   GNUNET_STATISTICS_update (stats,
1462                             gettext_noop ("# bytes pending with plugins"),
1463                             - (int64_t) mq->message_buf_size,
1464                             GNUNET_NO);
1465   if (result == GNUNET_OK)
1466     {
1467       GNUNET_STATISTICS_update (stats,
1468                                 gettext_noop ("# bytes successfully transmitted by plugins"),
1469                                 mq->message_buf_size,
1470                                 GNUNET_NO);
1471     }
1472   else
1473     {
1474       GNUNET_STATISTICS_update (stats,
1475                                 gettext_noop ("# bytes with transmission failure by plugins"),
1476                                 mq->message_buf_size,
1477                                 GNUNET_NO);
1478     }
1479   if (mq->specific_address != NULL)
1480     {
1481       if (result == GNUNET_OK)
1482         {
1483           mq->specific_address->timeout =
1484             GNUNET_TIME_relative_to_absolute
1485             (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
1486           if (mq->specific_address->validated == GNUNET_YES)
1487             mark_address_connected (mq->specific_address);
1488         }
1489       else
1490         {
1491           if (mq->specific_address->connected != GNUNET_NO)
1492             {
1493 #if DEBUG_TRANSPORT
1494               GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1495                           "Marking address `%s' as no longer connected (due to transmission problem)\n",
1496                           a2s (mq->specific_address->ready_list->plugin->short_name,
1497                                mq->specific_address->addr,
1498                                mq->specific_address->addrlen));
1499 #endif
1500               GNUNET_STATISTICS_update (stats,
1501                                         gettext_noop ("# connected addresses"),
1502                                         -1,
1503                                         GNUNET_NO);
1504               mq->specific_address->connected = GNUNET_NO;
1505             }
1506         }
1507       if (! mq->internal_msg)
1508         mq->specific_address->in_transmit = GNUNET_NO;
1509     }
1510   n = find_neighbour(&mq->neighbour_id);
1511   if (mq->client != NULL)
1512     transmit_send_ok (mq->client, n, target, result);
1513   GNUNET_free (mq);
1514   if (n != NULL)
1515     try_transmission_to_peer (n);
1516 }
1517
1518
1519 /**
1520  * Find an address in any of the available transports for
1521  * the given neighbour that would be good for message
1522  * transmission.  This is essentially the transport selection
1523  * routine.
1524  *
1525  * @param neighbour for whom to select an address
1526  * @return selected address, NULL if we have none
1527  */
1528 struct ForeignAddressList *
1529 find_ready_address(struct NeighbourList *neighbour)
1530 {
1531   struct ReadyList *head = neighbour->plugins;
1532   struct ForeignAddressList *addresses;
1533   struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
1534   struct ForeignAddressList *best_address;
1535
1536   /* Hack to prefer unix domain sockets */
1537   struct ForeignAddressList *unix_address = NULL;
1538
1539   best_address = NULL;
1540   while (head != NULL)
1541     {
1542       addresses = head->addresses;
1543       while (addresses != NULL)
1544         {
1545           if ( (addresses->timeout.abs_value < now.abs_value) &&
1546                (addresses->connected == GNUNET_YES) )
1547             {
1548 #if DEBUG_TRANSPORT
1549               GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1550                           "Marking long-time inactive connection to `%4s' as down.\n",
1551                           GNUNET_i2s (&neighbour->id));
1552 #endif
1553               GNUNET_STATISTICS_update (stats,
1554                                         gettext_noop ("# connected addresses"),
1555                                         -1,
1556                                         GNUNET_NO);
1557               addresses->connected = GNUNET_NO;
1558             }
1559           addresses = addresses->next;
1560         }
1561
1562       addresses = head->addresses;
1563       while (addresses != NULL)
1564         {
1565 #if DEBUG_TRANSPORT > 1
1566           if (addresses->addr != NULL)
1567             GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1568                         "Have address `%s' for peer `%4s' (status: %d, %d, %d, %u, %llums, %u)\n",
1569                         a2s (head->plugin->short_name,
1570                              addresses->addr,
1571                              addresses->addrlen),
1572                         GNUNET_i2s (&neighbour->id),
1573                         addresses->connected,
1574                         addresses->in_transmit,
1575                         addresses->validated,
1576                         addresses->connect_attempts,
1577                         (unsigned long long) addresses->timeout.abs_value,
1578                         (unsigned int) addresses->distance);
1579 #endif
1580                  if (0==strcmp(head->plugin->short_name,"unix"))
1581                  {
1582                          if ((unix_address == NULL) || ((unix_address != NULL) &&
1583                                  (addresses->latency.rel_value < unix_address->latency.rel_value)))
1584                                 unix_address = addresses;
1585                  }
1586           if ( ( (best_address == NULL) ||
1587                  (addresses->connected == GNUNET_YES) ||
1588                  (best_address->connected == GNUNET_NO) ) &&
1589                (addresses->in_transmit == GNUNET_NO) &&
1590                ( (best_address == NULL) ||
1591                  (addresses->latency.rel_value < best_address->latency.rel_value)) )
1592             best_address = addresses;
1593           /* FIXME: also give lower-latency addresses that are not
1594              connected a chance some times... */
1595           addresses = addresses->next;
1596         }
1597       if (unix_address != NULL)
1598           break;
1599       head = head->next;
1600     }
1601   if (unix_address != NULL)
1602   {
1603           best_address = unix_address;
1604 #if DEBUG_TRANSPORT
1605           GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Found unix address, forced this address\n");
1606 #endif
1607   }
1608   if (best_address != NULL)
1609     {
1610 #if DEBUG_TRANSPORT
1611
1612           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1613                   "Best address found (`%s') has latency of %llu ms.\n",
1614                   (best_address->addrlen > 0)
1615                   ? a2s (best_address->ready_list->plugin->short_name,
1616                        best_address->addr,
1617                        best_address->addrlen)
1618                   : "<inbound>",
1619                   best_address->latency.rel_value);
1620 #endif
1621     }
1622   else
1623     {
1624       GNUNET_STATISTICS_update (stats,
1625                                 gettext_noop ("# transmission attempts failed (no address)"),
1626                                 1,
1627                                 GNUNET_NO);
1628     }
1629
1630   return best_address;
1631
1632 }
1633
1634
1635 /**
1636  * We should re-try transmitting to the given peer,
1637  * hopefully we've learned something in the meantime.
1638  */
1639 static void
1640 retry_transmission_task (void *cls,
1641                          const struct GNUNET_SCHEDULER_TaskContext *tc)
1642 {
1643   struct NeighbourList *n = cls;
1644
1645   n->retry_task = GNUNET_SCHEDULER_NO_TASK;
1646   try_transmission_to_peer (n);
1647 }
1648
1649
1650 /**
1651  * Check the ready list for the given neighbour and if a plugin is
1652  * ready for transmission (and if we have a message), do so!
1653  *
1654  * @param neighbour target peer for which to transmit
1655  */
1656 static void
1657 try_transmission_to_peer (struct NeighbourList *n)
1658 {
1659   struct ReadyList *rl;
1660   struct MessageQueue *mq;
1661   struct GNUNET_TIME_Relative timeout;
1662   ssize_t ret;
1663   int force_address;
1664
1665   if (n->messages_head == NULL)
1666     {
1667 #if DEBUG_TRANSPORT
1668       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1669                   "Transmission queue for `%4s' is empty\n",
1670                   GNUNET_i2s (&neighbour->id));
1671 #endif
1672       return;                     /* nothing to do */
1673     }
1674   rl = NULL;
1675   mq = n->messages_head;
1676   force_address = GNUNET_YES;
1677   if (mq->specific_address == NULL)
1678     {
1679           /* TODO: ADD ATS */
1680       mq->specific_address = ats_get_preferred_address(n);
1681       GNUNET_STATISTICS_update (stats,
1682                                 gettext_noop ("# transport selected peer address freely"),
1683                                 1,
1684                                 GNUNET_NO);
1685       force_address = GNUNET_NO;
1686     }
1687   if (mq->specific_address == NULL)
1688     {
1689       GNUNET_STATISTICS_update (stats,
1690                                 gettext_noop ("# transport failed to selected peer address"),
1691                                 1,
1692                                 GNUNET_NO);
1693       timeout = GNUNET_TIME_absolute_get_remaining (mq->timeout);
1694       if (timeout.rel_value == 0)
1695         {
1696 #if DEBUG_TRANSPORT
1697           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1698                       "No destination address available to transmit message of size %u to peer `%4s'\n",
1699                       mq->message_buf_size,
1700                       GNUNET_i2s (&mq->neighbour_id));
1701 #endif
1702           GNUNET_STATISTICS_update (stats,
1703                                     gettext_noop ("# bytes in message queue for other peers"),
1704                                     - (int64_t) mq->message_buf_size,
1705                                     GNUNET_NO);
1706           GNUNET_STATISTICS_update (stats,
1707                                     gettext_noop ("# bytes discarded (no destination address available)"),
1708                                     mq->message_buf_size,
1709                                     GNUNET_NO);
1710           if (mq->client != NULL)
1711             transmit_send_ok (mq->client, n, &n->id, GNUNET_NO);
1712           GNUNET_CONTAINER_DLL_remove (n->messages_head,
1713                                        n->messages_tail,
1714                                        mq);
1715           GNUNET_free (mq);
1716           return;               /* nobody ready */
1717         }
1718       GNUNET_STATISTICS_update (stats,
1719                                 gettext_noop ("# message delivery deferred (no address)"),
1720                                 1,
1721                                 GNUNET_NO);
1722       if (n->retry_task != GNUNET_SCHEDULER_NO_TASK)
1723         GNUNET_SCHEDULER_cancel (n->retry_task);
1724       n->retry_task = GNUNET_SCHEDULER_add_delayed (timeout,
1725                                                             &retry_transmission_task,
1726                                                             n);
1727 #if DEBUG_TRANSPORT
1728       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1729                   "No validated destination address available to transmit message of size %u to peer `%4s', will wait %llums to find an address.\n",
1730                   mq->message_buf_size,
1731                   GNUNET_i2s (&mq->neighbour_id),
1732                   timeout.rel_value);
1733 #endif
1734       /* FIXME: might want to trigger peerinfo lookup here
1735          (unless that's already pending...) */
1736       return;
1737     }
1738   GNUNET_CONTAINER_DLL_remove (n->messages_head,
1739                                n->messages_tail,
1740                                mq);
1741   if (mq->specific_address->connected == GNUNET_NO)
1742     mq->specific_address->connect_attempts++;
1743   rl = mq->specific_address->ready_list;
1744   mq->plugin = rl->plugin;
1745   if (!mq->internal_msg)
1746     mq->specific_address->in_transmit = GNUNET_YES;
1747 #if DEBUG_TRANSPORT
1748   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1749               "Sending message of size %u for `%4s' to `%s' via plugin `%s'\n",
1750               mq->message_buf_size,
1751               GNUNET_i2s (&neighbour->id),
1752               (mq->specific_address->addr != NULL)
1753               ? a2s (mq->plugin->short_name,
1754                      mq->specific_address->addr,
1755                      mq->specific_address->addrlen)
1756               : "<inbound>",
1757               rl->plugin->short_name);
1758 #endif
1759   GNUNET_STATISTICS_update (stats,
1760                             gettext_noop ("# bytes in message queue for other peers"),
1761                             - (int64_t) mq->message_buf_size,
1762                             GNUNET_NO);
1763   GNUNET_STATISTICS_update (stats,
1764                             gettext_noop ("# bytes pending with plugins"),
1765                             mq->message_buf_size,
1766                             GNUNET_NO);
1767   ret = rl->plugin->api->send (rl->plugin->api->cls,
1768                                &mq->neighbour_id,
1769                                mq->message_buf,
1770                                mq->message_buf_size,
1771                                mq->priority,
1772                                GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
1773                                mq->specific_address->session,
1774                                mq->specific_address->addr,
1775                                mq->specific_address->addrlen,
1776                                force_address,
1777                                &transmit_send_continuation, mq);
1778   if (ret == -1)
1779     {
1780       /* failure, but 'send' would not call continuation in this case,
1781          so we need to do it here! */
1782       transmit_send_continuation (mq,
1783                                   &mq->neighbour_id,
1784                                   GNUNET_SYSERR);
1785     }
1786 }
1787
1788
1789 /**
1790  * Send the specified message to the specified peer.
1791  *
1792  * @param client source of the transmission request (can be NULL)
1793  * @param peer_address ForeignAddressList where we should send this message
1794  * @param priority how important is the message
1795  * @param timeout how long do we have to transmit?
1796  * @param message_buf message(s) to send GNUNET_MessageHeader(s)
1797  * @param message_buf_size total size of all messages in message_buf
1798  * @param is_internal is this an internal message; these are pre-pended and
1799  *                    also do not count for plugins being "ready" to transmit
1800  * @param neighbour handle to the neighbour for transmission
1801  */
1802 static void
1803 transmit_to_peer (struct TransportClient *client,
1804                   struct ForeignAddressList *peer_address,
1805                   unsigned int priority,
1806                   struct GNUNET_TIME_Relative timeout,
1807                   const char *message_buf,
1808                   size_t message_buf_size,
1809                   int is_internal, struct NeighbourList *neighbour)
1810 {
1811   struct MessageQueue *mq;
1812
1813 #if EXTRA_CHECKS
1814   if (client != NULL)
1815     {
1816       /* check for duplicate submission */
1817       mq = neighbour->messages_head;
1818       while (NULL != mq)
1819         {
1820           if (mq->client == client)
1821             {
1822               /* client transmitted to same peer twice
1823                  before getting SEND_OK! */
1824               GNUNET_break (0);
1825               return;
1826             }
1827           mq = mq->next;
1828         }
1829     }
1830 #endif
1831   GNUNET_STATISTICS_update (stats,
1832                             gettext_noop ("# bytes in message queue for other peers"),
1833                             message_buf_size,
1834                             GNUNET_NO);
1835   mq = GNUNET_malloc (sizeof (struct MessageQueue) + message_buf_size);
1836   mq->specific_address = peer_address;
1837   mq->client = client;
1838   /* FIXME: this memcpy can be up to 7% of our total runtime! */
1839   memcpy (&mq[1], message_buf, message_buf_size);
1840   mq->message_buf = (const char*) &mq[1];
1841   mq->message_buf_size = message_buf_size;
1842   memcpy(&mq->neighbour_id, &neighbour->id, sizeof(struct GNUNET_PeerIdentity));
1843   mq->internal_msg = is_internal;
1844   mq->priority = priority;
1845   mq->timeout = GNUNET_TIME_relative_to_absolute (timeout);
1846   if (is_internal)
1847     GNUNET_CONTAINER_DLL_insert (neighbour->messages_head,
1848                                  neighbour->messages_tail,
1849                                  mq);
1850   else
1851     GNUNET_CONTAINER_DLL_insert_after (neighbour->messages_head,
1852                                        neighbour->messages_tail,
1853                                        neighbour->messages_tail,
1854                                        mq);
1855   try_transmission_to_peer (neighbour);
1856 }
1857
1858
1859 /**
1860  * FIXME: document.
1861  */
1862 struct GeneratorContext
1863 {
1864   struct TransportPlugin *plug_pos;
1865   struct OwnAddressList *addr_pos;
1866   struct GNUNET_TIME_Absolute expiration;
1867 };
1868
1869
1870 /**
1871  * FIXME: document.
1872  */
1873 static size_t
1874 address_generator (void *cls, size_t max, void *buf)
1875 {
1876   struct GeneratorContext *gc = cls;
1877   size_t ret;
1878
1879   while ((gc->addr_pos == NULL) && (gc->plug_pos != NULL))
1880     {
1881       gc->plug_pos = gc->plug_pos->next;
1882       gc->addr_pos = (gc->plug_pos != NULL) ? gc->plug_pos->addresses : NULL;
1883     }
1884   if (NULL == gc->plug_pos)
1885     {
1886
1887       return 0;
1888     }
1889   ret = GNUNET_HELLO_add_address (gc->plug_pos->short_name,
1890                                   gc->expiration,
1891                                   &gc->addr_pos[1],
1892                                   gc->addr_pos->addrlen, buf, max);
1893   gc->addr_pos = gc->addr_pos->next;
1894   return ret;
1895 }
1896
1897
1898 /**
1899  * Construct our HELLO message from all of the addresses of
1900  * all of the transports.
1901  */
1902 static void
1903 refresh_hello ()
1904 {
1905   struct GNUNET_HELLO_Message *hello;
1906   struct TransportClient *cpos;
1907   struct NeighbourList *npos;
1908   struct GeneratorContext gc;
1909
1910   gc.plug_pos = plugins;
1911   gc.addr_pos = plugins != NULL ? plugins->addresses : NULL;
1912   gc.expiration = GNUNET_TIME_relative_to_absolute (HELLO_ADDRESS_EXPIRATION);
1913   hello = GNUNET_HELLO_create (&my_public_key, &address_generator, &gc);
1914 #if DEBUG_TRANSPORT
1915   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
1916               "Refreshed my `%s', new size is %d\n", "HELLO", GNUNET_HELLO_size(hello));
1917 #endif
1918   GNUNET_STATISTICS_update (stats,
1919                             gettext_noop ("# refreshed my HELLO"),
1920                             1,
1921                             GNUNET_NO);
1922   cpos = clients;
1923   while (cpos != NULL)
1924     {
1925       transmit_to_client (cpos,
1926                           (const struct GNUNET_MessageHeader *) hello,
1927                           GNUNET_NO);
1928       cpos = cpos->next;
1929     }
1930
1931   GNUNET_free_non_null (our_hello);
1932   our_hello = hello;
1933   GNUNET_PEERINFO_add_peer (peerinfo, our_hello);
1934   npos = neighbours;
1935   while (npos != NULL)
1936     {
1937 #if DEBUG_TRANSPORT
1938       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
1939                   "Transmitting updated `%s' to neighbour `%4s'\n",
1940                   "HELLO", GNUNET_i2s (&npos->id));
1941 #endif
1942       GNUNET_STATISTICS_update (stats,
1943                                 gettext_noop ("# transmitted my HELLO to other peers"),
1944                                 1,
1945                                 GNUNET_NO);
1946       transmit_to_peer (NULL, NULL, 0,
1947                         HELLO_ADDRESS_EXPIRATION,
1948                         (const char *) our_hello,
1949                         GNUNET_HELLO_size(our_hello),
1950                         GNUNET_NO, npos);
1951       npos = npos->next;
1952     }
1953 }
1954
1955
1956 /**
1957  * Task used to clean up expired addresses for a plugin.
1958  *
1959  * @param cls closure
1960  * @param tc context
1961  */
1962 static void
1963 expire_address_task (void *cls,
1964                      const struct GNUNET_SCHEDULER_TaskContext *tc);
1965
1966
1967 /**
1968  * Update the list of addresses for this plugin,
1969  * expiring those that are past their expiration date.
1970  *
1971  * @param plugin addresses of which plugin should be recomputed?
1972  * @param fresh set to GNUNET_YES if a new address was added
1973  *        and we need to regenerate the HELLO even if nobody
1974  *        expired
1975  */
1976 static void
1977 update_addresses (struct TransportPlugin *plugin, 
1978                   int fresh)
1979 {
1980   static struct GNUNET_TIME_Absolute last_update;
1981   struct GNUNET_TIME_Relative min_remaining;
1982   struct GNUNET_TIME_Relative remaining;
1983   struct GNUNET_TIME_Absolute now;
1984   struct OwnAddressList *pos;
1985   struct OwnAddressList *prev;
1986   struct OwnAddressList *next;
1987   int expired;
1988
1989   if (plugin->address_update_task != GNUNET_SCHEDULER_NO_TASK)
1990     GNUNET_SCHEDULER_cancel (plugin->address_update_task);
1991   plugin->address_update_task = GNUNET_SCHEDULER_NO_TASK;
1992   now = GNUNET_TIME_absolute_get ();
1993   min_remaining = GNUNET_TIME_UNIT_FOREVER_REL;
1994   expired = (GNUNET_TIME_absolute_get_duration (last_update).rel_value > (HELLO_ADDRESS_EXPIRATION.rel_value / 4));
1995   prev = NULL;
1996   pos = plugin->addresses;
1997   while (pos != NULL)
1998     {
1999       next = pos->next;
2000       if (pos->expires.abs_value < now.abs_value)
2001         {
2002           expired = GNUNET_YES;
2003           if (prev == NULL)
2004             plugin->addresses = pos->next;
2005           else
2006             prev->next = pos->next;
2007           GNUNET_free (pos);
2008         }
2009       else
2010         {
2011           remaining = GNUNET_TIME_absolute_get_remaining (pos->expires);
2012           if (remaining.rel_value < min_remaining.rel_value)
2013             min_remaining = remaining;
2014           prev = pos;
2015         }
2016       pos = next;
2017     }
2018
2019   if (expired || fresh)
2020     {
2021       last_update = now;
2022       refresh_hello ();
2023     }
2024   min_remaining = GNUNET_TIME_relative_min (min_remaining,
2025                                             GNUNET_TIME_relative_divide (HELLO_ADDRESS_EXPIRATION,
2026                                                                          2));
2027   plugin->address_update_task
2028     = GNUNET_SCHEDULER_add_delayed (min_remaining,
2029                                     &expire_address_task, plugin);
2030 }
2031
2032
2033 /**
2034  * Task used to clean up expired addresses for a plugin.
2035  *
2036  * @param cls closure
2037  * @param tc context
2038  */
2039 static void
2040 expire_address_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2041 {
2042   struct TransportPlugin *plugin = cls;
2043
2044   plugin->address_update_task = GNUNET_SCHEDULER_NO_TASK;
2045   if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
2046     update_addresses (plugin, GNUNET_NO);
2047 }
2048
2049
2050 /**
2051  * Iterator over hash map entries that NULLs the session of validation
2052  * entries that match the given session.
2053  *
2054  * @param cls closure (the 'struct Session*' to match against)
2055  * @param key current key code (peer ID, not used)
2056  * @param value value in the hash map ('struct ValidationEntry*')
2057  * @return GNUNET_YES (we should continue to iterate)
2058  */
2059 static int
2060 remove_session_validations (void *cls,
2061                             const GNUNET_HashCode * key,
2062                             void *value)
2063 {
2064   struct Session *session = cls;
2065   struct ValidationEntry *ve = value;
2066
2067   if (session == ve->session)
2068     ve->session = NULL;
2069   return GNUNET_YES;
2070 }
2071
2072
2073 /**
2074  * We've been disconnected from the other peer (for some
2075  * connection-oriented transport).  Either quickly
2076  * re-establish the connection or signal the disconnect
2077  * to the CORE.
2078  *
2079  * Only signal CORE level disconnect if ALL addresses
2080  * for the peer are exhausted.
2081  *
2082  * @param p overall plugin context
2083  * @param nl neighbour that was disconnected
2084  */
2085 static void
2086 try_fast_reconnect (struct TransportPlugin *p,
2087                     struct NeighbourList *nl)
2088 {
2089   /* FIXME-MW: fast reconnect / transport switching not implemented... */
2090   /* Note: the idea here is to hide problems with transports (or
2091      switching between plugins) from the core to eliminate the need to
2092      re-negotiate session keys and the like; OTOH, we should tell core
2093      quickly (much faster than timeout) `if a connection was lost and
2094      could not be re-established (i.e. other peer went down or is
2095      unable / refuses to communicate);
2096
2097      So we should consider:
2098      1) ideally: our own willingness / need to connect
2099      2) prior failures to connect to this peer (by plugin)
2100      3) ideally: reasons why other peer terminated (as far as knowable)
2101
2102      Most importantly, it must be POSSIBLE for another peer to terminate
2103      a connection for a while (without us instantly re-establishing it).
2104      Similarly, if another peer is gone we should quickly notify CORE.
2105      OTOH, if there was a minor glitch (i.e. crash of gnunet-service-transport
2106      on the other end), we should reconnect in such a way that BOTH CORE
2107      services never even notice.
2108      Furthermore, the same mechanism (or small variation) could be used
2109      to switch to a better-performing plugin (ATS).
2110
2111      Finally, this needs to be tested throughly... */                                                           
2112
2113   /*
2114    * GNUNET_NO in the call below makes transport disconnect the peer,
2115    * even if only a single address (out of say, six) went away.  This
2116    * function must be careful to ONLY disconnect if the peer is gone,
2117    * not just a specifi address.
2118    *
2119    * More specifically, half the places it was used had it WRONG.
2120    */
2121
2122   /* No reconnect, signal disconnect instead! */
2123   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2124             "Disconnecting peer `%4s', %s\n", GNUNET_i2s(&nl->id),
2125             "try_fast_reconnect");
2126   disconnect_neighbour (nl, GNUNET_YES);
2127 }
2128
2129
2130 /**
2131  * Function that will be called whenever the plugin internally
2132  * cleans up a session pointer and hence the service needs to
2133  * discard all of those sessions as well.  Plugins that do not
2134  * use sessions can simply omit calling this function and always
2135  * use NULL wherever a session pointer is needed.
2136  *
2137  * @param cls closure
2138  * @param peer which peer was the session for
2139  * @param session which session is being destoyed
2140  */
2141 static void
2142 plugin_env_session_end  (void *cls,
2143                          const struct GNUNET_PeerIdentity *peer,
2144                          struct Session *session)
2145 {
2146   struct TransportPlugin *p = cls;
2147   struct NeighbourList *nl;
2148   struct ReadyList *rl;
2149   struct ForeignAddressList *pos;
2150   struct ForeignAddressList *prev;
2151
2152   GNUNET_CONTAINER_multihashmap_iterate (validation_map,
2153                                          &remove_session_validations,
2154                                          session);
2155   nl = find_neighbour (peer);
2156   if (nl == NULL)
2157     return; /* was never marked as connected */
2158   rl = nl->plugins;
2159   while (rl != NULL)
2160     {
2161       if (rl->plugin == p)
2162         break;
2163       rl = rl->next;
2164     }
2165   if (rl == NULL)
2166     return; /* was never marked as connected */
2167   prev = NULL;
2168   pos = rl->addresses;
2169   while ( (pos != NULL) &&
2170           (pos->session != session) )
2171     {
2172       prev = pos;
2173       pos = pos->next;
2174     }
2175   if (pos == NULL)
2176     return; /* was never marked as connected */
2177   pos->session = NULL;
2178   if (pos->addrlen != 0)
2179     {
2180       if (nl->received_pong != GNUNET_NO)
2181         try_fast_reconnect (p, nl);
2182       return;
2183     }
2184   /* was inbound connection, free 'pos' */
2185   if (prev == NULL)
2186     rl->addresses = pos->next;
2187   else
2188     prev->next = pos->next;
2189   if (GNUNET_SCHEDULER_NO_TASK != pos->revalidate_task)
2190     {
2191       GNUNET_SCHEDULER_cancel (pos->revalidate_task);
2192       pos->revalidate_task = GNUNET_SCHEDULER_NO_TASK;
2193     }
2194   GNUNET_free (pos);
2195   if (nl->received_pong == GNUNET_NO)
2196     return; /* nothing to do, never connected... */
2197   /* check if we have any validated addresses left */
2198   pos = rl->addresses;
2199   while (pos != NULL)
2200     {
2201       if (pos->validated)
2202         {
2203           try_fast_reconnect (p, nl);
2204           return;
2205         }
2206       pos = pos->next;
2207     }
2208   /* no valid addresses left, signal disconnect! */
2209
2210   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2211             "Disconnecting peer `%4s', %s\n", GNUNET_i2s(&nl->id),
2212             "plugin_env_session_end");
2213   /* FIXME: This doesn't mean there are no addresses left for this PEER,
2214    * it means there aren't any left for this PLUGIN/PEER combination! So
2215    * calling disconnect_neighbor here with GNUNET_NO forces disconnect
2216    * when it isn't necessary. Using GNUNET_YES at least checks to see
2217    * if there are any addresses that work first, so as not to overdo it.
2218    * --NE
2219    */
2220   disconnect_neighbour (nl, GNUNET_YES);
2221 }
2222
2223
2224 /**
2225  * Function that must be called by each plugin to notify the
2226  * transport service about the addresses under which the transport
2227  * provided by the plugin can be reached.
2228  *
2229  * @param cls closure
2230  * @param name name of the transport that generated the address
2231  * @param addr one of the addresses of the host, NULL for the last address
2232  *        the specific address format depends on the transport
2233  * @param addrlen length of the address
2234  * @param expires when should this address automatically expire?
2235  */
2236 static void
2237 plugin_env_notify_address (void *cls,
2238                            const char *name,
2239                            const void *addr,
2240                            uint16_t addrlen,
2241                            struct GNUNET_TIME_Relative expires)
2242 {
2243   struct TransportPlugin *p = cls;
2244   struct OwnAddressList *al;
2245   struct GNUNET_TIME_Absolute abex;
2246
2247   GNUNET_assert (addr != NULL);
2248   abex = GNUNET_TIME_relative_to_absolute (expires);
2249   GNUNET_assert (p == find_transport (name));
2250   al = p->addresses;
2251   while (al != NULL)
2252     {
2253       if ((addrlen == al->addrlen) && (0 == memcmp (addr, &al[1], addrlen)))
2254         {             
2255           al->expires = abex;
2256           update_addresses (p, GNUNET_NO);
2257           return;
2258         }
2259       al = al->next;
2260     }
2261
2262   al = GNUNET_malloc (sizeof (struct OwnAddressList) + addrlen);
2263   al->next = p->addresses;
2264   p->addresses = al;
2265   al->expires = abex;
2266   al->addrlen = addrlen;
2267   memcpy (&al[1], addr, addrlen);
2268   update_addresses (p, GNUNET_YES);
2269 }
2270
2271
2272 /**
2273  * Notify all of our clients about a peer connecting.
2274  */
2275 static void
2276 notify_clients_connect (const struct GNUNET_PeerIdentity *peer,
2277                         struct GNUNET_TIME_Relative latency,
2278                         uint32_t distance)
2279 {
2280   struct ConnectInfoMessage * cim;
2281   struct TransportClient *cpos;
2282   uint32_t ats_count;
2283   size_t size;
2284
2285 #if DEBUG_TRANSPORT
2286   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2287               "Notifying clients about connection from `%s'\n",
2288               GNUNET_i2s (peer));
2289 #endif
2290   GNUNET_STATISTICS_update (stats,
2291                             gettext_noop ("# peers connected"),
2292                             1,
2293                             GNUNET_NO);
2294
2295   ats_count = 2;
2296   size  = sizeof (struct ConnectInfoMessage) + ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
2297   if (size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
2298   {
2299           GNUNET_break(0);
2300   }
2301   cim = GNUNET_malloc (size);
2302
2303   cim->header.size = htons (size);
2304   cim->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
2305   cim->ats_count = htonl(2);
2306   (&(cim->ats))[0].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE);
2307   (&(cim->ats))[0].value = htonl (distance);
2308   (&(cim->ats))[1].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DELAY);
2309   (&(cim->ats))[1].value = htonl ((uint32_t) latency.rel_value);
2310   (&(cim->ats))[2].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
2311   (&(cim->ats))[2].value = htonl (0);
2312   memcpy (&cim->id, peer, sizeof (struct GNUNET_PeerIdentity));
2313
2314   /* notify ats about connecting peer */
2315   ats_notify_peer_connect (peer, &(cim->ats));
2316
2317   cpos = clients;
2318   while (cpos != NULL)
2319     {
2320       transmit_to_client (cpos, &(cim->header), GNUNET_NO);
2321       cpos = cpos->next;
2322     }
2323
2324   GNUNET_free (cim);
2325 }
2326
2327
2328 /**
2329  * Notify all of our clients about a peer disconnecting.
2330  */
2331 static void
2332 notify_clients_disconnect (const struct GNUNET_PeerIdentity *peer)
2333 {
2334   struct DisconnectInfoMessage dim;
2335   struct TransportClient *cpos;
2336
2337 #if DEBUG_TRANSPORT
2338   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2339               "Notifying clients about lost connection to `%s'\n",
2340               GNUNET_i2s (peer));
2341 #endif
2342   GNUNET_STATISTICS_update (stats,
2343                             gettext_noop ("# peers connected"),
2344                             -1,
2345                             GNUNET_NO);
2346   dim.header.size = htons (sizeof (struct DisconnectInfoMessage));
2347   dim.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT);
2348   dim.reserved = htonl (0);
2349   memcpy (&dim.peer, peer, sizeof (struct GNUNET_PeerIdentity));
2350
2351   /* notify ats about connecting peer */
2352   ats_notify_peer_disconnect (peer);
2353
2354   cpos = clients;
2355   while (cpos != NULL)
2356     {
2357       transmit_to_client (cpos, &dim.header, GNUNET_NO);
2358       cpos = cpos->next;
2359     }
2360 }
2361
2362
2363 /**
2364  * Find a ForeignAddressList entry for the given neighbour
2365  * that matches the given address and transport.
2366  *
2367  * @param neighbour which peer we care about
2368  * @param tname name of the transport plugin
2369  * @param session session to look for, NULL for 'any'; otherwise
2370  *        can be used for the service to "learn" this session ID
2371  *        if 'addr' matches
2372  * @param addr binary address
2373  * @param addrlen length of addr
2374  * @return NULL if no such entry exists
2375  */
2376 static struct ForeignAddressList *
2377 find_peer_address(struct NeighbourList *neighbour,
2378                   const char *tname,
2379                   struct Session *session,
2380                   const char *addr,
2381                   uint16_t addrlen)
2382 {
2383   struct ReadyList *head;
2384   struct ForeignAddressList *pos;
2385
2386   head = neighbour->plugins;
2387   while (head != NULL)
2388     {
2389       if (0 == strcmp (tname, head->plugin->short_name))
2390         break;
2391       head = head->next;
2392     }
2393   if (head == NULL)
2394     return NULL;
2395   pos = head->addresses;
2396   while ( (pos != NULL) &&
2397           ( (pos->addrlen != addrlen) ||
2398             (memcmp(pos->addr, addr, addrlen) != 0) ) )
2399     {
2400       if ( (session != NULL) &&
2401            (pos->session == session) )
2402         return pos;
2403       pos = pos->next;
2404     }
2405   if ( (session != NULL) && (pos != NULL) )
2406     pos->session = session; /* learn it! */
2407   return pos;
2408 }
2409
2410
2411 /**
2412  * Get the peer address struct for the given neighbour and
2413  * address.  If it doesn't yet exist, create it.
2414  *
2415  * @param neighbour which peer we care about
2416  * @param tname name of the transport plugin
2417  * @param session session of the plugin, or NULL for none
2418  * @param addr binary address
2419  * @param addrlen length of addr
2420  * @return NULL if we do not have a transport plugin for 'tname'
2421  */
2422 static struct ForeignAddressList *
2423 add_peer_address (struct NeighbourList *neighbour,
2424                   const char *tname,
2425                   struct Session *session,
2426                   const char *addr,
2427                   uint16_t addrlen)
2428 {
2429   struct ReadyList *head;
2430   struct ForeignAddressList *ret;
2431
2432   ret = find_peer_address (neighbour, tname, session, addr, addrlen);
2433   if (ret != NULL)
2434     return ret;
2435   head = neighbour->plugins;
2436
2437   while (head != NULL)
2438     {
2439       if (0 == strcmp (tname, head->plugin->short_name))
2440         break;
2441       head = head->next;
2442     }
2443   if (head == NULL)
2444     return NULL;
2445   ret = GNUNET_malloc(sizeof(struct ForeignAddressList) + addrlen);
2446   ret->session = session;
2447   if (addrlen > 0)
2448     {
2449       ret->addr = (const char*) &ret[1];
2450       memcpy (&ret[1], addr, addrlen);
2451     }
2452   else
2453     {
2454       ret->addr = NULL;
2455     }
2456   ret->addrlen = addrlen;
2457   ret->expires = GNUNET_TIME_relative_to_absolute
2458     (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
2459   ret->latency = GNUNET_TIME_relative_get_forever();
2460   ret->distance = -1;
2461   ret->timeout = GNUNET_TIME_relative_to_absolute
2462     (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
2463   ret->ready_list = head;
2464   ret->next = head->addresses;
2465   head->addresses = ret;
2466   return ret;
2467 }
2468
2469
2470 /**
2471  * Closure for 'add_validated_address'.
2472  */
2473 struct AddValidatedAddressContext
2474 {
2475   /**
2476    * Entry that has been validated.
2477    */
2478   const struct ValidationEntry *ve;
2479
2480   /**
2481    * Flag set after we have added the address so
2482    * that we terminate the iteration next time.
2483    */
2484   int done;
2485 };
2486
2487
2488 /**
2489  * Callback function used to fill a buffer of max bytes with a list of
2490  * addresses in the format used by HELLOs.  Should use
2491  * "GNUNET_HELLO_add_address" as a helper function.
2492  *
2493  * @param cls the 'struct AddValidatedAddressContext' with the validated address
2494  * @param max maximum number of bytes that can be written to buf
2495  * @param buf where to write the address information
2496  * @return number of bytes written, 0 to signal the
2497  *         end of the iteration.
2498  */
2499 static size_t
2500 add_validated_address (void *cls,
2501                        size_t max, void *buf)
2502 {
2503   struct AddValidatedAddressContext *avac = cls;
2504   const struct ValidationEntry *ve = avac->ve;
2505
2506   if (GNUNET_YES == avac->done)
2507     return 0;
2508   avac->done = GNUNET_YES;
2509   return GNUNET_HELLO_add_address (ve->transport_name,
2510                                    GNUNET_TIME_relative_to_absolute (HELLO_ADDRESS_EXPIRATION),
2511                                    ve->addr,
2512                                    ve->addrlen,
2513                                    buf,
2514                                    max);
2515 }
2516
2517
2518
2519 /**
2520  * Closure for 'check_address_exists'.
2521  */
2522 struct CheckAddressExistsClosure
2523 {
2524   /**
2525    * Address to check for.
2526    */
2527   const void *addr;
2528
2529   /**
2530    * Name of the transport.
2531    */
2532   const char *tname;
2533
2534   /**
2535    * Session, or NULL.
2536    */
2537   struct Session *session;
2538
2539   /**
2540    * Set to GNUNET_YES if the address exists.
2541    */
2542   int exists;
2543
2544   /**
2545    * Length of addr.
2546    */
2547   uint16_t addrlen;
2548
2549 };
2550
2551
2552 /**
2553  * Iterator over hash map entries.  Checks if the given
2554  * validation entry is for the same address as what is given
2555  * in the closure.
2556  *
2557  * @param cls the 'struct CheckAddressExistsClosure*'
2558  * @param key current key code (ignored)
2559  * @param value value in the hash map ('struct ValidationEntry')
2560  * @return GNUNET_YES if we should continue to
2561  *         iterate (mismatch), GNUNET_NO if not (entry matched)
2562  */
2563 static int
2564 check_address_exists (void *cls,
2565                       const GNUNET_HashCode * key,
2566                       void *value)
2567 {
2568   struct CheckAddressExistsClosure *caec = cls;
2569   struct ValidationEntry *ve = value;
2570
2571   if ( (0 == strcmp (caec->tname,
2572                      ve->transport_name)) &&
2573        (caec->addrlen == ve->addrlen) &&
2574        (0 == memcmp (caec->addr,
2575                      ve->addr,
2576                      caec->addrlen)) )
2577     {
2578       caec->exists = GNUNET_YES;
2579       return GNUNET_NO;
2580     }
2581   if ( (ve->session != NULL) &&
2582        (caec->session == ve->session) )
2583     {
2584       caec->exists = GNUNET_YES;
2585       return GNUNET_NO;
2586     }
2587   return GNUNET_YES;
2588 }
2589
2590
2591
2592 /**
2593  * Iterator to free entries in the validation_map.
2594  *
2595  * @param cls closure (unused)
2596  * @param key current key code
2597  * @param value value in the hash map (validation to abort)
2598  * @return GNUNET_YES (always)
2599  */
2600 static int
2601 abort_validation (void *cls,
2602                   const GNUNET_HashCode * key,
2603                   void *value)
2604 {
2605   struct ValidationEntry *va = value;
2606
2607   if (GNUNET_SCHEDULER_NO_TASK != va->timeout_task)
2608     GNUNET_SCHEDULER_cancel (va->timeout_task);
2609   GNUNET_free (va->transport_name);
2610   if (va->chvc != NULL)
2611     {
2612       va->chvc->ve_count--;
2613       if (va->chvc->ve_count == 0)
2614         {
2615           GNUNET_CONTAINER_DLL_remove (chvc_head,
2616                                        chvc_tail,
2617                                        va->chvc);
2618           GNUNET_free (va->chvc);
2619         }
2620       va->chvc = NULL;
2621     }
2622   GNUNET_free (va);
2623   return GNUNET_YES;
2624 }
2625
2626
2627 /**
2628  * HELLO validation cleanup task (validation failed).
2629  *
2630  * @param cls the 'struct ValidationEntry' that failed
2631  * @param tc scheduler context (unused)
2632  */
2633 static void
2634 timeout_hello_validation (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2635 {
2636   struct ValidationEntry *va = cls;
2637   struct GNUNET_PeerIdentity pid;
2638
2639   va->timeout_task = GNUNET_SCHEDULER_NO_TASK;
2640   GNUNET_STATISTICS_update (stats,
2641                             gettext_noop ("# address validation timeouts"),
2642                             1,
2643                             GNUNET_NO);
2644   GNUNET_CRYPTO_hash (&va->publicKey,
2645                       sizeof (struct
2646                               GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
2647                       &pid.hashPubKey);
2648   GNUNET_break (GNUNET_OK ==
2649                 GNUNET_CONTAINER_multihashmap_remove (validation_map,
2650                                                       &pid.hashPubKey,
2651                                                       va));
2652   abort_validation (NULL, NULL, va);
2653 }
2654
2655
2656 static void
2657 neighbour_timeout_task (void *cls,
2658                        const struct GNUNET_SCHEDULER_TaskContext *tc)
2659 {
2660   struct NeighbourList *n = cls;
2661
2662 #if DEBUG_TRANSPORT
2663   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2664               "Neighbour `%4s' has timed out!\n", GNUNET_i2s (&n->id));
2665 #endif
2666   GNUNET_STATISTICS_update (stats,
2667                             gettext_noop ("# disconnects due to timeout"),
2668                             1,
2669                             GNUNET_NO);
2670   n->timeout_task = GNUNET_SCHEDULER_NO_TASK;
2671   disconnect_neighbour (n, GNUNET_NO);
2672 }
2673
2674
2675 /**
2676  * Schedule the job that will cause us to send a PING to the
2677  * foreign address to evaluate its validity and latency.
2678  *
2679  * @param fal address to PING
2680  */
2681 static void
2682 schedule_next_ping (struct ForeignAddressList *fal);
2683
2684
2685 /**
2686  * Add the given address to the list of foreign addresses
2687  * available for the given peer (check for duplicates).
2688  *
2689  * @param cls the respective 'struct NeighbourList' to update
2690  * @param tname name of the transport
2691  * @param expiration expiration time
2692  * @param addr the address
2693  * @param addrlen length of the address
2694  * @return GNUNET_OK (always)
2695  */
2696 static int
2697 add_to_foreign_address_list (void *cls,
2698                              const char *tname,
2699                              struct GNUNET_TIME_Absolute expiration,
2700                              const void *addr,
2701                              uint16_t addrlen)
2702 {
2703   struct NeighbourList *n = cls;
2704   struct ForeignAddressList *fal;
2705   int try;
2706
2707   GNUNET_STATISTICS_update (stats,
2708                             gettext_noop ("# valid peer addresses returned by PEERINFO"),
2709                             1,
2710                             GNUNET_NO);
2711   try = GNUNET_NO;
2712   fal = find_peer_address (n, tname, NULL, addr, addrlen);
2713   if (fal == NULL)
2714     {
2715 #if DEBUG_TRANSPORT_HELLO
2716       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2717                   "Adding address `%s' (%s) for peer `%4s' due to PEERINFO data for %llums.\n",
2718                   a2s (tname, addr, addrlen),
2719                   tname,
2720                   GNUNET_i2s (&n->id),
2721                   expiration.abs_value);
2722 #endif
2723       fal = add_peer_address (n, tname, NULL, addr, addrlen);
2724       if (fal == NULL)
2725         {
2726           GNUNET_STATISTICS_update (stats,
2727                                     gettext_noop ("# previously validated addresses lacking transport"),
2728                                     1,
2729                                     GNUNET_NO);
2730         }
2731       else
2732         {
2733           fal->expires = GNUNET_TIME_absolute_max (expiration,
2734                                                    fal->expires);
2735           schedule_next_ping (fal);
2736         }
2737       try = GNUNET_YES;
2738     }
2739   else
2740     {
2741       fal->expires = GNUNET_TIME_absolute_max (expiration,
2742                                                fal->expires);
2743     }
2744   if (fal == NULL)
2745     {
2746       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2747                   "Failed to add new address for `%4s'\n",
2748                   GNUNET_i2s (&n->id));
2749       return GNUNET_OK;
2750     }
2751   if (fal->validated == GNUNET_NO)
2752     {
2753       fal->validated = GNUNET_YES;
2754       GNUNET_STATISTICS_update (stats,
2755                                 gettext_noop ("# peer addresses considered valid"),
2756                                 1,
2757                                 GNUNET_NO);
2758     }
2759   if (try == GNUNET_YES)
2760     {
2761       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2762                   "Have new addresses, will try to trigger transmissions.\n");
2763       try_transmission_to_peer (n);
2764     }
2765   return GNUNET_OK;
2766 }
2767
2768
2769 /**
2770  * Add addresses in validated HELLO "h" to the set of addresses
2771  * we have for this peer.
2772  *
2773  * @param cls closure ('struct NeighbourList*')
2774  * @param peer id of the peer, NULL for last call
2775  * @param h hello message for the peer (can be NULL)
2776  * @param err_msg NULL if successful, otherwise contains error message
2777  */
2778 static void
2779 add_hello_for_peer (void *cls,
2780                     const struct GNUNET_PeerIdentity *peer,
2781                     const struct GNUNET_HELLO_Message *h,
2782                     const char *err_msg)
2783 {
2784   struct NeighbourList *n = cls;
2785
2786   if (err_msg != NULL)
2787   {
2788           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2789                       _("Error in communication with PEERINFO service\n"));
2790         /* return; */
2791   }
2792   if ((peer == NULL))
2793     {
2794       GNUNET_STATISTICS_update (stats,
2795                                 gettext_noop ("# outstanding peerinfo iterate requests"),
2796                                 -1,
2797                                 GNUNET_NO);
2798       n->piter = NULL;
2799       return;
2800     }
2801   if (h == NULL)
2802     return; /* no HELLO available */
2803 #if DEBUG_TRANSPORT
2804   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2805               "Peerinfo had `%s' message for peer `%4s', adding existing addresses.\n",
2806               "HELLO",
2807               GNUNET_i2s (peer));
2808 #endif
2809   if (GNUNET_YES != n->public_key_valid)
2810     {
2811       GNUNET_HELLO_get_key (h, &n->publicKey);
2812       n->public_key_valid = GNUNET_YES;
2813     }
2814   GNUNET_HELLO_iterate_addresses (h,
2815                                   GNUNET_NO,
2816                                   &add_to_foreign_address_list,
2817                                   n);
2818 }
2819
2820
2821 /**
2822  * Create a fresh entry in our neighbour list for the given peer.
2823  * Will try to transmit our current HELLO to the new neighbour.
2824  * Do not call this function directly, use 'setup_peer_check_blacklist.
2825  *
2826  * @param peer the peer for which we create the entry
2827  * @param do_hello should we schedule transmitting a HELLO
2828  * @return the new neighbour list entry
2829  */
2830 static struct NeighbourList *
2831 setup_new_neighbour (const struct GNUNET_PeerIdentity *peer,
2832                      int do_hello)
2833 {
2834   struct NeighbourList *n;
2835   struct TransportPlugin *tp;
2836   struct ReadyList *rl;
2837
2838 #if DEBUG_TRANSPORT
2839   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2840               "Setting up state for neighbour `%4s'\n",
2841               GNUNET_i2s (peer));
2842 #endif
2843   GNUNET_assert (our_hello != NULL);
2844   GNUNET_STATISTICS_update (stats,
2845                             gettext_noop ("# active neighbours"),
2846                             1,
2847                             GNUNET_NO);
2848   n = GNUNET_malloc (sizeof (struct NeighbourList));
2849   n->next = neighbours;
2850   neighbours = n;
2851   n->id = *peer;
2852   n->peer_timeout =
2853     GNUNET_TIME_relative_to_absolute
2854     (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
2855   GNUNET_BANDWIDTH_tracker_init (&n->in_tracker,
2856                                  GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT,
2857                                  MAX_BANDWIDTH_CARRY_S);
2858   tp = plugins;
2859   while (tp != NULL)
2860     {
2861       if ((tp->api->send != NULL) && (!is_blacklisted(peer, tp)))
2862         {
2863           rl = GNUNET_malloc (sizeof (struct ReadyList));
2864           rl->neighbour = n;
2865           rl->next = n->plugins;
2866           n->plugins = rl;
2867           rl->plugin = tp;
2868           rl->addresses = NULL;
2869         }
2870       tp = tp->next;
2871     }
2872   n->latency = GNUNET_TIME_UNIT_FOREVER_REL;
2873   n->distance = -1;
2874   n->timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
2875                                                   &neighbour_timeout_task, n);
2876   if (do_hello)
2877     {
2878       GNUNET_STATISTICS_update (stats,
2879                                 gettext_noop ("# peerinfo new neighbor iterate requests"),
2880                                 1,
2881                                 GNUNET_NO);
2882       GNUNET_STATISTICS_update (stats,
2883                                 gettext_noop ("# outstanding peerinfo iterate requests"),
2884                                 1,
2885                                 GNUNET_NO);
2886       n->piter = GNUNET_PEERINFO_iterate (peerinfo, peer,
2887                                           GNUNET_TIME_UNIT_FOREVER_REL,
2888                                           &add_hello_for_peer, n);
2889
2890       GNUNET_STATISTICS_update (stats,
2891                                 gettext_noop ("# HELLO's sent to new neighbors"),
2892                                 1,
2893                                 GNUNET_NO);
2894       transmit_to_peer (NULL, NULL, 0,
2895                         HELLO_ADDRESS_EXPIRATION,
2896                         (const char *) our_hello, GNUNET_HELLO_size(our_hello),
2897                         GNUNET_NO, n);
2898     }
2899   return n;
2900 }
2901
2902
2903 /**
2904  * Function called after we have checked if communicating
2905  * with a given peer is acceptable.
2906  *
2907  * @param cls closure
2908  * @param n NULL if communication is not acceptable
2909  */
2910 typedef void (*SetupContinuation)(void *cls,
2911                                   struct NeighbourList *n);
2912
2913
2914 /**
2915  * Information kept for each client registered to perform
2916  * blacklisting.
2917  */
2918 struct Blacklisters
2919 {
2920   /**
2921    * This is a linked list.
2922    */
2923   struct Blacklisters *next;
2924
2925   /**
2926    * This is a linked list.
2927    */
2928   struct Blacklisters *prev;
2929
2930   /**
2931    * Client responsible for this entry.
2932    */
2933   struct GNUNET_SERVER_Client *client;
2934
2935   /**
2936    * Blacklist check that we're currently performing.
2937    */
2938   struct BlacklistCheck *bc;
2939
2940 };
2941
2942
2943 /**
2944  * Head of DLL of blacklisting clients.
2945  */
2946 static struct Blacklisters *bl_head;
2947
2948 /**
2949  * Tail of DLL of blacklisting clients.
2950  */
2951 static struct Blacklisters *bl_tail;
2952
2953
2954 /**
2955  * Context we use when performing a blacklist check.
2956  */
2957 struct BlacklistCheck
2958 {
2959
2960   /**
2961    * This is a linked list.
2962    */
2963   struct BlacklistCheck *next;
2964
2965   /**
2966    * This is a linked list.
2967    */
2968   struct BlacklistCheck *prev;
2969
2970   /**
2971    * Peer being checked.
2972    */
2973   struct GNUNET_PeerIdentity peer;
2974
2975   /**
2976    * Option for setup neighbour afterwards.
2977    */
2978   int do_hello;
2979
2980   /**
2981    * Continuation to call with the result.
2982    */
2983   SetupContinuation cont;
2984
2985   /**
2986    * Closure for cont.
2987    */
2988   void *cont_cls;
2989
2990   /**
2991    * Current transmission request handle for this client, or NULL if no
2992    * request is pending.
2993    */
2994   struct GNUNET_CONNECTION_TransmitHandle *th;
2995
2996   /**
2997    * Our current position in the blacklisters list.
2998    */
2999   struct Blacklisters *bl_pos;
3000
3001   /**
3002    * Current task performing the check.
3003    */
3004   GNUNET_SCHEDULER_TaskIdentifier task;
3005
3006 };
3007
3008 /**
3009  * Head of DLL of active blacklisting queries.
3010  */
3011 static struct BlacklistCheck *bc_head;
3012
3013 /**
3014  * Tail of DLL of active blacklisting queries.
3015  */
3016 static struct BlacklistCheck *bc_tail;
3017
3018
3019 /**
3020  * Perform next action in the blacklist check.
3021  *
3022  * @param cls the 'struct BlacklistCheck*'
3023  * @param tc unused
3024  */
3025 static void
3026 do_blacklist_check (void *cls,
3027                     const struct GNUNET_SCHEDULER_TaskContext *tc);
3028
3029 /**
3030  * Transmit blacklist query to the client.
3031  *
3032  * @param cls the 'struct BlacklistCheck'
3033  * @param size number of bytes allowed
3034  * @param buf where to copy the message
3035  * @return number of bytes copied to buf
3036  */
3037 static size_t
3038 transmit_blacklist_message (void *cls,
3039                             size_t size,
3040                             void *buf)
3041 {
3042   struct BlacklistCheck *bc = cls;
3043   struct Blacklisters *bl;
3044   struct BlacklistMessage bm;
3045
3046   bc->th = NULL;
3047   if (size == 0)
3048     {
3049       GNUNET_assert (bc->task == GNUNET_SCHEDULER_NO_TASK);
3050       bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check,
3051                                            bc);
3052       return 0;
3053     }
3054   bl = bc->bl_pos;
3055   bm.header.size = htons (sizeof (struct BlacklistMessage));
3056   bm.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_QUERY);
3057   bm.is_allowed = htonl (0);
3058   bm.peer = bc->peer;
3059   memcpy (buf, &bm, sizeof (bm));
3060   GNUNET_SERVER_receive_done (bl->client, GNUNET_OK);
3061   return sizeof (bm);
3062 }
3063
3064
3065 /**
3066  * Perform next action in the blacklist check.
3067  *
3068  * @param cls the 'struct BlacklistCheck*'
3069  * @param tc unused
3070  */
3071 static void
3072 do_blacklist_check (void *cls,
3073                     const struct GNUNET_SCHEDULER_TaskContext *tc)
3074 {
3075   struct BlacklistCheck *bc = cls;
3076   struct Blacklisters *bl;
3077
3078   bc->task = GNUNET_SCHEDULER_NO_TASK;
3079   bl = bc->bl_pos;
3080   if (bl == NULL)
3081     {
3082       bc->cont (bc->cont_cls,
3083                 setup_new_neighbour (&bc->peer, bc->do_hello));         
3084       GNUNET_free (bc);
3085       return;
3086     }
3087   if (bl->bc == NULL)
3088     {
3089       bl->bc = bc;
3090       bc->th = GNUNET_SERVER_notify_transmit_ready (bl->client,
3091                                                     sizeof (struct BlacklistMessage),
3092                                                     GNUNET_TIME_UNIT_FOREVER_REL,
3093                                                     &transmit_blacklist_message,
3094                                                     bc);
3095     }
3096 }
3097
3098
3099 /**
3100  * Obtain a 'struct NeighbourList' for the given peer.  If such an entry
3101  * does not yet exist, check the blacklist.  If the blacklist says creating
3102  * one is acceptable, create one and call the continuation; otherwise
3103  * call the continuation with NULL.
3104  *
3105  * @param peer peer to setup or look up a struct NeighbourList for
3106  * @param do_hello should we also schedule sending our HELLO to the peer
3107  *        if this is a new record
3108  * @param cont function to call with the 'struct NeigbhbourList*'
3109  * @param cont_cls closure for cont
3110  */
3111 static void
3112 setup_peer_check_blacklist (const struct GNUNET_PeerIdentity *peer,
3113                             int do_hello,
3114                             SetupContinuation cont,
3115                             void *cont_cls)
3116 {
3117   struct NeighbourList *n;
3118   struct BlacklistCheck *bc;
3119
3120   n = find_neighbour(peer);
3121   if (n != NULL)
3122     {
3123       if (cont != NULL)
3124         cont (cont_cls, n);
3125       return;
3126     }
3127   if (bl_head == NULL)
3128     {
3129       if (cont != NULL)
3130         cont (cont_cls, setup_new_neighbour (peer, do_hello));
3131       else
3132         setup_new_neighbour(peer, do_hello);
3133       return;
3134     }
3135   bc = GNUNET_malloc (sizeof (struct BlacklistCheck));
3136   GNUNET_CONTAINER_DLL_insert (bc_head, bc_tail, bc);
3137   bc->peer = *peer;
3138   bc->do_hello = do_hello;
3139   bc->cont = cont;
3140   bc->cont_cls = cont_cls;
3141   bc->bl_pos = bl_head;
3142   bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check,
3143                                        bc);
3144 }
3145
3146
3147 /**
3148  * Function called with the result of querying a new blacklister about
3149  * it being allowed (or not) to continue to talk to an existing neighbour.
3150  *
3151  * @param cls the original 'struct NeighbourList'
3152  * @param n NULL if we need to disconnect
3153  */
3154 static void
3155 confirm_or_drop_neighbour (void *cls,
3156                            struct NeighbourList *n)
3157 {
3158   struct NeighbourList * orig = cls;
3159
3160   if (n == NULL)
3161     {
3162       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3163               "Disconnecting peer `%4s', %s\n", GNUNET_i2s(&orig->id),
3164               "confirm_or_drop_neighboUr");
3165       disconnect_neighbour (orig, GNUNET_NO);
3166     }
3167 }
3168
3169
3170 /**
3171  * Handle a request to start a blacklist.
3172  *
3173  * @param cls closure (always NULL)
3174  * @param client identification of the client
3175  * @param message the actual message
3176  */
3177 static void
3178 handle_blacklist_init (void *cls,
3179                        struct GNUNET_SERVER_Client *client,
3180                        const struct GNUNET_MessageHeader *message)
3181 {
3182   struct Blacklisters *bl;
3183   struct BlacklistCheck *bc;
3184   struct NeighbourList *n;
3185
3186   bl = bl_head;
3187   while (bl != NULL)
3188     {
3189       if (bl->client == client)
3190         {
3191           GNUNET_break (0);
3192           GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3193           return;
3194         }
3195       bl = bl->next;
3196     }
3197   bl = GNUNET_malloc (sizeof (struct Blacklisters));
3198   bl->client = client;
3199   GNUNET_SERVER_client_keep (client);
3200   GNUNET_CONTAINER_DLL_insert_after (bl_head, bl_tail, bl_tail, bl);
3201   /* confirm that all existing connections are OK! */
3202   n = neighbours;
3203   while (NULL != n)
3204     {
3205       bc = GNUNET_malloc (sizeof (struct BlacklistCheck));
3206       GNUNET_CONTAINER_DLL_insert (bc_head, bc_tail, bc);
3207       bc->peer = n->id;
3208       bc->do_hello = GNUNET_NO;
3209       bc->cont = &confirm_or_drop_neighbour;
3210       bc->cont_cls = n;
3211       bc->bl_pos = bl;
3212       if (n == neighbours) /* all would wait for the same client, no need to
3213                               create more than just the first task right now */
3214         bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check,
3215                                              bc);
3216       n = n->next;
3217     }
3218 }
3219
3220
3221 /**
3222  * Handle a request to blacklist a peer.
3223  *
3224  * @param cls closure (always NULL)
3225  * @param client identification of the client
3226  * @param message the actual message
3227  */
3228 static void
3229 handle_blacklist_reply (void *cls,
3230                         struct GNUNET_SERVER_Client *client,
3231                         const struct GNUNET_MessageHeader *message)
3232 {
3233   const struct BlacklistMessage *msg = (const struct BlacklistMessage*) message;
3234   struct Blacklisters *bl;
3235   struct BlacklistCheck *bc;
3236
3237   bl = bl_head;
3238   while ( (bl != NULL) &&
3239           (bl->client != client) )
3240     bl = bl->next;
3241   if (bl == NULL)
3242     {
3243       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3244       return;
3245     }
3246   bc = bl->bc;
3247   bl->bc = NULL;
3248   if (ntohl (msg->is_allowed) == GNUNET_SYSERR)
3249     {
3250       bc->cont (bc->cont_cls, NULL);
3251       GNUNET_CONTAINER_DLL_remove (bc_head, bc_tail, bc);
3252       GNUNET_free (bc);
3253     }
3254   else
3255     {
3256       bc->bl_pos = bc->bl_pos->next;
3257       bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check,
3258                                            bc);
3259     }
3260   /* check if any other bc's are waiting for this blacklister */
3261   bc = bc_head;
3262   while (bc != NULL)
3263     {
3264       if ( (bc->bl_pos == bl) &&
3265            (GNUNET_SCHEDULER_NO_TASK == bc->task) )
3266         bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check,
3267                                              bc);
3268       bc = bc->next;
3269     }
3270 }
3271
3272
3273 /**
3274  * Send periodic PING messages to a given foreign address.
3275  *
3276  * @param cls our 'struct PeriodicValidationContext*'
3277  * @param tc task context
3278  */
3279 static void
3280 send_periodic_ping (void *cls,
3281                     const struct GNUNET_SCHEDULER_TaskContext *tc)
3282 {
3283   struct ForeignAddressList *peer_address = cls;
3284   struct TransportPlugin *tp;
3285   struct ValidationEntry *va;
3286   struct NeighbourList *neighbour;
3287   struct TransportPingMessage ping;
3288   struct CheckAddressExistsClosure caec;
3289   char * message_buf;
3290   uint16_t hello_size;
3291   size_t slen;
3292   size_t tsize;
3293
3294   peer_address->revalidate_task = GNUNET_SCHEDULER_NO_TASK;
3295   if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
3296     return;
3297   tp = peer_address->ready_list->plugin;
3298   neighbour = peer_address->ready_list->neighbour;
3299   if (GNUNET_YES != neighbour->public_key_valid)
3300     {
3301       /* no public key yet, try again later */
3302       schedule_next_ping (peer_address);
3303       return;
3304     }
3305   caec.addr = peer_address->addr;
3306   caec.addrlen = peer_address->addrlen;
3307   caec.tname = tp->short_name;
3308   caec.session = peer_address->session;
3309   caec.exists = GNUNET_NO;
3310   GNUNET_CONTAINER_multihashmap_iterate (validation_map,
3311                                          &check_address_exists,
3312                                          &caec);
3313   if (caec.exists == GNUNET_YES)
3314     {
3315       /* During validation attempts we will likely trigger the other
3316          peer trying to validate our address which in turn will cause
3317          it to send us its HELLO, so we expect to hit this case rather
3318          frequently.  Only print something if we are very verbose. */
3319 #if DEBUG_TRANSPORT > 1
3320       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3321                   "Some validation of address `%s' via `%s' for peer `%4s' already in progress.\n",
3322                   (peer_address->addr != NULL)
3323                   ? a2s (tp->short_name,
3324                          peer_address->addr,
3325                          peer_address->addrlen)
3326                   : "<inbound>",
3327                   tp->short_name,
3328                   GNUNET_i2s (&neighbour->id));
3329 #endif
3330       schedule_next_ping (peer_address);
3331       return;
3332     }
3333   va = GNUNET_malloc (sizeof (struct ValidationEntry) + peer_address->addrlen);
3334   va->transport_name = GNUNET_strdup (tp->short_name);
3335   va->challenge = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
3336                                             UINT_MAX);
3337   va->send_time = GNUNET_TIME_absolute_get();
3338   va->session = peer_address->session;
3339   if (peer_address->addr != NULL)
3340     {
3341       va->addr = (const void*) &va[1];
3342       memcpy (&va[1], peer_address->addr, peer_address->addrlen);
3343       va->addrlen = peer_address->addrlen;
3344     }
3345   memcpy(&va->publicKey,
3346          &neighbour->publicKey,
3347          sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
3348
3349   va->timeout_task = GNUNET_SCHEDULER_add_delayed (HELLO_VERIFICATION_TIMEOUT,
3350                                                    &timeout_hello_validation,
3351                                                    va);
3352   GNUNET_CONTAINER_multihashmap_put (validation_map,
3353                                      &neighbour->id.hashPubKey,
3354                                      va,
3355                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
3356
3357   if (peer_address->validated != GNUNET_YES)
3358     hello_size = GNUNET_HELLO_size(our_hello);
3359   else
3360     hello_size = 0;
3361
3362   tsize = sizeof(struct TransportPingMessage) + hello_size;
3363
3364   if (peer_address->addr != NULL)
3365     {
3366       slen = strlen (tp->short_name) + 1;
3367       tsize += slen + peer_address->addrlen;
3368     }
3369   else
3370     {
3371       slen = 0; /* make gcc happy */
3372     }
3373   message_buf = GNUNET_malloc(tsize);
3374   ping.header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_PING);
3375   ping.challenge = htonl(va->challenge);
3376   memcpy(&ping.target, &neighbour->id, sizeof(struct GNUNET_PeerIdentity));
3377   if (peer_address->validated != GNUNET_YES)
3378     {
3379       memcpy(message_buf, our_hello, hello_size);
3380     }
3381
3382   if (peer_address->addr != NULL)
3383     {
3384       ping.header.size = htons(sizeof(struct TransportPingMessage) +
3385                                peer_address->addrlen +
3386                                slen);
3387       memcpy(&message_buf[hello_size + sizeof (struct TransportPingMessage)],
3388              tp->short_name,
3389              slen);
3390       memcpy(&message_buf[hello_size + sizeof (struct TransportPingMessage) + slen],
3391              peer_address->addr,
3392              peer_address->addrlen);
3393     }
3394   else
3395     {
3396       ping.header.size = htons(sizeof(struct TransportPingMessage));
3397     }
3398
3399   memcpy(&message_buf[hello_size],
3400          &ping,
3401          sizeof(struct TransportPingMessage));
3402
3403 #if DEBUG_TRANSPORT_REVALIDATION
3404   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3405               "Performing re-validation of address `%s' via `%s' for peer `%4s' sending `%s' (%u bytes) and `%s'\n",
3406               (peer_address->addr != NULL)
3407               ? a2s (peer_address->plugin->short_name,
3408                      peer_address->addr,
3409                      peer_address->addrlen)
3410               : "<inbound>",
3411               tp->short_name,
3412               GNUNET_i2s (&neighbour->id),
3413               "HELLO", hello_size,
3414               "PING");
3415 #endif
3416   if (peer_address->validated != GNUNET_YES)
3417     GNUNET_STATISTICS_update (stats,
3418                               gettext_noop ("# PING with HELLO messages sent"),
3419                               1,
3420                               GNUNET_NO);
3421   else
3422     GNUNET_STATISTICS_update (stats,
3423                               gettext_noop ("# PING without HELLO messages sent"),
3424                               1,
3425                               GNUNET_NO);
3426   GNUNET_STATISTICS_update (stats,
3427                             gettext_noop ("# PING messages sent for re-validation"),
3428                             1,
3429                             GNUNET_NO);
3430   transmit_to_peer (NULL, peer_address,
3431                     GNUNET_SCHEDULER_PRIORITY_DEFAULT,
3432                     HELLO_VERIFICATION_TIMEOUT,
3433                     message_buf, tsize,
3434                     GNUNET_YES, neighbour);
3435   GNUNET_free(message_buf);
3436   schedule_next_ping (peer_address);
3437 }
3438
3439
3440 /**
3441  * Schedule the job that will cause us to send a PING to the
3442  * foreign address to evaluate its validity and latency.
3443  *
3444  * @param fal address to PING
3445  */
3446 static void
3447 schedule_next_ping (struct ForeignAddressList *fal)
3448 {
3449   struct GNUNET_TIME_Relative delay;
3450
3451   if (fal->revalidate_task != GNUNET_SCHEDULER_NO_TASK)
3452     return;
3453   delay = GNUNET_TIME_absolute_get_remaining (fal->expires);
3454   delay.rel_value /= 2; /* do before expiration */
3455   delay = GNUNET_TIME_relative_min (delay,
3456                                     LATENCY_EVALUATION_MAX_DELAY);
3457   if (GNUNET_YES != fal->estimated)
3458     {
3459       delay = GNUNET_TIME_UNIT_ZERO;
3460       fal->estimated = GNUNET_YES;
3461     }                           
3462   if (GNUNET_YES == fal->connected)
3463     {
3464       delay = GNUNET_TIME_relative_min (delay,
3465                                         CONNECTED_LATENCY_EVALUATION_MAX_DELAY);
3466     }
3467   /* FIXME: also adjust delay based on how close the last
3468      observed latency is to the latency of the best alternative */
3469   /* bound how fast we can go */
3470   delay = GNUNET_TIME_relative_max (delay,
3471                                     GNUNET_TIME_UNIT_SECONDS);
3472   /* randomize a bit (to avoid doing all at the same time) */
3473   delay.rel_value += GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 1000);
3474   fal->revalidate_task = GNUNET_SCHEDULER_add_delayed(delay,
3475                                                       &send_periodic_ping,
3476                                                       fal);
3477 }
3478
3479
3480
3481
3482 /**
3483  * Function that will be called if we receive some payload
3484  * from another peer.
3485  *
3486  * @param message the payload
3487  * @param n peer who claimed to be the sender
3488  */
3489 static void
3490 handle_payload_message (const struct GNUNET_MessageHeader *message,
3491                                                 struct NeighbourList *n)
3492 {
3493   struct InboundMessage *im;
3494   struct TransportClient *cpos;
3495   uint16_t msize;
3496
3497   msize = ntohs (message->size);
3498   if (n->received_pong == GNUNET_NO)
3499     {
3500       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3501                   "Received message of type %u and size %u from `%4s', but no pong yet!!\n",
3502                   ntohs (message->type),
3503                   ntohs (message->size),
3504                   GNUNET_i2s (&n->id));
3505       GNUNET_free_non_null (n->pre_connect_message_buffer);
3506       n->pre_connect_message_buffer = GNUNET_malloc (msize);
3507       memcpy (n->pre_connect_message_buffer, message, msize);
3508       return;
3509     }
3510
3511 #if DEBUG_TRANSPORT
3512   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3513               "Received message of type %u and size %u from `%4s', sending to all clients.\n",
3514               ntohs (message->type),
3515               ntohs (message->size),
3516               GNUNET_i2s (&n->id));
3517 #endif
3518   if (GNUNET_YES == GNUNET_BANDWIDTH_tracker_consume (&n->in_tracker,
3519                                                       (ssize_t) msize))
3520     {
3521       n->quota_violation_count++;
3522 #if DEBUG_TRANSPORT
3523       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,                      
3524                   "Bandwidth quota (%u b/s) violation detected (total of %u).\n",
3525                   n->in_tracker.available_bytes_per_s__,
3526                   n->quota_violation_count);
3527 #endif
3528       /* Discount 32k per violation */
3529       GNUNET_BANDWIDTH_tracker_consume (&n->in_tracker,
3530                                         - 32 * 1024);           
3531     }
3532   else
3533     {
3534       if (n->quota_violation_count > 0)
3535         {
3536           /* try to add 32k back */
3537           GNUNET_BANDWIDTH_tracker_consume (&n->in_tracker,
3538                                             32 * 1024);
3539           n->quota_violation_count--;
3540         }
3541     }
3542   GNUNET_STATISTICS_update (stats,
3543                             gettext_noop ("# payload received from other peers"),
3544                             msize,
3545                             GNUNET_NO);
3546   /* transmit message to all clients */
3547   uint32_t ats_count = 2;
3548   size_t size = sizeof (struct InboundMessage) + ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information) + msize;
3549   if (size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
3550           GNUNET_break(0);
3551
3552   im = GNUNET_malloc (size);
3553   im->header.size = htons (size);
3554   im->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RECV);
3555   im->peer = n->id;
3556   im->ats_count = htonl(ats_count);
3557   /* Setting ATS data */
3558   (&(im->ats))[0].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE);
3559   (&(im->ats))[0].value = htonl (n->distance);
3560   (&(im->ats))[1].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DELAY);
3561   (&(im->ats))[1].value = htonl ((uint32_t) n->latency.rel_value);
3562   (&(im->ats))[ats_count].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
3563   (&(im->ats))[ats_count].value = htonl (0);
3564
3565   memcpy (&((&(im->ats))[ats_count+1]), message, msize);
3566   cpos = clients;
3567   while (cpos != NULL)
3568     {
3569       transmit_to_client (cpos, &im->header, GNUNET_YES);
3570       cpos = cpos->next;
3571     }
3572   GNUNET_free (im);
3573 }
3574
3575
3576 /**
3577  * Iterator over hash map entries.  Checks if the given validation
3578  * entry is for the same challenge as what is given in the PONG.
3579  *
3580  * @param cls the 'struct TransportPongMessage*'
3581  * @param key peer identity
3582  * @param value value in the hash map ('struct ValidationEntry')
3583  * @return GNUNET_YES if we should continue to
3584  *         iterate (mismatch), GNUNET_NO if not (entry matched)
3585  */
3586 static int
3587 check_pending_validation (void *cls,
3588                           const GNUNET_HashCode * key,
3589                           void *value)
3590 {
3591   const struct TransportPongMessage *pong = cls;
3592   struct ValidationEntry *ve = value;
3593   struct AddValidatedAddressContext avac;
3594   unsigned int challenge = ntohl(pong->challenge);
3595   struct GNUNET_HELLO_Message *hello;
3596   struct GNUNET_PeerIdentity target;
3597   struct NeighbourList *n;
3598   struct ForeignAddressList *fal;
3599   struct OwnAddressList *oal;
3600   struct TransportPlugin *tp;
3601   struct GNUNET_MessageHeader *prem;
3602   uint16_t ps;
3603   const char *addr;
3604   size_t slen;
3605   size_t alen;
3606
3607   ps = ntohs (pong->header.size);
3608   if (ps < sizeof (struct TransportPongMessage))
3609     {
3610       GNUNET_break_op (0);
3611       return GNUNET_NO;
3612     }
3613   addr = (const char*) &pong[1];
3614   slen = strlen (ve->transport_name) + 1;
3615   if ( (ps - sizeof (struct TransportPongMessage) < slen) ||
3616        (ve->challenge != challenge) ||
3617        (addr[slen-1] != '\0') ||
3618        (0 != strcmp (addr, ve->transport_name)) ||
3619        (ntohl (pong->purpose.size)
3620         != sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) +
3621         sizeof (uint32_t) +
3622         sizeof (struct GNUNET_TIME_AbsoluteNBO) +
3623         sizeof (struct GNUNET_PeerIdentity) + ps - sizeof (struct TransportPongMessage)) )
3624     {
3625       return GNUNET_YES;
3626     }
3627
3628   alen = ps - sizeof (struct TransportPongMessage) - slen;
3629   switch (ntohl (pong->purpose.purpose))
3630     {
3631     case GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN:
3632       if ( (ve->addrlen + slen != ntohl (pong->addrlen)) ||
3633            (0 != memcmp (&addr[slen],
3634                          ve->addr,
3635                          ve->addrlen)) )
3636         {
3637           return GNUNET_YES; /* different entry, keep trying! */
3638         }
3639       if (0 != memcmp (&pong->pid,
3640                        key,
3641                        sizeof (struct GNUNET_PeerIdentity)))
3642         {
3643           GNUNET_break_op (0);
3644           return GNUNET_NO;
3645         }
3646       if (GNUNET_OK !=
3647           GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN,
3648                                     &pong->purpose,
3649                                     &pong->signature,
3650                                     &ve->publicKey))
3651         {
3652           GNUNET_break_op (0);
3653           return GNUNET_NO;
3654         }
3655
3656 #if DEBUG_TRANSPORT
3657       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3658                   "Confirmed validity of address, peer `%4s' has address `%s' (%s).\n",
3659                   GNUNET_h2s (key),
3660                   a2s (ve->transport_name,
3661                        (const struct sockaddr *) ve->addr,
3662                        ve->addrlen),
3663                   ve->transport_name);
3664 #endif
3665       break;
3666     case GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_USING:
3667       if (0 != memcmp (&pong->pid,
3668                          &my_identity,
3669                          sizeof (struct GNUNET_PeerIdentity)))
3670         {
3671           GNUNET_break_op (0);
3672           return GNUNET_NO;
3673         }
3674       if (ve->addrlen != 0)
3675         {
3676           /* must have been for a different validation entry */
3677           return GNUNET_YES;
3678         }
3679       tp = find_transport (ve->transport_name);
3680       if (tp == NULL)
3681         {
3682           GNUNET_break (0);
3683           return GNUNET_YES;
3684         }
3685       oal = tp->addresses;
3686       while (NULL != oal)
3687         {
3688           if ( (oal->addrlen == alen) &&
3689                (0 == memcmp (&oal[1],
3690                              &addr[slen],
3691                              alen)) )
3692             break;
3693           oal = oal->next;
3694         }
3695       if (oal == NULL)
3696         {
3697           GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3698                       _("Not accepting PONG with address `%s' since I cannot confirm having this address.\n"),
3699                       a2s (ve->transport_name,
3700                            &addr[slen],
3701                            alen));
3702           return GNUNET_NO;     
3703         }
3704       if (GNUNET_OK !=
3705           GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_USING,
3706                                     &pong->purpose,
3707                                     &pong->signature,
3708                                     &ve->publicKey))
3709         {
3710           GNUNET_break_op (0);
3711           return GNUNET_NO;
3712         }
3713
3714 #if DEBUG_TRANSPORT
3715       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3716                   "Confirmed that peer `%4s' is talking to us using address `%s' (%s) for us.\n",
3717                   GNUNET_h2s (key),
3718                   a2s (ve->transport_name,
3719                        &addr[slen],
3720                        alen),
3721                   ve->transport_name);
3722 #endif
3723       break;
3724     default:
3725       GNUNET_break_op (0);
3726       return GNUNET_NO;
3727     }
3728   if (GNUNET_TIME_absolute_get_remaining (GNUNET_TIME_absolute_ntoh (pong->expiration)).rel_value == 0)
3729     {
3730       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3731                   _("Received expired signature.  Check system time.\n"));
3732       return GNUNET_NO;
3733     }
3734   GNUNET_STATISTICS_update (stats,
3735                             gettext_noop ("# address validation successes"),
3736                             1,
3737                             GNUNET_NO);
3738   /* create the updated HELLO */
3739   GNUNET_CRYPTO_hash (&ve->publicKey,
3740                       sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
3741                       &target.hashPubKey);
3742   if (ve->addr != NULL)
3743     {
3744       avac.done = GNUNET_NO;
3745       avac.ve = ve;
3746       hello = GNUNET_HELLO_create (&ve->publicKey,
3747                                    &add_validated_address,
3748                                    &avac);
3749       GNUNET_PEERINFO_add_peer (peerinfo,
3750                                 hello);
3751       GNUNET_free (hello);
3752     }
3753   n = find_neighbour (&target);
3754   if (n != NULL)
3755     {
3756       n->publicKey = ve->publicKey;
3757       n->public_key_valid = GNUNET_YES;
3758       fal = add_peer_address (n,
3759                               ve->transport_name,
3760                               ve->session,
3761                               ve->addr,
3762                               ve->addrlen);
3763       GNUNET_assert (fal != NULL);
3764       fal->expires = GNUNET_TIME_relative_to_absolute (HELLO_ADDRESS_EXPIRATION);
3765       fal->validated = GNUNET_YES;
3766       mark_address_connected (fal);
3767       GNUNET_STATISTICS_update (stats,
3768                                 gettext_noop ("# peer addresses considered valid"),
3769                                 1,
3770                                 GNUNET_NO);
3771       fal->latency = GNUNET_TIME_absolute_get_duration (ve->send_time);
3772       schedule_next_ping (fal);
3773       if (n->latency.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
3774         n->latency = fal->latency;
3775       else
3776         n->latency.rel_value = (fal->latency.rel_value + n->latency.rel_value) / 2;
3777
3778       n->distance = fal->distance;
3779       if (GNUNET_NO == n->received_pong)
3780         {
3781           n->received_pong = GNUNET_YES;
3782
3783           notify_clients_connect (&target, n->latency, n->distance);
3784           if (NULL != (prem = n->pre_connect_message_buffer))
3785             {
3786               n->pre_connect_message_buffer = NULL;
3787               handle_payload_message (prem, n);
3788               GNUNET_free (prem);
3789             }
3790         }
3791       if (n->retry_task != GNUNET_SCHEDULER_NO_TASK)
3792         {
3793           GNUNET_SCHEDULER_cancel (n->retry_task);
3794           n->retry_task = GNUNET_SCHEDULER_NO_TASK;
3795           try_transmission_to_peer (n);
3796         }
3797     }
3798
3799   /* clean up validation entry */
3800   GNUNET_assert (GNUNET_YES ==
3801                  GNUNET_CONTAINER_multihashmap_remove (validation_map,
3802                                                        key,
3803                                                        ve));
3804   abort_validation (NULL, NULL, ve);
3805   return GNUNET_NO;
3806 }
3807
3808
3809 /**
3810  * Function that will be called if we receive a validation
3811  * of an address challenge that we transmitted to another
3812  * peer.  Note that the validation should only be considered
3813  * acceptable if the challenge matches AND if the sender
3814  * address is at least a plausible address for this peer
3815  * (otherwise we may be seeing a MiM attack).
3816  *
3817  * @param cls closure
3818  * @param message the pong message
3819  * @param peer who responded to our challenge
3820  * @param sender_address string describing our sender address (as observed
3821  *         by the other peer in binary format)
3822  * @param sender_address_len number of bytes in 'sender_address'
3823  */
3824 static void
3825 handle_pong (void *cls, const struct GNUNET_MessageHeader *message,
3826              const struct GNUNET_PeerIdentity *peer,
3827              const char *sender_address,
3828              size_t sender_address_len)
3829 {
3830 #if DEBUG_TRANSPORT > 1
3831   /* we get tons of these that just get discarded, only log
3832      if we are quite verbose */
3833   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3834               "Receiving `%s' message from `%4s'.\n", "PONG",
3835               GNUNET_i2s (peer));
3836 #endif
3837   GNUNET_STATISTICS_update (stats,
3838                             gettext_noop ("# PONG messages received"),
3839                             1,
3840                             GNUNET_NO);
3841   if (GNUNET_SYSERR !=
3842       GNUNET_CONTAINER_multihashmap_get_multiple (validation_map,
3843                                                   &peer->hashPubKey,
3844                                                   &check_pending_validation,
3845                                                   (void*) message))
3846     {
3847       /* This is *expected* to happen a lot since we send
3848          PONGs to *all* known addresses of the sender of
3849          the PING, so most likely we get multiple PONGs
3850          per PING, and all but the first PONG will end up
3851          here. So really we should not print anything here
3852          unless we want to be very, very verbose... */
3853 #if DEBUG_TRANSPORT > 2
3854       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3855                   "Received `%s' message from `%4s' but have no record of a matching `%s' message. Ignoring.\n",
3856                   "PONG",
3857                   GNUNET_i2s (peer),
3858                   "PING");
3859 #endif
3860       return;
3861     }
3862
3863 }
3864
3865
3866 /**
3867  * Try to validate a neighbour's address by sending him our HELLO and a PING.
3868  *
3869  * @param cls the 'struct ValidationEntry*'
3870  * @param neighbour neighbour to validate, NULL if validation failed
3871  */
3872 static void
3873 transmit_hello_and_ping (void *cls,
3874                          struct NeighbourList *neighbour)
3875 {
3876   struct ValidationEntry *va = cls;
3877   struct ForeignAddressList *peer_address;
3878   struct TransportPingMessage ping;
3879   uint16_t hello_size;
3880   size_t tsize;
3881   char * message_buf;
3882   struct GNUNET_PeerIdentity id;
3883   size_t slen;
3884
3885   GNUNET_CRYPTO_hash (&va->publicKey,
3886                       sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
3887                       &id.hashPubKey);
3888   if (neighbour == NULL)
3889     {
3890       /* FIXME: stats... */
3891       GNUNET_break (GNUNET_OK ==
3892                     GNUNET_CONTAINER_multihashmap_remove (validation_map,
3893                                                           &id.hashPubKey,
3894                                                           va));
3895       abort_validation (NULL, NULL, va);
3896       return;
3897     }
3898   neighbour->publicKey = va->publicKey;
3899   neighbour->public_key_valid = GNUNET_YES;
3900   peer_address = add_peer_address (neighbour,
3901                                    va->transport_name, NULL,
3902                                    (const void*) &va[1],
3903                                    va->addrlen);
3904   if (peer_address == NULL)
3905     {
3906       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3907                   "Failed to add peer `%4s' for plugin `%s'\n",
3908                   GNUNET_i2s (&neighbour->id),
3909                   va->transport_name);
3910       GNUNET_break (GNUNET_OK ==
3911                     GNUNET_CONTAINER_multihashmap_remove (validation_map,
3912                                                           &id.hashPubKey,
3913                                                           va));
3914       abort_validation (NULL, NULL, va);
3915       return;
3916     }
3917   hello_size = GNUNET_HELLO_size(our_hello);
3918   slen = strlen(va->transport_name) + 1;
3919   tsize = sizeof(struct TransportPingMessage) + hello_size + va->addrlen + slen;
3920   message_buf = GNUNET_malloc(tsize);
3921   ping.challenge = htonl(va->challenge);
3922   ping.header.size = htons(sizeof(struct TransportPingMessage) + slen + va->addrlen);
3923   ping.header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_PING);
3924   memcpy(&ping.target, &neighbour->id, sizeof(struct GNUNET_PeerIdentity));
3925   memcpy(message_buf, our_hello, hello_size);
3926   memcpy(&message_buf[hello_size],
3927          &ping,
3928          sizeof(struct TransportPingMessage));
3929   memcpy(&message_buf[hello_size + sizeof (struct TransportPingMessage)],
3930          va->transport_name,
3931          slen);
3932   memcpy(&message_buf[hello_size + sizeof (struct TransportPingMessage) + slen],
3933          &va[1],
3934          va->addrlen);
3935 #if DEBUG_TRANSPORT
3936   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3937               "Performing validation of address `%s' via `%s' for peer `%4s' sending `%s' (%u bytes) and `%s' (%u bytes)\n",
3938               (va->addrlen == 0)
3939               ? "<inbound>"
3940               : a2s (va->transport_name,
3941                      (const void*) &va[1], va->addrlen),
3942               va->transport_name,
3943               GNUNET_i2s (&neighbour->id),
3944               "HELLO", hello_size,
3945               "PING", sizeof (struct TransportPingMessage) + va->addrlen + slen);
3946 #endif
3947
3948   GNUNET_STATISTICS_update (stats,
3949                             gettext_noop ("# PING messages sent for initial validation"),
3950                             1,
3951                             GNUNET_NO);
3952   transmit_to_peer (NULL, peer_address,
3953                     GNUNET_SCHEDULER_PRIORITY_DEFAULT,
3954                     HELLO_VERIFICATION_TIMEOUT,
3955                     message_buf, tsize,
3956                     GNUNET_YES, neighbour);
3957   GNUNET_free(message_buf);
3958 }
3959
3960
3961 /**
3962  * Check if the given address is already being validated; if not,
3963  * append the given address to the list of entries that are being be
3964  * validated and initiate validation.
3965  *
3966  * @param cls closure ('struct CheckHelloValidatedContext *')
3967  * @param tname name of the transport
3968  * @param expiration expiration time
3969  * @param addr the address
3970  * @param addrlen length of the address
3971  * @return GNUNET_OK (always)
3972  */
3973 static int
3974 run_validation (void *cls,
3975                 const char *tname,
3976                 struct GNUNET_TIME_Absolute expiration,
3977                 const void *addr,
3978                 uint16_t addrlen)
3979 {
3980   struct CheckHelloValidatedContext *chvc = cls;
3981   struct GNUNET_PeerIdentity id;
3982   struct TransportPlugin *tp;
3983   struct ValidationEntry *va;
3984   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pk;
3985   struct CheckAddressExistsClosure caec;
3986   struct OwnAddressList *oal;
3987
3988   GNUNET_assert (addr != NULL);
3989
3990   GNUNET_STATISTICS_update (stats,
3991                             gettext_noop ("# peer addresses scheduled for validation"),
3992                             1,
3993                             GNUNET_NO);
3994   tp = find_transport (tname);
3995   if (tp == NULL)
3996     {
3997       GNUNET_log (GNUNET_ERROR_TYPE_INFO |
3998                   GNUNET_ERROR_TYPE_BULK,
3999                   _
4000                   ("Transport `%s' not loaded, will not try to validate peer address using this transport.\n"),
4001                   tname);
4002       GNUNET_STATISTICS_update (stats,
4003                                 gettext_noop ("# peer addresses not validated (plugin not available)"),
4004                                 1,
4005                                 GNUNET_NO);
4006       return GNUNET_OK;
4007     }
4008   /* check if this is one of our own addresses */
4009   oal = tp->addresses;
4010   while (NULL != oal)
4011     {
4012       if ( (oal->addrlen == addrlen) &&
4013            (0 == memcmp (&oal[1],
4014                          addr,
4015                          addrlen)) )
4016         {
4017           /* not plausible, this address is equivalent to our own address! */
4018           GNUNET_STATISTICS_update (stats,
4019                                     gettext_noop ("# peer addresses not validated (loopback)"),
4020                                     1,
4021                                     GNUNET_NO);
4022           return GNUNET_OK;
4023         }
4024       oal = oal->next;
4025     }
4026   GNUNET_HELLO_get_key (chvc->hello, &pk);
4027   GNUNET_CRYPTO_hash (&pk,
4028                       sizeof (struct
4029                               GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
4030                       &id.hashPubKey);
4031
4032   if (is_blacklisted(&id, tp))
4033     {
4034 #if DEBUG_TRANSPORT
4035       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4036                   "Attempted to validate blacklisted peer `%s' using `%s'!\n",
4037                   GNUNET_i2s(&id),
4038                   tname);
4039 #endif
4040       return GNUNET_OK;
4041     }
4042
4043   caec.addr = addr;
4044   caec.addrlen = addrlen;
4045   caec.session = NULL;
4046   caec.tname = tname;
4047   caec.exists = GNUNET_NO;
4048   GNUNET_CONTAINER_multihashmap_iterate (validation_map,
4049                                          &check_address_exists,
4050                                          &caec);
4051   if (caec.exists == GNUNET_YES)
4052     {
4053       /* During validation attempts we will likely trigger the other
4054          peer trying to validate our address which in turn will cause
4055          it to send us its HELLO, so we expect to hit this case rather
4056          frequently.  Only print something if we are very verbose. */
4057 #if DEBUG_TRANSPORT > 1
4058       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4059                   "Validation of address `%s' via `%s' for peer `%4s' already in progress.\n",
4060                   a2s (tname, addr, addrlen),
4061                   tname,
4062                   GNUNET_i2s (&id));
4063 #endif
4064       GNUNET_STATISTICS_update (stats,
4065                                 gettext_noop ("# peer addresses not validated (in progress)"),
4066                                 1,
4067                                 GNUNET_NO);
4068       return GNUNET_OK;
4069     }
4070   va = GNUNET_malloc (sizeof (struct ValidationEntry) + addrlen);
4071   va->chvc = chvc;
4072   chvc->ve_count++;
4073   va->transport_name = GNUNET_strdup (tname);
4074   va->challenge = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
4075                                             UINT_MAX);
4076   va->send_time = GNUNET_TIME_absolute_get();
4077   va->addr = (const void*) &va[1];
4078   memcpy (&va[1], addr, addrlen);
4079   va->addrlen = addrlen;
4080   GNUNET_HELLO_get_key (chvc->hello,
4081                         &va->publicKey);
4082   va->timeout_task = GNUNET_SCHEDULER_add_delayed (HELLO_VERIFICATION_TIMEOUT,
4083                                                    &timeout_hello_validation,
4084                                                    va);
4085   GNUNET_CONTAINER_multihashmap_put (validation_map,
4086                                      &id.hashPubKey,
4087                                      va,
4088                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
4089   setup_peer_check_blacklist (&id, GNUNET_NO,
4090                               &transmit_hello_and_ping,
4091                               va);
4092   return GNUNET_OK;
4093 }
4094
4095
4096 /**
4097  * Check if addresses in validated hello "h" overlap with
4098  * those in "chvc->hello" and validate the rest.
4099  *
4100  * @param cls closure
4101  * @param peer id of the peer, NULL for last call
4102  * @param h hello message for the peer (can be NULL)
4103  * @param err_msg NULL if successful, otherwise contains error message
4104  */
4105 static void
4106 check_hello_validated (void *cls,
4107                        const struct GNUNET_PeerIdentity *peer,
4108                        const struct GNUNET_HELLO_Message *h,
4109                        const char *err_msg)
4110 {
4111   struct CheckHelloValidatedContext *chvc = cls;
4112   struct GNUNET_HELLO_Message *plain_hello;
4113   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pk;
4114   struct GNUNET_PeerIdentity target;
4115   struct NeighbourList *n;
4116
4117   if (err_msg != NULL)
4118   {
4119     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4120                 _("Error in communication with PEERINFO service\n"));
4121    /* return; */
4122   }
4123
4124   if (peer == NULL)
4125     {
4126       GNUNET_STATISTICS_update (stats,
4127                                 gettext_noop ("# outstanding peerinfo iterate requests"),
4128                                 -1,
4129                                 GNUNET_NO);
4130       chvc->piter = NULL;
4131       if (GNUNET_NO == chvc->hello_known)
4132         {
4133           /* notify PEERINFO about the peer now, so that we at least
4134              have the public key if some other component needs it */
4135           GNUNET_HELLO_get_key (chvc->hello, &pk);
4136           GNUNET_CRYPTO_hash (&pk,
4137                               sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
4138                               &target.hashPubKey);
4139           plain_hello = GNUNET_HELLO_create (&pk,
4140                                              NULL,
4141                                              NULL);
4142           GNUNET_PEERINFO_add_peer (peerinfo, plain_hello);
4143           GNUNET_free (plain_hello);
4144 #if DEBUG_TRANSPORT_HELLO
4145           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4146                       "PEERINFO had no `%s' message for peer `%4s', full validation needed.\n",
4147                       "HELLO",
4148                       GNUNET_i2s (&target));
4149 #endif
4150           GNUNET_STATISTICS_update (stats,
4151                                     gettext_noop ("# new HELLOs requiring full validation"),
4152                                     1,
4153                                     GNUNET_NO);
4154           GNUNET_HELLO_iterate_addresses (chvc->hello,
4155                                           GNUNET_NO,
4156                                           &run_validation,
4157                                           chvc);
4158         }
4159       else
4160         {
4161           GNUNET_STATISTICS_update (stats,
4162                                     gettext_noop ("# duplicate HELLO (peer known)"),
4163                                     1,
4164                                     GNUNET_NO);
4165         }
4166       chvc->ve_count--;
4167       if (chvc->ve_count == 0)
4168         {
4169           GNUNET_CONTAINER_DLL_remove (chvc_head,
4170                                        chvc_tail,
4171                                        chvc);
4172           GNUNET_free (chvc);   
4173         }
4174       return;
4175     }
4176   if (h == NULL)
4177     return;
4178 #if DEBUG_TRANSPORT_HELLO
4179   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4180               "PEERINFO had `%s' message for peer `%4s', validating only new addresses.\n",
4181               "HELLO",
4182               GNUNET_i2s (peer));
4183 #endif
4184   chvc->hello_known = GNUNET_YES;
4185   n = find_neighbour (peer);
4186   if (n != NULL)
4187     {
4188 #if DEBUG_TRANSPORT_HELLO
4189       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4190                   "Calling hello_iterate_addresses for %s!\n",
4191                   GNUNET_i2s (peer));
4192 #endif
4193       GNUNET_HELLO_iterate_addresses (h,
4194                                       GNUNET_NO,
4195                                       &add_to_foreign_address_list,
4196                                       n);
4197       try_transmission_to_peer (n);
4198     }
4199   else
4200     {
4201 #if DEBUG_TRANSPORT_HELLO
4202       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4203                   "No existing neighbor record for %s!\n",
4204                   GNUNET_i2s (peer));
4205 #endif
4206       GNUNET_STATISTICS_update (stats,
4207                                 gettext_noop ("# no existing neighbour record (validating HELLO)"),
4208                                 1,
4209                                 GNUNET_NO);
4210     }
4211   GNUNET_STATISTICS_update (stats,
4212                             gettext_noop ("# HELLO validations (update case)"),
4213                             1,
4214                             GNUNET_NO);
4215   GNUNET_HELLO_iterate_new_addresses (chvc->hello,
4216                                       h,
4217                                       GNUNET_TIME_relative_to_absolute (HELLO_REVALIDATION_START_TIME),
4218                                       &run_validation,
4219                                       chvc);
4220 }
4221
4222
4223 /**
4224  * Process HELLO-message.
4225  *
4226  * @param plugin transport involved, may be NULL
4227  * @param message the actual message
4228  * @return GNUNET_OK if the HELLO was well-formed, GNUNET_SYSERR otherwise
4229  */
4230 static int
4231 process_hello (struct TransportPlugin *plugin,
4232                const struct GNUNET_MessageHeader *message)
4233 {
4234   uint16_t hsize;
4235   struct GNUNET_PeerIdentity target;
4236   const struct GNUNET_HELLO_Message *hello;
4237   struct CheckHelloValidatedContext *chvc;
4238   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded publicKey;
4239 #if DEBUG_TRANSPORT_HELLO > 2
4240   char *my_id;
4241 #endif
4242   hsize = ntohs (message->size);
4243   if ((ntohs (message->type) != GNUNET_MESSAGE_TYPE_HELLO) ||
4244       (hsize < sizeof (struct GNUNET_MessageHeader)))
4245     {
4246       GNUNET_break (0);
4247       return GNUNET_SYSERR;
4248     }
4249   GNUNET_STATISTICS_update (stats,
4250                             gettext_noop ("# HELLOs received for validation"),
4251                             1,
4252                             GNUNET_NO);
4253
4254   /* first, check if load is too high */
4255   if (GNUNET_SCHEDULER_get_load (GNUNET_SCHEDULER_PRIORITY_BACKGROUND) > MAX_HELLO_LOAD)
4256     {
4257       GNUNET_STATISTICS_update (stats,
4258                                 gettext_noop ("# HELLOs ignored due to high load"),
4259                                 1,
4260                                 GNUNET_NO);
4261 #if DEBUG_TRANSPORT_HELLO
4262       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4263                   "Ignoring `%s' for `%4s', load too high.\n",
4264                   "HELLO",
4265                   GNUNET_i2s (&target));
4266 #endif
4267       return GNUNET_OK;
4268     }
4269   hello = (const struct GNUNET_HELLO_Message *) message;
4270   if (GNUNET_OK != GNUNET_HELLO_get_key (hello, &publicKey))
4271     {
4272 #if DEBUG_TRANSPORT_HELLO
4273       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4274                   "Unable to get public key from `%s' for `%4s'!\n",
4275                   "HELLO",
4276                   GNUNET_i2s (&target));
4277 #endif
4278       GNUNET_break_op (0);
4279       return GNUNET_SYSERR;
4280     }
4281
4282   GNUNET_CRYPTO_hash (&publicKey,
4283                       sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
4284                       &target.hashPubKey);
4285
4286 #if DEBUG_TRANSPORT_HELLO
4287   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4288               "Received `%s' message for `%4s'\n",
4289               "HELLO",
4290               GNUNET_i2s (&target));
4291 #endif
4292
4293   if (0 == memcmp (&my_identity,
4294                    &target,
4295                    sizeof (struct GNUNET_PeerIdentity)))
4296     {
4297       GNUNET_STATISTICS_update (stats,
4298                                 gettext_noop ("# HELLOs ignored for validation (is my own HELLO)"),
4299                                 1,
4300                                 GNUNET_NO);
4301       return GNUNET_OK;
4302     }
4303   chvc = chvc_head;
4304   while (NULL != chvc)
4305     {
4306       if (GNUNET_HELLO_equals (hello,
4307                                chvc->hello,
4308                                GNUNET_TIME_absolute_get ()).abs_value > 0)
4309         {
4310 #if DEBUG_TRANSPORT_HELLO > 2
4311           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4312                       "Received duplicate `%s' message for `%4s'; ignored\n",
4313                       "HELLO",
4314                       GNUNET_i2s (&target));
4315 #endif
4316           return GNUNET_OK; /* validation already pending */
4317         }
4318       if (GNUNET_HELLO_size(hello) == GNUNET_HELLO_size (chvc->hello))
4319         GNUNET_break (0 != memcmp (hello, chvc->hello,
4320                                    GNUNET_HELLO_size(hello)));
4321       chvc = chvc->next;
4322     }
4323
4324 #if BREAK_TESTS
4325   struct NeighbourList *temp_neighbor = find_neighbour(&target);
4326   if ((NULL != temp_neighbor))
4327     {
4328       fprintf(stderr, "Already know peer, ignoring hello\n");
4329       return GNUNET_OK;
4330     }
4331 #endif
4332
4333 #if DEBUG_TRANSPORT_HELLO > 2
4334   if (plugin != NULL)
4335     {
4336       my_id = GNUNET_strdup(GNUNET_i2s(plugin->env.my_identity));
4337       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4338                   "%s: Starting validation of `%s' message for `%4s' via '%s' of size %u\n",
4339                   my_id,
4340                   "HELLO",
4341                   GNUNET_i2s (&target),
4342                   plugin->short_name,
4343                   GNUNET_HELLO_size(hello));
4344       GNUNET_free(my_id);
4345     }
4346 #endif
4347   chvc = GNUNET_malloc (sizeof (struct CheckHelloValidatedContext) + hsize);
4348   chvc->ve_count = 1;
4349   chvc->hello = (const struct GNUNET_HELLO_Message *) &chvc[1];
4350   memcpy (&chvc[1], hello, hsize);
4351   GNUNET_CONTAINER_DLL_insert (chvc_head,
4352                                chvc_tail,
4353                                chvc);
4354   /* finally, check if HELLO was previously validated
4355      (continuation will then schedule actual validation) */
4356   GNUNET_STATISTICS_update (stats,
4357                             gettext_noop ("# peerinfo process hello iterate requests"),
4358                             1,
4359                             GNUNET_NO);
4360   GNUNET_STATISTICS_update (stats,
4361                             gettext_noop ("# outstanding peerinfo iterate requests"),
4362                             1,
4363                             GNUNET_NO);
4364   chvc->piter = GNUNET_PEERINFO_iterate (peerinfo,
4365                                          &target,
4366                                          HELLO_VERIFICATION_TIMEOUT,
4367                                          &check_hello_validated, chvc);
4368   return GNUNET_OK;
4369 }
4370
4371
4372 /**
4373  * The peer specified by the given neighbour has timed-out or a plugin
4374  * has disconnected.  We may either need to do nothing (other plugins
4375  * still up), or trigger a full disconnect and clean up.  This
4376  * function updates our state and does the necessary notifications.
4377  * Also notifies our clients that the neighbour is now officially
4378  * gone.
4379  *
4380  * @param n the neighbour list entry for the peer
4381  * @param check GNUNET_YES to check if ALL addresses for this peer
4382  *              are gone, GNUNET_NO to force a disconnect of the peer
4383  *              regardless of whether other addresses exist.
4384  */
4385 static void
4386 disconnect_neighbour (struct NeighbourList *n, int check)
4387 {
4388   struct ReadyList *rpos;
4389   struct NeighbourList *npos;
4390   struct NeighbourList *nprev;
4391   struct MessageQueue *mq;
4392   struct ForeignAddressList *peer_addresses;
4393   struct ForeignAddressList *peer_pos;
4394
4395   if (GNUNET_YES == check)
4396     {
4397       rpos = n->plugins;
4398       while (NULL != rpos)
4399         {
4400           peer_addresses = rpos->addresses;
4401           while (peer_addresses != NULL)
4402             {
4403               if (GNUNET_YES == peer_addresses->connected)
4404                 {
4405                   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4406                             "NOT Disconnecting from `%4s', still have live addresses!\n",
4407                             GNUNET_i2s (&n->id));
4408                   return;             /* still connected */
4409                 }
4410               peer_addresses = peer_addresses->next;
4411             }
4412           rpos = rpos->next;
4413         }
4414     }
4415 #if DEBUG_TRANSPORT
4416   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
4417               "Disconnecting from `%4s'\n",
4418               GNUNET_i2s (&n->id));
4419 #endif
4420   /* remove n from neighbours list */
4421   nprev = NULL;
4422   npos = neighbours;
4423   while ((npos != NULL) && (npos != n))
4424     {
4425       nprev = npos;
4426       npos = npos->next;
4427     }
4428   GNUNET_assert (npos != NULL);
4429   if (nprev == NULL)
4430     neighbours = n->next;
4431   else
4432     nprev->next = n->next;
4433
4434   /* notify all clients about disconnect */
4435   if (GNUNET_YES == n->received_pong)
4436     notify_clients_disconnect (&n->id);
4437
4438   /* clean up all plugins, cancel connections and pending transmissions */
4439   while (NULL != (rpos = n->plugins))
4440     {
4441       n->plugins = rpos->next;
4442       rpos->plugin->api->disconnect (rpos->plugin->api->cls, &n->id);
4443       while (rpos->addresses != NULL)
4444         {
4445           peer_pos = rpos->addresses;
4446           rpos->addresses = peer_pos->next;
4447           if (peer_pos->connected == GNUNET_YES)
4448             GNUNET_STATISTICS_update (stats,
4449                                       gettext_noop ("# connected addresses"),
4450                                       -1,
4451                                       GNUNET_NO);
4452           if (GNUNET_YES == peer_pos->validated)
4453             GNUNET_STATISTICS_update (stats,
4454                                       gettext_noop ("# peer addresses considered valid"),
4455                                       -1,
4456                                       GNUNET_NO);
4457           if (GNUNET_SCHEDULER_NO_TASK != peer_pos->revalidate_task)
4458             {
4459               GNUNET_SCHEDULER_cancel (peer_pos->revalidate_task);
4460               peer_pos->revalidate_task = GNUNET_SCHEDULER_NO_TASK;
4461             }
4462           GNUNET_free(peer_pos);
4463         }
4464       GNUNET_free (rpos);
4465     }
4466
4467   /* free all messages on the queue */
4468   while (NULL != (mq = n->messages_head))
4469     {
4470       GNUNET_STATISTICS_update (stats,
4471                                 gettext_noop ("# bytes in message queue for other peers"),
4472                                 - (int64_t) mq->message_buf_size,
4473                                 GNUNET_NO);
4474       GNUNET_STATISTICS_update (stats,
4475                                 gettext_noop ("# bytes discarded due to disconnect"),
4476                                 mq->message_buf_size,
4477                                 GNUNET_NO);
4478       GNUNET_CONTAINER_DLL_remove (n->messages_head,
4479                                    n->messages_tail,
4480                                    mq);
4481       GNUNET_assert (0 == memcmp(&mq->neighbour_id,
4482                                  &n->id,
4483                                  sizeof(struct GNUNET_PeerIdentity)));
4484       GNUNET_free (mq);
4485     }
4486   if (n->timeout_task != GNUNET_SCHEDULER_NO_TASK)
4487     {
4488       GNUNET_SCHEDULER_cancel (n->timeout_task);
4489       n->timeout_task = GNUNET_SCHEDULER_NO_TASK;
4490     }
4491   if (n->retry_task != GNUNET_SCHEDULER_NO_TASK)
4492     {
4493       GNUNET_SCHEDULER_cancel (n->retry_task);
4494       n->retry_task = GNUNET_SCHEDULER_NO_TASK;
4495     }
4496   if (n->piter != NULL)
4497     {
4498       GNUNET_PEERINFO_iterate_cancel (n->piter);
4499       GNUNET_STATISTICS_update (stats,
4500                                 gettext_noop ("# outstanding peerinfo iterate requests"),
4501                                 -1,
4502                                 GNUNET_NO);
4503       n->piter = NULL;
4504     }
4505   /* finally, free n itself */
4506   GNUNET_STATISTICS_update (stats,
4507                             gettext_noop ("# active neighbours"),
4508                             -1,
4509                             GNUNET_NO);
4510   GNUNET_free_non_null (n->pre_connect_message_buffer);
4511   GNUNET_free (n);
4512 }
4513
4514
4515 /**
4516  * We have received a PING message from someone.  Need to send a PONG message
4517  * in response to the peer by any means necessary.
4518  */
4519 static int
4520 handle_ping(void *cls, const struct GNUNET_MessageHeader *message,
4521             const struct GNUNET_PeerIdentity *peer,
4522             struct Session *session,
4523             const char *sender_address,
4524             uint16_t sender_address_len)
4525 {
4526   struct TransportPlugin *plugin = cls;
4527   struct SessionHeader *session_header = (struct SessionHeader*) session;
4528   struct TransportPingMessage *ping;
4529   struct TransportPongMessage *pong;
4530   struct NeighbourList *n;
4531   struct ReadyList *rl;
4532   struct ForeignAddressList *fal;
4533   struct OwnAddressList *oal;
4534   const char *addr;
4535   size_t alen;
4536   size_t slen;
4537
4538   if (ntohs (message->size) < sizeof (struct TransportPingMessage))
4539     {
4540       GNUNET_break_op (0);
4541       return GNUNET_SYSERR;
4542     }
4543
4544   ping = (struct TransportPingMessage *) message;
4545   if (0 != memcmp (&ping->target,
4546                    plugin->env.my_identity,
4547                    sizeof (struct GNUNET_PeerIdentity)))
4548     {
4549       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4550                   _("Received `%s' message from `%s' destined for `%s' which is not me!\n"),
4551                   "PING",
4552                   (sender_address != NULL)
4553                   ? a2s (plugin->short_name,
4554                          (const struct sockaddr *)sender_address,
4555                          sender_address_len)
4556                   : "<inbound>",
4557                   GNUNET_i2s (&ping->target));
4558       return GNUNET_SYSERR;
4559     }
4560 #if DEBUG_PING_PONG
4561   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
4562               "Processing `%s' from `%s'\n",
4563               "PING",
4564               (sender_address != NULL)
4565               ? a2s (plugin->short_name,
4566                      (const struct sockaddr *)sender_address,
4567                      sender_address_len)
4568               : "<inbound>");
4569 #endif
4570   GNUNET_STATISTICS_update (stats,
4571                             gettext_noop ("# PING messages received"),
4572                             1,
4573                             GNUNET_NO);
4574   addr = (const char*) &ping[1];
4575   alen = ntohs (message->size) - sizeof (struct TransportPingMessage);
4576   slen = strlen (plugin->short_name) + 1;
4577   if (alen == 0)
4578     {
4579       /* peer wants to confirm that we have an outbound connection to him */
4580       if (session == NULL)
4581         {
4582           GNUNET_log (GNUNET_ERROR_TYPE_INFO,
4583                       _("Refusing to create PONG since I do not have a session with `%s'.\n"),
4584                       GNUNET_i2s (peer));
4585           return GNUNET_SYSERR;
4586         }
4587       pong = GNUNET_malloc (sizeof (struct TransportPongMessage) + sender_address_len + slen);
4588       pong->header.size = htons (sizeof (struct TransportPongMessage) + sender_address_len + slen);
4589       pong->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_PONG);
4590       pong->purpose.size =
4591         htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) +
4592                sizeof (uint32_t) +
4593                sizeof (struct GNUNET_TIME_AbsoluteNBO) +
4594                sizeof (struct GNUNET_PeerIdentity) + sender_address_len + slen);
4595       pong->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_USING);
4596       pong->challenge = ping->challenge;
4597       pong->addrlen = htonl(sender_address_len + slen);
4598       memcpy(&pong->pid,
4599              peer,
4600              sizeof(struct GNUNET_PeerIdentity));
4601       memcpy (&pong[1],
4602               plugin->short_name,
4603               slen);
4604       if ((sender_address!=NULL) && (sender_address_len > 0))
4605                   memcpy (&((char*)&pong[1])[slen],
4606                           sender_address,
4607                           sender_address_len);
4608       if (GNUNET_TIME_absolute_get_remaining (session_header->pong_sig_expires).rel_value < PONG_SIGNATURE_LIFETIME.rel_value / 4)
4609         {
4610           /* create / update cached sig */
4611 #if DEBUG_TRANSPORT
4612           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4613                       "Creating PONG signature to indicate active connection.\n");
4614 #endif
4615           session_header->pong_sig_expires = GNUNET_TIME_relative_to_absolute (PONG_SIGNATURE_LIFETIME);
4616           pong->expiration = GNUNET_TIME_absolute_hton (session_header->pong_sig_expires);
4617           GNUNET_assert (GNUNET_OK ==
4618                          GNUNET_CRYPTO_rsa_sign (my_private_key,
4619                                                  &pong->purpose,
4620                                                  &session_header->pong_signature));
4621         }
4622       else
4623         {
4624           pong->expiration = GNUNET_TIME_absolute_hton (session_header->pong_sig_expires);
4625         }
4626       memcpy (&pong->signature,
4627               &session_header->pong_signature,
4628               sizeof (struct GNUNET_CRYPTO_RsaSignature));
4629
4630
4631     }
4632   else
4633     {
4634       /* peer wants to confirm that this is one of our addresses */
4635       addr += slen;
4636       alen -= slen;
4637       if (GNUNET_OK !=
4638           plugin->api->check_address (plugin->api->cls,
4639                                       addr,
4640                                       alen))
4641         {
4642           GNUNET_log (GNUNET_ERROR_TYPE_INFO,
4643                       _("Not confirming PING with address `%s' since I cannot confirm having this address.\n"),
4644                       a2s (plugin->short_name,
4645                            addr,
4646                            alen));
4647           return GNUNET_NO;
4648         }
4649       oal = plugin->addresses;
4650       while (NULL != oal)
4651         {
4652           if ( (oal->addrlen == alen) &&
4653                (0 == memcmp (addr,
4654                              &oal[1],
4655                              alen)) )
4656             break;
4657           oal = oal->next;
4658         }
4659       pong = GNUNET_malloc (sizeof (struct TransportPongMessage) + alen + slen);
4660       pong->header.size = htons (sizeof (struct TransportPongMessage) + alen + slen);
4661       pong->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_PONG);
4662       pong->purpose.size =
4663         htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) +
4664                sizeof (uint32_t) +
4665                sizeof (struct GNUNET_TIME_AbsoluteNBO) +
4666                sizeof (struct GNUNET_PeerIdentity) + alen + slen);
4667       pong->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN);
4668       pong->challenge = ping->challenge;
4669       pong->addrlen = htonl(alen + slen);
4670       memcpy(&pong->pid,
4671              &my_identity,
4672              sizeof(struct GNUNET_PeerIdentity));
4673       memcpy (&pong[1], plugin->short_name, slen);
4674       memcpy (&((char*)&pong[1])[slen], addr, alen);
4675       if ( (oal != NULL) &&
4676            (GNUNET_TIME_absolute_get_remaining (oal->pong_sig_expires).rel_value < PONG_SIGNATURE_LIFETIME.rel_value / 4) )
4677         {
4678           /* create / update cached sig */
4679 #if DEBUG_TRANSPORT
4680           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4681                       "Creating PONG signature to indicate ownership.\n");
4682 #endif
4683           oal->pong_sig_expires = GNUNET_TIME_absolute_min (oal->expires,
4684                                                             GNUNET_TIME_relative_to_absolute (PONG_SIGNATURE_LIFETIME));
4685           pong->expiration = GNUNET_TIME_absolute_hton (oal->pong_sig_expires);
4686           GNUNET_assert (GNUNET_OK ==
4687                          GNUNET_CRYPTO_rsa_sign (my_private_key,
4688                                                  &pong->purpose,
4689                                                  &oal->pong_signature));        
4690           memcpy (&pong->signature,
4691                   &oal->pong_signature,
4692                   sizeof (struct GNUNET_CRYPTO_RsaSignature));
4693         }
4694       else if (oal == NULL)
4695         {
4696           /* not using cache (typically DV-only) */
4697           pong->expiration = GNUNET_TIME_absolute_hton (GNUNET_TIME_relative_to_absolute (PONG_SIGNATURE_LIFETIME));
4698           GNUNET_assert (GNUNET_OK ==
4699                          GNUNET_CRYPTO_rsa_sign (my_private_key,
4700                                                  &pong->purpose,
4701                                                  &pong->signature));    
4702         }
4703       else
4704         {
4705           /* can used cached version */
4706           pong->expiration = GNUNET_TIME_absolute_hton (oal->pong_sig_expires);
4707           memcpy (&pong->signature,
4708                   &oal->pong_signature,
4709                   sizeof (struct GNUNET_CRYPTO_RsaSignature));
4710         }
4711     }
4712   n = find_neighbour(peer);
4713   GNUNET_assert (n != NULL);
4714   /* first try reliable response transmission */
4715   rl = n->plugins;
4716   while (rl != NULL)
4717     {
4718       fal = rl->addresses;
4719       while (fal != NULL)
4720         {
4721           if (-1 != rl->plugin->api->send (rl->plugin->api->cls,
4722                                            peer,
4723                                            (const char*) pong,
4724                                            ntohs (pong->header.size),
4725                                            TRANSPORT_PONG_PRIORITY,
4726                                            HELLO_VERIFICATION_TIMEOUT,
4727                                            fal->session,
4728                                            fal->addr,
4729                                            fal->addrlen,
4730                                            GNUNET_SYSERR,
4731                                            NULL, NULL))
4732             {
4733               /* done! */
4734               GNUNET_STATISTICS_update (stats,
4735                                         gettext_noop ("# PONGs unicast via reliable transport"),
4736                                         1,
4737                                         GNUNET_NO);
4738               GNUNET_free (pong);
4739               return GNUNET_OK;
4740             }
4741           fal = fal->next;
4742         }
4743       rl = rl->next;
4744     }
4745   /* no reliable method found, do multicast */
4746   GNUNET_STATISTICS_update (stats,
4747                             gettext_noop ("# PONGs multicast to all available addresses"),
4748                             1,
4749                             GNUNET_NO);
4750   rl = n->plugins;
4751   while (rl != NULL)
4752     {
4753       fal = rl->addresses;
4754       while (fal != NULL)
4755         {
4756           transmit_to_peer(NULL, fal,
4757                            TRANSPORT_PONG_PRIORITY,
4758                            HELLO_VERIFICATION_TIMEOUT,
4759                            (const char *)pong,
4760                            ntohs(pong->header.size),
4761                            GNUNET_YES,
4762                            n);
4763           fal = fal->next;
4764         }
4765       rl = rl->next;
4766     }
4767   GNUNET_free(pong);
4768   return GNUNET_OK;
4769 }
4770
4771
4772 /**
4773  * Function called by the plugin for each received message.
4774  * Update data volumes, possibly notify plugins about
4775  * reducing the rate at which they read from the socket
4776  * and generally forward to our receive callback.
4777  *
4778  * @param cls the "struct TransportPlugin *" we gave to the plugin
4779  * @param peer (claimed) identity of the other peer
4780  * @param message the message, NULL if we only care about
4781  *                learning about the delay until we should receive again
4782  * @param ats_data information for automatic transport selection
4783  * @param ats_count number of elements in ats not including 0-terminator
4784  * @param session identifier used for this session (can be NULL)
4785  * @param sender_address binary address of the sender (if observed)
4786  * @param sender_address_len number of bytes in sender_address
4787  * @return how long in ms the plugin should wait until receiving more data
4788  *         (plugins that do not support this, can ignore the return value)
4789  */
4790 static struct GNUNET_TIME_Relative
4791 plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
4792                     const struct GNUNET_MessageHeader *message,
4793                     const struct GNUNET_TRANSPORT_ATS_Information *ats_data,
4794                     uint32_t ats_count,
4795                     struct Session *session,
4796                     const char *sender_address,
4797                     uint16_t sender_address_len)
4798 {
4799   struct TransportPlugin *plugin = cls;
4800   struct ReadyList *service_context;
4801   struct ForeignAddressList *peer_address;
4802   uint16_t msize;
4803   struct NeighbourList *n;
4804   struct GNUNET_TIME_Relative ret;
4805   if (is_blacklisted (peer, plugin))
4806     return GNUNET_TIME_UNIT_FOREVER_REL;
4807   uint32_t distance;
4808   int c;
4809
4810   n = find_neighbour (peer);
4811   if (n == NULL)
4812     n = setup_new_neighbour (peer, GNUNET_YES);
4813   service_context = n->plugins;
4814   while ((service_context != NULL) && (plugin != service_context->plugin))
4815     service_context = service_context->next;
4816   GNUNET_assert ((plugin->api->send == NULL) || (service_context != NULL));
4817   peer_address = NULL;
4818   distance = 1;
4819   for (c=0; c<ats_count; c++)
4820   {
4821           if (ntohl(ats_data[c].type) == GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE)
4822           {
4823                   distance = ntohl(ats_data[c].value);
4824           }
4825   }
4826   /* notify ATS about incoming data */
4827   ats_notify_ats_data(peer, ats_data);
4828
4829   if (message != NULL)
4830     {
4831       if ( (session != NULL) ||
4832            (sender_address != NULL) )
4833         peer_address = add_peer_address (n,
4834                                          plugin->short_name,
4835                                          session,
4836                                          sender_address,
4837                                          sender_address_len);
4838       if (peer_address != NULL)
4839         {
4840           peer_address->distance = distance;
4841           if (GNUNET_YES == peer_address->validated)
4842             mark_address_connected (peer_address);
4843           peer_address->timeout
4844             =
4845             GNUNET_TIME_relative_to_absolute
4846             (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
4847           schedule_next_ping (peer_address);
4848         }
4849       /* update traffic received amount ... */
4850       msize = ntohs (message->size);
4851       GNUNET_STATISTICS_update (stats,
4852                                 gettext_noop ("# bytes received from other peers"),
4853                                 msize,
4854                                 GNUNET_NO);
4855       n->distance = distance;
4856       n->peer_timeout =
4857         GNUNET_TIME_relative_to_absolute
4858         (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
4859       GNUNET_SCHEDULER_cancel (n->timeout_task);
4860       n->timeout_task =
4861         GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
4862                                       &neighbour_timeout_task, n);
4863       if (n->quota_violation_count > QUOTA_VIOLATION_DROP_THRESHOLD)
4864         {
4865           /* dropping message due to frequent inbound volume violations! */
4866           GNUNET_log (GNUNET_ERROR_TYPE_WARNING |
4867                       GNUNET_ERROR_TYPE_BULK,
4868                       _
4869                       ("Dropping incoming message due to repeated bandwidth quota (%u b/s) violations (total of %u).\n"),
4870                       n->in_tracker.available_bytes_per_s__,
4871                       n->quota_violation_count);
4872           GNUNET_STATISTICS_update (stats,
4873                                     gettext_noop ("# bandwidth quota violations by other peers"),
4874                                     1,
4875                                     GNUNET_NO);
4876           return GNUNET_CONSTANTS_QUOTA_VIOLATION_TIMEOUT;
4877         }
4878
4879 #if DEBUG_PING_PONG
4880           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4881                       "Received message of type %u and size %u from `%4s', sending to all clients.\n",
4882                       ntohs (message->type),
4883                       ntohs (message->size),
4884                       GNUNET_i2s (peer));
4885 #endif
4886       switch (ntohs (message->type))
4887         {
4888         case GNUNET_MESSAGE_TYPE_HELLO:
4889           GNUNET_STATISTICS_update (stats,
4890                                     gettext_noop ("# HELLO messages received from other peers"),
4891                                     1,
4892                                     GNUNET_NO);
4893           process_hello (plugin, message);
4894           break;
4895         case GNUNET_MESSAGE_TYPE_TRANSPORT_PING:
4896           handle_ping (plugin, message, peer, session, sender_address, sender_address_len);
4897           break;
4898         case GNUNET_MESSAGE_TYPE_TRANSPORT_PONG:
4899           handle_pong (plugin, message, peer, sender_address, sender_address_len);
4900           break;
4901         default:
4902           handle_payload_message (message, n);
4903           break;
4904         }
4905     }
4906   ret = GNUNET_BANDWIDTH_tracker_get_delay (&n->in_tracker, 0);
4907   if (ret.rel_value > 0)
4908     {
4909       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4910                   "Throttling read (%llu bytes excess at %u b/s), waiting %llums before reading more.\n",
4911                   (unsigned long long) n->in_tracker.consumption_since_last_update__,
4912                   (unsigned int) n->in_tracker.available_bytes_per_s__,
4913                   (unsigned long long) ret.rel_value);
4914       GNUNET_STATISTICS_update (stats,
4915                                 gettext_noop ("# ms throttling suggested"),
4916                                 (int64_t) ret.rel_value,
4917                                 GNUNET_NO);
4918     }
4919   return ret;
4920 }
4921
4922 /**
4923  * Handle START-message.  This is the first message sent to us
4924  * by any client which causes us to add it to our list.
4925  *
4926  * @param cls closure (always NULL)
4927  * @param client identification of the client
4928  * @param message the actual message
4929  */
4930 static void
4931 handle_start (void *cls,
4932               struct GNUNET_SERVER_Client *client,
4933               const struct GNUNET_MessageHeader *message)
4934 {
4935   const struct StartMessage *start;
4936   struct TransportClient *c;
4937   struct ConnectInfoMessage * cim;
4938   struct NeighbourList *n;
4939   uint32_t ats_count;
4940   size_t size;
4941
4942   start = (const struct StartMessage*) message;
4943 #if DEBUG_TRANSPORT
4944   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4945               "Received `%s' request from client\n", "START");
4946 #endif
4947   c = clients;
4948   while (c != NULL)
4949     {
4950       if (c->client == client)
4951         {
4952           /* client already on our list! */
4953           GNUNET_break (0);
4954           GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4955           return;
4956         }
4957       c = c->next;
4958     }
4959   if ( (GNUNET_NO != ntohl (start->do_check)) &&
4960        (0 != memcmp (&start->self,
4961                      &my_identity,
4962                      sizeof (struct GNUNET_PeerIdentity))) )
4963     {
4964       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
4965                   _("Rejecting control connection from peer `%s', which is not me!\n"),
4966                   GNUNET_i2s (&start->self));
4967       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4968       return;
4969     }
4970   c = GNUNET_malloc (sizeof (struct TransportClient));
4971   c->next = clients;
4972   clients = c;
4973   c->client = client;
4974   if (our_hello != NULL)
4975   {
4976 #if DEBUG_TRANSPORT
4977       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4978                   "Sending our own `%s' to new client\n", "HELLO");
4979 #endif
4980       transmit_to_client (c,
4981                           (const struct GNUNET_MessageHeader *) our_hello,
4982                           GNUNET_NO);
4983       /* tell new client about all existing connections */
4984       ats_count = 2;
4985       size  = sizeof (struct ConnectInfoMessage) + ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
4986       if (size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
4987       {
4988           GNUNET_break(0);
4989       }
4990       cim = GNUNET_malloc (size);
4991       cim->header.size = htons (size);
4992       cim->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
4993       cim->ats_count = htonl(ats_count);
4994       (&(cim->ats))[2].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
4995       (&(cim->ats))[2].value = htonl (0);
4996       n = neighbours;
4997       while (n != NULL)
4998           {
4999                   if (GNUNET_YES == n->received_pong)
5000                   {
5001                           (&(cim->ats))[0].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE);
5002                           (&(cim->ats))[0].value = htonl (n->distance);
5003                           (&(cim->ats))[1].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DELAY);
5004                           (&(cim->ats))[1].value = htonl ((uint32_t) n->latency.rel_value);
5005                           cim->id = n->id;
5006                           transmit_to_client (c, &cim->header, GNUNET_NO);
5007                   }
5008             n = n->next;
5009       }
5010       GNUNET_free (cim);
5011   }
5012   GNUNET_SERVER_receive_done (client, GNUNET_OK);
5013 }
5014
5015
5016 /**
5017  * Handle HELLO-message.
5018  *
5019  * @param cls closure (always NULL)
5020  * @param client identification of the client
5021  * @param message the actual message
5022  */
5023 static void
5024 handle_hello (void *cls,
5025               struct GNUNET_SERVER_Client *client,
5026               const struct GNUNET_MessageHeader *message)
5027 {
5028   int ret;
5029
5030   GNUNET_STATISTICS_update (stats,
5031                             gettext_noop ("# HELLOs received from clients"),
5032                             1,
5033                             GNUNET_NO);
5034   ret = process_hello (NULL, message);
5035   GNUNET_SERVER_receive_done (client, ret);
5036 }
5037
5038
5039 /**
5040  * Closure for 'transmit_client_message'; followed by
5041  * 'msize' bytes of the actual message.
5042  */
5043 struct TransmitClientMessageContext
5044 {
5045   /**
5046    * Client on whom's behalf we are sending.
5047    */
5048   struct GNUNET_SERVER_Client *client;
5049
5050   /**
5051    * Timeout for the transmission.
5052    */
5053   struct GNUNET_TIME_Absolute timeout;
5054
5055   /**
5056    * Message priority.
5057    */
5058   uint32_t priority;
5059
5060   /**
5061    * Size of the message in bytes.
5062    */
5063   uint16_t msize;
5064 };
5065
5066
5067 /**
5068  * Schedule transmission of a message we got from a client to a peer.
5069  *
5070  * @param cls the 'struct TransmitClientMessageContext*'
5071  * @param n destination, or NULL on error (in that case, drop the message)
5072  */
5073 static void
5074 transmit_client_message (void *cls,
5075                          struct NeighbourList *n)
5076 {
5077   struct TransmitClientMessageContext *tcmc = cls;
5078   struct TransportClient *tc;
5079
5080   tc = clients;
5081   while ((tc != NULL) && (tc->client != tcmc->client))
5082     tc = tc->next;
5083
5084   if (n != NULL)
5085     {
5086       transmit_to_peer (tc, NULL, tcmc->priority,
5087                         GNUNET_TIME_absolute_get_remaining (tcmc->timeout),
5088                         (char *)&tcmc[1],
5089                         tcmc->msize, GNUNET_NO, n);
5090     }
5091   GNUNET_SERVER_receive_done (tcmc->client, GNUNET_OK);
5092   GNUNET_SERVER_client_drop (tcmc->client);
5093   GNUNET_free (tcmc);
5094 }
5095
5096
5097 /**
5098  * Handle SEND-message.
5099  *
5100  * @param cls closure (always NULL)
5101  * @param client identification of the client
5102  * @param message the actual message
5103  */
5104 static void
5105 handle_send (void *cls,
5106              struct GNUNET_SERVER_Client *client,
5107              const struct GNUNET_MessageHeader *message)
5108 {
5109   const struct OutboundMessage *obm;
5110   const struct GNUNET_MessageHeader *obmm;
5111   struct TransmitClientMessageContext *tcmc;
5112   uint16_t size;
5113   uint16_t msize;
5114
5115   size = ntohs (message->size);
5116   if (size <
5117       sizeof (struct OutboundMessage) + sizeof (struct GNUNET_MessageHeader))
5118     {
5119       GNUNET_break (0);
5120       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
5121       return;
5122     }
5123   GNUNET_STATISTICS_update (stats,
5124                             gettext_noop ("# payload received for other peers"),
5125                             size,
5126                             GNUNET_NO);
5127   obm = (const struct OutboundMessage *) message;
5128   obmm = (const struct GNUNET_MessageHeader *) &obm[1];
5129   msize = size - sizeof (struct OutboundMessage);
5130
5131   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5132               "Received `%s' request from client with target `%4s' and message of type %u and size %u\n",
5133               "SEND", GNUNET_i2s (&obm->peer),
5134               ntohs (obmm->type),
5135               msize);
5136
5137   tcmc = GNUNET_malloc (sizeof (struct TransmitClientMessageContext) + msize);
5138   tcmc->client = client;
5139   tcmc->priority = ntohl (obm->priority);
5140   tcmc->timeout = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_relative_ntoh (obm->timeout));
5141   tcmc->msize = msize;
5142   /* FIXME: this memcpy can be up to 7% of our total runtime */
5143   memcpy (&tcmc[1], obmm, msize);
5144   GNUNET_SERVER_client_keep (client);
5145   setup_peer_check_blacklist (&obm->peer, GNUNET_YES,
5146                               &transmit_client_message,
5147                               tcmc);
5148 }
5149
5150
5151 /**
5152  * Handle request connect message
5153  *
5154  * @param cls closure (always NULL)
5155  * @param client identification of the client
5156  * @param message the actual message
5157  */
5158 static void
5159 handle_request_connect (void *cls,
5160                         struct GNUNET_SERVER_Client *client,
5161                         const struct GNUNET_MessageHeader *message)
5162 {
5163   const struct TransportRequestConnectMessage *trcm =
5164     (const struct TransportRequestConnectMessage *) message;
5165
5166   GNUNET_STATISTICS_update (stats,
5167                             gettext_noop ("# REQUEST CONNECT messages received"),
5168                             1,
5169                             GNUNET_NO);
5170   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Received a request connect message for peer %s\n", GNUNET_i2s(&trcm->peer));
5171   setup_peer_check_blacklist (&trcm->peer, GNUNET_YES,
5172                               NULL, NULL);
5173   GNUNET_SERVER_receive_done (client, GNUNET_OK);
5174 }
5175
5176 /**
5177  * Handle SET_QUOTA-message.
5178  *
5179  * @param cls closure (always NULL)
5180  * @param client identification of the client
5181  * @param message the actual message
5182  */
5183 static void
5184 handle_set_quota (void *cls,
5185                   struct GNUNET_SERVER_Client *client,
5186                   const struct GNUNET_MessageHeader *message)
5187 {
5188   const struct QuotaSetMessage *qsm =
5189     (const struct QuotaSetMessage *) message;
5190   struct NeighbourList *n;
5191
5192   GNUNET_STATISTICS_update (stats,
5193                             gettext_noop ("# SET QUOTA messages received"),
5194                             1,
5195                             GNUNET_NO);
5196   n = find_neighbour (&qsm->peer);
5197   if (n == NULL)
5198     {
5199       GNUNET_SERVER_receive_done (client, GNUNET_OK);
5200       GNUNET_STATISTICS_update (stats,
5201                                 gettext_noop ("# SET QUOTA messages ignored (no such peer)"),
5202                                 1,
5203                                 GNUNET_NO);
5204       return;
5205     }
5206 #if DEBUG_TRANSPORT
5207   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5208               "Received `%s' request (new quota %u, old quota %u) from client for peer `%4s'\n",
5209               "SET_QUOTA",
5210               (unsigned int) ntohl (qsm->quota.value__),
5211               (unsigned int) n->in_tracker.available_bytes_per_s__,
5212               GNUNET_i2s (&qsm->peer));
5213 #endif
5214   GNUNET_BANDWIDTH_tracker_update_quota (&n->in_tracker,
5215                                          qsm->quota);
5216   if (0 == ntohl (qsm->quota.value__))
5217     {
5218       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5219                 "Disconnecting peer `%4s', %s\n", GNUNET_i2s(&n->id),
5220                 "SET_QUOTA");
5221       disconnect_neighbour (n, GNUNET_NO);
5222     }
5223   GNUNET_SERVER_receive_done (client, GNUNET_OK);
5224 }
5225
5226
5227 /**
5228  * Take the given address and append it to the set of results sent back to
5229  * the client.
5230  *
5231  * @param cls the transmission context used ('struct GNUNET_SERVER_TransmitContext*')
5232  * @param address the resolved name, NULL to indicate the last response
5233  */
5234 static void
5235 transmit_address_to_client (void *cls, const char *address)
5236 {
5237   struct GNUNET_SERVER_TransmitContext *tc = cls;
5238   size_t slen;
5239
5240   if (NULL == address)
5241     slen = 0;
5242   else
5243     slen = strlen (address) + 1;
5244
5245   GNUNET_SERVER_transmit_context_append_data (tc, address, slen,
5246                                               GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_REPLY);
5247   if (NULL == address)
5248     GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
5249 }
5250
5251
5252 /**
5253  * Handle AddressLookup-message.
5254  *
5255  * @param cls closure (always NULL)
5256  * @param client identification of the client
5257  * @param message the actual message
5258  */
5259 static void
5260 handle_address_lookup (void *cls,
5261                        struct GNUNET_SERVER_Client *client,
5262                        const struct GNUNET_MessageHeader *message)
5263 {
5264   const struct AddressLookupMessage *alum;
5265   struct TransportPlugin *lsPlugin;
5266   const char *nameTransport;
5267   const char *address;
5268   uint16_t size;
5269   struct GNUNET_SERVER_TransmitContext *tc;
5270   struct GNUNET_TIME_Absolute timeout;
5271   struct GNUNET_TIME_Relative rtimeout;
5272   int32_t numeric;
5273
5274   size = ntohs (message->size);
5275   if (size < sizeof (struct AddressLookupMessage))
5276     {
5277       GNUNET_break_op (0);
5278       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
5279       return;
5280     }
5281   alum = (const struct AddressLookupMessage *) message;
5282   uint32_t addressLen = ntohl (alum->addrlen);
5283   if (size <= sizeof (struct AddressLookupMessage) + addressLen)
5284     {
5285       GNUNET_break_op (0);
5286       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
5287       return;
5288     }
5289   address = (const char *) &alum[1];
5290   nameTransport = (const char *) &address[addressLen];
5291   if (nameTransport
5292       [size - sizeof (struct AddressLookupMessage) - addressLen - 1] != '\0')
5293     {
5294       GNUNET_break_op (0);
5295       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
5296       return;
5297     }
5298   timeout = GNUNET_TIME_absolute_ntoh (alum->timeout);
5299   rtimeout = GNUNET_TIME_absolute_get_remaining (timeout);
5300   numeric = ntohl (alum->numeric_only);
5301   lsPlugin = find_transport (nameTransport);
5302   if (NULL == lsPlugin)
5303     {
5304       tc = GNUNET_SERVER_transmit_context_create (client);
5305       GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
5306                                                   GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_REPLY);
5307       GNUNET_SERVER_transmit_context_run (tc, rtimeout);
5308       return;
5309     }
5310   tc = GNUNET_SERVER_transmit_context_create (client);
5311   lsPlugin->api->address_pretty_printer (lsPlugin->api->cls,
5312                                          nameTransport,
5313                                          address, addressLen,
5314                                          numeric,
5315                                          rtimeout,
5316                                          &transmit_address_to_client, tc);
5317 }
5318
5319
5320 /**
5321  * Setup the environment for this plugin.
5322  */
5323 static void
5324 create_environment (struct TransportPlugin *plug)
5325 {
5326   plug->env.cfg = cfg;
5327   plug->env.my_identity = &my_identity;
5328   plug->env.our_hello = &our_hello;
5329   plug->env.cls = plug;
5330   plug->env.receive = &plugin_env_receive;
5331   plug->env.notify_address = &plugin_env_notify_address;
5332   plug->env.session_end = &plugin_env_session_end;
5333   plug->env.max_connections = max_connect_per_transport;
5334   plug->env.stats = stats;
5335 }
5336
5337
5338 /**
5339  * Start the specified transport (load the plugin).
5340  */
5341 static void
5342 start_transport (struct GNUNET_SERVER_Handle *server,
5343                  const char *name)
5344 {
5345   struct TransportPlugin *plug;
5346   char *libname;
5347
5348   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
5349               _("Loading `%s' transport plugin\n"), name);
5350   GNUNET_asprintf (&libname, "libgnunet_plugin_transport_%s", name);
5351   plug = GNUNET_malloc (sizeof (struct TransportPlugin));
5352   create_environment (plug);
5353   plug->short_name = GNUNET_strdup (name);
5354   plug->lib_name = libname;
5355   plug->next = plugins;
5356   plugins = plug;
5357   plug->api = GNUNET_PLUGIN_load (libname, &plug->env);
5358   if (plug->api == NULL)
5359     {
5360       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
5361                   _("Failed to load transport plugin for `%s'\n"), name);
5362       GNUNET_free (plug->short_name);
5363       plugins = plug->next;
5364       GNUNET_free (libname);
5365       GNUNET_free (plug);
5366     }
5367 }
5368
5369
5370 /**
5371  * Called whenever a client is disconnected.  Frees our
5372  * resources associated with that client.
5373  *
5374  * @param cls closure
5375  * @param client identification of the client
5376  */
5377 static void
5378 client_disconnect_notification (void *cls,
5379                                 struct GNUNET_SERVER_Client *client)
5380 {
5381   struct TransportClient *pos;
5382   struct TransportClient *prev;
5383   struct ClientMessageQueueEntry *mqe;
5384   struct Blacklisters *bl;
5385   struct BlacklistCheck *bc;
5386
5387   if (client == NULL)
5388     return;
5389 #if DEBUG_TRANSPORT
5390   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
5391               "Client disconnected, cleaning up.\n");
5392 #endif
5393   /* clean up blacklister */
5394   bl = bl_head;
5395   while (bl != NULL)
5396     {
5397       if (bl->client == client)
5398         {
5399           bc = bc_head;
5400           while (bc != NULL)
5401             {
5402               if (bc->bl_pos == bl)
5403                 {
5404                   bc->bl_pos = bl->next;
5405                   if (bc->th != NULL)
5406                     {
5407                       GNUNET_CONNECTION_notify_transmit_ready_cancel (bc->th);
5408                       bc->th = NULL;            
5409                     }
5410                   if (bc->task == GNUNET_SCHEDULER_NO_TASK)
5411                     bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check,
5412                                                          bc);
5413                   break;
5414                 }
5415               bc = bc->next;
5416             }
5417           GNUNET_CONTAINER_DLL_remove (bl_head,
5418                                        bl_tail,
5419                                        bl);
5420           GNUNET_SERVER_client_drop (bl->client);
5421           GNUNET_free (bl);
5422           break;
5423         }
5424       bl = bl->next;
5425     }
5426   /* clean up 'normal' clients */
5427   prev = NULL;
5428   pos = clients;
5429   while ((pos != NULL) && (pos->client != client))
5430     {
5431       prev = pos;
5432       pos = pos->next;
5433     }
5434   if (pos == NULL)
5435     return;
5436   while (NULL != (mqe = pos->message_queue_head))
5437     {
5438       GNUNET_CONTAINER_DLL_remove (pos->message_queue_head,
5439                                    pos->message_queue_tail,
5440                                    mqe);
5441       pos->message_count--;
5442       GNUNET_free (mqe);
5443     }
5444   if (prev == NULL)
5445     clients = pos->next;
5446   else
5447     prev->next = pos->next;
5448   if (GNUNET_YES == pos->tcs_pending)
5449     {
5450       pos->client = NULL;
5451       return;
5452     }
5453   if (pos->th != NULL)
5454     {
5455       GNUNET_CONNECTION_notify_transmit_ready_cancel (pos->th);
5456       pos->th = NULL;
5457     }
5458   GNUNET_break (0 == pos->message_count);
5459   GNUNET_free (pos);
5460 }
5461
5462
5463 /**
5464  * Function called when the service shuts down.  Unloads our plugins
5465  * and cancels pending validations.
5466  *
5467  * @param cls closure, unused
5468  * @param tc task context (unused)
5469  */
5470 static void
5471 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
5472 {
5473   struct TransportPlugin *plug;
5474   struct OwnAddressList *al;
5475   struct CheckHelloValidatedContext *chvc;
5476
5477   while (neighbours != NULL)
5478     {
5479       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5480               "Disconnecting peer `%4s', %s\n", GNUNET_i2s(&neighbours->id),
5481               "SHUTDOWN_TASK");
5482       disconnect_neighbour (neighbours, GNUNET_NO);
5483     }
5484 #if DEBUG_TRANSPORT
5485   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5486               "Transport service is unloading plugins...\n");
5487 #endif
5488   while (NULL != (plug = plugins))
5489     {
5490       plugins = plug->next;
5491       if (plug->address_update_task != GNUNET_SCHEDULER_NO_TASK)
5492         {
5493           GNUNET_SCHEDULER_cancel (plug->address_update_task);
5494           plug->address_update_task = GNUNET_SCHEDULER_NO_TASK;
5495         }
5496       GNUNET_break (NULL == GNUNET_PLUGIN_unload (plug->lib_name, plug->api));
5497       GNUNET_free (plug->lib_name);
5498       GNUNET_free (plug->short_name);
5499       while (NULL != (al = plug->addresses))
5500         {
5501           plug->addresses = al->next;
5502           GNUNET_free (al);
5503         }
5504       GNUNET_free (plug);
5505     }
5506   if (my_private_key != NULL)
5507     GNUNET_CRYPTO_rsa_key_free (my_private_key);
5508   GNUNET_free_non_null (our_hello);
5509
5510   GNUNET_CONTAINER_multihashmap_iterate (validation_map,
5511                                          &abort_validation,
5512                                          NULL);
5513   GNUNET_CONTAINER_multihashmap_destroy (validation_map);
5514   validation_map = NULL;
5515
5516   ats_shutdown(ats);
5517
5518   /* free 'chvc' data structure */
5519   while (NULL != (chvc = chvc_head))
5520     {
5521       chvc_head = chvc->next;
5522       if (chvc->piter != NULL)
5523         {
5524           GNUNET_PEERINFO_iterate_cancel (chvc->piter);
5525           GNUNET_STATISTICS_update (stats,
5526                                     gettext_noop ("# outstanding peerinfo iterate requests"),
5527                                     -1,
5528                                     GNUNET_NO);
5529         }
5530       else
5531         GNUNET_break (0);
5532       GNUNET_assert (chvc->ve_count == 0);
5533       GNUNET_free (chvc);
5534     }
5535   chvc_tail = NULL;
5536
5537   if (stats != NULL)
5538     {
5539       GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
5540       stats = NULL;
5541     }
5542   if (peerinfo != NULL)
5543     {
5544       GNUNET_PEERINFO_disconnect (peerinfo);
5545       peerinfo = NULL;
5546     }
5547   /* Can we assume those are gone by now, or do we need to clean up
5548      explicitly!? */
5549   GNUNET_break (bl_head == NULL);
5550   GNUNET_break (bc_head == NULL);
5551 }
5552
5553 struct ATS_transports
5554 {
5555         int     id;
5556         double c_max;
5557         double c_1;
5558 };
5559
5560
5561 #if HAVE_LIBGLPK
5562 static glp_prob *
5563 ats_create_problem (int peers,
5564                     int transports, 
5565                     double b_min, 
5566                     double b_max,
5567                     double r, double R, 
5568                     const struct ATS_peer * pl, 
5569                     const struct ATS_transports * tl, 
5570                     int max_it, 
5571                     int max_dur)
5572 {
5573         int result = GLP_UNDEF;
5574         int c1, c2;
5575         glp_prob *lp;
5576         char * peer_n;
5577
5578         int rows = 1 + (3*peers) +  (transports);
5579         int cols = peers;
5580         int index = 1;
5581         int start = 0;
5582         int cur_row = 0;
5583
5584         int ia[1+(rows*cols)], ja[1+(rows*cols)];
5585         double ar[1+(rows*cols)];
5586         double value;
5587
5588         /* Setting GLPK options */
5589         glp_smcp * options = GNUNET_malloc( sizeof (glp_smcp));
5590         glp_init_smcp(options);
5591
5592         /* maximum iterations */
5593         options->it_lim = max_it;
5594         /* maximum durations */
5595         options->tm_lim = max_dur;
5596         /* output level */
5597         if (VERBOSE_ATS)
5598                 options->msg_lev = GLP_MSG_ALL;
5599         else
5600                 options->msg_lev = GLP_MSG_OFF;
5601
5602         if (DEBUG_ATS) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Creating LP problem: %i peers, relativity r %3.2f, b_max %5.2f, b_min %5.2f, \n",peers, r, b_max, b_min);
5603         lp = glp_create_prob();
5604         glp_set_prob_name(lp, "gnunet ats bandwidth distribution");
5605         glp_set_obj_dir(lp, GLP_MAX);
5606
5607         /* Adding transports and objective function coefficients*/
5608         glp_add_cols(lp, cols);
5609         for (c1=1; c1<=cols; c1++)
5610         {
5611                 GNUNET_asprintf(&peer_n,"%s",GNUNET_i2s(&pl[c1-1].peer));
5612                 if (DEBUG_ATS) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Peer[%i] , transport %i, %s: f: %f\n",c1-1 , pl[c1-1].t, peer_n, pl[c1-1].f);
5613                 /* add a single transport*/
5614                 glp_set_col_name(lp, c1, peer_n);
5615                 /* add a lower bound */
5616                 glp_set_col_bnds(lp, c1, GLP_LO, 0.0, 0.0);
5617                 /* set coefficient function */
5618                 value = pl[c1-1].f/b_max;
5619                 value = 1.0;
5620                 glp_set_obj_coef(lp, c1, value);
5621                 GNUNET_free(peer_n);
5622         }
5623
5624         /* Adding constraints */
5625         glp_add_rows(lp, rows);
5626         cur_row = 1;
5627
5628         /* constraint 1: Maximum bandwidth for all peers
5629          * sum(b_i) <= b_max
5630          */
5631         glp_set_row_bnds(lp, cur_row, GLP_UP, 0.0, b_max);
5632         for (index=1; index<=cols; index++)
5633         {
5634                 ia[index] = 1, ja[index] = index, ar[index] = 1.0;
5635         }
5636
5637         /* constraint 2: Maximum bandwidth per peer
5638          * V b_i in B:  b_i <= b_max
5639          */
5640         cur_row = 2;
5641         start = index+1;
5642         for (c1=0; c1<peers; c1++)
5643         {
5644                 //GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "row: %i \n", cur_row);
5645                 glp_set_row_bnds(lp, cur_row , GLP_UP, 0.0, b_max);
5646
5647                 for (c2 = 1; c2 <= cols; c2++)
5648                 {
5649                         ia[index] = cur_row;
5650                         ja[index] = c2;
5651                         ar[index] = ((c1+1 == c2) ? 1.0 : 0.0);
5652                         index++;
5653                 }
5654                 cur_row++;
5655         }
5656
5657         /* constraint 3: Minimum bandwidth
5658          * V b_i in B:  b_i >= b_min
5659          */
5660         start = index+1;
5661         for (c1=0; c1<peers; c1++)
5662         {
5663                 glp_set_row_bnds(lp, cur_row , GLP_LO, b_min, 0.0);
5664
5665                 for (c2 = 1; c2 <= cols; c2++)
5666                 {
5667                         ia[index] = cur_row;
5668                         ja[index] = c2;
5669                         ar[index] = ((c1+1 == c2) ? 1.0 : 0.0);
5670                         index++;
5671                 }
5672                 cur_row++;
5673         }
5674
5675         /* constraint 4: Bandwidth assignment relativity to peer preference
5676          * V b_i in B:  b_i >= b_min
5677          */
5678         start = index+1;
5679         for (c1=0; c1<peers; c1++)
5680         {
5681
5682                 value = pl[c1].f * r;
5683                 glp_set_row_bnds(lp, cur_row , GLP_LO, value, 0.0);
5684                 for (c2 = 1; c2 <= cols; c2++)
5685                 {
5686                         //GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "c1: %i c2 %i  index: %i \n",c1 , c2, index);
5687                         ia[index] = cur_row;
5688                         ja[index] = c2;
5689                         ar[index] = ((c1+1 == c2) ? (1.0/b_max) : 0.0);
5690                         //GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ia: %i ja %i  ar: %f \n",cur_row , c2, ((c1+1 == c2) ? 1.0 : 0.0));
5691                         index++;
5692                 }
5693                 cur_row++;
5694         }
5695
5696         /* constraint 4: transport capacity
5697          * sum of b * c_i < c_max */
5698         start = index+1;
5699         for (c1=0; c1<transports; c1++)
5700         {
5701
5702                 value = tl[c1].c_max;
5703                 if (DEBUG_ATS) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transport %i: c_max %5.2f c_1 %5.2f \n", c1, value, tl[c1].c_1);
5704                 glp_set_row_bnds(lp, cur_row , GLP_UP, 0.0 , value);
5705
5706                 for (c2 = 1; c2 <= cols; c2++)
5707                 {
5708                         ia[index] = cur_row;
5709                         ja[index] = c2;
5710                         ar[index] = ((pl[c1-1].t == tl[c1].id) ? (tl[c1].c_1) : 0.0);
5711                         index++;
5712                 }
5713                 cur_row++;
5714         }
5715
5716         glp_load_matrix(lp, rows * cols, ia, ja, ar);
5717         result = glp_simplex(lp, options);
5718         if (DEBUG_ATS)
5719         {
5720                 switch (result) {
5721                 case GLP_ESTOP  :    /* search terminated by application */
5722                         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Search terminated by application ");
5723                 case GLP_EITLIM :    /* iteration limit exceeded */
5724                         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Iteration limit exceeded ");
5725                 break;
5726                 case GLP_ETMLIM :    /* time limit exceeded */
5727                         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Time limit exceeded ");
5728                 break;
5729                 case GLP_ENOFEAS:    /* no primal/dual feasible solution */
5730                 case GLP_ENOCVG :    /* no convergence */
5731                 case GLP_ERANGE :        /* result out of range */
5732                 case GLP_ENOPFS :    /* no primal feasible solution */
5733                 case GLP_ENODFS :    /* no dual feasible solution */
5734                         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No feasible solution");
5735                 break;
5736
5737                 case GLP_EBADB  :    /* invalid basis */
5738                 case GLP_ESING  :    /* singular matrix */
5739                 case GLP_ECOND  :    /* ill-conditioned matrix */
5740                 case GLP_EBOUND :    /* invalid bounds */
5741                 case GLP_EFAIL  :    /* solver failed */
5742                 case GLP_EOBJLL :    /* objective lower limit reached */
5743                 case GLP_EOBJUL :    /* objective upper limit reached */
5744                 case GLP_EROOT  :    /* root LP optimum not provided */
5745                 case GLP_EMIPGAP:    /* relative mip gap tolerance reached */
5746                 case GLP_EINSTAB:    /* numerical instability */
5747                 case GLP_EDATA  :    /* invalid data */
5748                         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Invalid Input data\n");
5749                 break;
5750
5751                 break;
5752                         default:
5753                                 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Optimal solution\n");
5754                 break;
5755                 }
5756         }
5757
5758         char * debug_solution = NULL;
5759         char * old = NULL;
5760         for (c1=1; c1<= peers; c1++ )
5761         {
5762                 old = debug_solution;
5763                 GNUNET_asprintf(&debug_solution, "%s %s = %g;", (debug_solution!=NULL) ? debug_solution : "", GNUNET_i2s(&pl[c1-1].peer), glp_get_col_prim(lp, c1));
5764                 if (old!=NULL) GNUNET_free(old);
5765         }
5766         GNUNET_asprintf(&debug_solution, "%s z = %g; \n", debug_solution,  glp_get_obj_val(lp));
5767         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s \n",debug_solution);
5768         GNUNET_free(debug_solution);
5769
5770         glp_delete_prob(lp);
5771         GNUNET_free(options);
5772         return lp;
5773 }
5774 #else
5775 static void *
5776 ats_create_problem (int peers,
5777                     int transports, 
5778                     double b_min, 
5779                     double b_max,
5780                     double r, double R, 
5781                     const struct ATS_peer * pl, 
5782                     const struct ATS_transports * tl, 
5783                     int max_it, 
5784                     int max_dur)
5785 {
5786   return NULL;
5787 }
5788 #endif
5789
5790
5791 void ats_calculate_bandwidth_distribution ()
5792 {
5793         struct GNUNET_TIME_Relative delta = GNUNET_TIME_absolute_get_difference(ats->last,GNUNET_TIME_absolute_get());
5794         if (delta.rel_value < ats->min_delta.rel_value)
5795         {
5796 #if DEBUG_ATS
5797                 //GNUNET_log (GNUNET_ERROR_TYPE_BULK, "Minimum time between cycles not reached\n");
5798 #endif
5799                 return;
5800         }
5801
5802         int peers = 3;
5803         int transports = 3;
5804
5805         double b_min   = 10;
5806         double b_max   = 100.0;
5807         double r           = 0.85;//1.0;
5808         double R           = 1.0;
5809
5810         int it = 50;
5811         int dur = 500;
5812         //if (INT_MAX) ats.max_exec_duration.rel_value;
5813
5814         struct ATS_transports * tl = GNUNET_malloc(transports * sizeof (struct ATS_peer));
5815
5816         struct ATS_peer * pl = GNUNET_malloc(peers * sizeof (struct ATS_peer));
5817         int c = 0;
5818         while (c < peers)
5819         {
5820                 pl[c].peer.hashPubKey.bits[0] = c+1;
5821                 pl[c].f = 1 / (double) peers ;
5822                 pl[c].t = 1;
5823                 //GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ats_calculate_bandwidth_distribution Peer[%i] : %s %p \n",c , GNUNET_i2s(&list[c].peer), &list[c].peer);
5824                 c++;
5825         }
5826         c = 0;
5827         while (c < transports)
5828         {
5829                 tl[c].id = c;
5830                 tl[c].c_max = 100;
5831                 tl[c].c_1 = 1;
5832                 c++;
5833         }
5834
5835         // test //
5836
5837         pl[0].f = 0.33;
5838         pl[2].f = 0.43;
5839         pl[1].f = 0.33;
5840         // test //
5841
5842         ats_create_problem(peers, transports, b_min, b_max, r, R, pl, tl, it, dur);
5843
5844         GNUNET_free (pl);
5845         GNUNET_free (tl);
5846
5847         ats->last = GNUNET_TIME_absolute_get();
5848
5849 }
5850
5851
5852
5853 void
5854 ats_schedule_calculation (void *cls,
5855                           const struct GNUNET_SCHEDULER_TaskContext *tc)
5856 {
5857         struct ATS_info *ats = (struct ATS_info *) cls;
5858         if (ats==NULL)
5859                 return;
5860
5861         ats->ats_task = GNUNET_SCHEDULER_NO_TASK;
5862         if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
5863             return;
5864
5865 #if DEBUG_ATS
5866         GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Running scheduled calculation\n");
5867 #endif
5868         ats_calculate_bandwidth_distribution (ats);
5869
5870         ats->ats_task = GNUNET_SCHEDULER_add_delayed (ats->exec_intervall,
5871                                         &ats_schedule_calculation, ats);
5872 }
5873
5874
5875 int ats_map_remove_peer (void *cls,
5876                 const GNUNET_HashCode * key,
5877                 void *value)
5878 {
5879
5880         struct ATS_peer * p =  (struct ATS_peer *) value;
5881 #if DEBUG_ATS
5882         GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "map_remove_peer_it: `%s'\n", GNUNET_i2s(&p->peer));
5883 #endif
5884         /* cleanup peer */
5885         GNUNET_free(p);
5886
5887         return GNUNET_YES;
5888 }
5889
5890
5891 struct ATS_info * ats_init ()
5892 {
5893         struct ATS_info * ats;
5894 #if DEBUG_ATS
5895         GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ats_init\n");
5896 #endif
5897         ats = GNUNET_malloc(sizeof (struct ATS_info));
5898         ats->peers = GNUNET_CONTAINER_multihashmap_create(10);
5899         GNUNET_assert(ats->peers!=NULL);
5900
5901         ats->min_delta = ATS_MIN_INTERVAL;
5902         ats->exec_intervall = ATS_EXEC_INTERVAL;
5903         ats->max_exec_duration = ATS_MAX_EXEC_DURATION;
5904
5905         ats->ats_task = GNUNET_SCHEDULER_NO_TASK;
5906 /*
5907         ats->ats_task = GNUNET_SCHEDULER_add_delayed (ats->reg_delta,
5908                                         &schedule_calculation, NULL);
5909
5910         ats->ats_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
5911                                         &schedule_calculation, NULL);
5912 */
5913         ats->ats_task = GNUNET_SCHEDULER_add_now(&ats_schedule_calculation, ats);
5914
5915         return ats;
5916 }
5917
5918
5919 void ats_shutdown ()
5920 {
5921 #if DEBUG_ATS
5922         GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ats_destroy\n");
5923 #endif
5924         if (ats->ats_task != GNUNET_SCHEDULER_NO_TASK)
5925                 GNUNET_SCHEDULER_cancel(ats->ats_task);
5926         ats->ats_task = GNUNET_SCHEDULER_NO_TASK;
5927
5928         GNUNET_CONTAINER_multihashmap_iterate (ats->peers,ats_map_remove_peer,NULL);
5929         GNUNET_CONTAINER_multihashmap_destroy (ats->peers);
5930         GNUNET_free (ats);
5931 }
5932
5933
5934 void ats_notify_peer_connect (
5935                 const struct GNUNET_PeerIdentity *peer,
5936                 const struct GNUNET_TRANSPORT_ATS_Information *ats_data)
5937 {
5938         int c = 0;
5939 #if DEBUG_ATS
5940         GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ats_notify_peer_connect: %s\n",GNUNET_i2s(peer));
5941 #endif
5942
5943         while (ntohl(ats_data[c].type)!=0)
5944         {
5945 #if DEBUG_ATS
5946                 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ats type [%i]: %i\n",ntohl(ats_data[c].type), ntohl(ats_data[c].value));
5947 #endif
5948                 c++;
5949         }
5950         /* check if peer is already known */
5951         if (!GNUNET_CONTAINER_multihashmap_contains (ats->peers,&peer->hashPubKey))
5952         {
5953                 struct ATS_peer * p = GNUNET_malloc (sizeof (struct ATS_peer));
5954                 memcpy(&p->peer, peer, sizeof (struct GNUNET_PeerIdentity));
5955                 GNUNET_CONTAINER_multihashmap_put(ats->peers, &p->peer.hashPubKey, p, GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
5956         }
5957
5958         ats_calculate_bandwidth_distribution(ats);
5959 }
5960
5961 void ats_notify_peer_disconnect (
5962                 const struct GNUNET_PeerIdentity *peer)
5963 {
5964 #if DEBUG_ATS
5965         GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ats_notify_peer_disconnect: %s\n",GNUNET_i2s(peer));
5966 #endif
5967         /* remove peer */
5968         if (GNUNET_CONTAINER_multihashmap_contains (ats->peers, &peer->hashPubKey))
5969         {
5970                 ats_map_remove_peer(NULL, &peer->hashPubKey, GNUNET_CONTAINER_multihashmap_get (ats->peers, &peer->hashPubKey));
5971                 GNUNET_CONTAINER_multihashmap_remove_all (ats->peers, &peer->hashPubKey);
5972         }
5973
5974         ats_calculate_bandwidth_distribution (ats);
5975 }
5976
5977
5978 void ats_notify_ats_data (
5979                 const struct GNUNET_PeerIdentity *peer,
5980                 const struct GNUNET_TRANSPORT_ATS_Information *ats_data)
5981 {
5982 #if DEBUG_ATS
5983         GNUNET_log (GNUNET_ERROR_TYPE_BULK, "ATS_notify_ats_data: %s\n",GNUNET_i2s(peer));
5984 #endif
5985         ats_calculate_bandwidth_distribution(ats);
5986 }
5987
5988 struct ForeignAddressList * ats_get_preferred_address (
5989                 struct NeighbourList *n)
5990 {
5991 #if DEBUG_ATS
5992         //GNUNET_log (GNUNET_ERROR_TYPE_BULK, "ats_get_prefered_transport for peer: %s\n",GNUNET_i2s(&n->id));
5993 #endif
5994         struct ReadyList *next = n->plugins;
5995         while (next != NULL)
5996         {
5997 #if DEBUG_ATS
5998                 //GNUNET_log (GNUNET_ERROR_TYPE_BULK, "plugin: %s %i\n",next->plugin->short_name,strcmp(next->plugin->short_name,"unix"));
5999 #endif
6000                 next = next->next;
6001         }
6002         return find_ready_address(n);
6003 }
6004
6005 /**
6006  * Initiate transport service.
6007  *
6008  * @param cls closure
6009  * @param server the initialized server
6010  * @param c configuration to use
6011  */
6012 static void
6013 run (void *cls,
6014      struct GNUNET_SERVER_Handle *server,
6015      const struct GNUNET_CONFIGURATION_Handle *c)
6016 {
6017   static const struct GNUNET_SERVER_MessageHandler handlers[] = {
6018     {&handle_start, NULL,
6019      GNUNET_MESSAGE_TYPE_TRANSPORT_START, sizeof (struct StartMessage)},
6020     {&handle_hello, NULL,
6021      GNUNET_MESSAGE_TYPE_HELLO, 0},
6022     {&handle_send, NULL,
6023      GNUNET_MESSAGE_TYPE_TRANSPORT_SEND, 0},
6024     {&handle_request_connect, NULL,
6025      GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_CONNECT, sizeof(struct TransportRequestConnectMessage)},
6026     {&handle_set_quota, NULL,
6027      GNUNET_MESSAGE_TYPE_TRANSPORT_SET_QUOTA, sizeof (struct QuotaSetMessage)},
6028     {&handle_address_lookup, NULL,
6029      GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_LOOKUP,
6030      0},
6031     {&handle_blacklist_init, NULL,
6032      GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_INIT, sizeof (struct GNUNET_MessageHeader)},
6033     {&handle_blacklist_reply, NULL,
6034      GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_REPLY, sizeof (struct BlacklistMessage)},
6035     {NULL, NULL, 0, 0}
6036   };
6037   char *plugs;
6038   char *pos;
6039   int no_transports;
6040   unsigned long long tneigh;
6041   char *keyfile;
6042
6043   cfg = c;
6044   stats = GNUNET_STATISTICS_create ("transport", cfg);
6045   validation_map = GNUNET_CONTAINER_multihashmap_create (64);
6046   /* parse configuration */
6047   if ((GNUNET_OK !=
6048        GNUNET_CONFIGURATION_get_value_number (c,
6049                                               "TRANSPORT",
6050                                               "NEIGHBOUR_LIMIT",
6051                                               &tneigh)) ||
6052       (GNUNET_OK !=
6053        GNUNET_CONFIGURATION_get_value_filename (c,
6054                                                 "GNUNETD",
6055                                                 "HOSTKEY", &keyfile)))
6056     {
6057       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
6058                   _
6059                   ("Transport service is lacking key configuration settings.  Exiting.\n"));
6060       GNUNET_SCHEDULER_shutdown ();
6061       if (stats != NULL)
6062         {
6063           GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
6064           stats = NULL;
6065         }
6066       GNUNET_CONTAINER_multihashmap_destroy (validation_map);
6067       validation_map = NULL;
6068       return;
6069     }
6070 #if HAVE_GLPK
6071           GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("HAVE\n"));
6072 #else
6073           //GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("NOT HAVE\n"));
6074 #endif
6075
6076   ats = ats_init();
6077   max_connect_per_transport = (uint32_t) tneigh;
6078   peerinfo = GNUNET_PEERINFO_connect (cfg);
6079   if (peerinfo == NULL)
6080     {
6081       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
6082                   _("Could not access PEERINFO service.  Exiting.\n")); 
6083       GNUNET_SCHEDULER_shutdown ();
6084       if (stats != NULL)
6085         {
6086           GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
6087           stats = NULL;
6088         }
6089       GNUNET_CONTAINER_multihashmap_destroy (validation_map);
6090       validation_map = NULL;
6091       GNUNET_free (keyfile);
6092       return;
6093     }
6094   my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
6095   GNUNET_free (keyfile);
6096   if (my_private_key == NULL)
6097     {
6098       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
6099                   _
6100                   ("Transport service could not access hostkey.  Exiting.\n"));
6101       GNUNET_SCHEDULER_shutdown ();
6102       if (stats != NULL)
6103         {
6104           GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
6105           stats = NULL;
6106         }
6107       GNUNET_CONTAINER_multihashmap_destroy (validation_map);
6108       validation_map = NULL;
6109       return;
6110     }
6111   GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key);
6112   GNUNET_CRYPTO_hash (&my_public_key,
6113                       sizeof (my_public_key), &my_identity.hashPubKey);
6114   /* setup notification */
6115   GNUNET_SERVER_disconnect_notify (server,
6116                                    &client_disconnect_notification, NULL);
6117   /* load plugins... */
6118   no_transports = 1;
6119   if (GNUNET_OK ==
6120       GNUNET_CONFIGURATION_get_value_string (c,
6121                                              "TRANSPORT", "PLUGINS", &plugs))
6122     {
6123       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
6124                   _("Starting transport plugins `%s'\n"), plugs);
6125       pos = strtok (plugs, " ");
6126       while (pos != NULL)
6127         {
6128           start_transport (server, pos);
6129           no_transports = 0;
6130           pos = strtok (NULL, " ");
6131         }
6132       GNUNET_free (plugs);
6133     }
6134   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
6135                                 &shutdown_task, NULL);
6136   if (no_transports)
6137     refresh_hello ();
6138
6139 #if DEBUG_TRANSPORT
6140   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Transport service ready.\n"));
6141 #endif
6142   /* If we have a blacklist file, read from it */
6143   read_blacklist_file(cfg);
6144   /* process client requests */
6145   GNUNET_SERVER_add_handlers (server, handlers);
6146 }
6147
6148
6149 /**
6150  * The main function for the transport service.
6151  *
6152  * @param argc number of arguments from the command line
6153  * @param argv command line arguments
6154  * @return 0 ok, 1 on error
6155  */
6156 int
6157 main (int argc, char *const *argv)
6158 {
6159   a2s (NULL, NULL, 0); /* make compiler happy */
6160   return (GNUNET_OK ==
6161           GNUNET_SERVICE_run (argc,
6162                               argv,
6163                               "transport",
6164                               GNUNET_SERVICE_OPTION_NONE,
6165                               &run, NULL)) ? 0 : 1;
6166 }
6167
6168 /* end of gnunet-service-transport.c */