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