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