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