new transport address validation code -- see Mantis 1556
[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       tsize = tsize;
1112       transport_name = GNUNET_malloc(tsize + 1);
1113       memcpy(transport_name, &data[pos], tsize);
1114       pos = colon_pos + 1;
1115 #if DEBUG_TRANSPORT
1116       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1117                   _("Read transport name %s in blacklist file.\n"),
1118                   transport_name);
1119 #endif
1120       memcpy (&enc, &data[pos], sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded));
1121       if (!isspace ( (unsigned char) enc.encoding[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1]))
1122         {
1123           GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1124                       _("Syntax error in blacklist file at offset %llu, skipping bytes.\n"),
1125                       (unsigned long long) pos);
1126           pos++;
1127           while ((pos < frstat.st_size) && (!isspace ( (unsigned char) data[pos])))
1128             pos++;
1129           GNUNET_free_non_null(transport_name);
1130           continue;
1131         }
1132       enc.encoding[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] = '\0';
1133       if (GNUNET_OK != GNUNET_CRYPTO_hash_from_string ((char *) &enc, &pid.hashPubKey))
1134         {
1135           GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1136                       _("Syntax error in blacklist file at offset %llu, skipping bytes `%s'.\n"),
1137                       (unsigned long long) pos,
1138                       &enc);
1139         }
1140       else
1141         {
1142           if (0 != memcmp (&pid,
1143                            &my_identity,
1144                            sizeof (struct GNUNET_PeerIdentity)))
1145             {
1146               entries_found++;
1147               add_peer_to_blacklist (&pid,
1148                                      transport_name);
1149             }
1150           else
1151             {
1152               GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1153                           _("Found myself `%s' in blacklist (useless, ignored)\n"),
1154                           GNUNET_i2s (&pid));
1155             }
1156         }
1157       pos = pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded);
1158       GNUNET_free_non_null(transport_name);
1159       while ((pos < frstat.st_size) && isspace ( (unsigned char) data[pos]))
1160         pos++;
1161     }
1162   GNUNET_free (data);
1163   GNUNET_free (fn);
1164 }
1165
1166
1167 /**
1168  * Function called to notify a client about the socket being ready to
1169  * queue more data.  "buf" will be NULL and "size" zero if the socket
1170  * was closed for writing in the meantime.
1171  *
1172  * @param cls closure
1173  * @param size number of bytes available in buf
1174  * @param buf where the callee should write the message
1175  * @return number of bytes written to buf
1176  */
1177 static size_t
1178 transmit_to_client_callback (void *cls, size_t size, void *buf)
1179 {
1180   struct TransportClient *client = cls;
1181   struct ClientMessageQueueEntry *q;
1182   uint16_t msize;
1183   size_t tsize;
1184   const struct GNUNET_MessageHeader *msg;
1185   char *cbuf;
1186
1187   client->th = NULL;
1188   if (buf == NULL)
1189     {
1190       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1191                   "Transmission to client failed, closing connection.\n");
1192       /* fatal error with client, free message queue! */
1193       while (NULL != (q = client->message_queue_head))
1194         {
1195           GNUNET_STATISTICS_update (stats,
1196                                     gettext_noop ("# bytes discarded (could not transmit to client)"),
1197                                     ntohs (((const struct GNUNET_MessageHeader*)&q[1])->size),
1198                                     GNUNET_NO);      
1199           GNUNET_CONTAINER_DLL_remove (client->message_queue_head,
1200                                        client->message_queue_tail,
1201                                        q);
1202           GNUNET_free (q);
1203         }
1204       client->message_count = 0;
1205       return 0;
1206     }
1207   cbuf = buf;
1208   tsize = 0;
1209   while (NULL != (q = client->message_queue_head))
1210     {
1211       msg = (const struct GNUNET_MessageHeader *) &q[1];
1212       msize = ntohs (msg->size);
1213       if (msize + tsize > size)
1214         break;
1215 #if DEBUG_TRANSPORT
1216       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1217                   "Transmitting message of type %u to client.\n",
1218                   ntohs (msg->type));
1219 #endif
1220       GNUNET_CONTAINER_DLL_remove (client->message_queue_head,
1221                                    client->message_queue_tail,
1222                                    q);
1223       memcpy (&cbuf[tsize], msg, msize);
1224       tsize += msize;
1225       GNUNET_free (q);
1226       client->message_count--;
1227     }
1228   if (NULL != q)
1229     {
1230       GNUNET_assert (msize >= sizeof (struct GNUNET_MessageHeader));
1231       client->th = GNUNET_SERVER_notify_transmit_ready (client->client,
1232                                                         msize,
1233                                                         GNUNET_TIME_UNIT_FOREVER_REL,
1234                                                         &transmit_to_client_callback,
1235                                                         client);
1236       GNUNET_assert (client->th != NULL);
1237     }
1238   return tsize;
1239 }
1240
1241
1242 /**
1243  * Convert an address to a string.
1244  *
1245  * @param plugin name of the plugin responsible for the address
1246  * @param addr binary address
1247  * @param addr_len number of bytes in addr
1248  * @return NULL on error, otherwise address string
1249  */
1250 static const char*
1251 a2s (const char *plugin,
1252      const void *addr,
1253      uint16_t addr_len)
1254 {
1255   struct TransportPlugin *p;
1256
1257   if (plugin == NULL)
1258     return NULL;
1259   p = find_transport (plugin);
1260   if (p == NULL)
1261     return NULL;
1262   return p->api->address_to_string (p->api->cls,
1263                                     addr,
1264                                     addr_len);
1265 }   
1266
1267
1268 /**
1269  * Mark the given FAL entry as 'connected' (and hence preferred for
1270  * sending); also mark all others for the same peer as 'not connected'
1271  * (since only one can be preferred).
1272  *
1273  * @param fal address to set to 'connected'
1274  */
1275 static void
1276 mark_address_connected (struct ForeignAddressList *fal)
1277 {
1278   struct ForeignAddressList *pos;
1279   int cnt;
1280
1281   GNUNET_assert (GNUNET_YES == fal->validated);
1282   if (fal->connected == GNUNET_YES)
1283     return; /* nothing to do */
1284   cnt = GNUNET_YES;
1285   pos = fal->ready_list->addresses;
1286   while (pos != NULL)
1287     {
1288       if (GNUNET_YES == pos->connected)
1289         {
1290 #if DEBUG_TRANSPORT
1291           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1292                       "Marking address `%s' as no longer connected (due to connect on other address)\n",
1293                       a2s (pos->ready_list->plugin->short_name,
1294                            pos->addr,
1295                            pos->addrlen));
1296 #endif
1297           GNUNET_break (cnt == GNUNET_YES);
1298           cnt = GNUNET_NO;
1299           pos->connected = GNUNET_NO;
1300           GNUNET_STATISTICS_update (stats,
1301                                     gettext_noop ("# connected addresses"),
1302                                     -1,
1303                                     GNUNET_NO);
1304         }
1305       pos = pos->next;
1306     }
1307   fal->connected = GNUNET_YES;
1308   if (GNUNET_YES == cnt)
1309     {
1310       GNUNET_STATISTICS_update (stats,
1311                                 gettext_noop ("# connected addresses"),
1312                                 1,
1313                                 GNUNET_NO);
1314     }
1315 }
1316
1317
1318 /**
1319  * Send the specified message to the specified client.  Since multiple
1320  * messages may be pending for the same client at a time, this code
1321  * makes sure that no message is lost.
1322  *
1323  * @param client client to transmit the message to
1324  * @param msg the message to send
1325  * @param may_drop can this message be dropped if the
1326  *        message queue for this client is getting far too large?
1327  */
1328 static void
1329 transmit_to_client (struct TransportClient *client,
1330                     const struct GNUNET_MessageHeader *msg, int may_drop)
1331 {
1332   struct ClientMessageQueueEntry *q;
1333   uint16_t msize;
1334
1335   if ((client->message_count >= MAX_PENDING) && (GNUNET_YES == may_drop))
1336     {
1337       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1338                   _
1339                   ("Dropping message of type %u and size %u, have %u messages pending (%u is the soft limit)\n"),
1340                   ntohs (msg->type),
1341                   ntohs (msg->size),
1342                   client->message_count, 
1343                   MAX_PENDING);
1344       GNUNET_STATISTICS_update (stats,
1345                                 gettext_noop ("# messages dropped due to slow client"),
1346                                 1,
1347                                 GNUNET_NO);
1348       return;
1349     }
1350   msize = ntohs (msg->size);
1351   GNUNET_assert (msize >= sizeof (struct GNUNET_MessageHeader));
1352   q = GNUNET_malloc (sizeof (struct ClientMessageQueueEntry) + msize);
1353   memcpy (&q[1], msg, msize);
1354   GNUNET_CONTAINER_DLL_insert_after (client->message_queue_head,
1355                                      client->message_queue_tail,
1356                                      client->message_queue_tail,
1357                                      q);                                     
1358   client->message_count++;
1359   if (client->th == NULL)
1360     {
1361       client->th = GNUNET_SERVER_notify_transmit_ready (client->client,
1362                                                         msize,
1363                                                         GNUNET_TIME_UNIT_FOREVER_REL,
1364                                                         &transmit_to_client_callback,
1365                                                         client);
1366       GNUNET_assert (client->th != NULL);
1367     }
1368 }
1369
1370
1371 /**
1372  * Transmit a 'SEND_OK' notification to the given client for the
1373  * given neighbour.
1374  *
1375  * @param client who to notify
1376  * @param n neighbour to notify about
1377  * @param result status code for the transmission request
1378  */
1379 static void
1380 transmit_send_ok (struct TransportClient *client,
1381                   struct NeighbourList *n,
1382                   int result)
1383 {
1384   struct SendOkMessage send_ok_msg;
1385
1386   send_ok_msg.header.size = htons (sizeof (send_ok_msg));
1387   send_ok_msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK);
1388   send_ok_msg.success = htonl (result);
1389   send_ok_msg.latency = GNUNET_TIME_relative_hton (n->latency);
1390   send_ok_msg.peer = n->id;
1391   transmit_to_client (client, &send_ok_msg.header, GNUNET_NO); 
1392 }
1393
1394
1395 /**
1396  * Function called by the GNUNET_TRANSPORT_TransmitFunction
1397  * upon "completion" of a send request.  This tells the API
1398  * that it is now legal to send another message to the given
1399  * peer.
1400  *
1401  * @param cls closure, identifies the entry on the
1402  *            message queue that was transmitted and the
1403  *            client responsible for queueing the message
1404  * @param target the peer receiving the message
1405  * @param result GNUNET_OK on success, if the transmission
1406  *           failed, we should not tell the client to transmit
1407  *           more messages
1408  */
1409 static void
1410 transmit_send_continuation (void *cls,
1411                             const struct GNUNET_PeerIdentity *target,
1412                             int result)
1413 {
1414   struct MessageQueue *mq = cls;
1415   struct NeighbourList *n;
1416   
1417   GNUNET_STATISTICS_update (stats,
1418                             gettext_noop ("# bytes pending with plugins"),
1419                             - (int64_t) mq->message_buf_size,
1420                             GNUNET_NO);
1421   if (result == GNUNET_OK)
1422     {
1423       GNUNET_STATISTICS_update (stats,
1424                                 gettext_noop ("# bytes successfully transmitted by plugins"),
1425                                 mq->message_buf_size,
1426                                 GNUNET_NO);      
1427     }
1428   else
1429     {
1430       GNUNET_STATISTICS_update (stats,
1431                                 gettext_noop ("# bytes with transmission failure by plugins"),
1432                                 mq->message_buf_size,
1433                                 GNUNET_NO);      
1434     }  
1435   n = find_neighbour(&mq->neighbour_id);
1436   GNUNET_assert (n != NULL);
1437   if (mq->specific_address != NULL)
1438     {
1439       if (result == GNUNET_OK)    
1440         {
1441           mq->specific_address->timeout =
1442             GNUNET_TIME_relative_to_absolute
1443             (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
1444           if (mq->specific_address->validated == GNUNET_YES)
1445             mark_address_connected (mq->specific_address);
1446         }    
1447       else
1448         {
1449           if (mq->specific_address->connected != GNUNET_NO)
1450             {
1451 #if DEBUG_TRANSPORT
1452               GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1453                           "Marking address `%s' as no longer connected (due to transmission problem)\n",
1454                           a2s (mq->specific_address->ready_list->plugin->short_name,
1455                                mq->specific_address->addr,
1456                                mq->specific_address->addrlen));
1457 #endif
1458               GNUNET_STATISTICS_update (stats,
1459                                         gettext_noop ("# connected addresses"),
1460                                         -1,
1461                                         GNUNET_NO);
1462               mq->specific_address->connected = GNUNET_NO;
1463             }
1464         }    
1465       if (! mq->internal_msg) 
1466         mq->specific_address->in_transmit = GNUNET_NO;
1467     }
1468   if (mq->client != NULL)
1469     transmit_send_ok (mq->client, n, result);
1470   GNUNET_free (mq);
1471   try_transmission_to_peer (n);
1472 }
1473
1474
1475 /**
1476  * Find an address in any of the available transports for
1477  * the given neighbour that would be good for message
1478  * transmission.  This is essentially the transport selection
1479  * routine.
1480  *
1481  * @param neighbour for whom to select an address
1482  * @return selected address, NULL if we have none
1483  */
1484 struct ForeignAddressList *
1485 find_ready_address(struct NeighbourList *neighbour)
1486 {
1487   struct ReadyList *head = neighbour->plugins;
1488   struct ForeignAddressList *addresses;
1489   struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
1490   struct ForeignAddressList *best_address;
1491
1492   best_address = NULL;
1493   while (head != NULL)
1494     {
1495       addresses = head->addresses;
1496       while (addresses != NULL)
1497         {
1498           if ( (addresses->timeout.value < now.value) && 
1499                (addresses->connected == GNUNET_YES) )
1500             {
1501 #if DEBUG_TRANSPORT
1502               GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1503                           "Marking long-time inactive connection to `%4s' as down.\n",
1504                           GNUNET_i2s (&neighbour->id));
1505 #endif
1506               GNUNET_STATISTICS_update (stats,
1507                                         gettext_noop ("# connected addresses"),
1508                                         -1,
1509                                         GNUNET_NO);
1510               addresses->connected = GNUNET_NO;
1511             }
1512           addresses = addresses->next;
1513         }
1514
1515       addresses = head->addresses;
1516       while (addresses != NULL)
1517         {
1518 #if DEBUG_TRANSPORT > 1
1519           if (addresses->addr != NULL)
1520             GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1521                         "Have address `%s' for peer `%4s' (status: %d, %d, %d, %u, %llums, %u)\n",
1522                         a2s (head->plugin->short_name,
1523                              addresses->addr,
1524                              addresses->addrlen),
1525                         GNUNET_i2s (&neighbour->id),
1526                         addresses->connected,
1527                         addresses->in_transmit,
1528                         addresses->validated,
1529                         addresses->connect_attempts,
1530                         (unsigned long long) addresses->timeout.value,
1531                         (unsigned int) addresses->distance);
1532 #endif
1533           if ( ( (best_address == NULL) || 
1534                  (addresses->connected == GNUNET_YES) ||
1535                  (best_address->connected == GNUNET_NO) ) &&
1536                (addresses->in_transmit == GNUNET_NO) &&
1537                ( (best_address == NULL) || 
1538                  (addresses->latency.value < best_address->latency.value)) )
1539             best_address = addresses;            
1540           /* FIXME: also give lower-latency addresses that are not
1541              connected a chance some times... */
1542           addresses = addresses->next;
1543         }
1544       head = head->next;
1545     }
1546   if (best_address != NULL)
1547     {
1548 #if DEBUG_TRANSPORT
1549       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1550                   "Best address found (`%s') has latency of %llu ms.\n",
1551                   (best_address->addrlen > 0) 
1552                   ? a2s (best_address->ready_list->plugin->short_name,
1553                        best_address->addr,
1554                        best_address->addrlen)
1555                   : "<inbound>",
1556                   best_address->latency.value);
1557 #endif
1558     }
1559   else
1560     {
1561       GNUNET_STATISTICS_update (stats,
1562                                 gettext_noop ("# transmission attempts failed (no address)"),
1563                                 1,
1564                                 GNUNET_NO);
1565     }
1566   return best_address;
1567
1568 }
1569
1570
1571 /**
1572  * We should re-try transmitting to the given peer,
1573  * hopefully we've learned something in the meantime.
1574  */
1575 static void
1576 retry_transmission_task (void *cls,
1577                          const struct GNUNET_SCHEDULER_TaskContext *tc)
1578 {
1579   struct NeighbourList *n = cls;
1580
1581   n->retry_task = GNUNET_SCHEDULER_NO_TASK;
1582   try_transmission_to_peer (n);
1583 }
1584
1585
1586 /**
1587  * Check the ready list for the given neighbour and if a plugin is
1588  * ready for transmission (and if we have a message), do so!
1589  *
1590  * @param neighbour target peer for which to transmit
1591  */
1592 static void
1593 try_transmission_to_peer (struct NeighbourList *neighbour)
1594 {
1595   struct ReadyList *rl;
1596   struct MessageQueue *mq;
1597   struct GNUNET_TIME_Relative timeout;
1598   ssize_t ret;
1599   int force_address;
1600
1601   if (neighbour->messages_head == NULL)
1602     {
1603 #if DEBUG_TRANSPORT
1604       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1605                   "Transmission queue for `%4s' is empty\n",
1606                   GNUNET_i2s (&neighbour->id));
1607 #endif
1608       return;                     /* nothing to do */
1609     }
1610   rl = NULL;
1611   mq = neighbour->messages_head;
1612   force_address = GNUNET_YES;
1613   if (mq->specific_address == NULL)
1614     {
1615       mq->specific_address = find_ready_address(neighbour); 
1616       GNUNET_STATISTICS_update (stats,
1617                                 gettext_noop ("# transport selected peer address freely"),
1618                                 1,
1619                                 GNUNET_NO); 
1620       force_address = GNUNET_NO;
1621     }
1622   if (mq->specific_address == NULL)
1623     {
1624       GNUNET_STATISTICS_update (stats,
1625                                 gettext_noop ("# transport failed to selected peer address"),
1626                                 1,
1627                                 GNUNET_NO); 
1628       timeout = GNUNET_TIME_absolute_get_remaining (mq->timeout);
1629       if (timeout.value == 0)
1630         {
1631 #if DEBUG_TRANSPORT
1632           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1633                       "No destination address available to transmit message of size %u to peer `%4s'\n",
1634                       mq->message_buf_size,
1635                       GNUNET_i2s (&mq->neighbour_id));
1636 #endif
1637           GNUNET_STATISTICS_update (stats,
1638                                     gettext_noop ("# bytes in message queue for other peers"),
1639                                     - (int64_t) mq->message_buf_size,
1640                                     GNUNET_NO);
1641           GNUNET_STATISTICS_update (stats,
1642                                     gettext_noop ("# bytes discarded (no destination address available)"),
1643                                     mq->message_buf_size,
1644                                     GNUNET_NO);      
1645           if (mq->client != NULL)
1646             transmit_send_ok (mq->client, neighbour, GNUNET_NO);
1647           GNUNET_CONTAINER_DLL_remove (neighbour->messages_head,
1648                                        neighbour->messages_tail,
1649                                        mq);
1650           GNUNET_free (mq);
1651           return;               /* nobody ready */ 
1652         }
1653       GNUNET_STATISTICS_update (stats,
1654                                 gettext_noop ("# message delivery deferred (no address)"),
1655                                 1,
1656                                 GNUNET_NO);
1657       if (neighbour->retry_task != GNUNET_SCHEDULER_NO_TASK)
1658         GNUNET_SCHEDULER_cancel (sched,
1659                                  neighbour->retry_task);
1660       neighbour->retry_task = GNUNET_SCHEDULER_add_delayed (sched,
1661                                                             timeout,
1662                                                             &retry_transmission_task,
1663                                                             neighbour);
1664 #if DEBUG_TRANSPORT
1665       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1666                   "No validated destination address available to transmit message of size %u to peer `%4s', will wait %llums to find an address.\n",
1667                   mq->message_buf_size,
1668                   GNUNET_i2s (&mq->neighbour_id),
1669                   timeout.value);
1670 #endif
1671       /* FIXME: might want to trigger peerinfo lookup here
1672          (unless that's already pending...) */
1673       return;    
1674     }
1675   GNUNET_CONTAINER_DLL_remove (neighbour->messages_head,
1676                                neighbour->messages_tail,
1677                                mq);
1678   if (mq->specific_address->connected == GNUNET_NO)
1679     mq->specific_address->connect_attempts++;
1680   rl = mq->specific_address->ready_list;
1681   mq->plugin = rl->plugin;
1682   if (!mq->internal_msg)
1683     mq->specific_address->in_transmit = GNUNET_YES;
1684 #if DEBUG_TRANSPORT
1685   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1686               "Sending message of size %u for `%4s' to `%s' via plugin `%s'\n",
1687               mq->message_buf_size,
1688               GNUNET_i2s (&neighbour->id), 
1689               (mq->specific_address->addr != NULL)
1690               ? a2s (mq->plugin->short_name,
1691                      mq->specific_address->addr,
1692                      mq->specific_address->addrlen)
1693               : "<inbound>",
1694               rl->plugin->short_name);
1695 #endif
1696   GNUNET_STATISTICS_update (stats,
1697                             gettext_noop ("# bytes in message queue for other peers"),
1698                             - (int64_t) mq->message_buf_size,
1699                             GNUNET_NO);
1700   GNUNET_STATISTICS_update (stats,
1701                             gettext_noop ("# bytes pending with plugins"),
1702                             mq->message_buf_size,
1703                             GNUNET_NO);
1704   ret = rl->plugin->api->send (rl->plugin->api->cls,
1705                                &mq->neighbour_id,
1706                                mq->message_buf,
1707                                mq->message_buf_size,
1708                                mq->priority,
1709                                GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
1710                                mq->specific_address->session,
1711                                mq->specific_address->addr,
1712                                mq->specific_address->addrlen,
1713                                force_address,
1714                                &transmit_send_continuation, mq);
1715   if (ret == -1)
1716     {
1717       /* failure, but 'send' would not call continuation in this case,
1718          so we need to do it here! */
1719       transmit_send_continuation (mq, 
1720                                   &mq->neighbour_id,
1721                                   GNUNET_SYSERR);
1722     }
1723 }
1724
1725
1726 /**
1727  * Send the specified message to the specified peer.
1728  *
1729  * @param client source of the transmission request (can be NULL)
1730  * @param peer_address ForeignAddressList where we should send this message
1731  * @param priority how important is the message
1732  * @param timeout how long do we have to transmit?
1733  * @param message_buf message(s) to send GNUNET_MessageHeader(s)
1734  * @param message_buf_size total size of all messages in message_buf
1735  * @param is_internal is this an internal message; these are pre-pended and
1736  *                    also do not count for plugins being "ready" to transmit
1737  * @param neighbour handle to the neighbour for transmission
1738  */
1739 static void
1740 transmit_to_peer (struct TransportClient *client,
1741                   struct ForeignAddressList *peer_address,
1742                   unsigned int priority,
1743                   struct GNUNET_TIME_Relative timeout,
1744                   const char *message_buf,
1745                   size_t message_buf_size,
1746                   int is_internal, struct NeighbourList *neighbour)
1747 {
1748   struct MessageQueue *mq;
1749
1750 #if EXTRA_CHECKS
1751   if (client != NULL)
1752     {
1753       /* check for duplicate submission */
1754       mq = neighbour->messages_head;
1755       while (NULL != mq)
1756         {
1757           if (mq->client == client)
1758             {
1759               /* client transmitted to same peer twice
1760                  before getting SEND_OK! */
1761               GNUNET_break (0);
1762               return;
1763             }
1764           mq = mq->next;
1765         }
1766     }
1767 #endif
1768   GNUNET_STATISTICS_update (stats,
1769                             gettext_noop ("# bytes in message queue for other peers"),
1770                             message_buf_size,
1771                             GNUNET_NO);
1772   mq = GNUNET_malloc (sizeof (struct MessageQueue) + message_buf_size);
1773   mq->specific_address = peer_address;
1774   mq->client = client;
1775   memcpy (&mq[1], message_buf, message_buf_size);
1776   mq->message_buf = (const char*) &mq[1];
1777   mq->message_buf_size = message_buf_size;
1778   memcpy(&mq->neighbour_id, &neighbour->id, sizeof(struct GNUNET_PeerIdentity));
1779   mq->internal_msg = is_internal;
1780   mq->priority = priority;
1781   mq->timeout = GNUNET_TIME_relative_to_absolute (timeout);
1782   if (is_internal)    
1783     GNUNET_CONTAINER_DLL_insert (neighbour->messages_head,
1784                                  neighbour->messages_tail,
1785                                  mq);
1786   else
1787     GNUNET_CONTAINER_DLL_insert_after (neighbour->messages_head,
1788                                        neighbour->messages_tail,
1789                                        neighbour->messages_tail,
1790                                        mq);
1791   try_transmission_to_peer (neighbour);
1792 }
1793
1794
1795 /**
1796  * FIXME: document.
1797  */
1798 struct GeneratorContext
1799 {
1800   struct TransportPlugin *plug_pos;
1801   struct OwnAddressList *addr_pos;
1802   struct GNUNET_TIME_Absolute expiration;
1803 };
1804
1805
1806 /**
1807  * FIXME: document.
1808  */
1809 static size_t
1810 address_generator (void *cls, size_t max, void *buf)
1811 {
1812   struct GeneratorContext *gc = cls;
1813   size_t ret;
1814
1815   while ((gc->addr_pos == NULL) && (gc->plug_pos != NULL))
1816     {
1817       gc->plug_pos = gc->plug_pos->next;
1818       gc->addr_pos = (gc->plug_pos != NULL) ? gc->plug_pos->addresses : NULL;
1819     }
1820   if (NULL == gc->plug_pos)
1821     {
1822
1823       return 0;
1824     }
1825   ret = GNUNET_HELLO_add_address (gc->plug_pos->short_name,
1826                                   gc->expiration,
1827                                   &gc->addr_pos[1],
1828                                   gc->addr_pos->addrlen, buf, max);
1829   gc->addr_pos = gc->addr_pos->next;
1830   return ret;
1831 }
1832
1833
1834 /**
1835  * Construct our HELLO message from all of the addresses of
1836  * all of the transports.
1837  */
1838 static void
1839 refresh_hello ()
1840 {
1841   struct GNUNET_HELLO_Message *hello;
1842   struct TransportClient *cpos;
1843   struct NeighbourList *npos;
1844   struct GeneratorContext gc;
1845
1846   gc.plug_pos = plugins;
1847   gc.addr_pos = plugins != NULL ? plugins->addresses : NULL;
1848   gc.expiration = GNUNET_TIME_relative_to_absolute (HELLO_ADDRESS_EXPIRATION);
1849   hello = GNUNET_HELLO_create (&my_public_key, &address_generator, &gc);
1850 #if DEBUG_TRANSPORT
1851   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
1852               "Refreshed my `%s', new size is %d\n", "HELLO", GNUNET_HELLO_size(hello));
1853 #endif
1854   GNUNET_STATISTICS_update (stats,
1855                             gettext_noop ("# refreshed my HELLO"),
1856                             1,
1857                             GNUNET_NO);
1858   cpos = clients;
1859   while (cpos != NULL)
1860     {
1861       transmit_to_client (cpos,
1862                           (const struct GNUNET_MessageHeader *) hello,
1863                           GNUNET_NO);
1864       cpos = cpos->next;
1865     }
1866
1867   GNUNET_free_non_null (our_hello);
1868   our_hello = hello;
1869   GNUNET_PEERINFO_add_peer (peerinfo, our_hello);
1870   npos = neighbours;
1871   while (npos != NULL)
1872     {
1873 #if DEBUG_TRANSPORT
1874       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
1875                   "Transmitting updated `%s' to neighbour `%4s'\n",
1876                   "HELLO", GNUNET_i2s (&npos->id));
1877 #endif
1878       GNUNET_STATISTICS_update (stats,
1879                                 gettext_noop ("# transmitted my HELLO to other peers"),
1880                                 1,
1881                                 GNUNET_NO);
1882       transmit_to_peer (NULL, NULL, 0,
1883                         HELLO_ADDRESS_EXPIRATION,
1884                         (const char *) our_hello, 
1885                         GNUNET_HELLO_size(our_hello),
1886                         GNUNET_NO, npos);
1887       npos = npos->next;
1888     }
1889 }
1890
1891
1892 /**
1893  * Task used to clean up expired addresses for a plugin.
1894  *
1895  * @param cls closure
1896  * @param tc context
1897  */
1898 static void
1899 expire_address_task (void *cls,
1900                      const struct GNUNET_SCHEDULER_TaskContext *tc);
1901
1902
1903 /**
1904  * Update the list of addresses for this plugin,
1905  * expiring those that are past their expiration date.
1906  *
1907  * @param plugin addresses of which plugin should be recomputed?
1908  * @param fresh set to GNUNET_YES if a new address was added
1909  *        and we need to regenerate the HELLO even if nobody
1910  *        expired
1911  */
1912 static void
1913 update_addresses (struct TransportPlugin *plugin, int fresh)
1914 {
1915   static struct GNUNET_TIME_Absolute last_update;
1916   struct GNUNET_TIME_Relative min_remaining;
1917   struct GNUNET_TIME_Relative remaining;
1918   struct GNUNET_TIME_Absolute now;
1919   struct OwnAddressList *pos;
1920   struct OwnAddressList *prev;
1921   struct OwnAddressList *next;
1922   int expired;
1923
1924   if (plugin->address_update_task != GNUNET_SCHEDULER_NO_TASK)
1925     GNUNET_SCHEDULER_cancel (plugin->env.sched, plugin->address_update_task);
1926   plugin->address_update_task = GNUNET_SCHEDULER_NO_TASK;
1927   now = GNUNET_TIME_absolute_get ();
1928   min_remaining = GNUNET_TIME_UNIT_FOREVER_REL;
1929   expired = (GNUNET_TIME_absolute_get_duration (last_update).value > (HELLO_ADDRESS_EXPIRATION.value / 4));
1930   prev = NULL;
1931   pos = plugin->addresses;
1932   while (pos != NULL)
1933     {
1934       next = pos->next;
1935       if (pos->expires.value < now.value)
1936         {
1937           expired = GNUNET_YES;
1938           if (prev == NULL)
1939             plugin->addresses = pos->next;
1940           else
1941             prev->next = pos->next;  
1942           GNUNET_free (pos);
1943         }
1944       else
1945         {
1946           remaining = GNUNET_TIME_absolute_get_remaining (pos->expires);
1947           if (remaining.value < min_remaining.value)
1948             min_remaining = remaining;
1949           prev = pos;
1950         }
1951       pos = next;
1952     }
1953
1954   if (expired || fresh)
1955     {
1956       last_update = now;
1957       refresh_hello ();
1958     }
1959   min_remaining = GNUNET_TIME_relative_min (min_remaining,
1960                                             GNUNET_TIME_relative_divide (HELLO_ADDRESS_EXPIRATION,
1961                                                                          2));
1962   plugin->address_update_task
1963     = GNUNET_SCHEDULER_add_delayed (plugin->env.sched,
1964                                     min_remaining,
1965                                     &expire_address_task, plugin);
1966 }
1967
1968
1969 /**
1970  * Task used to clean up expired addresses for a plugin.
1971  *
1972  * @param cls closure
1973  * @param tc context
1974  */
1975 static void
1976 expire_address_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1977 {
1978   struct TransportPlugin *plugin = cls;
1979
1980   plugin->address_update_task = GNUNET_SCHEDULER_NO_TASK;
1981   if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
1982     update_addresses (plugin, GNUNET_NO);
1983 }
1984
1985
1986 /**
1987  * Iterator over hash map entries that NULLs the session of validation
1988  * entries that match the given session.
1989  *
1990  * @param cls closure (the 'struct Session*' to match against)
1991  * @param key current key code (peer ID, not used)
1992  * @param value value in the hash map ('struct ValidationEntry*')
1993  * @return GNUNET_YES (we should continue to iterate)
1994  */
1995 static int 
1996 remove_session_validations (void *cls,
1997                             const GNUNET_HashCode * key,
1998                             void *value)
1999 {
2000   struct Session *session = cls;
2001   struct ValidationEntry *ve = value;
2002
2003   if (session == ve->session)
2004     ve->session = NULL;
2005   return GNUNET_YES;
2006 }
2007
2008
2009 /**
2010  * Function that will be called whenever the plugin internally
2011  * cleans up a session pointer and hence the service needs to
2012  * discard all of those sessions as well.  Plugins that do not
2013  * use sessions can simply omit calling this function and always
2014  * use NULL wherever a session pointer is needed.
2015  * 
2016  * @param cls closure
2017  * @param peer which peer was the session for 
2018  * @param session which session is being destoyed
2019  */
2020 static void
2021 plugin_env_session_end  (void *cls,
2022                          const struct GNUNET_PeerIdentity *peer,
2023                          struct Session *session)
2024 {
2025   struct TransportPlugin *p = cls;
2026   struct NeighbourList *nl;
2027   struct ReadyList *rl;
2028   struct ForeignAddressList *pos;
2029   struct ForeignAddressList *prev;
2030
2031   GNUNET_CONTAINER_multihashmap_iterate (validation_map,
2032                                          &remove_session_validations,
2033                                          session);
2034   nl = find_neighbour (peer);
2035   if (nl == NULL)
2036     return;
2037   rl = nl->plugins;
2038   while (rl != NULL)
2039     {
2040       if (rl->plugin == p)
2041         break;
2042       rl = rl->next;
2043     }
2044   if (rl == NULL)
2045     return;
2046   prev = NULL;
2047   pos = rl->addresses;
2048   while ( (pos != NULL) &&
2049           (pos->session != session) )
2050     {
2051       prev = pos;
2052       pos = pos->next;
2053     }
2054   if (pos == NULL)
2055     return;
2056   pos->session = NULL;
2057   if (pos->addrlen != 0)
2058     return;
2059   if (prev == NULL)
2060     rl->addresses = pos->next;
2061   else
2062     prev->next = pos->next;
2063   if (GNUNET_SCHEDULER_NO_TASK != pos->revalidate_task)
2064     {
2065       GNUNET_SCHEDULER_cancel (sched,
2066                                pos->revalidate_task);
2067       pos->revalidate_task = GNUNET_SCHEDULER_NO_TASK;
2068     }
2069   GNUNET_free (pos);
2070   if (nl->received_pong == GNUNET_NO)
2071     return; /* nothing to do */
2072   /* check if we have any validated addresses left */
2073   pos = rl->addresses;
2074   while (pos != NULL)
2075     {
2076       if (pos->validated)
2077         return;
2078       pos = pos->next;
2079     }
2080   /* no valid addresses left, signal disconnect! */
2081   disconnect_neighbour (nl, GNUNET_NO);  
2082 }
2083
2084
2085 /**
2086  * Function that must be called by each plugin to notify the
2087  * transport service about the addresses under which the transport
2088  * provided by the plugin can be reached.
2089  *
2090  * @param cls closure
2091  * @param name name of the transport that generated the address
2092  * @param addr one of the addresses of the host, NULL for the last address
2093  *        the specific address format depends on the transport
2094  * @param addrlen length of the address
2095  * @param expires when should this address automatically expire?
2096  */
2097 static void
2098 plugin_env_notify_address (void *cls,
2099                            const char *name,
2100                            const void *addr,
2101                            uint16_t addrlen,
2102                            struct GNUNET_TIME_Relative expires)
2103 {
2104   struct TransportPlugin *p = cls;
2105   struct OwnAddressList *al;
2106   struct GNUNET_TIME_Absolute abex;
2107
2108   GNUNET_assert (addr != NULL);
2109   abex = GNUNET_TIME_relative_to_absolute (expires);
2110   GNUNET_assert (p == find_transport (name));
2111   al = p->addresses;
2112   while (al != NULL)
2113     {
2114       if ((addrlen == al->addrlen) && (0 == memcmp (addr, &al[1], addrlen)))
2115         {
2116           if (al->expires.value < abex.value)
2117             al->expires = abex;
2118           return;
2119         }
2120       al = al->next;
2121     }
2122
2123   al = GNUNET_malloc (sizeof (struct OwnAddressList) + addrlen);
2124   al->next = p->addresses;
2125   p->addresses = al;
2126   al->expires = abex;
2127   al->addrlen = addrlen;
2128   memcpy (&al[1], addr, addrlen);
2129   update_addresses (p, GNUNET_YES);
2130 }
2131
2132
2133 /**
2134  * Notify all of our clients about a peer connecting.
2135  */
2136 static void
2137 notify_clients_connect (const struct GNUNET_PeerIdentity *peer,
2138                         struct GNUNET_TIME_Relative latency,
2139                         uint32_t distance)
2140 {
2141   struct ConnectInfoMessage cim;
2142   struct TransportClient *cpos;
2143
2144 #if DEBUG_TRANSPORT
2145   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2146               "Notifying clients about connection from `%s'\n",
2147               GNUNET_i2s (peer));
2148 #endif
2149   GNUNET_STATISTICS_update (stats,
2150                             gettext_noop ("# peers connected"),
2151                             1,
2152                             GNUNET_NO);
2153   cim.header.size = htons (sizeof (struct ConnectInfoMessage));
2154   cim.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
2155   cim.distance = htonl (distance);
2156   cim.latency = GNUNET_TIME_relative_hton (latency);
2157   memcpy (&cim.id, peer, sizeof (struct GNUNET_PeerIdentity));
2158   cpos = clients;
2159   while (cpos != NULL)
2160     {
2161       transmit_to_client (cpos, &cim.header, GNUNET_NO);
2162       cpos = cpos->next;
2163     }
2164 }
2165
2166
2167 /**
2168  * Notify all of our clients about a peer disconnecting.
2169  */
2170 static void
2171 notify_clients_disconnect (const struct GNUNET_PeerIdentity *peer)
2172 {
2173   struct DisconnectInfoMessage dim;
2174   struct TransportClient *cpos;
2175
2176 #if DEBUG_TRANSPORT
2177   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2178               "Notifying clients about lost connection to `%s'\n",
2179               GNUNET_i2s (peer));
2180 #endif
2181   GNUNET_STATISTICS_update (stats,
2182                             gettext_noop ("# peers connected"),
2183                             -1,
2184                             GNUNET_NO);
2185   dim.header.size = htons (sizeof (struct DisconnectInfoMessage));
2186   dim.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT);
2187   dim.reserved = htonl (0);
2188   memcpy (&dim.peer, peer, sizeof (struct GNUNET_PeerIdentity));
2189   cpos = clients;
2190   while (cpos != NULL)
2191     {
2192       transmit_to_client (cpos, &dim.header, GNUNET_NO);
2193       cpos = cpos->next;
2194     }
2195 }
2196
2197
2198 /**
2199  * Find a ForeignAddressList entry for the given neighbour
2200  * that matches the given address and transport.
2201  *
2202  * @param neighbour which peer we care about
2203  * @param tname name of the transport plugin
2204  * @param session session to look for, NULL for 'any'; otherwise
2205  *        can be used for the service to "learn" this session ID
2206  *        if 'addr' matches
2207  * @param addr binary address
2208  * @param addrlen length of addr
2209  * @return NULL if no such entry exists
2210  */
2211 static struct ForeignAddressList *
2212 find_peer_address(struct NeighbourList *neighbour,
2213                   const char *tname,
2214                   struct Session *session,
2215                   const char *addr,
2216                   uint16_t addrlen)
2217 {
2218   struct ReadyList *head;
2219   struct ForeignAddressList *pos;
2220
2221   head = neighbour->plugins;
2222   while (head != NULL)
2223     {
2224       if (0 == strcmp (tname, head->plugin->short_name))
2225         break;
2226       head = head->next;
2227     }
2228   if (head == NULL)
2229     return NULL;
2230   pos = head->addresses;
2231   while ( (pos != NULL) &&
2232           ( (pos->addrlen != addrlen) ||
2233             (memcmp(pos->addr, addr, addrlen) != 0) ) )
2234     {
2235       if ( (session != NULL) &&
2236            (pos->session == session) )
2237         return pos;
2238       pos = pos->next;
2239     }
2240   if ( (session != NULL) && (pos != NULL) )
2241     pos->session = session; /* learn it! */
2242   return pos;
2243 }
2244
2245
2246 /**
2247  * Get the peer address struct for the given neighbour and
2248  * address.  If it doesn't yet exist, create it.
2249  *
2250  * @param neighbour which peer we care about
2251  * @param tname name of the transport plugin
2252  * @param session session of the plugin, or NULL for none
2253  * @param addr binary address
2254  * @param addrlen length of addr
2255  * @return NULL if we do not have a transport plugin for 'tname'
2256  */
2257 static struct ForeignAddressList *
2258 add_peer_address (struct NeighbourList *neighbour,
2259                   const char *tname,
2260                   struct Session *session,
2261                   const char *addr, 
2262                   uint16_t addrlen)
2263 {
2264   struct ReadyList *head;
2265   struct ForeignAddressList *ret;
2266
2267   ret = find_peer_address (neighbour, tname, session, addr, addrlen);
2268   if (ret != NULL)
2269     return ret;
2270   head = neighbour->plugins;
2271
2272   while (head != NULL)
2273     {
2274       if (0 == strcmp (tname, head->plugin->short_name))
2275         break;
2276       head = head->next;
2277     }
2278   if (head == NULL)
2279     return NULL;
2280   ret = GNUNET_malloc(sizeof(struct ForeignAddressList) + addrlen);
2281   ret->session = session;
2282   if (addrlen > 0)
2283     {
2284       ret->addr = (const char*) &ret[1];
2285       memcpy (&ret[1], addr, addrlen);
2286     }
2287   else
2288     {
2289       ret->addr = NULL;
2290     }
2291   ret->addrlen = addrlen;
2292   ret->expires = GNUNET_TIME_relative_to_absolute
2293     (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
2294   ret->latency = GNUNET_TIME_relative_get_forever();
2295   ret->distance = -1;
2296   ret->timeout = GNUNET_TIME_relative_to_absolute
2297     (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT); 
2298   ret->ready_list = head;
2299   ret->next = head->addresses;
2300   head->addresses = ret;
2301   return ret;
2302 }
2303
2304
2305 /**
2306  * Closure for 'add_validated_address'.
2307  */
2308 struct AddValidatedAddressContext
2309 {
2310   /**
2311    * Entry that has been validated.
2312    */
2313   const struct ValidationEntry *ve;
2314
2315   /**
2316    * Flag set after we have added the address so
2317    * that we terminate the iteration next time.
2318    */
2319   int done;
2320 };
2321
2322
2323 /**
2324  * Callback function used to fill a buffer of max bytes with a list of
2325  * addresses in the format used by HELLOs.  Should use
2326  * "GNUNET_HELLO_add_address" as a helper function.
2327  *
2328  * @param cls the 'struct AddValidatedAddressContext' with the validated address
2329  * @param max maximum number of bytes that can be written to buf
2330  * @param buf where to write the address information
2331  * @return number of bytes written, 0 to signal the
2332  *         end of the iteration.
2333  */
2334 static size_t
2335 add_validated_address (void *cls,
2336                        size_t max, void *buf)
2337 {
2338   struct AddValidatedAddressContext *avac = cls;
2339   const struct ValidationEntry *ve = avac->ve;
2340
2341   if (GNUNET_YES == avac->done)
2342     return 0;
2343   avac->done = GNUNET_YES;
2344   return GNUNET_HELLO_add_address (ve->transport_name,
2345                                    GNUNET_TIME_relative_to_absolute (HELLO_ADDRESS_EXPIRATION),
2346                                    ve->addr,
2347                                    ve->addrlen,
2348                                    buf,
2349                                    max);
2350 }
2351
2352
2353
2354 /**
2355  * Closure for 'check_address_exists'.
2356  */
2357 struct CheckAddressExistsClosure
2358 {
2359   /**
2360    * Address to check for.
2361    */
2362   const void *addr;
2363
2364   /**
2365    * Name of the transport.
2366    */
2367   const char *tname;
2368
2369   /**
2370    * Session, or NULL.
2371    */
2372   struct Session *session;
2373
2374   /**
2375    * Set to GNUNET_YES if the address exists.
2376    */
2377   int exists;
2378
2379   /**
2380    * Length of addr.
2381    */
2382   uint16_t addrlen;
2383
2384 };
2385
2386
2387 /**
2388  * Iterator over hash map entries.  Checks if the given
2389  * validation entry is for the same address as what is given
2390  * in the closure.
2391  *
2392  * @param cls the 'struct CheckAddressExistsClosure*'
2393  * @param key current key code (ignored)
2394  * @param value value in the hash map ('struct ValidationEntry')
2395  * @return GNUNET_YES if we should continue to
2396  *         iterate (mismatch), GNUNET_NO if not (entry matched)
2397  */
2398 static int
2399 check_address_exists (void *cls,
2400                       const GNUNET_HashCode * key,
2401                       void *value)
2402 {
2403   struct CheckAddressExistsClosure *caec = cls;
2404   struct ValidationEntry *ve = value;
2405
2406   if ( (0 == strcmp (caec->tname,
2407                      ve->transport_name)) &&
2408        (caec->addrlen == ve->addrlen) &&
2409        (0 == memcmp (caec->addr,
2410                      ve->addr,
2411                      caec->addrlen)) )
2412     {
2413       caec->exists = GNUNET_YES;
2414       return GNUNET_NO;
2415     }
2416   if ( (ve->session != NULL) &&
2417        (caec->session == ve->session) )
2418     {
2419       caec->exists = GNUNET_YES;
2420       return GNUNET_NO;
2421     }
2422   return GNUNET_YES;
2423 }
2424
2425
2426
2427 /**
2428  * Iterator to free entries in the validation_map.
2429  *
2430  * @param cls closure (unused)
2431  * @param key current key code
2432  * @param value value in the hash map (validation to abort)
2433  * @return GNUNET_YES (always)
2434  */
2435 static int 
2436 abort_validation (void *cls,
2437                   const GNUNET_HashCode * key,
2438                   void *value)
2439 {
2440   struct ValidationEntry *va = value;
2441
2442   if (GNUNET_SCHEDULER_NO_TASK != va->timeout_task)
2443     GNUNET_SCHEDULER_cancel (sched, va->timeout_task);
2444   GNUNET_free (va->transport_name);
2445   if (va->chvc != NULL)
2446     {
2447       va->chvc->ve_count--;
2448       if (va->chvc->ve_count == 0)
2449         {
2450           GNUNET_CONTAINER_DLL_remove (chvc_head,
2451                                        chvc_tail,
2452                                        va->chvc);
2453           GNUNET_free (va->chvc);
2454         }
2455       va->chvc = NULL;
2456     }
2457   GNUNET_free (va);
2458   return GNUNET_YES;
2459 }
2460
2461
2462 /**
2463  * HELLO validation cleanup task (validation failed).
2464  *
2465  * @param cls the 'struct ValidationEntry' that failed
2466  * @param tc scheduler context (unused)
2467  */
2468 static void
2469 timeout_hello_validation (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2470 {
2471   struct ValidationEntry *va = cls;
2472   struct GNUNET_PeerIdentity pid;
2473
2474   va->timeout_task = GNUNET_SCHEDULER_NO_TASK;
2475   GNUNET_STATISTICS_update (stats,
2476                             gettext_noop ("# address validation timeouts"),
2477                             1,
2478                             GNUNET_NO);
2479   GNUNET_CRYPTO_hash (&va->publicKey,
2480                       sizeof (struct
2481                               GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
2482                       &pid.hashPubKey);
2483   GNUNET_break (GNUNET_OK ==
2484                 GNUNET_CONTAINER_multihashmap_remove (validation_map,
2485                                                       &pid.hashPubKey,
2486                                                       va));
2487   abort_validation (NULL, NULL, va);
2488 }
2489
2490
2491 static void
2492 neighbour_timeout_task (void *cls,
2493                        const struct GNUNET_SCHEDULER_TaskContext *tc)
2494 {
2495   struct NeighbourList *n = cls;
2496
2497 #if DEBUG_TRANSPORT
2498   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2499               "Neighbour `%4s' has timed out!\n", GNUNET_i2s (&n->id));
2500 #endif
2501   GNUNET_STATISTICS_update (stats,
2502                             gettext_noop ("# disconnects due to timeout"),
2503                             1,
2504                             GNUNET_NO);
2505   n->timeout_task = GNUNET_SCHEDULER_NO_TASK;
2506   disconnect_neighbour (n, GNUNET_NO);
2507 }
2508
2509
2510 /**
2511  * Schedule the job that will cause us to send a PING to the
2512  * foreign address to evaluate its validity and latency.
2513  *
2514  * @param fal address to PING
2515  */
2516 static void
2517 schedule_next_ping (struct ForeignAddressList *fal);
2518
2519
2520 /**
2521  * Add the given address to the list of foreign addresses
2522  * available for the given peer (check for duplicates).
2523  *
2524  * @param cls the respective 'struct NeighbourList' to update
2525  * @param tname name of the transport
2526  * @param expiration expiration time
2527  * @param addr the address
2528  * @param addrlen length of the address
2529  * @return GNUNET_OK (always)
2530  */
2531 static int
2532 add_to_foreign_address_list (void *cls,
2533                              const char *tname,
2534                              struct GNUNET_TIME_Absolute expiration,
2535                              const void *addr,
2536                              uint16_t addrlen)
2537 {
2538   struct NeighbourList *n = cls;
2539   struct ForeignAddressList *fal;
2540   int try;
2541
2542   GNUNET_STATISTICS_update (stats,
2543                             gettext_noop ("# valid peer addresses returned by PEERINFO"),
2544                             1,
2545                             GNUNET_NO);      
2546   try = GNUNET_NO;
2547   fal = find_peer_address (n, tname, NULL, addr, addrlen);
2548   if (fal == NULL)
2549     {
2550 #if DEBUG_TRANSPORT
2551       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2552                   "Adding address `%s' (%s) for peer `%4s' due to PEERINFO data for %llums.\n",
2553                   a2s (tname, addr, addrlen),
2554                   tname,
2555                   GNUNET_i2s (&n->id),
2556                   expiration.value);
2557 #endif
2558       fal = add_peer_address (n, tname, NULL, addr, addrlen);
2559       if (fal == NULL)
2560         {
2561           GNUNET_STATISTICS_update (stats,
2562                                     gettext_noop ("# previously validated addresses lacking transport"),
2563                                     1,
2564                                     GNUNET_NO); 
2565         }
2566       else
2567         {
2568           fal->expires = GNUNET_TIME_absolute_max (expiration,
2569                                                    fal->expires);
2570           schedule_next_ping (fal);
2571         }
2572       try = GNUNET_YES;
2573     }
2574   else
2575     {
2576       fal->expires = GNUNET_TIME_absolute_max (expiration,
2577                                                fal->expires);
2578     }
2579   if (fal == NULL)
2580     {
2581       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2582                   "Failed to add new address for `%4s'\n",
2583                   GNUNET_i2s (&n->id));
2584       return GNUNET_OK;
2585     }
2586   if (fal->validated == GNUNET_NO)
2587     {
2588       fal->validated = GNUNET_YES;  
2589       GNUNET_STATISTICS_update (stats,
2590                                 gettext_noop ("# peer addresses considered valid"),
2591                                 1,
2592                                 GNUNET_NO);      
2593     }
2594   if (try == GNUNET_YES)
2595     {
2596       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2597                   "Have new addresses, will try to trigger transmissions.\n");
2598       try_transmission_to_peer (n);
2599     }
2600   return GNUNET_OK;
2601 }
2602
2603
2604 /**
2605  * Add addresses in validated HELLO "h" to the set of addresses
2606  * we have for this peer.
2607  *
2608  * @param cls closure ('struct NeighbourList*')
2609  * @param peer id of the peer, NULL for last call
2610  * @param h hello message for the peer (can be NULL)
2611  * @param trust amount of trust we have in the peer (not used)
2612  */
2613 static void
2614 add_hello_for_peer (void *cls,
2615                     const struct GNUNET_PeerIdentity *peer,
2616                     const struct GNUNET_HELLO_Message *h, 
2617                     uint32_t trust)
2618 {
2619   struct NeighbourList *n = cls;
2620
2621   if (peer == NULL)
2622     {
2623       n->piter = NULL;
2624       return;
2625     } 
2626   if (h == NULL)
2627     return; /* no HELLO available */
2628 #if DEBUG_TRANSPORT
2629   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2630               "Peerinfo had `%s' message for peer `%4s', adding existing addresses.\n",
2631               "HELLO",
2632               GNUNET_i2s (peer));
2633 #endif
2634   if (GNUNET_YES != n->public_key_valid)
2635     {
2636       GNUNET_HELLO_get_key (h, &n->publicKey);
2637       n->public_key_valid = GNUNET_YES;
2638     }
2639   GNUNET_HELLO_iterate_addresses (h,
2640                                   GNUNET_NO,
2641                                   &add_to_foreign_address_list,
2642                                   n);
2643 }
2644
2645
2646 /**
2647  * Create a fresh entry in our neighbour list for the given peer.
2648  * Will try to transmit our current HELLO to the new neighbour. 
2649  * Do not call this function directly, use 'setup_peer_check_blacklist.
2650  *
2651  * @param peer the peer for which we create the entry
2652  * @param do_hello should we schedule transmitting a HELLO
2653  * @return the new neighbour list entry
2654  */
2655 static struct NeighbourList *
2656 setup_new_neighbour (const struct GNUNET_PeerIdentity *peer,
2657                      int do_hello)
2658 {
2659   struct NeighbourList *n;
2660   struct TransportPlugin *tp;
2661   struct ReadyList *rl;
2662
2663 #if DEBUG_TRANSPORT
2664   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2665               "Setting up state for neighbour `%4s'\n",
2666               GNUNET_i2s (peer));
2667 #endif
2668   GNUNET_assert (our_hello != NULL);
2669   GNUNET_STATISTICS_update (stats,
2670                             gettext_noop ("# active neighbours"),
2671                             1,
2672                             GNUNET_NO);
2673   n = GNUNET_malloc (sizeof (struct NeighbourList));
2674   n->next = neighbours;
2675   neighbours = n;
2676   n->id = *peer;
2677   n->peer_timeout =
2678     GNUNET_TIME_relative_to_absolute
2679     (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
2680   GNUNET_BANDWIDTH_tracker_init (&n->in_tracker,
2681                                  GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT,
2682                                  MAX_BANDWIDTH_CARRY_S);
2683   tp = plugins;
2684   while (tp != NULL)
2685     {
2686       if ((tp->api->send != NULL) && (!is_blacklisted(peer, tp)))
2687         {
2688           rl = GNUNET_malloc (sizeof (struct ReadyList));
2689           rl->neighbour = n;
2690           rl->next = n->plugins;
2691           n->plugins = rl;
2692           rl->plugin = tp;
2693           rl->addresses = NULL;
2694         }
2695       tp = tp->next;
2696     }
2697   n->latency = GNUNET_TIME_UNIT_FOREVER_REL;
2698   n->distance = -1;
2699   n->timeout_task = GNUNET_SCHEDULER_add_delayed (sched,
2700                                                   GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
2701                                                   &neighbour_timeout_task, n);
2702   if (do_hello)
2703     {
2704       n->piter = GNUNET_PEERINFO_iterate (peerinfo, peer,
2705                                           0, GNUNET_TIME_UNIT_FOREVER_REL,
2706                                           &add_hello_for_peer, n);
2707       transmit_to_peer (NULL, NULL, 0,
2708                         HELLO_ADDRESS_EXPIRATION,
2709                         (const char *) our_hello, GNUNET_HELLO_size(our_hello),
2710                         GNUNET_NO, n);
2711     }
2712   return n;
2713 }
2714
2715
2716 /**
2717  * Function called after we have checked if communicating
2718  * with a given peer is acceptable.  
2719  *
2720  * @param cls closure
2721  * @param n NULL if communication is not acceptable
2722  */
2723 typedef void (*SetupContinuation)(void *cls,
2724                                   struct NeighbourList *n);
2725
2726
2727 /**
2728  * Information kept for each client registered to perform
2729  * blacklisting.
2730  */
2731 struct Blacklisters
2732 {
2733   /**
2734    * This is a linked list.
2735    */
2736   struct Blacklisters *next;
2737
2738   /**
2739    * This is a linked list.
2740    */
2741   struct Blacklisters *prev;
2742
2743   /**
2744    * Client responsible for this entry.
2745    */
2746   struct GNUNET_SERVER_Client *client;
2747
2748   /**
2749    * Blacklist check that we're currently performing.
2750    */
2751   struct BlacklistCheck *bc;
2752
2753 };
2754
2755
2756 /**
2757  * Head of DLL of blacklisting clients.
2758  */
2759 static struct Blacklisters *bl_head;
2760
2761 /**
2762  * Tail of DLL of blacklisting clients.
2763  */
2764 static struct Blacklisters *bl_tail;
2765
2766
2767 /**
2768  * Context we use when performing a blacklist check.
2769  */
2770 struct BlacklistCheck
2771 {
2772   
2773   /**
2774    * This is a linked list.
2775    */
2776   struct BlacklistCheck *next;
2777   
2778   /**
2779    * This is a linked list.
2780    */
2781   struct BlacklistCheck *prev;
2782
2783   /**
2784    * Peer being checked.
2785    */
2786   struct GNUNET_PeerIdentity peer;
2787
2788   /**
2789    * Option for setup neighbour afterwards.
2790    */
2791   int do_hello;
2792
2793   /**
2794    * Continuation to call with the result.
2795    */
2796   SetupContinuation cont;
2797
2798   /**
2799    * Closure for cont.
2800    */
2801   void *cont_cls;
2802
2803   /**
2804    * Current transmission request handle for this client, or NULL if no
2805    * request is pending.
2806    */
2807   struct GNUNET_CONNECTION_TransmitHandle *th;
2808
2809   /**
2810    * Our current position in the blacklisters list.
2811    */
2812   struct Blacklisters *bl_pos;
2813
2814   /**
2815    * Current task performing the check.
2816    */
2817   GNUNET_SCHEDULER_TaskIdentifier task;
2818
2819 };
2820
2821 /**
2822  * Head of DLL of active blacklisting queries.
2823  */
2824 static struct BlacklistCheck *bc_head;
2825
2826 /**
2827  * Tail of DLL of active blacklisting queries.
2828  */
2829 static struct BlacklistCheck *bc_tail;
2830
2831
2832 /**
2833  * Perform next action in the blacklist check.
2834  *
2835  * @param cls the 'struct BlacklistCheck*'
2836  * @param tc unused 
2837  */
2838 static void
2839 do_blacklist_check (void *cls,
2840                     const struct GNUNET_SCHEDULER_TaskContext *tc);
2841
2842
2843 /**
2844  * Transmit blacklist query to the client.
2845  *
2846  * @param cls the 'struct BlacklistCheck'
2847  * @param size number of bytes allowed
2848  * @param buf where to copy the message
2849  * @return number of bytes copied to buf
2850  */
2851 static size_t
2852 transmit_blacklist_message (void *cls,
2853                             size_t size,
2854                             void *buf)
2855 {
2856   struct BlacklistCheck *bc = cls;
2857   struct Blacklisters *bl;
2858   struct BlacklistMessage bm;
2859
2860   bc->th = NULL;
2861   if (size == 0)
2862     {
2863       GNUNET_assert (bc->task == GNUNET_SCHEDULER_NO_TASK);
2864       bc->task = GNUNET_SCHEDULER_add_now (sched,
2865                                            &do_blacklist_check,
2866                                            bc);
2867       return 0;
2868     }
2869   bl = bc->bl_pos;
2870   bm.header.size = htons (sizeof (struct BlacklistMessage));
2871   bm.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_QUERY);
2872   bm.is_allowed = htonl (0);
2873   bm.peer = bc->peer;
2874   memcpy (buf, &bm, sizeof (bm)); 
2875   GNUNET_SERVER_receive_done (bl->client, GNUNET_OK);
2876   return sizeof (bm);
2877 }
2878
2879
2880 /**
2881  * Perform next action in the blacklist check.
2882  *
2883  * @param cls the 'struct BlacklistCheck*'
2884  * @param tc unused 
2885  */
2886 static void
2887 do_blacklist_check (void *cls,
2888                     const struct GNUNET_SCHEDULER_TaskContext *tc)
2889 {
2890   struct BlacklistCheck *bc = cls;
2891   struct Blacklisters *bl;
2892
2893   bc->task = GNUNET_SCHEDULER_NO_TASK;
2894   bl = bc->bl_pos;
2895   if (bl == NULL)
2896     {
2897       bc->cont (bc->cont_cls,
2898                 setup_new_neighbour (&bc->peer, bc->do_hello));         
2899       GNUNET_free (bc);
2900       return;
2901     }
2902   if (bl->bc == NULL) 
2903     {
2904       bl->bc = bc;
2905       bc->th = GNUNET_SERVER_notify_transmit_ready (bl->client,
2906                                                     sizeof (struct BlacklistMessage),
2907                                                     GNUNET_TIME_UNIT_FOREVER_REL,
2908                                                     &transmit_blacklist_message,
2909                                                     bc); 
2910     }
2911 }
2912
2913
2914 /**
2915  * Obtain a 'struct NeighbourList' for the given peer.  If such an entry
2916  * does not yet exist, check the blacklist.  If the blacklist says creating
2917  * one is acceptable, create one and call the continuation; otherwise
2918  * call the continuation with NULL.
2919  *
2920  * @param peer peer to setup or look up a struct NeighbourList for
2921  * @param do_hello should we also schedule sending our HELLO to the peer
2922  *        if this is a new record
2923  * @param cont function to call with the 'struct NeigbhbourList*'
2924  * @param cont_cls closure for cont
2925  */
2926 static void
2927 setup_peer_check_blacklist (const struct GNUNET_PeerIdentity *peer,
2928                             int do_hello,
2929                             SetupContinuation cont,
2930                             void *cont_cls)
2931 {
2932   struct NeighbourList *n;
2933   struct BlacklistCheck *bc;
2934
2935   n = find_neighbour(peer);
2936   if (n != NULL)
2937     {
2938       cont (cont_cls, n);
2939       return;
2940     }
2941   if (bl_head == NULL)
2942     {
2943       cont (cont_cls,
2944             setup_new_neighbour (peer, do_hello));
2945       return;
2946     }
2947   bc = GNUNET_malloc (sizeof (struct BlacklistCheck));
2948   GNUNET_CONTAINER_DLL_insert (bc_head, bc_tail, bc);
2949   bc->peer = *peer;
2950   bc->do_hello = do_hello;
2951   bc->cont = cont;
2952   bc->cont_cls = cont_cls;
2953   bc->bl_pos = bl_head;
2954   bc->task = GNUNET_SCHEDULER_add_now (sched,
2955                                        &do_blacklist_check,
2956                                        bc);
2957 }
2958
2959
2960 /**
2961  * Function called with the result of querying a new blacklister about 
2962  * it being allowed (or not) to continue to talk to an existing neighbour.
2963  *
2964  * @param cls the original 'struct NeighbourList'
2965  * @param n NULL if we need to disconnect
2966  */
2967 static void
2968 confirm_or_drop_neighbour (void *cls,
2969                            struct NeighbourList *n)
2970 {
2971   struct NeighbourList * orig = cls;
2972
2973   if (n == NULL)
2974     disconnect_neighbour (orig, GNUNET_NO);
2975 }
2976
2977
2978 /**
2979  * Handle a request to start a blacklist.
2980  *
2981  * @param cls closure (always NULL)
2982  * @param client identification of the client
2983  * @param message the actual message
2984  */
2985 static void
2986 handle_blacklist_init (void *cls,
2987                        struct GNUNET_SERVER_Client *client,
2988                        const struct GNUNET_MessageHeader *message)
2989 {
2990   struct Blacklisters *bl;
2991   struct BlacklistCheck *bc;
2992   struct NeighbourList *n;
2993
2994   bl = bl_head;
2995   while (bl != NULL)
2996     {
2997       if (bl->client == client)
2998         {
2999           GNUNET_break (0);
3000           GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3001           return;
3002         }
3003       bl = bl->next;
3004     }
3005   bl = GNUNET_malloc (sizeof (struct Blacklisters));
3006   bl->client = client;
3007   GNUNET_SERVER_client_keep (client);
3008   GNUNET_CONTAINER_DLL_insert_after (bl_head, bl_tail, bl_tail, bl);
3009   /* confirm that all existing connections are OK! */
3010   n = neighbours;
3011   while (NULL != n)
3012     {
3013       bc = GNUNET_malloc (sizeof (struct BlacklistCheck));
3014       GNUNET_CONTAINER_DLL_insert (bc_head, bc_tail, bc);
3015       bc->peer = n->id;
3016       bc->do_hello = GNUNET_NO;
3017       bc->cont = &confirm_or_drop_neighbour;
3018       bc->cont_cls = n;
3019       bc->bl_pos = bl;
3020       if (n == neighbours) /* all would wait for the same client, no need to
3021                               create more than just the first task right now */
3022         bc->task = GNUNET_SCHEDULER_add_now (sched,
3023                                              &do_blacklist_check,
3024                                              bc);
3025       n = n->next;
3026     }
3027 }
3028
3029
3030 /**
3031  * Handle a request to blacklist a peer.
3032  *
3033  * @param cls closure (always NULL)
3034  * @param client identification of the client
3035  * @param message the actual message
3036  */
3037 static void
3038 handle_blacklist_reply (void *cls,
3039                         struct GNUNET_SERVER_Client *client,
3040                         const struct GNUNET_MessageHeader *message)
3041 {
3042   const struct BlacklistMessage *msg = (const struct BlacklistMessage*) message;
3043   struct Blacklisters *bl;
3044   struct BlacklistCheck *bc;
3045
3046   bl = bl_head;
3047   while ( (bl != NULL) &&
3048           (bl->client != client) )
3049     bl = bl->next;  
3050   if (bl == NULL)
3051     {
3052       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3053       return;
3054     }
3055   bc = bl->bc;
3056   bl->bc = NULL;  
3057   if (ntohl (msg->is_allowed) == GNUNET_SYSERR)
3058     {    
3059       bc->cont (bc->cont_cls, NULL);
3060       GNUNET_CONTAINER_DLL_remove (bc_head, bc_tail, bc);
3061       GNUNET_free (bc);
3062     }
3063   else
3064     {
3065       bc->bl_pos = bc->bl_pos->next;
3066       bc->task = GNUNET_SCHEDULER_add_now (sched,
3067                                            &do_blacklist_check,
3068                                            bc);      
3069     }
3070   /* check if any other bc's are waiting for this blacklister */
3071   bc = bc_head;
3072   while (bc != NULL)
3073     {
3074       if ( (bc->bl_pos == bl) &&
3075            (GNUNET_SCHEDULER_NO_TASK == bc->task) )
3076         bc->task = GNUNET_SCHEDULER_add_now (sched,
3077                                              &do_blacklist_check,
3078                                              bc);      
3079       bc = bc->next;
3080     }
3081 }
3082
3083
3084 /**
3085  * Send periodic PING messages to a given foreign address.
3086  *
3087  * @param cls our 'struct PeriodicValidationContext*'
3088  * @param tc task context
3089  */
3090 static void 
3091 send_periodic_ping (void *cls, 
3092                     const struct GNUNET_SCHEDULER_TaskContext *tc)
3093 {
3094   struct ForeignAddressList *peer_address = cls;
3095   struct TransportPlugin *tp;
3096   struct ValidationEntry *va;
3097   struct NeighbourList *neighbour;
3098   struct TransportPingMessage ping;
3099   struct CheckAddressExistsClosure caec;
3100   char * message_buf;
3101   uint16_t hello_size;
3102   size_t slen;
3103   size_t tsize;
3104
3105   peer_address->revalidate_task = GNUNET_SCHEDULER_NO_TASK;
3106   if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
3107     return; 
3108   tp = peer_address->ready_list->plugin;
3109   neighbour = peer_address->ready_list->neighbour;
3110   if (GNUNET_YES != neighbour->public_key_valid)
3111     {
3112       /* no public key yet, try again later */
3113       schedule_next_ping (peer_address);     
3114       return;
3115     }
3116   caec.addr = peer_address->addr;
3117   caec.addrlen = peer_address->addrlen;
3118   caec.tname = tp->short_name;
3119   caec.session = peer_address->session;
3120   caec.exists = GNUNET_NO;
3121   GNUNET_CONTAINER_multihashmap_iterate (validation_map,
3122                                          &check_address_exists,
3123                                          &caec);
3124   if (caec.exists == GNUNET_YES)
3125     {
3126       /* During validation attempts we will likely trigger the other
3127          peer trying to validate our address which in turn will cause
3128          it to send us its HELLO, so we expect to hit this case rather
3129          frequently.  Only print something if we are very verbose. */
3130 #if DEBUG_TRANSPORT > 1
3131       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3132                   "Some validation of address `%s' via `%s' for peer `%4s' already in progress.\n",
3133                   (peer_address->addr != NULL)
3134                   ? a2s (tp->short_name,
3135                          peer_address->addr,
3136                          peer_address->addrlen)
3137                   : "<inbound>",
3138                   tp->short_name,
3139                   GNUNET_i2s (&neighbour->id));
3140 #endif
3141       schedule_next_ping (peer_address);     
3142       return;
3143     }
3144   va = GNUNET_malloc (sizeof (struct ValidationEntry) + peer_address->addrlen);
3145   va->transport_name = GNUNET_strdup (tp->short_name);
3146   va->challenge = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
3147                                             UINT_MAX);
3148   va->send_time = GNUNET_TIME_absolute_get();
3149   va->session = peer_address->session;
3150   if (peer_address->addr != NULL)
3151     {
3152       va->addr = (const void*) &va[1];
3153       memcpy (&va[1], peer_address->addr, peer_address->addrlen);
3154       va->addrlen = peer_address->addrlen;
3155     }
3156   memcpy(&va->publicKey,
3157          &neighbour->publicKey, 
3158          sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
3159
3160   va->timeout_task = GNUNET_SCHEDULER_add_delayed (sched,
3161                                                    HELLO_VERIFICATION_TIMEOUT,
3162                                                    &timeout_hello_validation,
3163                                                    va);
3164   GNUNET_CONTAINER_multihashmap_put (validation_map,
3165                                      &neighbour->id.hashPubKey,
3166                                      va,
3167                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
3168   hello_size = GNUNET_HELLO_size(our_hello);
3169   tsize = sizeof(struct TransportPingMessage) + hello_size;
3170   if (peer_address->addr != NULL)
3171     {
3172       slen = strlen (tp->short_name) + 1;
3173       tsize += slen + peer_address->addrlen;
3174     }
3175   message_buf = GNUNET_malloc(tsize);
3176   ping.header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_PING);
3177   ping.challenge = htonl(va->challenge);
3178   memcpy(&ping.target, &neighbour->id, sizeof(struct GNUNET_PeerIdentity));
3179   memcpy(message_buf, our_hello, hello_size);
3180   if (peer_address->addr != NULL)
3181     {
3182       ping.header.size = htons(sizeof(struct TransportPingMessage) + 
3183                                peer_address->addrlen + 
3184                                slen);
3185       memcpy(&message_buf[hello_size + sizeof (struct TransportPingMessage)],
3186              tp->short_name, 
3187              slen);
3188       memcpy(&message_buf[hello_size + sizeof (struct TransportPingMessage) + slen],
3189              peer_address->addr, 
3190              peer_address->addrlen);
3191     }
3192   else
3193     {
3194       ping.header.size = htons(sizeof(struct TransportPingMessage));
3195     }
3196   memcpy(&message_buf[hello_size],
3197          &ping,
3198          sizeof(struct TransportPingMessage));
3199
3200 #if DEBUG_TRANSPORT_REVALIDATION
3201   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3202               "Performing re-validation of address `%s' via `%s' for peer `%4s' sending `%s' (%u bytes) and `%s'\n",
3203               (peer_address->addr != NULL) 
3204               ? a2s (peer_address->plugin->short_name,
3205                      peer_address->addr,
3206                      peer_address->addrlen)
3207               : "<inbound>",
3208               tp->short_name,
3209               GNUNET_i2s (&neighbour->id),
3210               "HELLO", hello_size,
3211               "PING");
3212 #endif
3213   GNUNET_STATISTICS_update (stats,
3214                             gettext_noop ("# PING messages sent for re-validation"),
3215                             1,
3216                             GNUNET_NO);
3217   transmit_to_peer (NULL, peer_address,
3218                     GNUNET_SCHEDULER_PRIORITY_DEFAULT,
3219                     HELLO_VERIFICATION_TIMEOUT,
3220                     message_buf, tsize,
3221                     GNUNET_YES, neighbour);
3222   GNUNET_free(message_buf);
3223   schedule_next_ping (peer_address);
3224 }
3225
3226
3227 /**
3228  * Schedule the job that will cause us to send a PING to the
3229  * foreign address to evaluate its validity and latency.
3230  *
3231  * @param fal address to PING
3232  */
3233 static void
3234 schedule_next_ping (struct ForeignAddressList *fal)
3235 {
3236   struct GNUNET_TIME_Relative delay;
3237
3238   if (fal->revalidate_task != GNUNET_SCHEDULER_NO_TASK)
3239     return;
3240   delay = GNUNET_TIME_absolute_get_remaining (fal->expires);
3241   delay.value /= 2; /* do before expiration */
3242   delay = GNUNET_TIME_relative_min (delay,
3243                                     LATENCY_EVALUATION_MAX_DELAY);
3244   if (GNUNET_YES != fal->estimated)
3245     {
3246       delay = GNUNET_TIME_UNIT_ZERO;
3247       fal->estimated = GNUNET_YES;
3248     }                               
3249   if (GNUNET_YES == fal->connected)
3250     {
3251       delay = GNUNET_TIME_relative_min (delay,
3252                                         CONNECTED_LATENCY_EVALUATION_MAX_DELAY);
3253     }  
3254   /* FIXME: also adjust delay based on how close the last
3255      observed latency is to the latency of the best alternative */
3256   /* bound how fast we can go */
3257   delay = GNUNET_TIME_relative_max (delay,
3258                                     GNUNET_TIME_UNIT_SECONDS);
3259   /* randomize a bit (to avoid doing all at the same time) */
3260   delay.value += GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 1000);
3261   fal->revalidate_task = GNUNET_SCHEDULER_add_delayed(sched, 
3262                                                       delay,
3263                                                       &send_periodic_ping, 
3264                                                       fal);
3265 }
3266
3267
3268
3269
3270 /**
3271  * Function that will be called if we receive some payload
3272  * from another peer.
3273  *
3274  * @param message the payload
3275  * @param n peer who claimed to be the sender
3276  */
3277 static void
3278 handle_payload_message (const struct GNUNET_MessageHeader *message,
3279                         struct NeighbourList *n)
3280 {
3281   struct InboundMessage *im;
3282   struct TransportClient *cpos;
3283   uint16_t msize;
3284
3285   msize = ntohs (message->size);
3286   if (n->received_pong == GNUNET_NO)
3287     {
3288       GNUNET_free_non_null (n->pre_connect_message_buffer);
3289       n->pre_connect_message_buffer = GNUNET_malloc (msize);
3290       memcpy (n->pre_connect_message_buffer, message, msize);
3291       return;
3292     }
3293 #if DEBUG_TRANSPORT
3294   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3295               "Received message of type %u and size %u from `%4s', sending to all clients.\n",
3296               ntohs (message->type), 
3297               ntohs (message->size), 
3298               GNUNET_i2s (&n->id));
3299 #endif
3300   if (GNUNET_YES == GNUNET_BANDWIDTH_tracker_consume (&n->in_tracker,
3301                                                       (ssize_t) msize))
3302     {
3303       n->quota_violation_count++;
3304 #if DEBUG_TRANSPORT
3305       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,                        
3306                   "Bandwidth quota (%u b/s) violation detected (total of %u).\n", 
3307                   n->in_tracker.available_bytes_per_s__,
3308                   n->quota_violation_count);
3309 #endif
3310       /* Discount 32k per violation */
3311       GNUNET_BANDWIDTH_tracker_consume (&n->in_tracker,
3312                                         - 32 * 1024);           
3313     }
3314   else 
3315     {
3316       if (n->quota_violation_count > 0)
3317         {
3318           /* try to add 32k back */
3319           GNUNET_BANDWIDTH_tracker_consume (&n->in_tracker,
3320                                             32 * 1024);
3321           n->quota_violation_count--;
3322         }
3323     }
3324   GNUNET_STATISTICS_update (stats,
3325                             gettext_noop ("# payload received from other peers"),
3326                             msize,
3327                             GNUNET_NO);
3328   /* transmit message to all clients */
3329   im = GNUNET_malloc (sizeof (struct InboundMessage) + msize);
3330   im->header.size = htons (sizeof (struct InboundMessage) + msize);
3331   im->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RECV);
3332   im->latency = GNUNET_TIME_relative_hton (n->latency);
3333   im->peer = n->id;
3334   im->distance = ntohl(n->distance);
3335   memcpy (&im[1], message, msize);
3336   cpos = clients;
3337   while (cpos != NULL)
3338     {
3339       transmit_to_client (cpos, &im->header, GNUNET_YES);
3340       cpos = cpos->next;
3341     }
3342   GNUNET_free (im);
3343 }
3344
3345
3346 /**
3347  * Iterator over hash map entries.  Checks if the given validation
3348  * entry is for the same challenge as what is given in the PONG.
3349  *
3350  * @param cls the 'struct TransportPongMessage*'
3351  * @param key peer identity
3352  * @param value value in the hash map ('struct ValidationEntry')
3353  * @return GNUNET_YES if we should continue to
3354  *         iterate (mismatch), GNUNET_NO if not (entry matched)
3355  */
3356 static int
3357 check_pending_validation (void *cls,
3358                           const GNUNET_HashCode * key,
3359                           void *value)
3360 {
3361   const struct TransportPongMessage *pong = cls;
3362   struct ValidationEntry *ve = value;
3363   struct AddValidatedAddressContext avac;
3364   unsigned int challenge = ntohl(pong->challenge);
3365   struct GNUNET_HELLO_Message *hello;
3366   struct GNUNET_PeerIdentity target;
3367   struct NeighbourList *n;
3368   struct ForeignAddressList *fal;
3369   struct OwnAddressList *oal;
3370   struct TransportPlugin *tp;
3371   struct GNUNET_MessageHeader *prem;
3372   uint16_t ps;
3373   const char *addr;
3374   size_t slen;
3375   size_t alen;
3376
3377   ps = ntohs (pong->header.size);
3378   if (ps < sizeof (struct TransportPongMessage))
3379     {
3380       GNUNET_break_op (0);
3381       return GNUNET_NO;
3382     }
3383   addr = (const char*) &pong[1];
3384   slen = strlen (ve->transport_name) + 1;
3385   if ( (ps - sizeof (struct TransportPongMessage) != ve->addrlen + slen) ||
3386        (ve->challenge != challenge) ||       
3387        (addr[slen-1] != '\0') ||
3388        (0 != strcmp (addr, ve->transport_name)) || 
3389        (ntohl (pong->purpose.size) 
3390         != sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) +
3391         sizeof (uint32_t) +
3392         sizeof (struct GNUNET_TIME_AbsoluteNBO) +
3393         sizeof (struct GNUNET_PeerIdentity) + ve->addrlen + slen) )
3394     return GNUNET_YES;
3395   alen = ps - sizeof (struct TransportPongMessage) - slen;
3396   switch (ntohl (pong->purpose.purpose))
3397     {
3398     case GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN:
3399       if ( (ve->addrlen + slen != ntohl (pong->addrlen)) ||
3400            (0 != memcmp (&addr[slen],
3401                          ve->addr,
3402                          ve->addrlen)) )
3403         return GNUNET_YES; /* different entry, keep trying! */
3404       if ( (0 != memcmp (&pong->pid,
3405                          key,
3406                          sizeof (struct GNUNET_PeerIdentity))) ||
3407            (ve->addrlen == 0) )
3408         {
3409           GNUNET_break_op (0);
3410           return GNUNET_NO;
3411         }
3412       if (GNUNET_OK !=
3413           GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN,
3414                                     &pong->purpose, 
3415                                     &pong->signature,
3416                                     &ve->publicKey)) 
3417         {
3418           GNUNET_break_op (0);
3419           return GNUNET_NO;
3420         }
3421 #if DEBUG_TRANSPORT
3422       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3423                   "Confirmed validity of address, peer `%4s' has address `%s' (%s).\n",
3424                   GNUNET_h2s (key),
3425                   a2s (ve->transport_name,
3426                        (const struct sockaddr *) ve->addr,
3427                        ve->addrlen),
3428                   ve->transport_name);
3429 #endif
3430       break;
3431     case GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_USING:
3432       if (ve->addrlen != 0) 
3433         return GNUNET_YES; /* different entry, keep trying */
3434       if ( (0 != memcmp (&pong->pid,
3435                          &my_identity,
3436                          sizeof (struct GNUNET_PeerIdentity))) ||
3437            (ve->addrlen != 0) )
3438         {
3439           GNUNET_break_op (0);
3440           return GNUNET_NO;
3441         }
3442       tp = find_transport (ve->transport_name);
3443       if (tp == NULL)
3444         {
3445           GNUNET_break (0);
3446           return GNUNET_YES;
3447         }
3448       oal = tp->addresses;
3449       while (NULL != oal)
3450         {
3451           if ( (oal->addrlen == alen) &&
3452                (0 == memcmp (&oal[1],
3453                              &addr[slen],
3454                              alen)) )
3455             break;
3456           oal = oal->next;
3457         }
3458       if (oal == NULL)
3459         {
3460           GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3461                       _("Not accepting PONG with address `%s' since I cannot confirm having this address.\n"),
3462                       a2s (ve->transport_name,
3463                            &addr[slen],
3464                            alen));
3465           return GNUNET_NO;       
3466         }
3467       if (GNUNET_OK !=
3468           GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_USING,
3469                                     &pong->purpose, 
3470                                     &pong->signature,
3471                                     &ve->publicKey)) 
3472         {
3473           GNUNET_break_op (0);
3474           return GNUNET_NO;
3475         }
3476 #if DEBUG_TRANSPORT
3477       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3478                   "Confirmed that peer `%4s' is talking to us using address `%s' (%s) for us.\n",
3479                   GNUNET_h2s (key),
3480                   a2s (ve->transport_name,
3481                        &addr[slen],
3482                        alen),
3483                   ve->transport_name);
3484 #endif
3485       break;
3486     default:
3487       GNUNET_break_op (0);
3488       return GNUNET_NO;
3489     }
3490   if (GNUNET_TIME_absolute_get_remaining (GNUNET_TIME_absolute_ntoh (pong->expiration)).value == 0)
3491     {
3492       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3493                   _("Received expired signature.  Check system time.\n"));
3494       return GNUNET_NO;
3495     }
3496   GNUNET_STATISTICS_update (stats,
3497                             gettext_noop ("# address validation successes"),
3498                             1,
3499                             GNUNET_NO);
3500   /* create the updated HELLO */
3501   GNUNET_CRYPTO_hash (&ve->publicKey,
3502                       sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
3503                       &target.hashPubKey);
3504   if (ve->addr != NULL)
3505     {
3506       avac.done = GNUNET_NO;
3507       avac.ve = ve;
3508       hello = GNUNET_HELLO_create (&ve->publicKey,
3509                                    &add_validated_address,
3510                                    &avac);
3511       GNUNET_PEERINFO_add_peer (peerinfo,
3512                                 hello);
3513       GNUNET_free (hello);
3514     }
3515   n = find_neighbour (&target);
3516   if (n != NULL)
3517     {
3518       n->publicKey = ve->publicKey;
3519       n->public_key_valid = GNUNET_YES;
3520       fal = add_peer_address (n,
3521                               ve->transport_name,
3522                               ve->session,
3523                               ve->addr,
3524                               ve->addrlen);
3525       GNUNET_assert (fal != NULL);
3526       fal->expires = GNUNET_TIME_relative_to_absolute (HELLO_ADDRESS_EXPIRATION);
3527       fal->validated = GNUNET_YES;
3528       mark_address_connected (fal);
3529       GNUNET_STATISTICS_update (stats,
3530                                 gettext_noop ("# peer addresses considered valid"),
3531                                 1,
3532                                 GNUNET_NO);      
3533       fal->latency = GNUNET_TIME_absolute_get_duration (ve->send_time);
3534       schedule_next_ping (fal);
3535       if (n->latency.value == GNUNET_TIME_UNIT_FOREVER_REL.value)
3536         n->latency = fal->latency;
3537       else
3538         n->latency.value = (fal->latency.value + n->latency.value) / 2;
3539
3540       n->distance = fal->distance;
3541       if (GNUNET_NO == n->received_pong)
3542         {
3543           n->received_pong = GNUNET_YES;
3544           notify_clients_connect (&target, n->latency, n->distance);
3545           if (NULL != (prem = n->pre_connect_message_buffer))
3546             {
3547               n->pre_connect_message_buffer = NULL;
3548               handle_payload_message (prem, n);
3549               GNUNET_free (prem);
3550             }
3551         }
3552       if (n->retry_task != GNUNET_SCHEDULER_NO_TASK)
3553         {
3554           GNUNET_SCHEDULER_cancel (sched,
3555                                    n->retry_task);
3556           n->retry_task = GNUNET_SCHEDULER_NO_TASK;
3557           try_transmission_to_peer (n);
3558         }
3559     }
3560
3561   /* clean up validation entry */
3562   GNUNET_assert (GNUNET_YES ==
3563                  GNUNET_CONTAINER_multihashmap_remove (validation_map,
3564                                                        key,
3565                                                        ve));
3566   abort_validation (NULL, NULL, ve);
3567   return GNUNET_NO;
3568 }
3569
3570
3571 /**
3572  * Function that will be called if we receive a validation
3573  * of an address challenge that we transmitted to another
3574  * peer.  Note that the validation should only be considered
3575  * acceptable if the challenge matches AND if the sender
3576  * address is at least a plausible address for this peer
3577  * (otherwise we may be seeing a MiM attack).
3578  *
3579  * @param cls closure
3580  * @param message the pong message
3581  * @param peer who responded to our challenge
3582  * @param sender_address string describing our sender address (as observed
3583  *         by the other peer in binary format)
3584  * @param sender_address_len number of bytes in 'sender_address'
3585  */
3586 static void
3587 handle_pong (void *cls, const struct GNUNET_MessageHeader *message,
3588              const struct GNUNET_PeerIdentity *peer,
3589              const char *sender_address,
3590              size_t sender_address_len)
3591 {
3592 #if DEBUG_TRANSPORT > 1
3593   /* we get tons of these that just get discarded, only log
3594      if we are quite verbose */
3595   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3596               "Receiving `%s' message from `%4s'.\n", "PONG",
3597               GNUNET_i2s (peer));
3598 #endif
3599   GNUNET_STATISTICS_update (stats,
3600                             gettext_noop ("# PONG messages received"),
3601                             1,
3602                             GNUNET_NO);
3603   if (GNUNET_SYSERR !=
3604       GNUNET_CONTAINER_multihashmap_get_multiple (validation_map,
3605                                                   &peer->hashPubKey,
3606                                                   &check_pending_validation,
3607                                                   (void*) message))
3608     {
3609       /* This is *expected* to happen a lot since we send
3610          PONGs to *all* known addresses of the sender of
3611          the PING, so most likely we get multiple PONGs
3612          per PING, and all but the first PONG will end up
3613          here. So really we should not print anything here
3614          unless we want to be very, very verbose... */
3615 #if DEBUG_TRANSPORT > 2
3616       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3617                   "Received `%s' message from `%4s' but have no record of a matching `%s' message. Ignoring.\n",
3618                   "PONG",
3619                   GNUNET_i2s (peer),
3620                   "PING");
3621 #endif
3622       return;
3623     }
3624
3625 }
3626
3627
3628 /**
3629  * Try to validate a neighbour's address by sending him our HELLO and a PING.
3630  *
3631  * @param cls the 'struct ValidationEntry*'
3632  * @param neighbour neighbour to validate, NULL if validation failed
3633  */
3634 static void
3635 transmit_hello_and_ping (void *cls,
3636                          struct NeighbourList *neighbour)
3637 {
3638   struct ValidationEntry *va = cls;
3639   struct ForeignAddressList *peer_address;
3640   struct TransportPingMessage ping;
3641   uint16_t hello_size;
3642   size_t tsize;
3643   char * message_buf;
3644   struct GNUNET_PeerIdentity id;
3645   size_t slen;
3646
3647   GNUNET_CRYPTO_hash (&va->publicKey,
3648                       sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
3649                       &id.hashPubKey);
3650   if (neighbour == NULL)
3651     {
3652       /* FIXME: stats... */
3653       GNUNET_break (GNUNET_OK ==
3654                     GNUNET_CONTAINER_multihashmap_remove (validation_map,
3655                                                           &id.hashPubKey,
3656                                                           va));
3657       abort_validation (NULL, NULL, va);
3658       return;
3659     }
3660   neighbour->publicKey = va->publicKey;
3661   neighbour->public_key_valid = GNUNET_YES;
3662   peer_address = add_peer_address (neighbour,
3663                                    va->transport_name, NULL,
3664                                    (const void*) &va[1],
3665                                    va->addrlen);
3666   if (peer_address == NULL)
3667     {
3668       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3669                   "Failed to add peer `%4s' for plugin `%s'\n",
3670                   GNUNET_i2s (&neighbour->id), 
3671                   va->transport_name);
3672       GNUNET_break (GNUNET_OK ==
3673                     GNUNET_CONTAINER_multihashmap_remove (validation_map,
3674                                                           &id.hashPubKey,
3675                                                           va));
3676       abort_validation (NULL, NULL, va);
3677       return;
3678     }
3679   hello_size = GNUNET_HELLO_size(our_hello);
3680   slen = strlen(va->transport_name) + 1;
3681   tsize = sizeof(struct TransportPingMessage) + hello_size + va->addrlen + slen;
3682   message_buf = GNUNET_malloc(tsize);
3683   ping.challenge = htonl(va->challenge);
3684   ping.header.size = htons(sizeof(struct TransportPingMessage) + slen + va->addrlen);
3685   ping.header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_PING);
3686   memcpy(&ping.target, &neighbour->id, sizeof(struct GNUNET_PeerIdentity));
3687   memcpy(message_buf, our_hello, hello_size);
3688   memcpy(&message_buf[hello_size],
3689          &ping,
3690          sizeof(struct TransportPingMessage));
3691   memcpy(&message_buf[hello_size + sizeof (struct TransportPingMessage)],
3692          va->transport_name,
3693          slen);
3694   memcpy(&message_buf[hello_size + sizeof (struct TransportPingMessage) + slen],
3695          &va[1],
3696          va->addrlen);
3697 #if DEBUG_TRANSPORT
3698   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3699               "Performing validation of address `%s' via `%s' for peer `%4s' sending `%s' (%u bytes) and `%s' (%u bytes)\n",
3700               (va->addrlen == 0) 
3701               ? "<inbound>"
3702               : a2s (va->transport_name,
3703                      (const void*) &va[1], va->addrlen),
3704               va->transport_name,
3705               GNUNET_i2s (&neighbour->id),
3706               "HELLO", hello_size,
3707               "PING", sizeof (struct TransportPingMessage) + va->addrlen + slen);
3708 #endif
3709
3710   GNUNET_STATISTICS_update (stats,
3711                             gettext_noop ("# PING messages sent for initial validation"),
3712                             1,
3713                             GNUNET_NO);      
3714   transmit_to_peer (NULL, peer_address,
3715                     GNUNET_SCHEDULER_PRIORITY_DEFAULT,
3716                     HELLO_VERIFICATION_TIMEOUT,
3717                     message_buf, tsize,
3718                     GNUNET_YES, neighbour);
3719   GNUNET_free(message_buf);
3720 }
3721
3722
3723 /**
3724  * Check if the given address is already being validated; if not,
3725  * append the given address to the list of entries that are being be
3726  * validated and initiate validation.
3727  *
3728  * @param cls closure ('struct CheckHelloValidatedContext *')
3729  * @param tname name of the transport
3730  * @param expiration expiration time
3731  * @param addr the address
3732  * @param addrlen length of the address
3733  * @return GNUNET_OK (always)
3734  */
3735 static int
3736 run_validation (void *cls,
3737                 const char *tname,
3738                 struct GNUNET_TIME_Absolute expiration,
3739                 const void *addr, 
3740                 uint16_t addrlen)
3741 {
3742   struct CheckHelloValidatedContext *chvc = cls;
3743   struct GNUNET_PeerIdentity id;
3744   struct TransportPlugin *tp;
3745   struct ValidationEntry *va;
3746   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pk;
3747   struct CheckAddressExistsClosure caec;
3748   struct OwnAddressList *oal;
3749
3750   GNUNET_assert (addr != NULL);
3751
3752   GNUNET_STATISTICS_update (stats,
3753                             gettext_noop ("# peer addresses scheduled for validation"),
3754                             1,
3755                             GNUNET_NO);      
3756   tp = find_transport (tname);
3757   if (tp == NULL)
3758     {
3759       GNUNET_log (GNUNET_ERROR_TYPE_INFO |
3760                   GNUNET_ERROR_TYPE_BULK,
3761                   _
3762                   ("Transport `%s' not loaded, will not try to validate peer address using this transport.\n"),
3763                   tname);
3764       GNUNET_STATISTICS_update (stats,
3765                                 gettext_noop ("# peer addresses not validated (plugin not available)"),
3766                                 1,
3767                                 GNUNET_NO);      
3768       return GNUNET_OK;
3769     }
3770   /* check if this is one of our own addresses */
3771   oal = tp->addresses;
3772   while (NULL != oal)
3773     {
3774       if ( (oal->addrlen == addrlen) &&
3775            (0 == memcmp (&oal[1],
3776                          addr,
3777                          addrlen)) )
3778         {
3779           /* not plausible, this address is equivalent to our own address! */
3780           GNUNET_STATISTICS_update (stats,
3781                                     gettext_noop ("# peer addresses not validated (loopback)"),
3782                                     1,
3783                                     GNUNET_NO);      
3784           return GNUNET_OK;
3785         }
3786       oal = oal->next;
3787     }
3788   GNUNET_HELLO_get_key (chvc->hello, &pk);
3789   GNUNET_CRYPTO_hash (&pk,
3790                       sizeof (struct
3791                               GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
3792                       &id.hashPubKey);
3793
3794   if (is_blacklisted(&id, tp))
3795     {
3796 #if DEBUG_TRANSPORT
3797       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3798                   "Attempted to validate blacklisted peer `%s' using `%s'!\n", 
3799                   GNUNET_i2s(&id), 
3800                   tname);
3801 #endif
3802       return GNUNET_OK;
3803     }
3804
3805   caec.addr = addr;
3806   caec.addrlen = addrlen;
3807   caec.session = NULL;
3808   caec.tname = tname;
3809   caec.exists = GNUNET_NO;
3810   GNUNET_CONTAINER_multihashmap_iterate (validation_map,
3811                                          &check_address_exists,
3812                                          &caec);
3813   if (caec.exists == GNUNET_YES)
3814     {
3815       /* During validation attempts we will likely trigger the other
3816          peer trying to validate our address which in turn will cause
3817          it to send us its HELLO, so we expect to hit this case rather
3818          frequently.  Only print something if we are very verbose. */
3819 #if DEBUG_TRANSPORT > 1
3820       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3821                   "Validation of address `%s' via `%s' for peer `%4s' already in progress.\n",
3822                   a2s (tname, addr, addrlen),
3823                   tname,
3824                   GNUNET_i2s (&id));
3825 #endif
3826       GNUNET_STATISTICS_update (stats,
3827                                 gettext_noop ("# peer addresses not validated (in progress)"),
3828                                 1,
3829                                 GNUNET_NO);      
3830       return GNUNET_OK;
3831     }
3832   va = GNUNET_malloc (sizeof (struct ValidationEntry) + addrlen);
3833   va->chvc = chvc;
3834   chvc->ve_count++;
3835   va->transport_name = GNUNET_strdup (tname);
3836   va->challenge = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
3837                                             UINT_MAX);
3838   va->send_time = GNUNET_TIME_absolute_get();
3839   va->addr = (const void*) &va[1];
3840   memcpy (&va[1], addr, addrlen);
3841   va->addrlen = addrlen;
3842   GNUNET_HELLO_get_key (chvc->hello,
3843                         &va->publicKey);
3844   va->timeout_task = GNUNET_SCHEDULER_add_delayed (sched,
3845                                                    HELLO_VERIFICATION_TIMEOUT,
3846                                                    &timeout_hello_validation,
3847                                                    va);
3848   GNUNET_CONTAINER_multihashmap_put (validation_map,
3849                                      &id.hashPubKey,
3850                                      va,
3851                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
3852   setup_peer_check_blacklist (&id, GNUNET_NO,
3853                               &transmit_hello_and_ping,
3854                               va);
3855   return GNUNET_OK;
3856 }
3857
3858
3859 /**
3860  * Check if addresses in validated hello "h" overlap with
3861  * those in "chvc->hello" and validate the rest.
3862  *
3863  * @param cls closure
3864  * @param peer id of the peer, NULL for last call
3865  * @param h hello message for the peer (can be NULL)
3866  * @param trust amount of trust we have in the peer (not used)
3867  */
3868 static void
3869 check_hello_validated (void *cls,
3870                        const struct GNUNET_PeerIdentity *peer,
3871                        const struct GNUNET_HELLO_Message *h, 
3872                        uint32_t trust)
3873 {
3874   struct CheckHelloValidatedContext *chvc = cls;
3875   struct GNUNET_HELLO_Message *plain_hello;
3876   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pk;
3877   struct GNUNET_PeerIdentity target;
3878   struct NeighbourList *n;
3879
3880   if (peer == NULL)
3881     {
3882       chvc->piter = NULL;
3883       if (GNUNET_NO == chvc->hello_known)
3884         {
3885           /* notify PEERINFO about the peer now, so that we at least
3886              have the public key if some other component needs it */
3887           GNUNET_HELLO_get_key (chvc->hello, &pk);
3888           GNUNET_CRYPTO_hash (&pk,
3889                               sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
3890                               &target.hashPubKey);
3891           plain_hello = GNUNET_HELLO_create (&pk,
3892                                              NULL, 
3893                                              NULL);
3894           GNUNET_PEERINFO_add_peer (peerinfo, plain_hello);
3895           GNUNET_free (plain_hello);
3896 #if DEBUG_TRANSPORT
3897           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3898                       "PEERINFO had no `%s' message for peer `%4s', full validation needed.\n",
3899                       "HELLO",
3900                       GNUNET_i2s (&target));
3901 #endif
3902           GNUNET_STATISTICS_update (stats,
3903                                     gettext_noop ("# new HELLOs requiring full validation"),
3904                                     1,
3905                                     GNUNET_NO);      
3906           GNUNET_HELLO_iterate_addresses (chvc->hello,
3907                                           GNUNET_NO, 
3908                                           &run_validation, 
3909                                           chvc);
3910         }
3911       else
3912         {
3913           GNUNET_STATISTICS_update (stats,
3914                                     gettext_noop ("# duplicate HELLO (peer known)"),
3915                                     1,
3916                                     GNUNET_NO);      
3917         }
3918       chvc->ve_count--;
3919       if (chvc->ve_count == 0)
3920         {
3921           GNUNET_CONTAINER_DLL_remove (chvc_head,
3922                                        chvc_tail,
3923                                        chvc);
3924           GNUNET_free (chvc);     
3925         }
3926       return;
3927     } 
3928   if (h == NULL)
3929     return;
3930 #if DEBUG_TRANSPORT
3931   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3932               "PEERINFO had `%s' message for peer `%4s', validating only new addresses.\n",
3933               "HELLO",
3934               GNUNET_i2s (peer));
3935 #endif
3936   chvc->hello_known = GNUNET_YES;
3937   n = find_neighbour (peer);
3938   if (n != NULL)
3939     {
3940       GNUNET_HELLO_iterate_addresses (h,
3941                                       GNUNET_NO,
3942                                       &add_to_foreign_address_list,
3943                                       n);
3944       try_transmission_to_peer (n);
3945     }
3946   else
3947     {
3948       GNUNET_STATISTICS_update (stats,
3949                                 gettext_noop ("# no existing neighbour record (validating HELLO)"),
3950                                 1,
3951                                 GNUNET_NO);      
3952     }
3953   GNUNET_STATISTICS_update (stats,
3954                             gettext_noop ("# HELLO validations (update case)"),
3955                             1,
3956                             GNUNET_NO);      
3957   GNUNET_HELLO_iterate_new_addresses (chvc->hello,
3958                                       h,
3959                                       GNUNET_TIME_relative_to_absolute (HELLO_REVALIDATION_START_TIME),
3960                                       &run_validation, 
3961                                       chvc);
3962 }
3963
3964
3965 /**
3966  * Process HELLO-message.
3967  *
3968  * @param plugin transport involved, may be NULL
3969  * @param message the actual message
3970  * @return GNUNET_OK if the HELLO was well-formed, GNUNET_SYSERR otherwise
3971  */
3972 static int
3973 process_hello (struct TransportPlugin *plugin,
3974                const struct GNUNET_MessageHeader *message)
3975 {
3976   uint16_t hsize;
3977   struct GNUNET_PeerIdentity target;
3978   const struct GNUNET_HELLO_Message *hello;
3979   struct CheckHelloValidatedContext *chvc;
3980   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded publicKey;
3981 #if DEBUG_TRANSPORT_HELLO
3982   char *my_id;
3983 #endif
3984   hsize = ntohs (message->size);
3985   if ((ntohs (message->type) != GNUNET_MESSAGE_TYPE_HELLO) ||
3986       (hsize < sizeof (struct GNUNET_MessageHeader)))
3987     {
3988       GNUNET_break (0);
3989       return GNUNET_SYSERR;
3990     }
3991   GNUNET_STATISTICS_update (stats,
3992                             gettext_noop ("# HELLOs received for validation"),
3993                             1,
3994                             GNUNET_NO);      
3995   /* first, check if load is too high */
3996   if (GNUNET_SCHEDULER_get_load (sched,
3997                                  GNUNET_SCHEDULER_PRIORITY_BACKGROUND) > MAX_HELLO_LOAD)
3998     {
3999       GNUNET_STATISTICS_update (stats,
4000                                 gettext_noop ("# HELLOs ignored due to high load"),
4001                                 1,
4002                                 GNUNET_NO);      
4003 #if DEBUG_TRANSPORT_HELLO
4004       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4005                   "Ignoring `%s' for `%4s', load too high.\n",
4006                   "HELLO",
4007                   GNUNET_i2s (&target));
4008 #endif
4009       return GNUNET_OK;
4010     }
4011   hello = (const struct GNUNET_HELLO_Message *) message;
4012   if (GNUNET_OK != GNUNET_HELLO_get_key (hello, &publicKey))
4013     {
4014 #if DEBUG_TRANSPORT_HELLO
4015       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4016                   "Unable to get public key from `%s' for `%4s'!\n",
4017                   "HELLO",
4018                   GNUNET_i2s (&target));
4019 #endif
4020       GNUNET_break_op (0);
4021       return GNUNET_SYSERR;
4022     }
4023   GNUNET_CRYPTO_hash (&publicKey,
4024                       sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
4025                       &target.hashPubKey);
4026   if (0 == memcmp (&my_identity,
4027                    &target,
4028                    sizeof (struct GNUNET_PeerIdentity)))
4029     {
4030       GNUNET_STATISTICS_update (stats,
4031                                 gettext_noop ("# HELLOs ignored for validation (is my own HELLO)"),
4032                                 1,
4033                                 GNUNET_NO);      
4034       return GNUNET_OK;      
4035     }
4036   chvc = chvc_head;
4037   while (NULL != chvc)
4038     {
4039       if (GNUNET_HELLO_equals (hello,
4040                                chvc->hello,
4041                                GNUNET_TIME_absolute_get ()).value > 0)
4042         {
4043 #if DEBUG_TRANSPORT_HELLO
4044           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4045                       "Received duplicate `%s' message for `%4s'; ignored\n",
4046                       "HELLO", 
4047                       GNUNET_i2s (&target));
4048 #endif
4049           return GNUNET_OK; /* validation already pending */
4050         }
4051       if (GNUNET_HELLO_size(hello) == GNUNET_HELLO_size (chvc->hello))
4052         GNUNET_break (0 != memcmp (hello, chvc->hello,
4053                                    GNUNET_HELLO_size(hello)));
4054       chvc = chvc->next;
4055     }
4056 #if DEBUG_TRANSPORT_HELLO
4057   if (plugin != NULL)
4058     {
4059       my_id = GNUNET_strdup(GNUNET_i2s(plugin->env.my_identity));
4060       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4061                   "%s: Starting validation of `%s' message for `%4s' via '%s' of size %u\n",
4062                   my_id,
4063                   "HELLO",
4064                   GNUNET_i2s (&target),
4065                   plugin->short_name,
4066                   GNUNET_HELLO_size(hello));
4067       GNUNET_free(my_id);
4068     }
4069 #endif
4070   chvc = GNUNET_malloc (sizeof (struct CheckHelloValidatedContext) + hsize);
4071   chvc->ve_count = 1;
4072   chvc->hello = (const struct GNUNET_HELLO_Message *) &chvc[1];
4073   memcpy (&chvc[1], hello, hsize);
4074   GNUNET_CONTAINER_DLL_insert (chvc_head,
4075                                chvc_tail,
4076                                chvc);
4077   /* finally, check if HELLO was previously validated
4078      (continuation will then schedule actual validation) */
4079   chvc->piter = GNUNET_PEERINFO_iterate (peerinfo,
4080                                          &target,
4081                                          0,
4082                                          HELLO_VERIFICATION_TIMEOUT,
4083                                          &check_hello_validated, chvc);
4084   return GNUNET_OK;
4085 }
4086
4087
4088 /**
4089  * The peer specified by the given neighbour has timed-out or a plugin
4090  * has disconnected.  We may either need to do nothing (other plugins
4091  * still up), or trigger a full disconnect and clean up.  This
4092  * function updates our state and does the necessary notifications.
4093  * Also notifies our clients that the neighbour is now officially
4094  * gone.
4095  *
4096  * @param n the neighbour list entry for the peer
4097  * @param check should we just check if all plugins
4098  *        disconnected or must we ask all plugins to
4099  *        disconnect?
4100  */
4101 static void
4102 disconnect_neighbour (struct NeighbourList *n, int check)
4103 {
4104   struct ReadyList *rpos;
4105   struct NeighbourList *npos;
4106   struct NeighbourList *nprev;
4107   struct MessageQueue *mq;
4108   struct ForeignAddressList *peer_addresses;
4109   struct ForeignAddressList *peer_pos;
4110
4111   if (GNUNET_YES == check)
4112     {
4113       rpos = n->plugins;
4114       while (NULL != rpos)
4115         {
4116           peer_addresses = rpos->addresses;
4117           while (peer_addresses != NULL)
4118             {
4119               if (GNUNET_YES == peer_addresses->connected)
4120                 return;             /* still connected */
4121               peer_addresses = peer_addresses->next;
4122             }
4123           rpos = rpos->next;
4124         }
4125     }
4126 #if DEBUG_TRANSPORT
4127   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
4128               "Disconnecting from `%4s'\n",
4129               GNUNET_i2s (&n->id));
4130 #endif
4131   /* remove n from neighbours list */
4132   nprev = NULL;
4133   npos = neighbours;
4134   while ((npos != NULL) && (npos != n))
4135     {
4136       nprev = npos;
4137       npos = npos->next;
4138     }
4139   GNUNET_assert (npos != NULL);
4140   if (nprev == NULL)
4141     neighbours = n->next;
4142   else
4143     nprev->next = n->next;
4144
4145   /* notify all clients about disconnect */
4146   if (GNUNET_YES == n->received_pong)
4147     notify_clients_disconnect (&n->id);
4148
4149   /* clean up all plugins, cancel connections and pending transmissions */
4150   while (NULL != (rpos = n->plugins))
4151     {
4152       n->plugins = rpos->next;
4153       rpos->plugin->api->disconnect (rpos->plugin->api->cls, &n->id);
4154       while (rpos->addresses != NULL)
4155         {
4156           peer_pos = rpos->addresses;
4157           rpos->addresses = peer_pos->next;
4158           if (peer_pos->connected == GNUNET_YES)
4159             GNUNET_STATISTICS_update (stats,
4160                                       gettext_noop ("# connected addresses"),
4161                                       -1,
4162                                       GNUNET_NO); 
4163           if (GNUNET_YES == peer_pos->validated)
4164             GNUNET_STATISTICS_update (stats,
4165                                       gettext_noop ("# peer addresses considered valid"),
4166                                       -1,
4167                                       GNUNET_NO);      
4168           if (GNUNET_SCHEDULER_NO_TASK != peer_pos->revalidate_task)
4169             {
4170               GNUNET_SCHEDULER_cancel (sched,
4171                                        peer_pos->revalidate_task);
4172               peer_pos->revalidate_task = GNUNET_SCHEDULER_NO_TASK;
4173             }
4174           GNUNET_free(peer_pos);
4175         }
4176       GNUNET_free (rpos);
4177     }
4178
4179   /* free all messages on the queue */
4180   while (NULL != (mq = n->messages_head))
4181     {
4182       GNUNET_STATISTICS_update (stats,
4183                                 gettext_noop ("# bytes in message queue for other peers"),
4184                                 - (int64_t) mq->message_buf_size,
4185                                 GNUNET_NO);
4186       GNUNET_STATISTICS_update (stats,
4187                                 gettext_noop ("# bytes discarded due to disconnect"),
4188                                 mq->message_buf_size,
4189                                 GNUNET_NO);
4190       GNUNET_CONTAINER_DLL_remove (n->messages_head,
4191                                    n->messages_tail,
4192                                    mq);
4193       GNUNET_assert (0 == memcmp(&mq->neighbour_id, 
4194                                  &n->id,
4195                                  sizeof(struct GNUNET_PeerIdentity)));
4196       GNUNET_free (mq);
4197     }
4198   if (n->timeout_task != GNUNET_SCHEDULER_NO_TASK)
4199     {
4200       GNUNET_SCHEDULER_cancel (sched, n->timeout_task);
4201       n->timeout_task = GNUNET_SCHEDULER_NO_TASK;
4202     }
4203   if (n->retry_task != GNUNET_SCHEDULER_NO_TASK)
4204     {
4205       GNUNET_SCHEDULER_cancel (sched, n->retry_task);
4206       n->retry_task = GNUNET_SCHEDULER_NO_TASK;
4207     }
4208   if (n->piter != NULL)
4209     {
4210       GNUNET_PEERINFO_iterate_cancel (n->piter);
4211       n->piter = NULL;
4212     }
4213   /* finally, free n itself */
4214   GNUNET_STATISTICS_update (stats,
4215                             gettext_noop ("# active neighbours"),
4216                             -1,
4217                             GNUNET_NO);
4218   GNUNET_free_non_null (n->pre_connect_message_buffer);
4219   GNUNET_free (n);
4220 }
4221
4222
4223 /**
4224  * We have received a PING message from someone.  Need to send a PONG message
4225  * in response to the peer by any means necessary. 
4226  */
4227 static int 
4228 handle_ping(void *cls, const struct GNUNET_MessageHeader *message,
4229             const struct GNUNET_PeerIdentity *peer,
4230             struct Session *session,
4231             const char *sender_address,
4232             uint16_t sender_address_len)
4233 {
4234   struct TransportPlugin *plugin = cls;
4235   struct SessionHeader *session_header = (struct SessionHeader*) session;
4236   struct TransportPingMessage *ping;
4237   struct TransportPongMessage *pong;
4238   struct NeighbourList *n;
4239   struct ReadyList *rl;
4240   struct ForeignAddressList *fal;
4241   struct OwnAddressList *oal;
4242   const char *addr;
4243   size_t alen;
4244   size_t slen;
4245
4246   if (ntohs (message->size) < sizeof (struct TransportPingMessage))
4247     {
4248       GNUNET_break_op (0);
4249       return GNUNET_SYSERR;
4250     }
4251
4252   ping = (struct TransportPingMessage *) message;
4253   if (0 != memcmp (&ping->target,
4254                    plugin->env.my_identity,
4255                    sizeof (struct GNUNET_PeerIdentity)))
4256     {
4257       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
4258                   _("Received `%s' message not destined for me!\n"), 
4259                   "PING");
4260       return GNUNET_SYSERR;
4261     }
4262 #if DEBUG_PING_PONG
4263   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
4264               "Processing `%s' from `%s'\n",
4265               "PING", 
4266               (sender_address != NULL) 
4267               ? a2s (plugin->short_name,
4268                      (const struct sockaddr *)sender_address, 
4269                      sender_address_len)
4270               : "<inbound>");
4271 #endif
4272   GNUNET_STATISTICS_update (stats,
4273                             gettext_noop ("# PING messages received"),
4274                             1,
4275                             GNUNET_NO);
4276   addr = (const char*) &ping[1];
4277   alen = ntohs (message->size) - sizeof (struct TransportPingMessage);
4278   slen = strlen (plugin->short_name) + 1;
4279   if (alen == 0)
4280     {      
4281       /* peer wants to confirm that we have an outbound connection to him */
4282       if (session == NULL)
4283         {
4284           GNUNET_log (GNUNET_ERROR_TYPE_INFO,
4285                       _("Refusing to create PONG since I do not have a session with `%s'.\n"),
4286                       GNUNET_i2s (peer));
4287           return GNUNET_SYSERR;
4288         }
4289       pong = GNUNET_malloc (sizeof (struct TransportPongMessage) + sender_address_len + slen);
4290       pong->header.size = htons (sizeof (struct TransportPongMessage) + sender_address_len + slen);
4291       pong->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_PONG);
4292       pong->purpose.size =
4293         htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) +
4294                sizeof (uint32_t) +
4295                sizeof (struct GNUNET_TIME_AbsoluteNBO) +
4296                sizeof (struct GNUNET_PeerIdentity) + sender_address_len + slen);
4297       pong->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_USING);
4298       pong->challenge = ping->challenge;
4299       pong->addrlen = htonl(sender_address_len + slen);
4300       memcpy(&pong->pid, 
4301              peer,
4302              sizeof(struct GNUNET_PeerIdentity));
4303       memcpy (&pong[1], 
4304               plugin->short_name, 
4305               slen);
4306       memcpy (&((char*)&pong[1])[slen], 
4307               sender_address, 
4308               sender_address_len);
4309       if (GNUNET_TIME_absolute_get_remaining (session_header->pong_sig_expires).value < PONG_SIGNATURE_LIFETIME.value / 4)
4310         {
4311           /* create / update cached sig */
4312 #if DEBUG_TRANSPORT
4313           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4314                       "Creating PONG signature to indicate active connection.\n");
4315 #endif
4316           session_header->pong_sig_expires = GNUNET_TIME_relative_to_absolute (PONG_SIGNATURE_LIFETIME);
4317           pong->expiration = GNUNET_TIME_absolute_hton (session_header->pong_sig_expires);
4318           GNUNET_assert (GNUNET_OK ==
4319                          GNUNET_CRYPTO_rsa_sign (my_private_key,
4320                                                  &pong->purpose,
4321                                                  &session_header->pong_signature));
4322         }
4323       else
4324         {
4325           pong->expiration = GNUNET_TIME_absolute_hton (session_header->pong_sig_expires);
4326         }
4327       memcpy (&pong->signature,
4328               &session_header->pong_signature,
4329               sizeof (struct GNUNET_CRYPTO_RsaSignature));    
4330
4331
4332     }
4333   else
4334     {
4335       /* peer wants to confirm that this is one of our addresses */
4336       addr += slen;
4337       alen -= slen;
4338       oal = plugin->addresses;
4339       while (NULL != oal)
4340         {
4341           if ( (oal->addrlen == alen) &&
4342                (0 == memcmp (addr,
4343                              &oal[1],
4344                              alen)) )
4345             break;
4346           oal = oal->next;
4347         }
4348       if (oal == NULL)
4349         {
4350           GNUNET_log (GNUNET_ERROR_TYPE_INFO,
4351                       _("Not confirming PING with address `%s' since I cannot confirm having this address.\n"),
4352                       a2s (plugin->short_name,
4353                            addr,
4354                            alen));
4355           return GNUNET_NO;
4356         }
4357       pong = GNUNET_malloc (sizeof (struct TransportPongMessage) + alen + slen);
4358       pong->header.size = htons (sizeof (struct TransportPongMessage) + alen + slen);
4359       pong->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_PONG);
4360       pong->purpose.size =
4361         htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) +
4362                sizeof (uint32_t) +
4363                sizeof (struct GNUNET_TIME_AbsoluteNBO) +
4364                sizeof (struct GNUNET_PeerIdentity) + alen + slen);
4365       pong->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN);
4366       pong->challenge = ping->challenge;
4367       pong->addrlen = htonl(alen + slen);
4368       memcpy(&pong->pid, 
4369              &my_identity, 
4370              sizeof(struct GNUNET_PeerIdentity));
4371       memcpy (&pong[1], plugin->short_name, slen);
4372       memcpy (&((char*)&pong[1])[slen], &oal[1], alen);
4373       if (GNUNET_TIME_absolute_get_remaining (oal->pong_sig_expires).value < PONG_SIGNATURE_LIFETIME.value / 4)
4374         {
4375           /* create / update cached sig */
4376 #if DEBUG_TRANSPORT
4377           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4378                       "Creating PONG signature to indicate ownership.\n");
4379 #endif
4380           oal->pong_sig_expires = GNUNET_TIME_absolute_min (oal->expires,
4381                                                             GNUNET_TIME_relative_to_absolute (PONG_SIGNATURE_LIFETIME));
4382           pong->expiration = GNUNET_TIME_absolute_hton (oal->pong_sig_expires);
4383           GNUNET_assert (GNUNET_OK ==
4384                          GNUNET_CRYPTO_rsa_sign (my_private_key,
4385                                                  &pong->purpose,
4386                                                  &oal->pong_signature));
4387         }
4388       else
4389         {
4390           pong->expiration = GNUNET_TIME_absolute_hton (oal->pong_sig_expires);
4391         }
4392       memcpy (&pong->signature,
4393               &oal->pong_signature,
4394               sizeof (struct GNUNET_CRYPTO_RsaSignature));    
4395     }
4396   n = find_neighbour(peer);
4397   GNUNET_assert (n != NULL);
4398   /* first try reliable response transmission */
4399   rl = n->plugins;
4400   while (rl != NULL)
4401     {
4402       fal = rl->addresses;
4403       while (fal != NULL)
4404         {
4405           if (-1 != rl->plugin->api->send (rl->plugin->api->cls,
4406                                            peer,
4407                                            (const char*) pong,
4408                                            ntohs (pong->header.size),
4409                                            TRANSPORT_PONG_PRIORITY, 
4410                                            HELLO_VERIFICATION_TIMEOUT,
4411                                            fal->session,
4412                                            fal->addr,
4413                                            fal->addrlen,
4414                                            GNUNET_SYSERR,
4415                                            NULL, NULL))
4416             {
4417               /* done! */
4418               GNUNET_STATISTICS_update (stats,
4419                                         gettext_noop ("# PONGs unicast via reliable transport"),
4420                                         1,
4421                                         GNUNET_NO);      
4422               GNUNET_free (pong);
4423               return GNUNET_OK;
4424             }
4425           fal = fal->next;
4426         }
4427       rl = rl->next;
4428     }
4429   /* no reliable method found, do multicast */
4430   GNUNET_STATISTICS_update (stats,
4431                             gettext_noop ("# PONGs multicast to all available addresses"),
4432                             1,
4433                             GNUNET_NO);      
4434   rl = n->plugins;
4435   while (rl != NULL)
4436     {
4437       fal = rl->addresses;
4438       while (fal != NULL)
4439         {
4440           transmit_to_peer(NULL, fal,
4441                            TRANSPORT_PONG_PRIORITY, 
4442                            HELLO_VERIFICATION_TIMEOUT,
4443                            (const char *)pong, 
4444                            ntohs(pong->header.size), 
4445                            GNUNET_YES, 
4446                            n);
4447           fal = fal->next;
4448         }
4449       rl = rl->next;
4450     }
4451   GNUNET_free(pong);
4452   return GNUNET_OK;
4453 }
4454
4455
4456 /**
4457  * Function called by the plugin for each received message.
4458  * Update data volumes, possibly notify plugins about
4459  * reducing the rate at which they read from the socket
4460  * and generally forward to our receive callback.
4461  *
4462  * @param cls the "struct TransportPlugin *" we gave to the plugin
4463  * @param peer (claimed) identity of the other peer
4464  * @param message the message, NULL if we only care about
4465  *                learning about the delay until we should receive again
4466  * @param distance in overlay hops; use 1 unless DV (or 0 if message == NULL)
4467  * @param session identifier used for this session (can be NULL)
4468  * @param sender_address binary address of the sender (if observed)
4469  * @param sender_address_len number of bytes in sender_address
4470  * @return how long the plugin should wait until receiving more data
4471  *         (plugins that do not support this, can ignore the return value)
4472  */
4473 static struct GNUNET_TIME_Relative
4474 plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
4475                     const struct GNUNET_MessageHeader *message,
4476                     uint32_t distance,
4477                     struct Session *session,
4478                     const char *sender_address,
4479                     uint16_t sender_address_len)
4480 {
4481   struct TransportPlugin *plugin = cls;
4482   struct ReadyList *service_context;
4483   struct ForeignAddressList *peer_address;
4484   uint16_t msize;
4485   struct NeighbourList *n;
4486   struct GNUNET_TIME_Relative ret;
4487
4488   if (is_blacklisted (peer, plugin))
4489     return GNUNET_TIME_UNIT_FOREVER_REL;
4490
4491   n = find_neighbour (peer);
4492   if (n == NULL)
4493     n = setup_new_neighbour (peer, GNUNET_YES);
4494   service_context = n->plugins;
4495   while ((service_context != NULL) && (plugin != service_context->plugin))
4496     service_context = service_context->next;
4497   GNUNET_assert ((plugin->api->send == NULL) || (service_context != NULL));
4498   peer_address = NULL;
4499   if (message != NULL)
4500     {
4501       if ( (session != NULL) ||
4502            (sender_address != NULL) )
4503         peer_address = add_peer_address (n, 
4504                                          plugin->short_name,
4505                                          session,
4506                                          sender_address, 
4507                                          sender_address_len);  
4508       if (peer_address != NULL)
4509         {
4510           peer_address->distance = distance;
4511           if (GNUNET_YES == peer_address->validated)
4512             mark_address_connected (peer_address);
4513           peer_address->timeout
4514             =
4515             GNUNET_TIME_relative_to_absolute
4516             (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
4517           schedule_next_ping (peer_address);
4518         }
4519       /* update traffic received amount ... */
4520       msize = ntohs (message->size);      
4521       GNUNET_STATISTICS_update (stats,
4522                                 gettext_noop ("# bytes received from other peers"),
4523                                 msize,
4524                                 GNUNET_NO);
4525       n->distance = distance;
4526       n->peer_timeout =
4527         GNUNET_TIME_relative_to_absolute
4528         (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
4529       GNUNET_SCHEDULER_cancel (sched,
4530                                n->timeout_task);
4531       n->timeout_task =
4532         GNUNET_SCHEDULER_add_delayed (sched,
4533                                       GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
4534                                       &neighbour_timeout_task, n);
4535       if (n->quota_violation_count > QUOTA_VIOLATION_DROP_THRESHOLD)
4536         {
4537           /* dropping message due to frequent inbound volume violations! */
4538           GNUNET_log (GNUNET_ERROR_TYPE_WARNING |
4539                       GNUNET_ERROR_TYPE_BULK,
4540                       _
4541                       ("Dropping incoming message due to repeated bandwidth quota (%u b/s) violations (total of %u).\n"), 
4542                       n->in_tracker.available_bytes_per_s__,
4543                       n->quota_violation_count);
4544           GNUNET_STATISTICS_update (stats,
4545                                     gettext_noop ("# bandwidth quota violations by other peers"),
4546                                     1,
4547                                     GNUNET_NO);
4548           return GNUNET_CONSTANTS_QUOTA_VIOLATION_TIMEOUT;
4549         }
4550 #if DEBUG_PING_PONG
4551           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4552                       "Received message of type %u and size %u from `%4s', sending to all clients.\n",
4553                       ntohs (message->type), 
4554                       ntohs (message->size), 
4555                       GNUNET_i2s (peer));
4556 #endif
4557       switch (ntohs (message->type))
4558         {
4559         case GNUNET_MESSAGE_TYPE_HELLO:
4560           GNUNET_STATISTICS_update (stats,
4561                                     gettext_noop ("# HELLO messages received from other peers"),
4562                                     1,
4563                                     GNUNET_NO);
4564           process_hello (plugin, message);
4565           break;
4566         case GNUNET_MESSAGE_TYPE_TRANSPORT_PING:
4567           handle_ping (plugin, message, peer, session, sender_address, sender_address_len);
4568           break;
4569         case GNUNET_MESSAGE_TYPE_TRANSPORT_PONG:
4570           handle_pong (plugin, message, peer, sender_address, sender_address_len);
4571           break;
4572         default:
4573           handle_payload_message (message, n);
4574           break;
4575         }
4576     }  
4577   ret = GNUNET_BANDWIDTH_tracker_get_delay (&n->in_tracker, 0);
4578   if (ret.value > 0)
4579     {
4580       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
4581                   "Throttling read (%llu bytes excess at %u b/s), waiting %llums before reading more.\n",
4582                   (unsigned long long) n->in_tracker.consumption_since_last_update__,
4583                   (unsigned int) n->in_tracker.available_bytes_per_s__,
4584                   (unsigned long long) ret.value);
4585       GNUNET_STATISTICS_update (stats,
4586                                 gettext_noop ("# ms throttling suggested"),
4587                                 (int64_t) ret.value,
4588                                 GNUNET_NO);      
4589     }
4590   return ret;
4591 }
4592
4593 /**
4594  * Handle START-message.  This is the first message sent to us
4595  * by any client which causes us to add it to our list.
4596  *
4597  * @param cls closure (always NULL)
4598  * @param client identification of the client
4599  * @param message the actual message
4600  */
4601 static void
4602 handle_start (void *cls,
4603               struct GNUNET_SERVER_Client *client,
4604               const struct GNUNET_MessageHeader *message)
4605 {
4606   struct TransportClient *c;
4607   struct ConnectInfoMessage cim;
4608   struct NeighbourList *n;
4609
4610 #if DEBUG_TRANSPORT
4611   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4612               "Received `%s' request from client\n", "START");
4613 #endif
4614   c = clients;
4615   while (c != NULL)
4616     {
4617       if (c->client == client)
4618         {
4619           /* client already on our list! */
4620           GNUNET_break (0);
4621           GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4622           return;
4623         }
4624       c = c->next;
4625     }
4626   c = GNUNET_malloc (sizeof (struct TransportClient));
4627   c->next = clients;
4628   clients = c;
4629   c->client = client;
4630   if (our_hello != NULL)
4631     {
4632 #if DEBUG_TRANSPORT
4633       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4634                   "Sending our own `%s' to new client\n", "HELLO");
4635 #endif
4636       transmit_to_client (c,
4637                           (const struct GNUNET_MessageHeader *) our_hello,
4638                           GNUNET_NO);
4639       /* tell new client about all existing connections */
4640       cim.header.size = htons (sizeof (struct ConnectInfoMessage));
4641       cim.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
4642       n = neighbours; 
4643       while (n != NULL)
4644         {
4645           if (GNUNET_YES == n->received_pong)
4646             {
4647               cim.id = n->id;
4648               cim.latency = GNUNET_TIME_relative_hton (n->latency);
4649               cim.distance = htonl (n->distance);
4650               transmit_to_client (c, &cim.header, GNUNET_NO);
4651             }
4652             n = n->next;
4653         }
4654     }
4655   GNUNET_SERVER_receive_done (client, GNUNET_OK);
4656 }
4657
4658
4659 /**
4660  * Handle HELLO-message.
4661  *
4662  * @param cls closure (always NULL)
4663  * @param client identification of the client
4664  * @param message the actual message
4665  */
4666 static void
4667 handle_hello (void *cls,
4668               struct GNUNET_SERVER_Client *client,
4669               const struct GNUNET_MessageHeader *message)
4670 {
4671   int ret;
4672
4673   GNUNET_STATISTICS_update (stats,
4674                             gettext_noop ("# HELLOs received from clients"),
4675                             1,
4676                             GNUNET_NO);      
4677   ret = process_hello (NULL, message);
4678   GNUNET_SERVER_receive_done (client, ret);
4679 }
4680
4681
4682 /**
4683  * Closure for 'transmit_client_message'; followed by
4684  * 'msize' bytes of the actual message.
4685  */
4686 struct TransmitClientMessageContext 
4687 {
4688   /**
4689    * Client on whom's behalf we are sending.
4690    */
4691   struct GNUNET_SERVER_Client *client;
4692
4693   /**
4694    * Timeout for the transmission.
4695    */
4696   struct GNUNET_TIME_Absolute timeout;
4697   
4698   /**
4699    * Message priority.
4700    */
4701   uint32_t priority;
4702
4703   /**
4704    * Size of the message in bytes.
4705    */ 
4706   uint16_t msize;
4707 };
4708
4709
4710 /**
4711  * Schedule transmission of a message we got from a client to a peer.
4712  *
4713  * @param cls the 'struct TransmitClientMessageContext*'
4714  * @param n destination, or NULL on error (in that case, drop the message)
4715  */
4716 static void
4717 transmit_client_message (void *cls,
4718                          struct NeighbourList *n)
4719 {
4720   struct TransmitClientMessageContext *tcmc = cls;
4721   struct TransportClient *tc;
4722
4723   tc = clients;
4724   while ((tc != NULL) && (tc->client != tcmc->client))
4725     tc = tc->next;
4726
4727   if (n != NULL)
4728     {
4729       transmit_to_peer (tc, NULL, tcmc->priority, 
4730                         GNUNET_TIME_absolute_get_remaining (tcmc->timeout),
4731                         (char *)&tcmc[1],
4732                         tcmc->msize, GNUNET_NO, n);
4733     }
4734   GNUNET_SERVER_receive_done (tcmc->client, GNUNET_OK);
4735   GNUNET_SERVER_client_drop (tcmc->client);
4736   GNUNET_free (tcmc);
4737 }
4738
4739
4740 /**
4741  * Handle SEND-message.
4742  *
4743  * @param cls closure (always NULL)
4744  * @param client identification of the client
4745  * @param message the actual message
4746  */
4747 static void
4748 handle_send (void *cls,
4749              struct GNUNET_SERVER_Client *client,
4750              const struct GNUNET_MessageHeader *message)
4751 {
4752   const struct OutboundMessage *obm;
4753   const struct GNUNET_MessageHeader *obmm;
4754   struct TransmitClientMessageContext *tcmc;
4755   uint16_t size;
4756   uint16_t msize;
4757
4758   size = ntohs (message->size);
4759   if (size <
4760       sizeof (struct OutboundMessage) + sizeof (struct GNUNET_MessageHeader))
4761     {
4762       GNUNET_break (0);
4763       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4764       return;
4765     }
4766   GNUNET_STATISTICS_update (stats,
4767                             gettext_noop ("# payload received for other peers"),
4768                             size,
4769                             GNUNET_NO);      
4770   obm = (const struct OutboundMessage *) message;
4771   obmm = (const struct GNUNET_MessageHeader *) &obm[1];
4772   msize = size - sizeof (struct OutboundMessage);
4773 #if DEBUG_TRANSPORT
4774   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4775               "Received `%s' request from client with target `%4s' and message of type %u and size %u\n",
4776               "SEND", GNUNET_i2s (&obm->peer),
4777               ntohs (obmm->type),
4778               msize);
4779 #endif
4780   tcmc = GNUNET_malloc (sizeof (struct TransmitClientMessageContext) + msize);
4781   tcmc->client = client;
4782   tcmc->priority = ntohl (obm->priority);
4783   tcmc->timeout = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_relative_ntoh (obm->timeout));
4784   tcmc->msize = msize;
4785   memcpy (&tcmc[1], obmm, msize);
4786   GNUNET_SERVER_client_keep (client);
4787   setup_peer_check_blacklist (&obm->peer, GNUNET_YES,
4788                               &transmit_client_message,
4789                               tcmc);
4790 }
4791
4792
4793 /**
4794  * Handle SET_QUOTA-message.
4795  *
4796  * @param cls closure (always NULL)
4797  * @param client identification of the client
4798  * @param message the actual message
4799  */
4800 static void
4801 handle_set_quota (void *cls,
4802                   struct GNUNET_SERVER_Client *client,
4803                   const struct GNUNET_MessageHeader *message)
4804 {
4805   const struct QuotaSetMessage *qsm =
4806     (const struct QuotaSetMessage *) message;
4807   struct NeighbourList *n;
4808   
4809   GNUNET_STATISTICS_update (stats,
4810                             gettext_noop ("# SET QUOTA messages received"),
4811                             1,
4812                             GNUNET_NO);      
4813   n = find_neighbour (&qsm->peer);
4814   if (n == NULL)
4815     {
4816       GNUNET_SERVER_receive_done (client, GNUNET_OK);
4817       GNUNET_STATISTICS_update (stats,
4818                                 gettext_noop ("# SET QUOTA messages ignored (no such peer)"),
4819                                 1,
4820                                 GNUNET_NO);      
4821       return;
4822     }
4823 #if DEBUG_TRANSPORT
4824   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4825               "Received `%s' request (new quota %u, old quota %u) from client for peer `%4s'\n",
4826               "SET_QUOTA", 
4827               (unsigned int) ntohl (qsm->quota.value__),
4828               (unsigned int) n->in_tracker.available_bytes_per_s__,
4829               GNUNET_i2s (&qsm->peer));
4830 #endif
4831   GNUNET_BANDWIDTH_tracker_update_quota (&n->in_tracker,
4832                                          qsm->quota);
4833   if (0 == ntohl (qsm->quota.value__)) 
4834     disconnect_neighbour (n, GNUNET_NO);    
4835   GNUNET_SERVER_receive_done (client, GNUNET_OK);
4836 }
4837
4838
4839 /**
4840  * Take the given address and append it to the set of results sent back to
4841  * the client.
4842  * 
4843  * @param cls the transmission context used ('struct GNUNET_SERVER_TransmitContext*')
4844  * @param address the resolved name, NULL to indicate the last response
4845  */
4846 static void
4847 transmit_address_to_client (void *cls, const char *address)
4848 {
4849   struct GNUNET_SERVER_TransmitContext *tc = cls;
4850   size_t slen;
4851
4852   if (NULL == address)
4853     slen = 0;
4854   else
4855     slen = strlen (address) + 1;
4856
4857   GNUNET_SERVER_transmit_context_append_data (tc, address, slen,
4858                                               GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_REPLY);
4859   if (NULL == address)
4860     GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
4861 }
4862
4863
4864 /**
4865  * Handle AddressLookup-message.
4866  *
4867  * @param cls closure (always NULL)
4868  * @param client identification of the client
4869  * @param message the actual message
4870  */
4871 static void
4872 handle_address_lookup (void *cls,
4873                        struct GNUNET_SERVER_Client *client,
4874                        const struct GNUNET_MessageHeader *message)
4875 {
4876   const struct AddressLookupMessage *alum;
4877   struct TransportPlugin *lsPlugin;
4878   const char *nameTransport;
4879   const char *address;
4880   uint16_t size;
4881   struct GNUNET_SERVER_TransmitContext *tc;
4882   struct GNUNET_TIME_Absolute timeout;
4883   struct GNUNET_TIME_Relative rtimeout;
4884   int32_t numeric;
4885
4886   size = ntohs (message->size);
4887   if (size < sizeof (struct AddressLookupMessage))
4888     {
4889       GNUNET_break_op (0);
4890       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4891       return;
4892     }
4893   alum = (const struct AddressLookupMessage *) message;
4894   uint32_t addressLen = ntohl (alum->addrlen);
4895   if (size <= sizeof (struct AddressLookupMessage) + addressLen)
4896     {
4897       GNUNET_break_op (0);
4898       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4899       return;
4900     }
4901   address = (const char *) &alum[1];
4902   nameTransport = (const char *) &address[addressLen];
4903   if (nameTransport
4904       [size - sizeof (struct AddressLookupMessage) - addressLen - 1] != '\0')
4905     {
4906       GNUNET_break_op (0);
4907       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4908       return;
4909     }
4910   timeout = GNUNET_TIME_absolute_ntoh (alum->timeout);
4911   rtimeout = GNUNET_TIME_absolute_get_remaining (timeout);
4912   numeric = ntohl (alum->numeric_only);
4913   lsPlugin = find_transport (nameTransport);
4914   if (NULL == lsPlugin)
4915     {
4916       tc = GNUNET_SERVER_transmit_context_create (client);
4917       GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
4918                                                   GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_REPLY);
4919       GNUNET_SERVER_transmit_context_run (tc, rtimeout);
4920       return;
4921     }
4922   tc = GNUNET_SERVER_transmit_context_create (client);
4923   lsPlugin->api->address_pretty_printer (lsPlugin->api->cls,
4924                                          nameTransport,
4925                                          address, addressLen, 
4926                                          numeric,
4927                                          rtimeout,
4928                                          &transmit_address_to_client, tc);
4929 }
4930
4931
4932 /**
4933  * Setup the environment for this plugin.
4934  */
4935 static void
4936 create_environment (struct TransportPlugin *plug)
4937 {
4938   plug->env.cfg = cfg;
4939   plug->env.sched = sched;
4940   plug->env.my_identity = &my_identity;
4941   plug->env.cls = plug;
4942   plug->env.receive = &plugin_env_receive;
4943   plug->env.notify_address = &plugin_env_notify_address;
4944   plug->env.session_end = &plugin_env_session_end;
4945   plug->env.max_connections = max_connect_per_transport;
4946   plug->env.stats = stats;
4947 }
4948
4949
4950 /**
4951  * Start the specified transport (load the plugin).
4952  */
4953 static void
4954 start_transport (struct GNUNET_SERVER_Handle *server, 
4955                  const char *name)
4956 {
4957   struct TransportPlugin *plug;
4958   char *libname;
4959
4960   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
4961               _("Loading `%s' transport plugin\n"), name);
4962   GNUNET_asprintf (&libname, "libgnunet_plugin_transport_%s", name);
4963   plug = GNUNET_malloc (sizeof (struct TransportPlugin));
4964   create_environment (plug);
4965   plug->short_name = GNUNET_strdup (name);
4966   plug->lib_name = libname;
4967   plug->next = plugins;
4968   plugins = plug;
4969   plug->api = GNUNET_PLUGIN_load (libname, &plug->env);
4970   if (plug->api == NULL)
4971     {
4972       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
4973                   _("Failed to load transport plugin for `%s'\n"), name);
4974       GNUNET_free (plug->short_name);
4975       plugins = plug->next;
4976       GNUNET_free (libname);
4977       GNUNET_free (plug);
4978     }
4979 }
4980
4981
4982 /**
4983  * Called whenever a client is disconnected.  Frees our
4984  * resources associated with that client.
4985  *
4986  * @param cls closure
4987  * @param client identification of the client
4988  */
4989 static void
4990 client_disconnect_notification (void *cls,
4991                                 struct GNUNET_SERVER_Client *client)
4992 {
4993   struct TransportClient *pos;
4994   struct TransportClient *prev;
4995   struct ClientMessageQueueEntry *mqe;
4996   struct Blacklisters *bl;
4997   struct BlacklistCheck *bc;
4998
4999   if (client == NULL)
5000     return;
5001 #if DEBUG_TRANSPORT
5002   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
5003               "Client disconnected, cleaning up.\n");
5004 #endif
5005   /* clean up blacklister */
5006   bl = bl_head;
5007   while (bl != NULL)
5008     {
5009       if (bl->client == client)
5010         {
5011           bc = bc_head;
5012           while (bc != NULL)
5013             {
5014               if (bc->bl_pos == bl)
5015                 {
5016                   bc->bl_pos = bl->next;
5017                   if (bc->th != NULL)
5018                     {
5019                       GNUNET_CONNECTION_notify_transmit_ready_cancel (bc->th);
5020                       bc->th = NULL;                  
5021                     }
5022                   if (bc->task == GNUNET_SCHEDULER_NO_TASK)
5023                     bc->task = GNUNET_SCHEDULER_add_now (sched,
5024                                                          &do_blacklist_check,
5025                                                          bc);
5026                   break;
5027                 }
5028               bc = bc->next;
5029             }
5030           GNUNET_CONTAINER_DLL_remove (bl_head,
5031                                        bl_tail,
5032                                        bl);
5033           GNUNET_SERVER_client_drop (bl->client);
5034           GNUNET_free (bl);
5035           break;
5036         }
5037       bl = bl->next;
5038     }
5039   /* clean up 'normal' clients */
5040   prev = NULL;
5041   pos = clients;
5042   while ((pos != NULL) && (pos->client != client))
5043     {
5044       prev = pos;
5045       pos = pos->next;
5046     }
5047   if (pos == NULL)
5048     return;
5049   while (NULL != (mqe = pos->message_queue_head))
5050     {
5051       GNUNET_CONTAINER_DLL_remove (pos->message_queue_head,
5052                                    pos->message_queue_tail,
5053                                    mqe);
5054       pos->message_count--;
5055       GNUNET_free (mqe);
5056     }
5057   if (prev == NULL)
5058     clients = pos->next;
5059   else
5060     prev->next = pos->next;
5061   if (GNUNET_YES == pos->tcs_pending)
5062     {
5063       pos->client = NULL;
5064       return;
5065     }
5066   if (pos->th != NULL)
5067     {
5068       GNUNET_CONNECTION_notify_transmit_ready_cancel (pos->th);
5069       pos->th = NULL;
5070     }
5071   GNUNET_break (0 == pos->message_count);
5072   GNUNET_free (pos);
5073 }
5074
5075
5076 /**
5077  * Function called when the service shuts down.  Unloads our plugins
5078  * and cancels pending validations.
5079  *
5080  * @param cls closure, unused
5081  * @param tc task context (unused)
5082  */
5083 static void
5084 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
5085 {
5086   struct TransportPlugin *plug;
5087   struct OwnAddressList *al;
5088   struct CheckHelloValidatedContext *chvc;
5089
5090   while (neighbours != NULL)
5091     disconnect_neighbour (neighbours, GNUNET_NO);
5092 #if DEBUG_TRANSPORT
5093   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5094               "Transport service is unloading plugins...\n");
5095 #endif
5096   while (NULL != (plug = plugins))
5097     {
5098       plugins = plug->next;
5099       if (plug->address_update_task != GNUNET_SCHEDULER_NO_TASK)
5100         {
5101           GNUNET_SCHEDULER_cancel (plug->env.sched, 
5102                                    plug->address_update_task);
5103           plug->address_update_task = GNUNET_SCHEDULER_NO_TASK;
5104         }
5105       GNUNET_break (NULL == GNUNET_PLUGIN_unload (plug->lib_name, plug->api));
5106       GNUNET_free (plug->lib_name);
5107       GNUNET_free (plug->short_name);
5108       while (NULL != (al = plug->addresses))
5109         {
5110           plug->addresses = al->next;
5111           GNUNET_free (al);
5112         }
5113       GNUNET_free (plug);
5114     }
5115   if (my_private_key != NULL)
5116     GNUNET_CRYPTO_rsa_key_free (my_private_key);
5117   GNUNET_free_non_null (our_hello);
5118
5119   GNUNET_CONTAINER_multihashmap_iterate (validation_map,
5120                                          &abort_validation,
5121                                          NULL);
5122   GNUNET_CONTAINER_multihashmap_destroy (validation_map);
5123   validation_map = NULL;
5124
5125   /* free 'chvc' data structure */
5126   while (NULL != (chvc = chvc_head))
5127     {
5128       chvc_head = chvc->next;
5129       if (chvc->piter != NULL)
5130         GNUNET_PEERINFO_iterate_cancel (chvc->piter);      
5131       else
5132         GNUNET_break (0);
5133       GNUNET_assert (chvc->ve_count == 0);
5134       GNUNET_free (chvc);
5135     }
5136   chvc_tail = NULL;
5137
5138   if (stats != NULL)
5139     {
5140       GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
5141       stats = NULL;
5142     }
5143   if (peerinfo != NULL)
5144     {
5145       GNUNET_PEERINFO_disconnect (peerinfo);
5146       peerinfo = NULL;
5147     }
5148   /* Can we assume those are gone by now, or do we need to clean up
5149      explicitly!? */
5150   GNUNET_break (bl_head == NULL);
5151   GNUNET_break (bc_head == NULL);
5152 }
5153
5154
5155 /**
5156  * Initiate transport service.
5157  *
5158  * @param cls closure
5159  * @param s scheduler to use
5160  * @param server the initialized server
5161  * @param c configuration to use
5162  */
5163 static void
5164 run (void *cls,
5165      struct GNUNET_SCHEDULER_Handle *s,
5166      struct GNUNET_SERVER_Handle *server,
5167      const struct GNUNET_CONFIGURATION_Handle *c)
5168 {
5169   static const struct GNUNET_SERVER_MessageHandler handlers[] = {
5170     {&handle_start, NULL,
5171      GNUNET_MESSAGE_TYPE_TRANSPORT_START, 0},
5172     {&handle_hello, NULL,
5173      GNUNET_MESSAGE_TYPE_HELLO, 0},
5174     {&handle_send, NULL,
5175      GNUNET_MESSAGE_TYPE_TRANSPORT_SEND, 0},
5176     {&handle_set_quota, NULL,
5177      GNUNET_MESSAGE_TYPE_TRANSPORT_SET_QUOTA, sizeof (struct QuotaSetMessage)},
5178     {&handle_address_lookup, NULL,
5179      GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_LOOKUP,
5180      0},
5181     {&handle_blacklist_init, NULL,
5182      GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_INIT, sizeof (struct GNUNET_MessageHeader)},
5183     {&handle_blacklist_reply, NULL,
5184      GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_REPLY, sizeof (struct BlacklistMessage)},
5185     {NULL, NULL, 0, 0}
5186   };
5187   char *plugs;
5188   char *pos;
5189   int no_transports;
5190   unsigned long long tneigh;
5191   char *keyfile;
5192
5193   sched = s;
5194   cfg = c;
5195   stats = GNUNET_STATISTICS_create (sched, "transport", cfg);
5196   validation_map = GNUNET_CONTAINER_multihashmap_create (64);
5197   /* parse configuration */
5198   if ((GNUNET_OK !=
5199        GNUNET_CONFIGURATION_get_value_number (c,
5200                                               "TRANSPORT",
5201                                               "NEIGHBOUR_LIMIT",
5202                                               &tneigh)) ||
5203       (GNUNET_OK !=
5204        GNUNET_CONFIGURATION_get_value_filename (c,
5205                                                 "GNUNETD",
5206                                                 "HOSTKEY", &keyfile)))
5207     {
5208       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
5209                   _
5210                   ("Transport service is lacking key configuration settings.  Exiting.\n"));
5211       GNUNET_SCHEDULER_shutdown (s);
5212       if (stats != NULL)
5213         {
5214           GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
5215           stats = NULL;
5216         }
5217       GNUNET_CONTAINER_multihashmap_destroy (validation_map);
5218       validation_map = NULL;
5219       return;
5220     }
5221   max_connect_per_transport = (uint32_t) tneigh;
5222   peerinfo = GNUNET_PEERINFO_connect (sched, cfg);
5223   if (peerinfo == NULL)
5224     {
5225       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
5226                   _("Could not access PEERINFO service.  Exiting.\n"));     
5227       GNUNET_SCHEDULER_shutdown (s);
5228       if (stats != NULL)
5229         {
5230           GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
5231           stats = NULL;
5232         }
5233       GNUNET_CONTAINER_multihashmap_destroy (validation_map);
5234       validation_map = NULL;
5235       GNUNET_free (keyfile);
5236       return;
5237     }
5238   my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
5239   GNUNET_free (keyfile);
5240   if (my_private_key == NULL)
5241     {
5242       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
5243                   _
5244                   ("Transport service could not access hostkey.  Exiting.\n"));
5245       GNUNET_SCHEDULER_shutdown (s);
5246       if (stats != NULL)
5247         {
5248           GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
5249           stats = NULL;
5250         }
5251       GNUNET_CONTAINER_multihashmap_destroy (validation_map);
5252       validation_map = NULL;
5253       return;
5254     }
5255   GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key);
5256   GNUNET_CRYPTO_hash (&my_public_key,
5257                       sizeof (my_public_key), &my_identity.hashPubKey);
5258   /* setup notification */
5259   GNUNET_SERVER_disconnect_notify (server,
5260                                    &client_disconnect_notification, NULL);
5261   /* load plugins... */
5262   no_transports = 1;
5263   if (GNUNET_OK ==
5264       GNUNET_CONFIGURATION_get_value_string (c,
5265                                              "TRANSPORT", "PLUGINS", &plugs))
5266     {
5267       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
5268                   _("Starting transport plugins `%s'\n"), plugs);
5269       pos = strtok (plugs, " ");
5270       while (pos != NULL)
5271         {
5272           start_transport (server, pos);
5273           no_transports = 0;
5274           pos = strtok (NULL, " ");
5275         }
5276       GNUNET_free (plugs);
5277     }
5278   GNUNET_SCHEDULER_add_delayed (sched,
5279                                 GNUNET_TIME_UNIT_FOREVER_REL,
5280                                 &shutdown_task, NULL);
5281   if (no_transports)
5282     refresh_hello ();
5283
5284 #if DEBUG_TRANSPORT
5285   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Transport service ready.\n"));
5286 #endif
5287   /* If we have a blacklist file, read from it */
5288   read_blacklist_file(cfg);
5289   /* process client requests */
5290   GNUNET_SERVER_add_handlers (server, handlers);
5291 }
5292
5293
5294 /**
5295  * The main function for the transport service.
5296  *
5297  * @param argc number of arguments from the command line
5298  * @param argv command line arguments
5299  * @return 0 ok, 1 on error
5300  */
5301 int
5302 main (int argc, char *const *argv)
5303 {
5304   a2s (NULL, NULL, 0); /* make compiler happy */
5305   return (GNUNET_OK ==
5306           GNUNET_SERVICE_run (argc,
5307                               argv,
5308                               "transport",
5309                               GNUNET_SERVICE_OPTION_NONE,
5310                               &run, NULL)) ? 0 : 1;
5311 }
5312
5313 /* end of gnunet-service-transport.c */