stuff
[oweals/gnunet.git] / src / transport / gnunet-service-transport.c
1 /*
2      This file is part of GNUnet.
3      (C) 2009 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  * BUGS:
27  * - bi-directional nature of TCP is not exploited
28  * - re-validation is broken (triggered only on successful validation,
29  *   does not consider expiration times)
30  * 
31  *
32  * NOTE:
33  * - This code uses 'GNUNET_a2s' for debug printing in many places,
34  *   which is technically wrong since it assumes we have IP+Port 
35  *   (v4/v6) addresses.  Once we add transports like http or smtp
36  *   this will have to be changed!
37  */
38 #include "platform.h"
39 #include "gnunet_client_lib.h"
40 #include "gnunet_container_lib.h"
41 #include "gnunet_constants.h"
42 #include "gnunet_getopt_lib.h"
43 #include "gnunet_hello_lib.h"
44 #include "gnunet_os_lib.h"
45 #include "gnunet_peerinfo_service.h"
46 #include "gnunet_plugin_lib.h"
47 #include "gnunet_protocols.h"
48 #include "gnunet_service_lib.h"
49 #include "gnunet_signatures.h"
50 #include "plugin_transport.h"
51 #include "transport.h"
52
53 /**
54  * Should we do some additional checks (to validate behavior
55  * of clients)?
56  */
57 #define EXTRA_CHECKS GNUNET_YES
58
59 /**
60  * How many messages can we have pending for a given client process
61  * before we start to drop incoming messages?  We typically should
62  * have only one client and so this would be the primary buffer for
63  * messages, so the number should be chosen rather generously.
64  *
65  * The expectation here is that most of the time the queue is large
66  * enough so that a drop is virtually never required.
67  */
68 #define MAX_PENDING 128
69
70 /**
71  * How often should we try to reconnect to a peer using a particular
72  * transport plugin before giving up?  Note that the plugin may be
73  * added back to the list after PLUGIN_RETRY_FREQUENCY expires.
74  */
75 #define MAX_CONNECT_RETRY 3
76
77 /**
78  * Limit on the number of ready-to-run tasks when validating 
79  * HELLOs.  If more tasks are ready to run, we will drop 
80  * HELLOs instead of validating them.
81  */
82 #define MAX_HELLO_LOAD 4
83
84 /**
85  * How often must a peer violate bandwidth quotas before we start
86  * to simply drop its messages?
87  */
88 #define QUOTA_VIOLATION_DROP_THRESHOLD 10
89
90 /**
91  * How long until a HELLO verification attempt should time out?
92  * Must be rather small, otherwise a partially successful HELLO
93  * validation (some addresses working) might not be available
94  * before a client's request for a connection fails for good.
95  * Besides, if a single request to an address takes a long time,
96  * then the peer is unlikely worthwhile anyway.
97  */
98 #define HELLO_VERIFICATION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
99
100 /**
101  * How long will we allow sending of a ping to be delayed?
102  */
103 #define TRANSPORT_DEFAULT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15)
104
105 /**
106  * How often will we re-validate for latency information
107  */
108 #define TRANSPORT_DEFAULT_REVALIDATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
109
110 /**
111  * Priority to use for PONG messages.
112  */
113 #define TRANSPORT_PONG_PRIORITY 4
114
115 /**
116  * How often do we re-add (cheaper) plugins to our list of plugins
117  * to try for a given connected peer?
118  */
119 #define PLUGIN_RETRY_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15)
120
121 /**
122  * After how long do we expire an address in a HELLO that we just
123  * validated?  This value is also used for our own addresses when we
124  * create a HELLO.
125  */
126 #define HELLO_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 12)
127
128
129 /**
130  * How long before an existing address expires should we again try to
131  * validate it?  Must be (significantly) smaller than
132  * HELLO_ADDRESS_EXPIRATION.
133  */
134 #define HELLO_REVALIDATION_START_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 1)
135
136
137 /**
138  * List of addresses of other peers
139  */
140 struct ForeignAddressList
141 {
142   /**
143    * This is a linked list.
144    */
145   struct ForeignAddressList *next;
146
147   /**
148    * Which ready list does this entry belong to.
149    */
150   struct ReadyList *ready_list;
151
152   /**
153    * How long until we auto-expire this address (unless it is
154    * re-confirmed by the transport)?
155    */
156   struct GNUNET_TIME_Absolute expires;
157
158   /**
159    * Task used to re-validate addresses, updates latencies and
160    * verifies liveness.
161    */
162   GNUNET_SCHEDULER_TaskIdentifier revalidate_task;
163
164   /**
165    * Length of addr.
166    */
167   size_t addrlen;
168
169   /**
170    * The address.
171    */
172   const void *addr;
173
174   /**
175    * What was the last latency observed for this plugin
176    * and peer?  Invalid if connected is GNUNET_NO.
177    */
178   struct GNUNET_TIME_Relative latency;
179
180   /**
181    * If we did not successfully transmit a message to the given peer
182    * via this connection during the specified time, we should consider
183    * the connection to be dead.  This is used in the case that a TCP
184    * transport simply stalls writing to the stream but does not
185    * formerly get a signal that the other peer died.
186    */
187   struct GNUNET_TIME_Absolute timeout;
188
189   /**
190    * Are we currently connected via this address?  The first time we
191    * successfully transmit or receive data to a peer via a particular
192    * address, we set this to GNUNET_YES.  If we later get an error
193    * (disconnect notification, transmission failure, timeout), we set
194    * it back to GNUNET_NO.  
195    */
196   int connected;
197
198   /**
199    * Is this plugin currently busy transmitting to the specific target?
200    * GNUNET_NO if not (initial, default state is GNUNET_NO).   Internal
201    * messages do not count as 'in transmit'.
202    */
203   int in_transmit;
204
205   /**
206    * Has this address been validated yet?
207    */
208   int validated;
209
210   /**
211    * How often have we tried to connect using this plugin?  Used to
212    * discriminate against addresses that do not work well.
213    * FIXME: not yet used, but should be!
214    */
215   unsigned int connect_attempts;
216
217   /**
218    * DV distance to this peer (1 if no DV is used). 
219    * FIXME: need to set this from transport plugins!
220    */
221   uint32_t distance;
222
223 };
224
225
226 /**
227  * Entry in linked list of network addresses for ourselves.
228  */
229 struct OwnAddressList
230 {
231   /**
232    * This is a linked list.
233    */
234   struct OwnAddressList *next;
235
236   /**
237    * The address, actually a pointer to the end
238    * of this struct.  Do not free!
239    */
240   const void *addr;
241   
242   /**
243    * How long until we auto-expire this address (unless it is
244    * re-confirmed by the transport)?
245    */
246   struct GNUNET_TIME_Absolute expires;
247
248   /**
249    * Length of addr.
250    */
251   size_t addrlen;
252
253 };
254
255
256 /**
257  * Entry in linked list of all of our plugins.
258  */
259 struct TransportPlugin
260 {
261
262   /**
263    * This is a linked list.
264    */
265   struct TransportPlugin *next;
266
267   /**
268    * API of the transport as returned by the plugin's
269    * initialization function.
270    */
271   struct GNUNET_TRANSPORT_PluginFunctions *api;
272
273   /**
274    * Short name for the plugin (i.e. "tcp").
275    */
276   char *short_name;
277
278   /**
279    * Name of the library (i.e. "gnunet_plugin_transport_tcp").
280    */
281   char *lib_name;
282
283   /**
284    * List of our known addresses for this transport.
285    */
286   struct OwnAddressList *addresses;
287
288   /**
289    * Environment this transport service is using
290    * for this plugin.
291    */
292   struct GNUNET_TRANSPORT_PluginEnvironment env;
293
294   /**
295    * ID of task that is used to clean up expired addresses.
296    */
297   GNUNET_SCHEDULER_TaskIdentifier address_update_task;
298
299   /**
300    * Set to GNUNET_YES if we need to scrap the existing
301    * list of "addresses" and start fresh when we receive
302    * the next address update from a transport.  Set to
303    * GNUNET_NO if we should just add the new address
304    * to the list and wait for the commit call.
305    */
306   int rebuild;
307
308 };
309
310 struct NeighbourList;
311
312 /**
313  * For each neighbour we keep a list of messages
314  * that we still want to transmit to the neighbour.
315  */
316 struct MessageQueue
317 {
318
319   /**
320    * This is a doubly linked list.
321    */
322   struct MessageQueue *next;
323
324   /**
325    * This is a doubly linked list.
326    */
327   struct MessageQueue *prev;
328
329   /**
330    * The message(s) we want to transmit, GNUNET_MessageHeader(s)
331    * stuck together in memory.  Allocated at the end of this struct.
332    */
333   const char *message_buf;
334
335   /**
336    * Size of the message buf
337    */
338   size_t message_buf_size;
339
340   /**
341    * Client responsible for queueing the message;
342    * used to check that a client has no two messages
343    * pending for the same target.  Can be NULL.
344    */
345   struct TransportClient *client;
346
347   /**
348    * Using which specific address should we send this message?
349    */
350   struct ForeignAddressList *specific_address;
351
352   /**
353    * Peer ID of the Neighbour this entry belongs to.
354    */
355   struct GNUNET_PeerIdentity neighbour_id;
356
357   /**
358    * Plugin that we used for the transmission.
359    * NULL until we scheduled a transmission.
360    */
361   struct TransportPlugin *plugin;
362
363   /**
364    * At what time should we fail?
365    */
366   struct GNUNET_TIME_Absolute timeout;
367
368   /**
369    * Internal message of the transport system that should not be
370    * included in the usual SEND-SEND_OK transmission confirmation
371    * traffic management scheme.  Typically, "internal_msg" will
372    * be set whenever "client" is NULL (but it is not strictly
373    * required).
374    */
375   int internal_msg;
376
377   /**
378    * How important is the message?
379    */
380   unsigned int priority;
381
382 };
383
384
385 /**
386  * For a given Neighbour, which plugins are available
387  * to talk to this peer and what are their costs?
388  */
389 struct ReadyList
390 {
391   /**
392    * This is a linked list.
393    */
394   struct ReadyList *next;
395
396   /**
397    * Which of our transport plugins does this entry
398    * represent?
399    */
400   struct TransportPlugin *plugin;
401
402   /**
403    * Transport addresses, latency, and readiness for
404    * this particular plugin.
405    */
406   struct ForeignAddressList *addresses;
407
408 };
409
410
411 /**
412  * Entry in linked list of all of our current neighbours.
413  */
414 struct NeighbourList
415 {
416
417   /**
418    * This is a linked list.
419    */
420   struct NeighbourList *next;
421
422   /**
423    * Which of our transports is connected to this peer
424    * and what is their status?
425    */
426   struct ReadyList *plugins;
427
428   /**
429    * Head of list of messages we would like to send to this peer;
430    * must contain at most one message per client.
431    */
432   struct MessageQueue *messages_head;
433
434   /**
435    * Tail of list of messages we would like to send to this peer; must
436    * contain at most one message per client.
437    */
438   struct MessageQueue *messages_tail;
439
440   /**
441    * Identity of this neighbour.
442    */
443   struct GNUNET_PeerIdentity id;
444
445   /**
446    * ID of task scheduled to run when this peer is about to
447    * time out (will free resources associated with the peer).
448    */
449   GNUNET_SCHEDULER_TaskIdentifier timeout_task;
450
451   /**
452    * ID of task scheduled to run when we should retry transmitting
453    * the head of the message queue.  Actually triggered when the
454    * transmission is timing out (we trigger instantly when we have
455    * a chance of success).
456    */
457   GNUNET_SCHEDULER_TaskIdentifier retry_task;
458
459   /**
460    * How long until we should consider this peer dead
461    * (if we don't receive another message in the
462    * meantime)?
463    */
464   struct GNUNET_TIME_Absolute peer_timeout;
465
466   /**
467    * Tracker for inbound bandwidth.
468    */
469   struct GNUNET_BANDWIDTH_Tracker in_tracker;
470
471   /**
472    * The latency we have seen for this particular address for
473    * this particular peer.  This latency may have been calculated
474    * over multiple transports.  This value reflects how long it took
475    * us to receive a response when SENDING via this particular
476    * transport/neighbour/address combination!
477    *
478    * FIXME: we need to periodically send PINGs to update this
479    * latency (at least more often than the current "huge" (11h?)
480    * update interval).
481    */
482   struct GNUNET_TIME_Relative latency;
483
484   /**
485    * How often has the other peer (recently) violated the
486    * inbound traffic limit?  Incremented by 10 per violation,
487    * decremented by 1 per non-violation (for each
488    * time interval).
489    */
490   unsigned int quota_violation_count;
491
492   /**
493    * DV distance to this peer (1 if no DV is used). 
494    */
495   uint32_t distance;
496
497   /**
498    * Have we seen an PONG from this neighbour in the past (and
499    * not had a disconnect since)?
500    */
501   int received_pong;
502
503 };
504
505 /**
506  * Message used to ask a peer to validate receipt (to check an address
507  * from a HELLO).  
508  */
509 struct TransportPingMessage
510 {
511
512   /**
513    * Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_PING
514    */
515   struct GNUNET_MessageHeader header;
516
517   /**
518    * Random challenge number (in network byte order).
519    */
520   uint32_t challenge GNUNET_PACKED;
521
522   /**
523    * Who is the intended recipient?
524    */
525   struct GNUNET_PeerIdentity target;
526
527 };
528
529
530 /**
531  * Message used to validate a HELLO.  The challenge is included in the
532  * confirmation to make matching of replies to requests possible.  The
533  * signature signs the original challenge number, our public key, the
534  * sender's address (so that the sender can check that the address we
535  * saw is plausible for him and possibly detect a MiM attack) and a
536  * timestamp (to limit replay).<p>
537  *
538  * This message is followed by the address of the
539  * client that we are observing (which is part of what
540  * is being signed).
541  */
542 struct TransportPongMessage
543 {
544
545   /**
546    * Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_PONG
547    */
548   struct GNUNET_MessageHeader header;
549
550   /**
551    * For padding, always zero.
552    */
553   uint32_t reserved GNUNET_PACKED;
554
555   /**
556    * Signature.
557    */
558   struct GNUNET_CRYPTO_RsaSignature signature;
559
560   /**
561    * What are we signing and why?
562    */
563   struct GNUNET_CRYPTO_RsaSignaturePurpose purpose;
564
565   /**
566    * Random challenge number (in network byte order).
567    */
568   uint32_t challenge GNUNET_PACKED;
569
570   /**
571    * Who signed this message?
572    */
573   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded signer;
574
575   /**
576    * Size of address appended to this message
577    */
578   size_t addrlen;
579
580 };
581
582
583 /**
584  * Linked list of messages to be transmitted to the client.  Each
585  * entry is followed by the actual message.
586  */
587 struct ClientMessageQueueEntry
588 {
589   /**
590    * This is a doubly-linked list.
591    */
592   struct ClientMessageQueueEntry *next;
593
594   /**
595    * This is a doubly-linked list.
596    */
597   struct ClientMessageQueueEntry *prev;
598 };
599
600
601 /**
602  * Client connected to the transport service.
603  */
604 struct TransportClient
605 {
606
607   /**
608    * This is a linked list.
609    */
610   struct TransportClient *next;
611
612   /**
613    * Handle to the client.
614    */
615   struct GNUNET_SERVER_Client *client;
616
617   /**
618    * Linked list of messages yet to be transmitted to
619    * the client.
620    */
621   struct ClientMessageQueueEntry *message_queue_head;
622
623   /**
624    * Tail of linked list of messages yet to be transmitted to the
625    * client.
626    */
627   struct ClientMessageQueueEntry *message_queue_tail;
628
629   /**
630    * Current transmit request handle.
631    */ 
632   struct GNUNET_CONNECTION_TransmitHandle *th;
633
634   /**
635    * Is a call to "transmit_send_continuation" pending?  If so, we
636    * must not free this struct (even if the corresponding client
637    * disconnects) and instead only remove it from the linked list and
638    * set the "client" field to NULL.
639    */
640   int tcs_pending;
641
642   /**
643    * Length of the list of messages pending for this client.
644    */
645   unsigned int message_count;
646
647 };
648
649
650 /**
651  * Entry in map of all HELLOs awaiting validation.
652  */
653 struct ValidationEntry
654 {
655
656   /**
657    * The address, actually a pointer to the end
658    * of this struct.  Do not free!
659    */
660   const void *addr;
661
662   /**
663    * Name of the transport.
664    */
665   char *transport_name;
666
667   /**
668    * The public key of the peer.
669    */
670   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded publicKey;
671
672   /**
673    * ID of task that will clean up this entry if we don't succeed
674    * with the validation first.
675    */
676   GNUNET_SCHEDULER_TaskIdentifier timeout_task;
677
678   /**
679    * At what time did we send this validation?
680    */
681   struct GNUNET_TIME_Absolute send_time;
682
683   /**
684    * Length of addr.
685    */
686   size_t addrlen;
687
688   /**
689    * Challenge number we used.
690    */
691   uint32_t challenge;
692
693 };
694
695
696 /**
697  * Context of currently active requests to peerinfo
698  * for validation of HELLOs.
699  */
700 struct CheckHelloValidatedContext
701 {
702
703   /**
704    * This is a doubly-linked list.
705    */
706   struct CheckHelloValidatedContext *next;
707
708   /**
709    * This is a doubly-linked list.
710    */
711   struct CheckHelloValidatedContext *prev;
712
713   /**
714    * Hello that we are validating.
715    */
716   const struct GNUNET_HELLO_Message *hello;
717
718   /**
719    * Context for peerinfo iteration.
720    * NULL after we are done processing peerinfo's information.
721    */
722   struct GNUNET_PEERINFO_IteratorContext *piter;
723   
724   /**
725    * Was a HELLO known for this peer to peerinfo?
726    */
727   int hello_known;
728
729 };
730
731 /**
732  * Struct for keeping information about addresses to validate
733  * so that we can re-use for sending around ping's and receiving
734  * pongs periodically to keep connections alive and also better
735  * estimate latency of connections.
736  *
737  */
738 struct PeriodicValidationContext
739 {
740
741   /**
742    * The address we are keeping alive
743    */
744   struct ForeignAddressList *foreign_address;
745
746   /**
747    * The name of the transport
748    */
749   char *transport;
750
751   /**
752    * Public Key of the peer to re-validate
753    */
754   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded publicKey;
755
756 };
757
758 /**
759  * Our HELLO message.
760  */
761 static struct GNUNET_HELLO_Message *our_hello;
762
763 /**
764  * "version" of "our_hello".  Used to see if a given neighbour has
765  * already been sent the latest version of our HELLO message.
766  */
767 static unsigned int our_hello_version;
768
769 /**
770  * Our public key.
771  */
772 static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded my_public_key;
773
774 /**
775  * Our identity.
776  */
777 static struct GNUNET_PeerIdentity my_identity;
778
779 /**
780  * Our private key.
781  */
782 static struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key;
783
784 /**
785  * Our scheduler.
786  */
787 struct GNUNET_SCHEDULER_Handle *sched;
788
789 /**
790  * Our configuration.
791  */
792 const struct GNUNET_CONFIGURATION_Handle *cfg;
793
794 /**
795  * Linked list of all clients to this service.
796  */
797 static struct TransportClient *clients;
798
799 /**
800  * All loaded plugins.
801  */
802 static struct TransportPlugin *plugins;
803
804 /**
805  * Our server.
806  */
807 static struct GNUNET_SERVER_Handle *server;
808
809 /**
810  * All known neighbours and their HELLOs.
811  */
812 static struct NeighbourList *neighbours;
813
814 /**
815  * Number of neighbours we'd like to have.
816  */
817 static uint32_t max_connect_per_transport;
818
819 /**
820  * Head of linked list.
821  */
822 static struct CheckHelloValidatedContext *chvc_head;
823
824 /**
825  * Tail of linked list.
826  */
827 static struct CheckHelloValidatedContext *chvc_tail;
828
829 /**
830  * Map of PeerIdentities to 'struct ValidationEntry*'s (addresses
831  * of the given peer that we are currently validating).
832  */
833 static struct GNUNET_CONTAINER_MultiHashMap *validation_map;
834
835 /**
836  * Handle for reporting statistics.
837  */
838 static struct GNUNET_STATISTICS_Handle *stats;
839
840
841 /**
842  * The peer specified by the given neighbour has timed-out or a plugin
843  * has disconnected.  We may either need to do nothing (other plugins
844  * still up), or trigger a full disconnect and clean up.  This
845  * function updates our state and do the necessary notifications.
846  * Also notifies our clients that the neighbour is now officially
847  * gone.
848  *
849  * @param n the neighbour list entry for the peer
850  * @param check should we just check if all plugins
851  *        disconnected or must we ask all plugins to
852  *        disconnect?
853  */
854 static void disconnect_neighbour (struct NeighbourList *n, int check);
855
856 /**
857  * Check the ready list for the given neighbour and if a plugin is
858  * ready for transmission (and if we have a message), do so!
859  *
860  * @param neighbour target peer for which to transmit
861  */
862 static void try_transmission_to_peer (struct NeighbourList *neighbour);
863
864
865 /**
866  * Find an entry in the neighbour list for a particular peer.
867  * if sender_address is not specified (NULL) then return the
868  * first matching entry.  If sender_address is specified, then
869  * make sure that the address and address_len also matches.
870  * 
871  * FIXME: This description does not fit the function.
872  *  
873  * @return NULL if not found.
874  */
875 static struct NeighbourList *
876 find_neighbour (const struct GNUNET_PeerIdentity *key)
877 {
878   struct NeighbourList *head = neighbours;
879
880   while ((head != NULL) &&
881         (0 != memcmp (key, &head->id, sizeof (struct GNUNET_PeerIdentity))))
882     head = head->next;
883   return head;
884 }
885
886
887 /**
888  * Find an entry in the transport list for a particular transport.
889  *
890  * @return NULL if not found.
891  */
892 static struct TransportPlugin *
893 find_transport (const char *short_name)
894 {
895   struct TransportPlugin *head = plugins;
896   while ((head != NULL) && (0 != strcmp (short_name, head->short_name)))
897     head = head->next;
898   return head;
899 }
900
901
902 /**
903  * Function called to notify a client about the socket being ready to
904  * queue more data.  "buf" will be NULL and "size" zero if the socket
905  * was closed for writing in the meantime.
906  *
907  * @param cls closure
908  * @param size number of bytes available in buf
909  * @param buf where the callee should write the message
910  * @return number of bytes written to buf
911  */
912 static size_t
913 transmit_to_client_callback (void *cls, size_t size, void *buf)
914 {
915   struct TransportClient *client = cls;
916   struct ClientMessageQueueEntry *q;
917   uint16_t msize;
918   size_t tsize;
919   const struct GNUNET_MessageHeader *msg;
920   char *cbuf;
921
922   client->th = NULL;
923   if (buf == NULL)
924     {
925       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
926                   "Transmission to client failed, closing connection.\n");
927       /* fatal error with client, free message queue! */
928       while (NULL != (q = client->message_queue_head))
929         {
930           GNUNET_STATISTICS_update (stats,
931                                     gettext_noop ("# bytes discarded (could not transmit to client)"),
932                                     ntohs (((const struct GNUNET_MessageHeader*)&q[1])->size),
933                                     GNUNET_NO);      
934           GNUNET_CONTAINER_DLL_remove (client->message_queue_head,
935                                        client->message_queue_tail,
936                                        q);
937           GNUNET_free (q);
938         }
939       client->message_count = 0;
940       return 0;
941     }
942   cbuf = buf;
943   tsize = 0;
944   while (NULL != (q = client->message_queue_head))
945     {
946       msg = (const struct GNUNET_MessageHeader *) &q[1];
947       msize = ntohs (msg->size);
948       if (msize + tsize > size)
949         break;
950 #if DEBUG_TRANSPORT
951       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
952                   "Transmitting message of type %u to client.\n",
953                   ntohs (msg->type));
954 #endif
955       GNUNET_CONTAINER_DLL_remove (client->message_queue_head,
956                                    client->message_queue_tail,
957                                    q);
958       memcpy (&cbuf[tsize], msg, msize);
959       tsize += msize;
960       GNUNET_free (q);
961       client->message_count--;
962     }
963   if (NULL != q)
964     {
965       GNUNET_assert (msize >= sizeof (struct GNUNET_MessageHeader));
966       client->th = GNUNET_SERVER_notify_transmit_ready (client->client,
967                                                         msize,
968                                                         GNUNET_TIME_UNIT_FOREVER_REL,
969                                                         &transmit_to_client_callback,
970                                                         client);
971       GNUNET_assert (client->th != NULL);
972     }
973   return tsize;
974 }
975
976
977 /**
978  * Send the specified message to the specified client.  Since multiple
979  * messages may be pending for the same client at a time, this code
980  * makes sure that no message is lost.
981  *
982  * @param client client to transmit the message to
983  * @param msg the message to send
984  * @param may_drop can this message be dropped if the
985  *        message queue for this client is getting far too large?
986  */
987 static void
988 transmit_to_client (struct TransportClient *client,
989                     const struct GNUNET_MessageHeader *msg, int may_drop)
990 {
991   struct ClientMessageQueueEntry *q;
992   uint16_t msize;
993
994   if ((client->message_count >= MAX_PENDING) && (GNUNET_YES == may_drop))
995     {
996       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
997                   _
998                   ("Dropping message, have %u messages pending (%u is the soft limit)\n"),
999                   client->message_count, MAX_PENDING);
1000       /* TODO: call to statistics... */
1001       return;
1002     }
1003   msize = ntohs (msg->size);
1004   GNUNET_assert (msize >= sizeof (struct GNUNET_MessageHeader));
1005   q = GNUNET_malloc (sizeof (struct ClientMessageQueueEntry) + msize);
1006   memcpy (&q[1], msg, msize);
1007   GNUNET_CONTAINER_DLL_insert_after (client->message_queue_head,
1008                                      client->message_queue_tail,
1009                                      client->message_queue_tail,
1010                                      q);                                     
1011   client->message_count++;
1012   if (client->th == NULL)
1013     {
1014       client->th = GNUNET_SERVER_notify_transmit_ready (client->client,
1015                                                         msize,
1016                                                         GNUNET_TIME_UNIT_FOREVER_REL,
1017                                                         &transmit_to_client_callback,
1018                                                         client);
1019       GNUNET_assert (client->th != NULL);
1020     }
1021 }
1022
1023
1024 /**
1025  * Transmit a 'SEND_OK' notification to the given client for the
1026  * given neighbour.
1027  *
1028  * @param client who to notify
1029  * @param n neighbour to notify about
1030  * @param result status code for the transmission request
1031  */
1032 static void
1033 transmit_send_ok (struct TransportClient *client,
1034                   struct NeighbourList *n,
1035                   int result)
1036 {
1037   struct SendOkMessage send_ok_msg;
1038
1039   send_ok_msg.header.size = htons (sizeof (send_ok_msg));
1040   send_ok_msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK);
1041   send_ok_msg.success = htonl (result);
1042   send_ok_msg.latency = GNUNET_TIME_relative_hton (n->latency);
1043   send_ok_msg.peer = n->id;
1044   transmit_to_client (client, &send_ok_msg.header, GNUNET_NO); 
1045 }
1046
1047
1048 /**
1049  * Function called by the GNUNET_TRANSPORT_TransmitFunction
1050  * upon "completion" of a send request.  This tells the API
1051  * that it is now legal to send another message to the given
1052  * peer.
1053  *
1054  * @param cls closure, identifies the entry on the
1055  *            message queue that was transmitted and the
1056  *            client responsible for queueing the message
1057  * @param target the peer receiving the message
1058  * @param result GNUNET_OK on success, if the transmission
1059  *           failed, we should not tell the client to transmit
1060  *           more messages
1061  */
1062 static void
1063 transmit_send_continuation (void *cls,
1064                             const struct GNUNET_PeerIdentity *target,
1065                             int result)
1066 {
1067   struct MessageQueue *mq = cls;
1068   struct NeighbourList *n;
1069   
1070   GNUNET_STATISTICS_update (stats,
1071                             gettext_noop ("# bytes pending with plugins"),
1072                             -mq->message_buf_size,
1073                             GNUNET_NO);
1074   if (result == GNUNET_OK)
1075     {
1076       GNUNET_STATISTICS_update (stats,
1077                                 gettext_noop ("# bytes successfully transmitted by plugins"),
1078                                 mq->message_buf_size,
1079                                 GNUNET_NO);      
1080     }
1081   else
1082     {
1083       GNUNET_STATISTICS_update (stats,
1084                                 gettext_noop ("# bytes with transmission failure by plugins"),
1085                                 mq->message_buf_size,
1086                                 GNUNET_NO);      
1087     }  
1088   n = find_neighbour(&mq->neighbour_id);
1089   GNUNET_assert (n != NULL);
1090   if (mq->specific_address != NULL)
1091     {
1092       if (result == GNUNET_OK)    
1093         {
1094           mq->specific_address->timeout =
1095             GNUNET_TIME_relative_to_absolute
1096             (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
1097           if (mq->specific_address->connected != GNUNET_YES)
1098             {
1099               GNUNET_STATISTICS_update (stats,
1100                                         gettext_noop ("# connected addresses"),
1101                                         1,
1102                                         GNUNET_NO);
1103               mq->specific_address->connected = GNUNET_YES;
1104             }
1105         }    
1106       else
1107         {
1108           if (mq->specific_address->connected != GNUNET_NO)
1109             {
1110               GNUNET_STATISTICS_update (stats,
1111                                         gettext_noop ("# connected addresses"),
1112                                         -1,
1113                                         GNUNET_NO);
1114               mq->specific_address->connected = GNUNET_NO;
1115             }
1116         }    
1117       if (! mq->internal_msg) 
1118         mq->specific_address->in_transmit = GNUNET_NO;
1119     }
1120   if (mq->client != NULL)
1121     transmit_send_ok (mq->client, n, result);
1122   GNUNET_free (mq);
1123   try_transmission_to_peer (n);
1124 }
1125
1126
1127 /**
1128  * Find an address in any of the available transports for
1129  * the given neighbour that would be good for message
1130  * transmission.  This is essentially the transport selection
1131  * routine.
1132  *
1133  * @param neighbour for whom to select an address
1134  * @return selected address, NULL if we have none
1135  */
1136 struct ForeignAddressList *
1137 find_ready_address(struct NeighbourList *neighbour)
1138 {
1139   struct ReadyList *head = neighbour->plugins;
1140   struct ForeignAddressList *addresses;
1141   struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
1142   struct ForeignAddressList *best_address;
1143
1144   best_address = NULL;
1145   while (head != NULL)
1146     {
1147       addresses = head->addresses;
1148       while (addresses != NULL)
1149         {
1150           if ( (addresses->timeout.value < now.value) && 
1151                (addresses->connected == GNUNET_YES) )
1152             {
1153 #if DEBUG_TRANSPORT
1154               GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1155                           "Marking long-time inactive connection to `%4s' as down.\n",
1156                           GNUNET_i2s (&neighbour->id));
1157 #endif
1158               GNUNET_STATISTICS_update (stats,
1159                                         gettext_noop ("# connected addresses"),
1160                                         -1,
1161                                         GNUNET_NO);
1162               addresses->connected = GNUNET_NO;
1163             }
1164           addresses = addresses->next;
1165         }
1166
1167       addresses = head->addresses;
1168       while (addresses != NULL)
1169         {
1170           if ( ( (best_address == NULL) || 
1171                  (addresses->connected == GNUNET_YES) ||
1172                  (best_address->connected == GNUNET_NO) ) &&
1173                (addresses->in_transmit == GNUNET_NO) &&
1174                ( (best_address == NULL) || 
1175                  (addresses->latency.value < best_address->latency.value)) )
1176             best_address = addresses;            
1177           /* FIXME: also give lower-latency addresses that are not
1178              connected a chance some times... */
1179           addresses = addresses->next;
1180         }
1181       head = head->next;
1182     }
1183   if (best_address != NULL)
1184     {
1185 #if DEBUG_TRANSPORT
1186       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1187                   "Best address found has latency of %llu ms.\n",
1188                   best_address->latency.value);
1189 #endif
1190     }
1191   else
1192     {
1193       GNUNET_STATISTICS_update (stats,
1194                                 gettext_noop ("# transmission attempts failed (no address)"),
1195                                 1,
1196                                 GNUNET_NO);
1197     }
1198   return best_address;
1199
1200 }
1201
1202
1203 /**
1204  * We should re-try transmitting to the given peer,
1205  * hopefully we've learned something in the meantime.
1206  */
1207 static void
1208 retry_transmission_task (void *cls,
1209                          const struct GNUNET_SCHEDULER_TaskContext *tc)
1210 {
1211   struct NeighbourList *n = cls;
1212
1213   n->retry_task = GNUNET_SCHEDULER_NO_TASK;
1214   try_transmission_to_peer (n);
1215 }
1216
1217
1218 /**
1219  * Check the ready list for the given neighbour and if a plugin is
1220  * ready for transmission (and if we have a message), do so!
1221  *
1222  * @param neighbour target peer for which to transmit
1223  */
1224 static void
1225 try_transmission_to_peer (struct NeighbourList *neighbour)
1226 {
1227   struct ReadyList *rl;
1228   struct MessageQueue *mq;
1229   struct GNUNET_TIME_Relative timeout;
1230
1231   if (neighbour->messages_head == NULL)
1232     return;                     /* nothing to do */
1233   rl = NULL;
1234   mq = neighbour->messages_head;
1235   /* FIXME: support bi-directional use of TCP */
1236   if (mq->specific_address == NULL)
1237     mq->specific_address = find_ready_address(neighbour); 
1238   if (mq->specific_address == NULL)
1239     {
1240       timeout = GNUNET_TIME_absolute_get_remaining (mq->timeout);
1241       if (timeout.value == 0)
1242         {
1243 #if DEBUG_TRANSPORT
1244           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1245                       "No destination address available to transmit message of size %u to peer `%4s'\n",
1246                       mq->message_buf_size,
1247                       GNUNET_i2s (&mq->neighbour_id));
1248 #endif
1249           GNUNET_STATISTICS_update (stats,
1250                                     gettext_noop ("# bytes in message queue for other peers"),
1251                                     -mq->message_buf_size,
1252                                     GNUNET_NO);
1253           GNUNET_STATISTICS_update (stats,
1254                                     gettext_noop ("# bytes discarded (no destination address available)"),
1255                                     mq->message_buf_size,
1256                                     GNUNET_NO);      
1257           if (mq->client != NULL)
1258             transmit_send_ok (mq->client, neighbour, GNUNET_NO);
1259           GNUNET_CONTAINER_DLL_remove (neighbour->messages_head,
1260                                        neighbour->messages_tail,
1261                                        mq);
1262           GNUNET_free (mq);
1263           return;               /* nobody ready */ 
1264         }
1265       GNUNET_STATISTICS_update (stats,
1266                                 gettext_noop ("# message delivery deferred (no address)"),
1267                                 1,
1268                                 GNUNET_NO);
1269       if (neighbour->retry_task != GNUNET_SCHEDULER_NO_TASK)
1270         GNUNET_SCHEDULER_cancel (sched,
1271                                  neighbour->retry_task);
1272       neighbour->retry_task = GNUNET_SCHEDULER_add_delayed (sched,
1273                                                             timeout,
1274                                                             &retry_transmission_task,
1275                                                             neighbour);
1276 #if DEBUG_TRANSPORT
1277       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1278                   "No validated destination address available to transmit message of size %u to peer `%4s', will wait %llums to find an address.\n",
1279                   mq->message_buf_size,
1280                   GNUNET_i2s (&mq->neighbour_id),
1281                   timeout.value);
1282 #endif
1283       /* FIXME: might want to trigger peerinfo lookup here
1284          (unless that's already pending...) */
1285       return;    
1286     }
1287   GNUNET_CONTAINER_DLL_remove (neighbour->messages_head,
1288                                neighbour->messages_tail,
1289                                mq);
1290   if (mq->specific_address->connected == GNUNET_NO)
1291     mq->specific_address->connect_attempts++;
1292   rl = mq->specific_address->ready_list;
1293   mq->plugin = rl->plugin;
1294   if (!mq->internal_msg)
1295     mq->specific_address->in_transmit = GNUNET_YES;
1296 #if DEBUG_TRANSPORT
1297   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1298               "Sending message of size %u for `%4s' to `%s' via plugin `%s'\n",
1299               mq->message_buf_size,
1300               GNUNET_i2s (&neighbour->id), 
1301               GNUNET_a2s (mq->specific_address->addr,
1302                           mq->specific_address->addrlen),
1303               rl->plugin->short_name);
1304 #endif
1305   GNUNET_STATISTICS_update (stats,
1306                             gettext_noop ("# bytes in message queue for other peers"),
1307                             -mq->message_buf_size,
1308                             GNUNET_NO);
1309   GNUNET_STATISTICS_update (stats,
1310                             gettext_noop ("# bytes pending with plugins"),
1311                             mq->message_buf_size,
1312                             GNUNET_NO);
1313   rl->plugin->api->send (rl->plugin->api->cls,
1314                          &mq->neighbour_id,
1315                          mq->message_buf,
1316                          mq->message_buf_size,
1317                          mq->priority,
1318                          GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
1319                          mq->specific_address->addr,
1320                          mq->specific_address->addrlen,
1321                          GNUNET_YES /* FIXME: sometimes, we want to be more tolerant here! */,
1322                          &transmit_send_continuation, mq);
1323 }
1324
1325
1326 /**
1327  * Send the specified message to the specified peer.
1328  *
1329  * @param client source of the transmission request (can be NULL)
1330  * @param peer_address ForeignAddressList where we should send this message
1331  * @param priority how important is the message
1332  * @param timeout how long do we have to transmit?
1333  * @param message_buf message(s) to send GNUNET_MessageHeader(s)
1334  * @param message_buf_size total size of all messages in message_buf
1335  * @param is_internal is this an internal message; these are pre-pended and
1336  *                    also do not count for plugins being "ready" to transmit
1337  * @param neighbour handle to the neighbour for transmission
1338  */
1339 static void
1340 transmit_to_peer (struct TransportClient *client,
1341                   struct ForeignAddressList *peer_address,
1342                   unsigned int priority,
1343                   struct GNUNET_TIME_Relative timeout,
1344                   const char *message_buf,
1345                   size_t message_buf_size,
1346                   int is_internal, struct NeighbourList *neighbour)
1347 {
1348   struct MessageQueue *mq;
1349
1350 #if EXTRA_CHECKS
1351   if (client != NULL)
1352     {
1353       /* check for duplicate submission */
1354       mq = neighbour->messages_head;
1355       while (NULL != mq)
1356         {
1357           if (mq->client == client)
1358             {
1359               /* client transmitted to same peer twice
1360                  before getting SEND_OK! */
1361               GNUNET_break (0);
1362               return;
1363             }
1364           mq = mq->next;
1365         }
1366     }
1367 #endif
1368   GNUNET_STATISTICS_update (stats,
1369                             gettext_noop ("# bytes in message queue for other peers"),
1370                             message_buf_size,
1371                             GNUNET_NO);
1372   mq = GNUNET_malloc (sizeof (struct MessageQueue) + message_buf_size);
1373   mq->specific_address = peer_address;
1374   mq->client = client;
1375   memcpy (&mq[1], message_buf, message_buf_size);
1376   mq->message_buf = (const char*) &mq[1];
1377   mq->message_buf_size = message_buf_size;
1378   memcpy(&mq->neighbour_id, &neighbour->id, sizeof(struct GNUNET_PeerIdentity));
1379   mq->internal_msg = is_internal;
1380   mq->priority = priority;
1381   mq->timeout = GNUNET_TIME_relative_to_absolute (timeout);
1382   if (is_internal)    
1383     GNUNET_CONTAINER_DLL_insert (neighbour->messages_head,
1384                                  neighbour->messages_tail,
1385                                  mq);
1386   else
1387     GNUNET_CONTAINER_DLL_insert_after (neighbour->messages_head,
1388                                        neighbour->messages_tail,
1389                                        neighbour->messages_tail,
1390                                        mq);
1391   try_transmission_to_peer (neighbour);
1392 }
1393
1394
1395 /**
1396  * FIXME: document.
1397  */
1398 struct GeneratorContext
1399 {
1400   struct TransportPlugin *plug_pos;
1401   struct OwnAddressList *addr_pos;
1402   struct GNUNET_TIME_Absolute expiration;
1403 };
1404
1405
1406 /**
1407  * FIXME: document.
1408  */
1409 static size_t
1410 address_generator (void *cls, size_t max, void *buf)
1411 {
1412   struct GeneratorContext *gc = cls;
1413   size_t ret;
1414
1415   while ((gc->addr_pos == NULL) && (gc->plug_pos != NULL))
1416     {
1417       gc->plug_pos = gc->plug_pos->next;
1418       gc->addr_pos = (gc->plug_pos != NULL) ? gc->plug_pos->addresses : NULL;
1419     }
1420   if (NULL == gc->plug_pos)
1421     {
1422
1423       return 0;
1424     }
1425   ret = GNUNET_HELLO_add_address (gc->plug_pos->short_name,
1426                                   gc->expiration,
1427                                   gc->addr_pos->addr,
1428                                   gc->addr_pos->addrlen, buf, max);
1429   gc->addr_pos = gc->addr_pos->next;
1430   return ret;
1431 }
1432
1433
1434 /**
1435  * Construct our HELLO message from all of the addresses of
1436  * all of the transports.
1437  */
1438 static void
1439 refresh_hello ()
1440 {
1441   struct GNUNET_HELLO_Message *hello;
1442   struct TransportClient *cpos;
1443   struct NeighbourList *npos;
1444   struct GeneratorContext gc;
1445
1446   gc.plug_pos = plugins;
1447   gc.addr_pos = plugins != NULL ? plugins->addresses : NULL;
1448   gc.expiration = GNUNET_TIME_relative_to_absolute (HELLO_ADDRESS_EXPIRATION);
1449   hello = GNUNET_HELLO_create (&my_public_key, &address_generator, &gc);
1450 #if DEBUG_TRANSPORT
1451   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
1452               "Refreshed my `%s', new size is %d\n", "HELLO", GNUNET_HELLO_size(hello));
1453 #endif
1454   GNUNET_STATISTICS_update (stats,
1455                             gettext_noop ("# refreshed my HELLO"),
1456                             1,
1457                             GNUNET_NO);
1458   cpos = clients;
1459   while (cpos != NULL)
1460     {
1461       transmit_to_client (cpos,
1462                           (const struct GNUNET_MessageHeader *) hello,
1463                           GNUNET_NO);
1464       cpos = cpos->next;
1465     }
1466
1467   GNUNET_free_non_null (our_hello);
1468   our_hello = hello;
1469   our_hello_version++;
1470   GNUNET_PEERINFO_add_peer (cfg, sched, &my_identity, our_hello);
1471   npos = neighbours;
1472   while (npos != NULL)
1473     {
1474 #if DEBUG_TRANSPORT
1475       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
1476                   "Transmitting updated `%s' to neighbour `%4s'\n",
1477                   "HELLO", GNUNET_i2s (&npos->id));
1478 #endif
1479       GNUNET_STATISTICS_update (stats,
1480                                 gettext_noop ("# transmitted my HELLO to other peers"),
1481                                 1,
1482                                 GNUNET_NO);
1483       transmit_to_peer (NULL, NULL, 0,
1484                         HELLO_ADDRESS_EXPIRATION,
1485                         (const char *) our_hello, 
1486                         GNUNET_HELLO_size(our_hello),
1487                         GNUNET_NO, npos);
1488       npos = npos->next;
1489     }
1490 }
1491
1492
1493 /**
1494  * Task used to clean up expired addresses for a plugin.
1495  *
1496  * @param cls closure
1497  * @param tc context
1498  */
1499 static void
1500 expire_address_task (void *cls,
1501                      const struct GNUNET_SCHEDULER_TaskContext *tc);
1502
1503
1504 /**
1505  * Update the list of addresses for this plugin,
1506  * expiring those that are past their expiration date.
1507  *
1508  * @param plugin addresses of which plugin should be recomputed?
1509  * @param fresh set to GNUNET_YES if a new address was added
1510  *        and we need to regenerate the HELLO even if nobody
1511  *        expired
1512  */
1513 static void
1514 update_addresses (struct TransportPlugin *plugin, int fresh)
1515 {
1516   struct GNUNET_TIME_Relative min_remaining;
1517   struct GNUNET_TIME_Relative remaining;
1518   struct GNUNET_TIME_Absolute now;
1519   struct OwnAddressList *pos;
1520   struct OwnAddressList *prev;
1521   struct OwnAddressList *next;
1522   int expired;
1523
1524   if (plugin->address_update_task != GNUNET_SCHEDULER_NO_TASK)
1525     GNUNET_SCHEDULER_cancel (plugin->env.sched, plugin->address_update_task);
1526   plugin->address_update_task = GNUNET_SCHEDULER_NO_TASK;
1527   now = GNUNET_TIME_absolute_get ();
1528   min_remaining = GNUNET_TIME_UNIT_FOREVER_REL;
1529   expired = GNUNET_NO;
1530   prev = NULL;
1531   pos = plugin->addresses;
1532   while (pos != NULL)
1533     {
1534       next = pos->next;
1535       if (pos->expires.value < now.value)
1536         {
1537           expired = GNUNET_YES;
1538           if (prev == NULL)
1539             plugin->addresses = pos->next;
1540           else
1541             prev->next = pos->next;
1542           GNUNET_free (pos);
1543         }
1544       else
1545         {
1546           remaining = GNUNET_TIME_absolute_get_remaining (pos->expires);
1547           if (remaining.value < min_remaining.value)
1548             min_remaining = remaining;
1549           prev = pos;
1550         }
1551       pos = next;
1552     }
1553
1554   if (expired || fresh)
1555     refresh_hello ();
1556   if (min_remaining.value < GNUNET_TIME_UNIT_FOREVER_REL.value)
1557     plugin->address_update_task
1558       = GNUNET_SCHEDULER_add_delayed (plugin->env.sched,
1559                                       min_remaining,
1560                                       &expire_address_task, plugin);
1561
1562 }
1563
1564
1565 /**
1566  * Task used to clean up expired addresses for a plugin.
1567  *
1568  * @param cls closure
1569  * @param tc context
1570  */
1571 static void
1572 expire_address_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1573 {
1574   struct TransportPlugin *plugin = cls;
1575   plugin->address_update_task = GNUNET_SCHEDULER_NO_TASK;
1576   update_addresses (plugin, GNUNET_NO);
1577 }
1578
1579
1580 /**
1581  * Function that must be called by each plugin to notify the
1582  * transport service about the addresses under which the transport
1583  * provided by the plugin can be reached.
1584  *
1585  * @param cls closure
1586  * @param name name of the transport that generated the address
1587  * @param addr one of the addresses of the host, NULL for the last address
1588  *        the specific address format depends on the transport
1589  * @param addrlen length of the address
1590  * @param expires when should this address automatically expire?
1591  */
1592 static void
1593 plugin_env_notify_address (void *cls,
1594                            const char *name,
1595                            const void *addr,
1596                            size_t addrlen,
1597                            struct GNUNET_TIME_Relative expires)
1598 {
1599   struct TransportPlugin *p = cls;
1600   struct OwnAddressList *al;
1601   struct GNUNET_TIME_Absolute abex;
1602
1603   abex = GNUNET_TIME_relative_to_absolute (expires);
1604   GNUNET_assert (p == find_transport (name));
1605
1606   al = p->addresses;
1607   while (al != NULL)
1608     {
1609       if ((addrlen == al->addrlen) && (0 == memcmp (addr, &al[1], addrlen)))
1610         {
1611           if (al->expires.value < abex.value)
1612             al->expires = abex;
1613           return;
1614         }
1615       al = al->next;
1616     }
1617
1618   al = GNUNET_malloc (sizeof (struct OwnAddressList) + addrlen);
1619   al->addr = &al[1];
1620   al->next = p->addresses;
1621   p->addresses = al;
1622   al->expires = abex;
1623   al->addrlen = addrlen;
1624   memcpy (&al[1], addr, addrlen);
1625   update_addresses (p, GNUNET_YES);
1626 }
1627
1628
1629 /**
1630  * Notify all of our clients about a peer connecting.
1631  */
1632 static void
1633 notify_clients_connect (const struct GNUNET_PeerIdentity *peer,
1634                         struct GNUNET_TIME_Relative latency,
1635                         uint32_t distance)
1636 {
1637   struct ConnectInfoMessage cim;
1638   struct TransportClient *cpos;
1639
1640 #if DEBUG_TRANSPORT
1641   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1642               "Notifying clients about connection from `%s'\n",
1643               GNUNET_i2s (peer));
1644 #endif
1645   GNUNET_STATISTICS_update (stats,
1646                             gettext_noop ("# peers connected"),
1647                             1,
1648                             GNUNET_NO);
1649   cim.header.size = htons (sizeof (struct ConnectInfoMessage));
1650   cim.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
1651   cim.distance = htonl (distance);
1652   cim.latency = GNUNET_TIME_relative_hton (latency);
1653   memcpy (&cim.id, peer, sizeof (struct GNUNET_PeerIdentity));
1654   cpos = clients;
1655   while (cpos != NULL)
1656     {
1657       transmit_to_client (cpos, &cim.header, GNUNET_NO);
1658       cpos = cpos->next;
1659     }
1660 }
1661
1662
1663 /**
1664  * Notify all of our clients about a peer disconnecting.
1665  */
1666 static void
1667 notify_clients_disconnect (const struct GNUNET_PeerIdentity *peer)
1668 {
1669   struct DisconnectInfoMessage dim;
1670   struct TransportClient *cpos;
1671
1672 #if DEBUG_TRANSPORT
1673   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1674               "Notifying clients about lost connection to `%s'\n",
1675               GNUNET_i2s (peer));
1676 #endif
1677   GNUNET_STATISTICS_update (stats,
1678                             gettext_noop ("# peers connected"),
1679                             -1,
1680                             GNUNET_NO);
1681   dim.header.size = htons (sizeof (struct DisconnectInfoMessage));
1682   dim.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT);
1683   dim.reserved = htonl (0);
1684   memcpy (&dim.peer, peer, sizeof (struct GNUNET_PeerIdentity));
1685   cpos = clients;
1686   while (cpos != NULL)
1687     {
1688       transmit_to_client (cpos, &dim.header, GNUNET_NO);
1689       cpos = cpos->next;
1690     }
1691 }
1692
1693
1694 /**
1695  * Find a ForeignAddressList entry for the given neighbour
1696  * that matches the given address and transport.
1697  *
1698  * @param neighbour which peer we care about
1699  * @param tname name of the transport plugin
1700  * @param addr binary address
1701  * @param addrlen length of addr
1702  * @return NULL if no such entry exists
1703  */
1704 static struct ForeignAddressList *
1705 find_peer_address(struct NeighbourList *neighbour,
1706                   const char *tname,
1707                   const char *addr,
1708                   size_t addrlen)
1709 {
1710   struct ReadyList *head;
1711   struct ForeignAddressList *address_head;
1712
1713   head = neighbour->plugins;
1714   while (head != NULL)
1715     {
1716       if (0 == strcmp (tname, head->plugin->short_name))
1717         break;
1718       head = head->next;
1719     }
1720   if (head == NULL)
1721     return NULL;
1722
1723   address_head = head->addresses;
1724   while ( (address_head != NULL) &&
1725           ( (address_head->addrlen != addrlen) ||
1726             (memcmp(address_head->addr, addr, addrlen) != 0) ) )
1727     address_head = address_head->next;
1728   return address_head;
1729 }
1730
1731
1732 /**
1733  * Get the peer address struct for the given neighbour and
1734  * address.  If it doesn't yet exist, create it.
1735  *
1736  * @param neighbour which peer we care about
1737  * @param tname name of the transport plugin
1738  * @param addr binary address
1739  * @param addrlen length of addr
1740  * @return NULL if we do not have a transport plugin for 'tname'
1741  */
1742 static struct ForeignAddressList *
1743 add_peer_address(struct NeighbourList *neighbour,
1744                  const char *tname,
1745                  const char *addr, 
1746                  size_t addrlen)
1747 {
1748   struct ReadyList *head;
1749   struct ForeignAddressList *ret;
1750
1751   ret = find_peer_address (neighbour, tname, addr, addrlen);
1752   if (ret != NULL)
1753     return ret;
1754   head = neighbour->plugins;
1755   while (head != NULL)
1756     {
1757       if (0 == strcmp (tname, head->plugin->short_name))
1758         break;
1759       head = head->next;
1760     }
1761   if (head == NULL)
1762     return NULL;
1763   ret = GNUNET_malloc(sizeof(struct ForeignAddressList) + addrlen);
1764   ret->addr = (const char*) &ret[1];
1765   memcpy (&ret[1], addr, addrlen);
1766   ret->addrlen = addrlen;
1767   ret->expires = GNUNET_TIME_relative_to_absolute
1768     (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
1769   ret->latency = GNUNET_TIME_relative_get_forever();
1770   ret->distance = -1;
1771   ret->timeout = GNUNET_TIME_relative_to_absolute
1772     (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT); 
1773   ret->ready_list = head;
1774   ret->next = head->addresses;
1775   head->addresses = ret;
1776   return ret;
1777 }
1778
1779
1780 /**
1781  * Closure for 'add_validated_address'.
1782  */
1783 struct AddValidatedAddressContext
1784 {
1785   /**
1786    * Entry that has been validated.
1787    */
1788   const struct ValidationEntry *ve;
1789
1790   /**
1791    * Flag set after we have added the address so
1792    * that we terminate the iteration next time.
1793    */
1794   int done;
1795 };
1796
1797
1798 /**
1799  * Callback function used to fill a buffer of max bytes with a list of
1800  * addresses in the format used by HELLOs.  Should use
1801  * "GNUNET_HELLO_add_address" as a helper function.
1802  *
1803  * @param cls the 'struct AddValidatedAddressContext' with the validated address
1804  * @param max maximum number of bytes that can be written to buf
1805  * @param buf where to write the address information
1806  * @return number of bytes written, 0 to signal the
1807  *         end of the iteration.
1808  */
1809 static size_t
1810 add_validated_address (void *cls,
1811                        size_t max, void *buf)
1812 {
1813   struct AddValidatedAddressContext *avac = cls;
1814   const struct ValidationEntry *ve = avac->ve;
1815
1816   if (GNUNET_YES == avac->done)
1817     return 0;
1818   avac->done = GNUNET_YES;
1819   return GNUNET_HELLO_add_address (ve->transport_name,
1820                                    GNUNET_TIME_relative_to_absolute (HELLO_ADDRESS_EXPIRATION),
1821                                    ve->addr,
1822                                    ve->addrlen,
1823                                    buf,
1824                                    max);
1825 }
1826
1827
1828
1829 /**
1830  * Closure for 'check_address_exists'.
1831  */
1832 struct CheckAddressExistsClosure
1833 {
1834   /**
1835    * Address to check for.
1836    */
1837   const void *addr;
1838
1839   /**
1840    * Name of the transport.
1841    */
1842   const char *tname;
1843
1844   /**
1845    * Length of addr.
1846    */
1847   size_t addrlen;
1848
1849   /**
1850    * Set to GNUNET_YES if the address exists.
1851    */
1852   int exists;
1853 };
1854
1855
1856 /**
1857  * Iterator over hash map entries.  Checks if the given
1858  * validation entry is for the same address as what is given
1859  * in the closure.
1860  *
1861  * @param cls the 'struct CheckAddressExistsClosure*'
1862  * @param key current key code (ignored)
1863  * @param value value in the hash map ('struct ValidationEntry')
1864  * @return GNUNET_YES if we should continue to
1865  *         iterate (mismatch), GNUNET_NO if not (entry matched)
1866  */
1867 static int
1868 check_address_exists (void *cls,
1869                       const GNUNET_HashCode * key,
1870                       void *value)
1871 {
1872   struct CheckAddressExistsClosure *caec = cls;
1873   struct ValidationEntry *ve = value;
1874   if ( (0 == strcmp (caec->tname,
1875                      ve->transport_name)) &&
1876        (caec->addrlen == ve->addrlen) &&
1877        (0 == memcmp (caec->addr,
1878                      ve->addr,
1879                      caec->addrlen)) )
1880     {
1881       caec->exists = GNUNET_YES;
1882       return GNUNET_NO;
1883     }
1884   return GNUNET_YES;
1885 }
1886
1887
1888 /**
1889  * HELLO validation cleanup task (validation failed).
1890  *
1891  * @param cls the 'struct ValidationEntry' that failed
1892  * @param tc scheduler context (unused)
1893  */
1894 static void
1895 timeout_hello_validation (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1896 {
1897   struct ValidationEntry *va = cls;
1898   struct GNUNET_PeerIdentity pid;
1899
1900   GNUNET_STATISTICS_update (stats,
1901                             gettext_noop ("# address validation timeouts"),
1902                             1,
1903                             GNUNET_NO);
1904   GNUNET_CRYPTO_hash (&va->publicKey,
1905                       sizeof (struct
1906                               GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1907                       &pid.hashPubKey);
1908   GNUNET_CONTAINER_multihashmap_remove (validation_map,
1909                                         &pid.hashPubKey,
1910                                         va);
1911   GNUNET_free (va->transport_name);
1912   GNUNET_free (va);
1913 }
1914
1915
1916 static void
1917 neighbour_timeout_task (void *cls,
1918                        const struct GNUNET_SCHEDULER_TaskContext *tc)
1919 {
1920   struct NeighbourList *n = cls;
1921
1922 #if DEBUG_TRANSPORT
1923   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
1924               "Neighbour `%4s' has timed out!\n", GNUNET_i2s (&n->id));
1925 #endif
1926   GNUNET_STATISTICS_update (stats,
1927                             gettext_noop ("# disconnects due to timeout"),
1928                             1,
1929                             GNUNET_NO);
1930   n->timeout_task = GNUNET_SCHEDULER_NO_TASK;
1931   disconnect_neighbour (n, GNUNET_NO);
1932 }
1933
1934
1935 /**
1936  * Create a fresh entry in our neighbour list for the given peer.
1937  * Will try to transmit our current HELLO to the new neighbour.
1938  *
1939  * @param peer the peer for which we create the entry
1940  * @return the new neighbour list entry
1941  */
1942 static struct NeighbourList *
1943 setup_new_neighbour (const struct GNUNET_PeerIdentity *peer)
1944 {
1945   struct NeighbourList *n;
1946   struct TransportPlugin *tp;
1947   struct ReadyList *rl;
1948
1949   GNUNET_assert (our_hello != NULL);
1950   GNUNET_STATISTICS_update (stats,
1951                             gettext_noop ("# active neighbours"),
1952                             1,
1953                             GNUNET_NO);
1954   n = GNUNET_malloc (sizeof (struct NeighbourList));
1955   n->next = neighbours;
1956   neighbours = n;
1957   n->id = *peer;
1958   n->peer_timeout =
1959     GNUNET_TIME_relative_to_absolute
1960     (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
1961   GNUNET_BANDWIDTH_tracker_init (&n->in_tracker,
1962                                  GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT,
1963                                  MAX_BANDWIDTH_CARRY_S);
1964   tp = plugins;
1965   while (tp != NULL)
1966     {
1967       if (tp->api->send != NULL)
1968         {
1969           rl = GNUNET_malloc (sizeof (struct ReadyList));
1970           rl->next = n->plugins;
1971           n->plugins = rl;
1972           rl->plugin = tp;
1973           rl->addresses = NULL;
1974         }
1975       tp = tp->next;
1976     }
1977   n->latency = GNUNET_TIME_UNIT_FOREVER_REL;
1978   n->distance = -1;
1979   n->timeout_task = GNUNET_SCHEDULER_add_delayed (sched,
1980                                                   GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
1981                                                   &neighbour_timeout_task, n);
1982   // FIXME: query PEERINFO for HELLO for this peer & 
1983   // add addresses!?
1984   transmit_to_peer (NULL, NULL, 0,
1985                     HELLO_ADDRESS_EXPIRATION,
1986                     (const char *) our_hello, GNUNET_HELLO_size(our_hello),
1987                     GNUNET_NO, n);
1988   return n;
1989 }
1990
1991
1992 /**
1993  * Send periodic PING messages to a give foreign address.
1994  *
1995  * @param cls our 'struct PeriodicValidationContext*'
1996  * @param tc task context
1997  */
1998 static void 
1999 send_periodic_ping (void *cls, 
2000                     const struct GNUNET_SCHEDULER_TaskContext *tc)
2001 {
2002   struct PeriodicValidationContext *pvc = cls;
2003   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded publicKey = pvc->publicKey;
2004   char *tname = pvc->transport;
2005   const void *addr = pvc->foreign_address->addr;
2006   size_t addrlen = pvc->foreign_address->addrlen;
2007   struct GNUNET_PeerIdentity id;
2008   struct TransportPlugin *tp;
2009   struct ValidationEntry *va;
2010   struct NeighbourList *neighbour;
2011   struct ForeignAddressList *peer_address;
2012   struct TransportPingMessage ping;
2013   struct CheckAddressExistsClosure caec;
2014   char * message_buf;
2015   uint16_t hello_size;
2016   size_t tsize;
2017
2018   GNUNET_free (pvc);
2019   if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
2020     {
2021       /* We have been shutdown, don't do anything! */
2022       GNUNET_free (tname);
2023       return; 
2024     }
2025   tp = find_transport (tname);
2026   if (tp == NULL)
2027     {
2028       GNUNET_log (GNUNET_ERROR_TYPE_INFO |
2029                   GNUNET_ERROR_TYPE_BULK,
2030                   _
2031                   ("Transport `%s' not loaded, will not try to validate peer address using this transport.\n"),
2032                   tname);
2033       GNUNET_free (tname);
2034       return;
2035     }
2036
2037   GNUNET_CRYPTO_hash (&publicKey,
2038                       sizeof (struct
2039                               GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
2040                       &id.hashPubKey);
2041   caec.addr = addr;
2042   caec.addrlen = addrlen;
2043   caec.tname = tname;
2044   caec.exists = GNUNET_NO;
2045   GNUNET_CONTAINER_multihashmap_iterate (validation_map,
2046                                          &check_address_exists,
2047                                          &caec);
2048   if (caec.exists == GNUNET_YES)
2049     {
2050       /* During validation attempts we will likely trigger the other
2051          peer trying to validate our address which in turn will cause
2052          it to send us its HELLO, so we expect to hit this case rather
2053          frequently.  Only print something if we are very verbose. */
2054 #if DEBUG_TRANSPORT > 1
2055       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2056                   "Some validation of address `%s' via `%s' for peer `%4s' already in progress.\n",
2057                   GNUNET_a2s (addr, addrlen),
2058                   tname,
2059                   GNUNET_i2s (&id));
2060 #endif
2061       GNUNET_free (tname);
2062       return;
2063     }
2064   va = GNUNET_malloc (sizeof (struct ValidationEntry) + addrlen);
2065   va->transport_name = tname;
2066   va->challenge = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2067                                             (unsigned int) -1);
2068   va->send_time = GNUNET_TIME_absolute_get();
2069   va->addr = (const void*) &va[1];
2070   memcpy (&va[1], addr, addrlen);
2071   va->addrlen = addrlen;
2072   memcpy(&va->publicKey, &publicKey, sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
2073   va->timeout_task = GNUNET_SCHEDULER_add_delayed (sched,
2074                                                    HELLO_VERIFICATION_TIMEOUT,
2075                                                    &timeout_hello_validation,
2076                                                    va);
2077   GNUNET_CONTAINER_multihashmap_put (validation_map,
2078                                      &id.hashPubKey,
2079                                      va,
2080                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
2081   neighbour = find_neighbour(&id);
2082   /* FIXME: can neighbour be NULL here? (why do we still PING?)?  If so,
2083      should we even do this? */
2084   if (neighbour == NULL)
2085     neighbour = setup_new_neighbour(&id);
2086   peer_address = add_peer_address(neighbour, tname, addr, addrlen);
2087   GNUNET_assert(peer_address != NULL);
2088   hello_size = GNUNET_HELLO_size(our_hello);
2089   tsize = sizeof(struct TransportPingMessage) + hello_size;
2090   message_buf = GNUNET_malloc(tsize);
2091   ping.challenge = htonl(va->challenge);
2092   ping.header.size = htons(sizeof(struct TransportPingMessage));
2093   ping.header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_PING);
2094   memcpy(&ping.target, &id, sizeof(struct GNUNET_PeerIdentity));
2095   memcpy(message_buf, our_hello, hello_size);
2096   memcpy(&message_buf[hello_size],
2097          &ping,
2098          sizeof(struct TransportPingMessage));
2099 #if DEBUG_TRANSPORT_REVALIDATION
2100   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2101               "Performing re-validation of address `%s' via `%s' for peer `%4s' sending `%s' (%u bytes) and `%s' (%u bytes)\n",
2102               GNUNET_a2s (addr, addrlen),
2103               tname,
2104               GNUNET_i2s (&id),
2105               "HELLO", hello_size,
2106               "PING", sizeof (struct TransportPingMessage));
2107 #endif
2108   GNUNET_STATISTICS_update (stats,
2109                             gettext_noop ("# PING messages sent for re-validation"),
2110                             1,
2111                             GNUNET_NO);
2112   transmit_to_peer (NULL, peer_address,
2113                     GNUNET_SCHEDULER_PRIORITY_DEFAULT,
2114                     HELLO_VERIFICATION_TIMEOUT,
2115                     message_buf, tsize,
2116                     GNUNET_YES, neighbour);
2117   GNUNET_free(message_buf);
2118 }
2119
2120
2121 /**
2122  * Iterator over hash map entries.  Checks if the given validation
2123  * entry is for the same challenge as what is given in the PONG.
2124  *
2125  * @param cls the 'struct TransportPongMessage*'
2126  * @param key peer identity
2127  * @param value value in the hash map ('struct ValidationEntry')
2128  * @return GNUNET_YES if we should continue to
2129  *         iterate (mismatch), GNUNET_NO if not (entry matched)
2130  */
2131 static int
2132 check_pending_validation (void *cls,
2133                           const GNUNET_HashCode * key,
2134                           void *value)
2135 {
2136   const struct TransportPongMessage *pong = cls;
2137   struct ValidationEntry *ve = value;
2138   struct AddValidatedAddressContext avac;
2139   unsigned int challenge = ntohl(pong->challenge);
2140   struct GNUNET_HELLO_Message *hello;
2141   struct GNUNET_PeerIdentity target;
2142   struct NeighbourList *n;
2143   struct ForeignAddressList *fal;
2144   struct PeriodicValidationContext *periodic_validation_context;
2145
2146   if (ve->challenge != challenge)
2147     return GNUNET_YES;
2148
2149 #if DEBUG_TRANSPORT
2150   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2151               "Confirmed validity of address, peer `%4s' has address `%s' (%s).\n",
2152               GNUNET_h2s (key),
2153               GNUNET_a2s ((const struct sockaddr *) ve->addr,
2154                           ve->addrlen),
2155               ve->transport_name);
2156 #endif
2157   GNUNET_STATISTICS_update (stats,
2158                             gettext_noop ("# address validation successes"),
2159                             1,
2160                             GNUNET_NO);
2161   /* create the updated HELLO */
2162   GNUNET_CRYPTO_hash (&ve->publicKey,
2163                       sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
2164                       &target.hashPubKey);
2165   avac.done = GNUNET_NO;
2166   avac.ve = ve;
2167   hello = GNUNET_HELLO_create (&ve->publicKey,
2168                                &add_validated_address,
2169                                &avac);
2170   GNUNET_PEERINFO_add_peer (cfg, sched,
2171                             &target,
2172                             hello);
2173   GNUNET_free (hello);
2174   n = find_neighbour (&target);
2175   if (n != NULL)
2176     {
2177       fal = add_peer_address (n,
2178                               ve->transport_name,
2179                               ve->addr,
2180                               ve->addrlen);
2181       GNUNET_assert (fal != NULL);
2182       fal->expires = GNUNET_TIME_relative_to_absolute (HELLO_ADDRESS_EXPIRATION);
2183       fal->validated = GNUNET_YES;
2184       GNUNET_STATISTICS_update (stats,
2185                                 gettext_noop ("# peer addresses considered valid"),
2186                                 1,
2187                                 GNUNET_NO);      
2188       fal->latency = GNUNET_TIME_absolute_get_duration (ve->send_time);
2189       periodic_validation_context = GNUNET_malloc(sizeof(struct PeriodicValidationContext));
2190       periodic_validation_context->foreign_address = fal;
2191       periodic_validation_context->transport = strdup(ve->transport_name);
2192       memcpy(&periodic_validation_context->publicKey, 
2193              &ve->publicKey, 
2194              sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
2195       /* FIXME: this causes all of the revalidation PINGs for the same HELLO
2196          to be transmitted in bulk, which is not nice; also,
2197          triggering these HERE means that revalidations do NOT happen AT ALL
2198          for HELLOs a previous instance of this process validated (since
2199          there is no "initial" validation PING => no revalidation => BUG! */
2200       fal->revalidate_task = GNUNET_SCHEDULER_add_delayed(sched, 
2201                                                           TRANSPORT_DEFAULT_REVALIDATION, 
2202                                                           &send_periodic_ping, 
2203                                                           periodic_validation_context);
2204       if (n->latency.value == GNUNET_TIME_UNIT_FOREVER_REL.value)
2205         n->latency = fal->latency;
2206       else
2207         n->latency.value = (fal->latency.value + n->latency.value) / 2;
2208       n->distance = fal->distance;
2209       if (GNUNET_NO == n->received_pong)
2210         {
2211           notify_clients_connect (&target, n->latency, n->distance);
2212           n->received_pong = GNUNET_YES;
2213         }
2214       if (n->retry_task != GNUNET_SCHEDULER_NO_TASK)
2215         {
2216           GNUNET_SCHEDULER_cancel (sched,
2217                                    n->retry_task);
2218           n->retry_task = GNUNET_SCHEDULER_NO_TASK;
2219           try_transmission_to_peer (n);
2220         }
2221     }
2222
2223   /* clean up validation entry */
2224   GNUNET_assert (GNUNET_YES ==
2225                  GNUNET_CONTAINER_multihashmap_remove (validation_map,
2226                                                        key,
2227                                                        ve));
2228   GNUNET_SCHEDULER_cancel (sched,
2229                            ve->timeout_task);
2230   GNUNET_free (ve->transport_name);
2231   GNUNET_free (ve);
2232   return GNUNET_NO;
2233 }
2234
2235
2236 /**
2237  * Function that will be called if we receive a validation
2238  * of an address challenge that we transmitted to another
2239  * peer.  Note that the validation should only be considered
2240  * acceptable if the challenge matches AND if the sender
2241  * address is at least a plausible address for this peer
2242  * (otherwise we may be seeing a MiM attack).
2243  *
2244  * @param cls closure
2245  * @param message the pong message
2246  * @param peer who responded to our challenge
2247  * @param sender_address string describing our sender address (as observed
2248  *         by the other peer in binary format)
2249  * @param sender_address_len number of bytes in 'sender_address'
2250  */
2251 static void
2252 handle_pong (void *cls, const struct GNUNET_MessageHeader *message,
2253              const struct GNUNET_PeerIdentity *peer,
2254              const char *sender_address,
2255              size_t sender_address_len)
2256 {
2257 #if DEBUG_TRANSPORT > 1
2258   /* we get tons of these that just get discarded, only log
2259      if we are quite verbose */
2260   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2261               "Receiving `%s' message from `%4s'.\n", "PONG",
2262               GNUNET_i2s (peer));
2263 #endif
2264   GNUNET_STATISTICS_update (stats,
2265                             gettext_noop ("# PONG messages received"),
2266                             1,
2267                             GNUNET_NO);
2268   if (GNUNET_SYSERR !=
2269       GNUNET_CONTAINER_multihashmap_get_multiple (validation_map,
2270                                                   &peer->hashPubKey,
2271                                                   &check_pending_validation,
2272                                                   (void*) message))
2273     {
2274       /* This is *expected* to happen a lot since we send
2275          PONGs to *all* known addresses of the sender of
2276          the PING, so most likely we get multiple PONGs
2277          per PING, and all but the first PONG will end up
2278          here. So really we should not print anything here
2279          unless we want to be very, very verbose... */
2280 #if DEBUG_TRANSPORT > 2
2281       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2282                   "Received `%s' message from `%4s' but have no record of a matching `%s' message. Ignoring.\n",
2283                   "PONG",
2284                   GNUNET_i2s (peer),
2285                   "PING");
2286 #endif
2287       return;
2288     }
2289
2290 #if 0
2291   /* FIXME: add given address to potential pool of our addresses
2292      (for voting) */
2293   GNUNET_log (GNUNET_ERROR_TYPE_INFO | GNUNET_ERROR_TYPE_BULK,
2294               _("Another peer saw us using the address `%s' via `%s'.\n"),
2295               GNUNET_a2s ((const struct sockaddr *) &pong[1],
2296                           ntohs(pong->addrlen)),
2297               va->transport_name);
2298 #endif
2299 }
2300
2301
2302 /**
2303  * Check if the given address is already being validated; if not,
2304  * append the given address to the list of entries that are being be
2305  * validated and initiate validation.
2306  *
2307  * @param cls closure ('struct CheckHelloValidatedContext *')
2308  * @param tname name of the transport
2309  * @param expiration expiration time
2310  * @param addr the address
2311  * @param addrlen length of the address
2312  * @return GNUNET_OK (always)
2313  */
2314 static int
2315 run_validation (void *cls,
2316                 const char *tname,
2317                 struct GNUNET_TIME_Absolute expiration,
2318                 const void *addr, size_t addrlen)
2319 {
2320   struct CheckHelloValidatedContext *chvc = cls;
2321   struct GNUNET_PeerIdentity id;
2322   struct TransportPlugin *tp;
2323   struct ValidationEntry *va;
2324   struct NeighbourList *neighbour;
2325   struct ForeignAddressList *peer_address;
2326   struct TransportPingMessage ping;
2327   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pk;
2328   struct CheckAddressExistsClosure caec;
2329   char * message_buf;
2330   uint16_t hello_size;
2331   size_t tsize;
2332
2333   GNUNET_STATISTICS_update (stats,
2334                             gettext_noop ("# peer addresses scheduled for validation"),
2335                             1,
2336                             GNUNET_NO);      
2337   tp = find_transport (tname);
2338   if (tp == NULL)
2339     {
2340       GNUNET_log (GNUNET_ERROR_TYPE_INFO |
2341                   GNUNET_ERROR_TYPE_BULK,
2342                   _
2343                   ("Transport `%s' not loaded, will not try to validate peer address using this transport.\n"),
2344                   tname);
2345       GNUNET_STATISTICS_update (stats,
2346                                 gettext_noop ("# peer addresses not validated (no applicable transport plugin available)"),
2347                                 1,
2348                                 GNUNET_NO);      
2349       return GNUNET_OK;
2350     }
2351   GNUNET_HELLO_get_key (chvc->hello, &pk);
2352   GNUNET_CRYPTO_hash (&pk,
2353                       sizeof (struct
2354                               GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
2355                       &id.hashPubKey);
2356   caec.addr = addr;
2357   caec.addrlen = addrlen;
2358   caec.tname = tname;
2359   caec.exists = GNUNET_NO;
2360   GNUNET_CONTAINER_multihashmap_iterate (validation_map,
2361                                          &check_address_exists,
2362                                          &caec);
2363   if (caec.exists == GNUNET_YES)
2364     {
2365       /* During validation attempts we will likely trigger the other
2366          peer trying to validate our address which in turn will cause
2367          it to send us its HELLO, so we expect to hit this case rather
2368          frequently.  Only print something if we are very verbose. */
2369 #if DEBUG_TRANSPORT > 1
2370       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2371                   "Validation of address `%s' via `%s' for peer `%4s' already in progress.\n",
2372                   GNUNET_a2s (addr, addrlen),
2373                   tname,
2374                   GNUNET_i2s (&id));
2375 #endif
2376       GNUNET_STATISTICS_update (stats,
2377                                 gettext_noop ("# peer addresses not validated (in progress)"),
2378                                 1,
2379                                 GNUNET_NO);      
2380       return GNUNET_OK;
2381     }
2382   va = GNUNET_malloc (sizeof (struct ValidationEntry) + addrlen);
2383   va->transport_name = GNUNET_strdup (tname);
2384   va->challenge = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2385                                             (unsigned int) -1);
2386   va->send_time = GNUNET_TIME_absolute_get();
2387   va->addr = (const void*) &va[1];
2388   memcpy (&va[1], addr, addrlen);
2389   va->addrlen = addrlen;
2390   GNUNET_HELLO_get_key (chvc->hello,
2391                         &va->publicKey);
2392   va->timeout_task = GNUNET_SCHEDULER_add_delayed (sched,
2393                                                    HELLO_VERIFICATION_TIMEOUT,
2394                                                    &timeout_hello_validation,
2395                                                    va);
2396   GNUNET_CONTAINER_multihashmap_put (validation_map,
2397                                      &id.hashPubKey,
2398                                      va,
2399                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
2400   neighbour = find_neighbour(&id);
2401   if (neighbour == NULL)
2402     neighbour = setup_new_neighbour(&id);
2403   peer_address = add_peer_address(neighbour, tname, addr, addrlen);
2404   GNUNET_assert(peer_address != NULL);
2405   hello_size = GNUNET_HELLO_size(our_hello);
2406   tsize = sizeof(struct TransportPingMessage) + hello_size;
2407   message_buf = GNUNET_malloc(tsize);
2408   ping.challenge = htonl(va->challenge);
2409   ping.header.size = htons(sizeof(struct TransportPingMessage));
2410   ping.header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_PING);
2411   memcpy(&ping.target, &id, sizeof(struct GNUNET_PeerIdentity));
2412   memcpy(message_buf, our_hello, hello_size);
2413   memcpy(&message_buf[hello_size],
2414          &ping,
2415          sizeof(struct TransportPingMessage));
2416 #if DEBUG_TRANSPORT
2417   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2418               "Performing validation of address `%s' via `%s' for peer `%4s' sending `%s' (%u bytes) and `%s' (%u bytes)\n",
2419               GNUNET_a2s (addr, addrlen),
2420               tname,
2421               GNUNET_i2s (&id),
2422               "HELLO", hello_size,
2423               "PING", sizeof (struct TransportPingMessage));
2424 #endif
2425   GNUNET_STATISTICS_update (stats,
2426                             gettext_noop ("# PING messages sent for initial validation"),
2427                             1,
2428                             GNUNET_NO);      
2429   transmit_to_peer (NULL, peer_address,
2430                     GNUNET_SCHEDULER_PRIORITY_DEFAULT,
2431                     HELLO_VERIFICATION_TIMEOUT,
2432                     message_buf, tsize,
2433                     GNUNET_YES, neighbour);
2434   GNUNET_free(message_buf);
2435   return GNUNET_OK;
2436 }
2437
2438
2439 /**
2440  * Add the given address to the list of foreign addresses
2441  * available for the given peer (check for duplicates).
2442  *
2443  * @param cls the respective 'struct NeighbourList' to update
2444  * @param tname name of the transport
2445  * @param expiration expiration time
2446  * @param addr the address
2447  * @param addrlen length of the address
2448  * @return GNUNET_OK (always)
2449  */
2450 static int
2451 add_to_foreign_address_list (void *cls,
2452                              const char *tname,
2453                              struct GNUNET_TIME_Absolute expiration,
2454                              const void *addr, size_t addrlen)
2455 {
2456   struct NeighbourList *n = cls;
2457   struct ForeignAddressList *fal;
2458   int try;
2459
2460   GNUNET_STATISTICS_update (stats,
2461                             gettext_noop ("# valid peer addresses returned by peerinfo"),
2462                             1,
2463                             GNUNET_NO);      
2464   try = GNUNET_NO;
2465   fal = find_peer_address (n, tname, addr, addrlen);
2466   if (fal == NULL)
2467     {
2468 #if DEBUG_TRANSPORT
2469       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2470                   "Adding address `%s' (%s) for peer `%4s' due to peerinfo data for %llums.\n",
2471                   GNUNET_a2s (addr, addrlen),
2472                   tname,
2473                   GNUNET_i2s (&n->id),
2474                   expiration.value);
2475 #endif
2476       fal = add_peer_address (n, tname, addr, addrlen);
2477       if (fal == NULL)
2478         {
2479           GNUNET_STATISTICS_update (stats,
2480                                     gettext_noop ("# previously validated addresses lacking transport"),
2481                                     1,
2482                                     GNUNET_NO); 
2483         }
2484       try = GNUNET_YES;
2485     }
2486   if (fal == NULL)
2487     return GNUNET_OK;
2488   fal->expires = GNUNET_TIME_absolute_max (expiration,
2489                                            fal->expires);
2490   if (fal->validated == GNUNET_NO)
2491     {
2492       fal->validated = GNUNET_YES;  
2493       GNUNET_STATISTICS_update (stats,
2494                                 gettext_noop ("# peer addresses considered valid"),
2495                                 1,
2496                                 GNUNET_NO);      
2497     }
2498   if (try == GNUNET_YES)
2499     try_transmission_to_peer (n);
2500   return GNUNET_OK;
2501 }
2502
2503
2504 /**
2505  * Check if addresses in validated hello "h" overlap with
2506  * those in "chvc->hello" and validate the rest.
2507  *
2508  * @param cls closure
2509  * @param peer id of the peer, NULL for last call
2510  * @param h hello message for the peer (can be NULL)
2511  * @param trust amount of trust we have in the peer (not used)
2512  */
2513 static void
2514 check_hello_validated (void *cls,
2515                        const struct GNUNET_PeerIdentity *peer,
2516                        const struct GNUNET_HELLO_Message *h, 
2517                        uint32_t trust)
2518 {
2519   struct CheckHelloValidatedContext *chvc = cls;
2520   struct GNUNET_HELLO_Message *plain_hello;
2521   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pk;
2522   struct GNUNET_PeerIdentity target;
2523   struct NeighbourList *n;
2524
2525   if (peer == NULL)
2526     {
2527       chvc->piter = NULL;
2528       GNUNET_CONTAINER_DLL_remove (chvc_head,
2529                                    chvc_tail,
2530                                    chvc);
2531       if (GNUNET_NO == chvc->hello_known)
2532         {
2533           /* notify PEERINFO about the peer now, so that we at least
2534              have the public key if some other component needs it */
2535           GNUNET_HELLO_get_key (chvc->hello, &pk);
2536           GNUNET_CRYPTO_hash (&pk,
2537                               sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
2538                               &target.hashPubKey);
2539           plain_hello = GNUNET_HELLO_create (&pk,
2540                                              NULL, 
2541                                              NULL);
2542           GNUNET_PEERINFO_add_peer (cfg, sched, &target, plain_hello);
2543           GNUNET_free (plain_hello);
2544 #if DEBUG_TRANSPORT
2545           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2546                       "Peerinfo had no `%s' message for peer `%4s', full validation needed.\n",
2547                       "HELLO",
2548                       GNUNET_i2s (&target));
2549 #endif
2550           GNUNET_STATISTICS_update (stats,
2551                                     gettext_noop ("# new HELLOs requiring full validation"),
2552                                     1,
2553                                     GNUNET_NO);      
2554           GNUNET_HELLO_iterate_addresses (chvc->hello,
2555                                           GNUNET_NO, 
2556                                           &run_validation, 
2557                                           chvc);
2558         }
2559       else
2560         {
2561           GNUNET_STATISTICS_update (stats,
2562                                     gettext_noop ("# duplicate HELLO (peer known)"),
2563                                     1,
2564                                     GNUNET_NO);      
2565         }
2566       GNUNET_free (chvc);
2567       return;
2568     } 
2569   if (h == NULL)
2570     return;
2571 #if DEBUG_TRANSPORT
2572   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2573               "Peerinfo had `%s' message for peer `%4s', validating only new addresses.\n",
2574               "HELLO",
2575               GNUNET_i2s (peer));
2576 #endif
2577   chvc->hello_known = GNUNET_YES;
2578   n = find_neighbour (peer);
2579   if (n != NULL)
2580     {
2581       GNUNET_HELLO_iterate_addresses (h,
2582                                       GNUNET_NO,
2583                                       &add_to_foreign_address_list,
2584                                       n);
2585       try_transmission_to_peer (n);
2586     }
2587   else
2588     {
2589       GNUNET_STATISTICS_update (stats,
2590                                 gettext_noop ("# no existing neighbour record (validating HELLO)"),
2591                                 1,
2592                                 GNUNET_NO);      
2593     }
2594   GNUNET_STATISTICS_update (stats,
2595                             gettext_noop ("# HELLO validations (update case)"),
2596                             1,
2597                             GNUNET_NO);      
2598   GNUNET_HELLO_iterate_new_addresses (chvc->hello,
2599                                       h,
2600                                       GNUNET_TIME_relative_to_absolute (HELLO_REVALIDATION_START_TIME),
2601                                       &run_validation, 
2602                                       chvc);
2603 }
2604
2605 /**
2606  * Process HELLO-message.
2607  *
2608  * @param plugin transport involved, may be NULL
2609  * @param message the actual message
2610  * @return GNUNET_OK if the HELLO was well-formed, GNUNET_SYSERR otherwise
2611  */
2612 static int
2613 process_hello (struct TransportPlugin *plugin,
2614                const struct GNUNET_MessageHeader *message)
2615 {
2616   uint16_t hsize;
2617   struct GNUNET_PeerIdentity target;
2618   const struct GNUNET_HELLO_Message *hello;
2619   struct CheckHelloValidatedContext *chvc;
2620   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded publicKey;
2621
2622   hsize = ntohs (message->size);
2623   if ((ntohs (message->type) != GNUNET_MESSAGE_TYPE_HELLO) ||
2624       (hsize < sizeof (struct GNUNET_MessageHeader)))
2625     {
2626       GNUNET_break (0);
2627       return GNUNET_SYSERR;
2628     }
2629   GNUNET_STATISTICS_update (stats,
2630                             gettext_noop ("# HELLOs received for validation"),
2631                             1,
2632                             GNUNET_NO);      
2633   /* first, check if load is too high */
2634   if (GNUNET_SCHEDULER_get_load (sched,
2635                                  GNUNET_SCHEDULER_PRIORITY_BACKGROUND) > MAX_HELLO_LOAD)
2636     {
2637       GNUNET_STATISTICS_update (stats,
2638                                 gettext_noop ("# HELLOs ignored due to high load"),
2639                                 1,
2640                                 GNUNET_NO);      
2641       return GNUNET_OK;
2642     }
2643   hello = (const struct GNUNET_HELLO_Message *) message;
2644   if (GNUNET_OK != GNUNET_HELLO_get_key (hello, &publicKey))
2645     {
2646       GNUNET_break_op (0);
2647       return GNUNET_SYSERR;
2648     }
2649   GNUNET_CRYPTO_hash (&publicKey,
2650                       sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
2651                       &target.hashPubKey);
2652   if (0 == memcmp (&my_identity,
2653                    &target,
2654                    sizeof (struct GNUNET_PeerIdentity)))
2655     {
2656       GNUNET_STATISTICS_update (stats,
2657                                 gettext_noop ("# HELLOs ignored for validation (is my own HELLO)"),
2658                                 1,
2659                                 GNUNET_NO);      
2660       return GNUNET_OK;      
2661     }
2662 #if DEBUG_TRANSPORT > 1
2663   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2664               "Processing `%s' message for `%4s' of size %u\n",
2665               "HELLO", 
2666               GNUNET_i2s (&target), 
2667               GNUNET_HELLO_size(hello));
2668 #endif
2669   chvc = GNUNET_malloc (sizeof (struct CheckHelloValidatedContext) + hsize);
2670   chvc->hello = (const struct GNUNET_HELLO_Message *) &chvc[1];
2671   memcpy (&chvc[1], hello, hsize);
2672   GNUNET_CONTAINER_DLL_insert (chvc_head,
2673                                chvc_tail,
2674                                chvc);
2675   /* finally, check if HELLO was previously validated
2676      (continuation will then schedule actual validation) */
2677   chvc->piter = GNUNET_PEERINFO_iterate (cfg,
2678                                          sched,
2679                                          &target,
2680                                          0,
2681                                          HELLO_VERIFICATION_TIMEOUT,
2682                                          &check_hello_validated, chvc);
2683   return GNUNET_OK;
2684 }
2685
2686
2687 /**
2688  * The peer specified by the given neighbour has timed-out or a plugin
2689  * has disconnected.  We may either need to do nothing (other plugins
2690  * still up), or trigger a full disconnect and clean up.  This
2691  * function updates our state and does the necessary notifications.
2692  * Also notifies our clients that the neighbour is now officially
2693  * gone.
2694  *
2695  * @param n the neighbour list entry for the peer
2696  * @param check should we just check if all plugins
2697  *        disconnected or must we ask all plugins to
2698  *        disconnect?
2699  */
2700 static void
2701 disconnect_neighbour (struct NeighbourList *n, int check)
2702 {
2703   struct ReadyList *rpos;
2704   struct NeighbourList *npos;
2705   struct NeighbourList *nprev;
2706   struct MessageQueue *mq;
2707   struct ForeignAddressList *peer_addresses;
2708   struct ForeignAddressList *peer_pos;
2709
2710   if (GNUNET_YES == check)
2711     {
2712       rpos = n->plugins;
2713       while (NULL != rpos)
2714         {
2715           peer_addresses = rpos->addresses;
2716           while (peer_addresses != NULL)
2717             {
2718               if (GNUNET_YES == peer_addresses->connected)
2719                 return;             /* still connected */
2720               peer_addresses = peer_addresses->next;
2721             }
2722           rpos = rpos->next;
2723         }
2724     }
2725 #if DEBUG_TRANSPORT
2726   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2727               "Disconnecting from `%4s'\n",
2728               GNUNET_i2s (&n->id));
2729 #endif
2730   /* remove n from neighbours list */
2731   nprev = NULL;
2732   npos = neighbours;
2733   while ((npos != NULL) && (npos != n))
2734     {
2735       nprev = npos;
2736       npos = npos->next;
2737     }
2738   GNUNET_assert (npos != NULL);
2739   if (nprev == NULL)
2740     neighbours = n->next;
2741   else
2742     nprev->next = n->next;
2743
2744   /* notify all clients about disconnect */
2745   if (GNUNET_YES == n->received_pong)
2746     notify_clients_disconnect (&n->id);
2747
2748   /* clean up all plugins, cancel connections and pending transmissions */
2749   while (NULL != (rpos = n->plugins))
2750     {
2751       n->plugins = rpos->next;
2752       rpos->plugin->api->disconnect (rpos->plugin->api->cls, &n->id);
2753       while (rpos->addresses != NULL)
2754         {
2755           peer_pos = rpos->addresses;
2756           rpos->addresses = peer_pos->next;
2757           if (peer_pos->connected == GNUNET_YES)
2758             GNUNET_STATISTICS_update (stats,
2759                                       gettext_noop ("# connected addresses"),
2760                                       -1,
2761                                       GNUNET_NO); 
2762           if (GNUNET_YES == peer_pos->validated)
2763             GNUNET_STATISTICS_update (stats,
2764                                       gettext_noop ("# peer addresses considered valid"),
2765                                       -1,
2766                                       GNUNET_NO);      
2767           GNUNET_free(peer_pos);
2768         }
2769       GNUNET_free (rpos);
2770     }
2771
2772   /* free all messages on the queue */
2773   while (NULL != (mq = n->messages_head))
2774     {
2775       GNUNET_STATISTICS_update (stats,
2776                                 gettext_noop ("# bytes in message queue for other peers"),
2777                                 -mq->message_buf_size,
2778                                 GNUNET_NO);
2779       GNUNET_STATISTICS_update (stats,
2780                                 gettext_noop ("# bytes discarded due to disconnect"),
2781                                 mq->message_buf_size,
2782                                 GNUNET_NO);
2783       GNUNET_CONTAINER_DLL_remove (n->messages_head,
2784                                    n->messages_tail,
2785                                    mq);
2786       GNUNET_assert (0 == memcmp(&mq->neighbour_id, 
2787                                  &n->id,
2788                                  sizeof(struct GNUNET_PeerIdentity)));
2789       GNUNET_free (mq);
2790     }
2791   if (n->timeout_task != GNUNET_SCHEDULER_NO_TASK)
2792     {
2793       GNUNET_SCHEDULER_cancel (sched, n->timeout_task);
2794       n->timeout_task = GNUNET_SCHEDULER_NO_TASK;
2795     }
2796   if (n->retry_task != GNUNET_SCHEDULER_NO_TASK)
2797     {
2798       GNUNET_SCHEDULER_cancel (sched, n->retry_task);
2799       n->retry_task = GNUNET_SCHEDULER_NO_TASK;
2800     }
2801   /* finally, free n itself */
2802   GNUNET_STATISTICS_update (stats,
2803                             gettext_noop ("# active neighbours"),
2804                             -1,
2805                             GNUNET_NO);
2806   GNUNET_free (n);
2807 }
2808
2809
2810 /**
2811  * We have received a PING message from someone.  Need to send a PONG message
2812  * in response to the peer by any means necessary. 
2813  *
2814  * FIXME: With something like TCP where a connection exists, we may
2815  * want to send it that way.  But the current API does not seem to
2816  * allow us to do so (can't tell this to the transport!)
2817  */
2818 static int 
2819 handle_ping(void *cls, const struct GNUNET_MessageHeader *message,
2820             const struct GNUNET_PeerIdentity *peer,
2821             const char *sender_address,
2822             size_t sender_address_len)
2823 {
2824   struct TransportPlugin *plugin = cls;
2825   struct TransportPingMessage *ping;
2826   struct TransportPongMessage *pong;
2827   struct NeighbourList *n;
2828   struct ReadyList *rl;
2829   struct ForeignAddressList *fal;
2830
2831   if (ntohs (message->size) != sizeof (struct TransportPingMessage))
2832     {
2833       GNUNET_break_op (0);
2834       return GNUNET_SYSERR;
2835     }
2836   ping = (struct TransportPingMessage *) message;
2837   if (0 != memcmp (&ping->target,
2838                    plugin->env.my_identity,
2839                    sizeof (struct GNUNET_PeerIdentity)))
2840     {
2841       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2842                   _("Received `%s' message not destined for me!\n"), 
2843                   "PING");
2844       return GNUNET_SYSERR;
2845     }
2846 #if DEBUG_TRANSPORT
2847   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2848               "Processing `%s' from `%s'\n",
2849               "PING", 
2850               GNUNET_a2s ((const struct sockaddr *)sender_address, 
2851                           sender_address_len));
2852 #endif
2853   GNUNET_STATISTICS_update (stats,
2854                             gettext_noop ("# PING messages received"),
2855                             1,
2856                             GNUNET_NO);
2857   pong = GNUNET_malloc (sizeof (struct TransportPongMessage) + sender_address_len);
2858   pong->header.size = htons (sizeof (struct TransportPongMessage) + sender_address_len);
2859   pong->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_PONG);
2860   pong->purpose.size =
2861     htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) +
2862            sizeof (uint32_t) +
2863            sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) + sender_address_len);
2864   pong->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_TCP_PING);
2865   pong->challenge = ping->challenge;
2866   pong->addrlen = htons(sender_address_len);
2867   memcpy(&pong->signer, 
2868          &my_public_key, 
2869          sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
2870   memcpy (&pong[1], sender_address, sender_address_len);
2871   GNUNET_assert (GNUNET_OK ==
2872                  GNUNET_CRYPTO_rsa_sign (my_private_key,
2873                                          &pong->purpose, &pong->signature));
2874
2875   n = find_neighbour(peer);
2876   if (n == NULL)
2877     n = setup_new_neighbour(peer);
2878   /* broadcast 'PONG' to all available addresses */
2879   rl = n->plugins;
2880   while (rl != NULL)
2881     {
2882       fal = rl->addresses;
2883       while (fal != NULL)
2884         {
2885           transmit_to_peer(NULL, fal,
2886                            TRANSPORT_PONG_PRIORITY, 
2887                            HELLO_VERIFICATION_TIMEOUT,
2888                            (const char *)pong, 
2889                            ntohs(pong->header.size), 
2890                            GNUNET_YES, 
2891                            n);
2892           fal = fal->next;
2893         }
2894       rl = rl->next;
2895     }
2896   GNUNET_free(pong);
2897   return GNUNET_OK;
2898 }
2899
2900
2901 /**
2902  * Function called by the plugin for each received message.
2903  * Update data volumes, possibly notify plugins about
2904  * reducing the rate at which they read from the socket
2905  * and generally forward to our receive callback.
2906  *
2907  * @param cls the "struct TransportPlugin *" we gave to the plugin
2908  * @param peer (claimed) identity of the other peer
2909  * @param message the message, NULL if we only care about
2910  *                learning about the delay until we should receive again
2911  * @param distance in overlay hops; use 1 unless DV (or 0 if message == NULL)
2912  * @param sender_address binary address of the sender (if observed)
2913  * @param sender_address_len number of bytes in sender_address
2914  * @return how long the plugin should wait until receiving more data
2915  *         (plugins that do not support this, can ignore the return value)
2916  */
2917 static struct GNUNET_TIME_Relative
2918 plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
2919                     const struct GNUNET_MessageHeader *message,
2920                     unsigned int distance, const char *sender_address,
2921                     size_t sender_address_len)
2922 {
2923   struct ReadyList *service_context;
2924   struct TransportPlugin *plugin = cls;
2925   struct TransportClient *cpos;
2926   struct InboundMessage *im;
2927   struct ForeignAddressList *peer_address;
2928   uint16_t msize;
2929   struct NeighbourList *n;
2930   struct GNUNET_TIME_Relative ret;
2931
2932   n = find_neighbour (peer);
2933   if (n == NULL)
2934     n = setup_new_neighbour (peer);    
2935   service_context = n->plugins;
2936   while ((service_context != NULL) && (plugin != service_context->plugin))
2937     service_context = service_context->next;
2938   GNUNET_assert ((plugin->api->send == NULL) || (service_context != NULL));
2939   if (message != NULL)
2940     {
2941       peer_address = add_peer_address(n, 
2942                                       plugin->short_name,
2943                                       sender_address, 
2944                                       sender_address_len);  
2945       if (peer_address != NULL)
2946         {
2947           peer_address->distance = distance;
2948           if (peer_address->connected == GNUNET_NO)
2949             {
2950               peer_address->connected = GNUNET_YES;
2951               peer_address->connect_attempts++;
2952               GNUNET_STATISTICS_update (stats,
2953                                         gettext_noop ("# connected addresses"),
2954                                         1,
2955                                         GNUNET_NO);
2956             }
2957           peer_address->timeout
2958             =
2959             GNUNET_TIME_relative_to_absolute
2960             (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
2961         }
2962       /* update traffic received amount ... */
2963       msize = ntohs (message->size);      
2964       GNUNET_STATISTICS_update (stats,
2965                                 gettext_noop ("# bytes received from other peers"),
2966                                 msize,
2967                                 GNUNET_NO);
2968       n->distance = distance;
2969       n->peer_timeout =
2970         GNUNET_TIME_relative_to_absolute
2971         (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
2972       GNUNET_SCHEDULER_cancel (sched,
2973                                n->timeout_task);
2974       n->timeout_task =
2975         GNUNET_SCHEDULER_add_delayed (sched,
2976                                       GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
2977                                       &neighbour_timeout_task, n);
2978       if (n->quota_violation_count > QUOTA_VIOLATION_DROP_THRESHOLD)
2979         {
2980           /* dropping message due to frequent inbound volume violations! */
2981           GNUNET_log (GNUNET_ERROR_TYPE_WARNING |
2982                       GNUNET_ERROR_TYPE_BULK,
2983                       _
2984                       ("Dropping incoming message due to repeated bandwidth quota (%u b/s) violations (total of %u).\n"), 
2985                       n->in_tracker.available_bytes_per_s__,
2986                       n->quota_violation_count);
2987           GNUNET_STATISTICS_update (stats,
2988                                     gettext_noop ("# bandwidth quota violations by other peers"),
2989                                     1,
2990                                     GNUNET_NO);
2991           return GNUNET_TIME_UNIT_MINUTES; /* minimum penalty, likely ignored (UDP...) */
2992         }
2993       switch (ntohs (message->type))
2994         {
2995         case GNUNET_MESSAGE_TYPE_HELLO:
2996           GNUNET_STATISTICS_update (stats,
2997                                     gettext_noop ("# HELLO messages received from other peers"),
2998                                     1,
2999                                     GNUNET_NO);
3000           process_hello (plugin, message);
3001           break;
3002         case GNUNET_MESSAGE_TYPE_TRANSPORT_PING:
3003           handle_ping(plugin, message, peer, sender_address, sender_address_len);
3004           break;
3005         case GNUNET_MESSAGE_TYPE_TRANSPORT_PONG:
3006           handle_pong(plugin, message, peer, sender_address, sender_address_len);
3007           break;
3008         default:
3009 #if DEBUG_TRANSPORT
3010           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3011                       "Received message of type %u from `%4s', sending to all clients.\n",
3012                       ntohs (message->type), GNUNET_i2s (peer));
3013 #endif
3014           if (GNUNET_YES == GNUNET_BANDWIDTH_tracker_consume (&n->in_tracker,
3015                                                               msize))
3016             n->quota_violation_count++;
3017           else 
3018             n->quota_violation_count = 0; /* back within limits */
3019           GNUNET_STATISTICS_update (stats,
3020                                     gettext_noop ("# payload received from other peers"),
3021                                     msize,
3022                                     GNUNET_NO);
3023           /* transmit message to all clients */
3024           im = GNUNET_malloc (sizeof (struct InboundMessage) + msize);
3025           im->header.size = htons (sizeof (struct InboundMessage) + msize);
3026           im->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RECV);
3027           im->latency = GNUNET_TIME_relative_hton (n->latency);
3028           im->peer = *peer;
3029           memcpy (&im[1], message, msize);
3030           cpos = clients;
3031           while (cpos != NULL)
3032             {
3033               transmit_to_client (cpos, &im->header, GNUNET_YES);
3034               cpos = cpos->next;
3035             }
3036           GNUNET_free (im);
3037         }
3038     }  
3039   ret = GNUNET_BANDWIDTH_tracker_get_delay (&n->in_tracker, 0);
3040   if (ret.value > 0)
3041     {
3042       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3043                   "Throttling read (%llu bytes excess at %u b/s), waiting %llums before reading more.\n",
3044                   (unsigned long long) n->in_tracker.consumption_since_last_update__,
3045                   (unsigned int) n->in_tracker.available_bytes_per_s__,
3046                   (unsigned long long) ret.value);
3047       GNUNET_STATISTICS_update (stats,
3048                                 gettext_noop ("# ms throttling suggested"),
3049                                 (int64_t) ret.value,
3050                                 GNUNET_NO);      
3051     }
3052   return ret;
3053 }
3054
3055
3056 /**
3057  * Handle START-message.  This is the first message sent to us
3058  * by any client which causes us to add it to our list.
3059  *
3060  * @param cls closure (always NULL)
3061  * @param client identification of the client
3062  * @param message the actual message
3063  */
3064 static void
3065 handle_start (void *cls,
3066               struct GNUNET_SERVER_Client *client,
3067               const struct GNUNET_MessageHeader *message)
3068 {
3069   struct TransportClient *c;
3070   struct ConnectInfoMessage cim;
3071   struct NeighbourList *n;
3072
3073 #if DEBUG_TRANSPORT
3074   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3075               "Received `%s' request from client\n", "START");
3076 #endif
3077   c = clients;
3078   while (c != NULL)
3079     {
3080       if (c->client == client)
3081         {
3082           /* client already on our list! */
3083           GNUNET_break (0);
3084           GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3085           return;
3086         }
3087       c = c->next;
3088     }
3089   c = GNUNET_malloc (sizeof (struct TransportClient));
3090   c->next = clients;
3091   clients = c;
3092   c->client = client;
3093   if (our_hello != NULL)
3094     {
3095 #if DEBUG_TRANSPORT
3096       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3097                   "Sending our own `%s' to new client\n", "HELLO");
3098 #endif
3099       transmit_to_client (c,
3100                           (const struct GNUNET_MessageHeader *) our_hello,
3101                           GNUNET_NO);
3102       /* tell new client about all existing connections */
3103       cim.header.size = htons (sizeof (struct ConnectInfoMessage));
3104       cim.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
3105       n = neighbours; 
3106       while (n != NULL)
3107         {
3108           if (GNUNET_YES == n->received_pong)
3109             {
3110               cim.id = n->id;
3111               cim.latency = GNUNET_TIME_relative_hton (n->latency);
3112               cim.distance = htonl (n->distance);
3113               transmit_to_client (c, &cim.header, GNUNET_NO);
3114             }
3115             n = n->next;
3116         }
3117     }
3118   GNUNET_SERVER_receive_done (client, GNUNET_OK);
3119 }
3120
3121
3122 /**
3123  * Handle HELLO-message.
3124  *
3125  * @param cls closure (always NULL)
3126  * @param client identification of the client
3127  * @param message the actual message
3128  */
3129 static void
3130 handle_hello (void *cls,
3131               struct GNUNET_SERVER_Client *client,
3132               const struct GNUNET_MessageHeader *message)
3133 {
3134   int ret;
3135
3136   GNUNET_STATISTICS_update (stats,
3137                             gettext_noop ("# HELLOs received from clients"),
3138                             1,
3139                             GNUNET_NO);      
3140   ret = process_hello (NULL, message);
3141   GNUNET_SERVER_receive_done (client, ret);
3142 }
3143
3144
3145 /**
3146  * Handle SEND-message.
3147  *
3148  * @param cls closure (always NULL)
3149  * @param client identification of the client
3150  * @param message the actual message
3151  */
3152 static void
3153 handle_send (void *cls,
3154              struct GNUNET_SERVER_Client *client,
3155              const struct GNUNET_MessageHeader *message)
3156 {
3157   struct TransportClient *tc;
3158   struct NeighbourList *n;
3159   const struct OutboundMessage *obm;
3160   const struct GNUNET_MessageHeader *obmm;
3161   uint16_t size;
3162   uint16_t msize;
3163
3164   size = ntohs (message->size);
3165   if (size <
3166       sizeof (struct OutboundMessage) + sizeof (struct GNUNET_MessageHeader))
3167     {
3168       GNUNET_break (0);
3169       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3170       return;
3171     }
3172   GNUNET_STATISTICS_update (stats,
3173                             gettext_noop ("# payload received for other peers"),
3174                             size,
3175                             GNUNET_NO);      
3176   obm = (const struct OutboundMessage *) message;
3177 #if DEBUG_TRANSPORT
3178   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3179               "Received `%s' request from client with target `%4s'\n",
3180               "SEND", GNUNET_i2s (&obm->peer));
3181 #endif
3182   obmm = (const struct GNUNET_MessageHeader *) &obm[1];
3183   msize = ntohs (obmm->size);
3184   if (size != msize + sizeof (struct OutboundMessage))
3185     {
3186       GNUNET_break (0);
3187       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3188       return;
3189     }
3190   n = find_neighbour (&obm->peer);
3191   if (n == NULL)
3192     n = setup_new_neighbour (&obm->peer);
3193   tc = clients;
3194   while ((tc != NULL) && (tc->client != client))
3195     tc = tc->next;
3196
3197 #if DEBUG_TRANSPORT
3198   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3199               "Client asked to transmit %u-byte message of type %u to `%4s'\n",
3200               ntohs (obmm->size),
3201               ntohs (obmm->type), GNUNET_i2s (&obm->peer));
3202 #endif
3203   transmit_to_peer (tc, NULL, ntohl (obm->priority), 
3204                     GNUNET_TIME_relative_ntoh (obm->timeout),
3205                     (char *)obmm, 
3206                     ntohs (obmm->size), GNUNET_NO, n);
3207   GNUNET_SERVER_receive_done (client, GNUNET_OK);
3208 }
3209
3210
3211 /**
3212  * Handle SET_QUOTA-message.
3213  *
3214  * @param cls closure (always NULL)
3215  * @param client identification of the client
3216  * @param message the actual message
3217  */
3218 static void
3219 handle_set_quota (void *cls,
3220                   struct GNUNET_SERVER_Client *client,
3221                   const struct GNUNET_MessageHeader *message)
3222 {
3223   const struct QuotaSetMessage *qsm =
3224     (const struct QuotaSetMessage *) message;
3225   struct NeighbourList *n;
3226   
3227   GNUNET_STATISTICS_update (stats,
3228                             gettext_noop ("# SET QUOTA messages received"),
3229                             1,
3230                             GNUNET_NO);      
3231   n = find_neighbour (&qsm->peer);
3232   if (n == NULL)
3233     {
3234       GNUNET_SERVER_receive_done (client, GNUNET_OK);
3235       GNUNET_STATISTICS_update (stats,
3236                                 gettext_noop ("# SET QUOTA messages ignored (no such peer)"),
3237                                 1,
3238                                 GNUNET_NO);      
3239       return;
3240     }
3241 #if DEBUG_TRANSPORT
3242   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3243               "Received `%s' request (new quota %u, old quota %u) from client for peer `%4s'\n",
3244               "SET_QUOTA", 
3245               (unsigned int) ntohl (qsm->quota.value__),
3246               (unsigned int) n->in_tracker.available_bytes_per_s__,
3247               GNUNET_i2s (&qsm->peer));
3248 #endif
3249   GNUNET_BANDWIDTH_tracker_update_quota (&n->in_tracker,
3250                                          qsm->quota);
3251   if (0 == ntohl (qsm->quota.value__)) 
3252     disconnect_neighbour (n, GNUNET_NO);    
3253   GNUNET_SERVER_receive_done (client, GNUNET_OK);
3254 }
3255
3256
3257 static void
3258 transmit_address_to_client (void *cls, const char *address)
3259 {
3260   struct GNUNET_SERVER_TransmitContext *tc = cls;
3261   size_t slen;
3262
3263   if (NULL == address)
3264     slen = 0;
3265   else
3266     slen = strlen (address) + 1;
3267   GNUNET_SERVER_transmit_context_append_data (tc, address, slen,
3268                                               GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_REPLY);
3269   if (NULL == address)
3270     GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
3271 }
3272
3273
3274 /**
3275  * Handle AddressLookup-message.
3276  *
3277  * @param cls closure (always NULL)
3278  * @param client identification of the client
3279  * @param message the actual message
3280  */
3281 static void
3282 handle_address_lookup (void *cls,
3283                        struct GNUNET_SERVER_Client *client,
3284                        const struct GNUNET_MessageHeader *message)
3285 {
3286   const struct AddressLookupMessage *alum;
3287   struct TransportPlugin *lsPlugin;
3288   const char *nameTransport;
3289   const char *address;
3290   uint16_t size;
3291   struct GNUNET_SERVER_TransmitContext *tc;
3292
3293   size = ntohs (message->size);
3294   if (size < sizeof (struct AddressLookupMessage))
3295     {
3296       GNUNET_break_op (0);
3297       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3298       return;
3299     }
3300   alum = (const struct AddressLookupMessage *) message;
3301   uint32_t addressLen = ntohl (alum->addrlen);
3302   if (size <= sizeof (struct AddressLookupMessage) + addressLen)
3303     {
3304       GNUNET_break_op (0);
3305       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3306       return;
3307     }
3308   address = (const char *) &alum[1];
3309   nameTransport = (const char *) &address[addressLen];
3310   if (nameTransport
3311       [size - sizeof (struct AddressLookupMessage) - addressLen - 1] != '\0')
3312     {
3313       GNUNET_break_op (0);
3314       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3315       return;
3316     }
3317   struct GNUNET_TIME_Absolute timeout =
3318     GNUNET_TIME_absolute_ntoh (alum->timeout);
3319   struct GNUNET_TIME_Relative rtimeout =
3320     GNUNET_TIME_absolute_get_remaining (timeout);
3321   lsPlugin = find_transport (nameTransport);
3322   if (NULL == lsPlugin)
3323     {
3324       tc = GNUNET_SERVER_transmit_context_create (client);
3325       GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
3326                                                   GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_REPLY);
3327       GNUNET_SERVER_transmit_context_run (tc, rtimeout);
3328       return;
3329     }
3330   tc = GNUNET_SERVER_transmit_context_create (client);
3331   lsPlugin->api->address_pretty_printer (cls, nameTransport,
3332                                          address, addressLen, GNUNET_YES,
3333                                          rtimeout,
3334                                          &transmit_address_to_client, tc);
3335 }
3336
3337 /**
3338  * List of handlers for the messages understood by this
3339  * service.
3340  */
3341 static struct GNUNET_SERVER_MessageHandler handlers[] = {
3342   {&handle_start, NULL,
3343    GNUNET_MESSAGE_TYPE_TRANSPORT_START, 0},
3344   {&handle_hello, NULL,
3345    GNUNET_MESSAGE_TYPE_HELLO, 0},
3346   {&handle_send, NULL,
3347    GNUNET_MESSAGE_TYPE_TRANSPORT_SEND, 0},
3348   {&handle_set_quota, NULL,
3349    GNUNET_MESSAGE_TYPE_TRANSPORT_SET_QUOTA, sizeof (struct QuotaSetMessage)},
3350   {&handle_address_lookup, NULL,
3351    GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_LOOKUP,
3352    0},
3353   {NULL, NULL, 0, 0}
3354 };
3355
3356
3357 /**
3358  * Setup the environment for this plugin.
3359  */
3360 static void
3361 create_environment (struct TransportPlugin *plug)
3362 {
3363   plug->env.cfg = cfg;
3364   plug->env.sched = sched;
3365   plug->env.my_identity = &my_identity;
3366   plug->env.cls = plug;
3367   plug->env.receive = &plugin_env_receive;
3368   plug->env.notify_address = &plugin_env_notify_address;
3369   plug->env.max_connections = max_connect_per_transport;
3370   plug->env.stats = stats;
3371 }
3372
3373
3374 /**
3375  * Start the specified transport (load the plugin).
3376  */
3377 static void
3378 start_transport (struct GNUNET_SERVER_Handle *server, const char *name)
3379 {
3380   struct TransportPlugin *plug;
3381   char *libname;
3382
3383   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3384               _("Loading `%s' transport plugin\n"), name);
3385   GNUNET_asprintf (&libname, "libgnunet_plugin_transport_%s", name);
3386   plug = GNUNET_malloc (sizeof (struct TransportPlugin));
3387   create_environment (plug);
3388   plug->short_name = GNUNET_strdup (name);
3389   plug->lib_name = libname;
3390   plug->next = plugins;
3391   plugins = plug;
3392   plug->api = GNUNET_PLUGIN_load (libname, &plug->env);
3393   if (plug->api == NULL)
3394     {
3395       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3396                   _("Failed to load transport plugin for `%s'\n"), name);
3397       GNUNET_free (plug->short_name);
3398       plugins = plug->next;
3399       GNUNET_free (libname);
3400       GNUNET_free (plug);
3401     }
3402 }
3403
3404
3405 /**
3406  * Called whenever a client is disconnected.  Frees our
3407  * resources associated with that client.
3408  *
3409  * @param cls closure
3410  * @param client identification of the client
3411  */
3412 static void
3413 client_disconnect_notification (void *cls,
3414                                 struct GNUNET_SERVER_Client *client)
3415 {
3416   struct TransportClient *pos;
3417   struct TransportClient *prev;
3418   struct ClientMessageQueueEntry *mqe;
3419
3420   if (client == NULL)
3421     return;
3422 #if DEBUG_TRANSPORT
3423   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
3424               "Client disconnected, cleaning up.\n");
3425 #endif
3426   prev = NULL;
3427   pos = clients;
3428   while ((pos != NULL) && (pos->client != client))
3429     {
3430       prev = pos;
3431       pos = pos->next;
3432     }
3433   if (pos == NULL)
3434     return;
3435   while (NULL != (mqe = pos->message_queue_head))
3436     {
3437       GNUNET_CONTAINER_DLL_remove (pos->message_queue_head,
3438                                    pos->message_queue_tail,
3439                                    mqe);
3440       pos->message_count--;
3441       GNUNET_free (mqe);
3442     }
3443   if (prev == NULL)
3444     clients = pos->next;
3445   else
3446     prev->next = pos->next;
3447   if (GNUNET_YES == pos->tcs_pending)
3448     {
3449       pos->client = NULL;
3450       return;
3451     }
3452   if (pos->th != NULL)
3453     {
3454       GNUNET_CONNECTION_notify_transmit_ready_cancel (pos->th);
3455       pos->th = NULL;
3456     }
3457   GNUNET_break (0 == pos->message_count);
3458   GNUNET_free (pos);
3459 }
3460
3461
3462 /**
3463  * Iterator to free entries in the validation_map.
3464  *
3465  * @param cls closure (unused)
3466  * @param key current key code
3467  * @param value value in the hash map (validation to abort)
3468  * @return GNUNET_YES (always)
3469  */
3470 static int 
3471 abort_validation (void *cls,
3472                   const GNUNET_HashCode * key,
3473                   void *value)
3474 {
3475   struct ValidationEntry *va = value;
3476
3477   GNUNET_SCHEDULER_cancel (sched, va->timeout_task);
3478   GNUNET_free (va->transport_name);
3479   GNUNET_free (va);
3480   return GNUNET_YES;
3481 }
3482
3483
3484 /**
3485  * Function called when the service shuts down.  Unloads our plugins
3486  * and cancels pending validations.
3487  *
3488  * @param cls closure, unused
3489  * @param tc task context (unused)
3490  */
3491 static void
3492 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
3493 {
3494   struct TransportPlugin *plug;
3495   struct OwnAddressList *al;
3496   struct CheckHelloValidatedContext *chvc;
3497
3498   while (neighbours != NULL)
3499     disconnect_neighbour (neighbours, GNUNET_NO);
3500 #if DEBUG_TRANSPORT
3501   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3502               "Transport service is unloading plugins...\n");
3503 #endif
3504   while (NULL != (plug = plugins))
3505     {
3506       plugins = plug->next;
3507       GNUNET_break (NULL == GNUNET_PLUGIN_unload (plug->lib_name, plug->api));
3508       GNUNET_free (plug->lib_name);
3509       GNUNET_free (plug->short_name);
3510       while (NULL != (al = plug->addresses))
3511         {
3512           plug->addresses = al->next;
3513           GNUNET_free (al);
3514         }
3515       GNUNET_free (plug);
3516     }
3517   if (my_private_key != NULL)
3518     GNUNET_CRYPTO_rsa_key_free (my_private_key);
3519   GNUNET_free_non_null (our_hello);
3520
3521   /* free 'chvc' data structure */
3522   while (NULL != (chvc = chvc_head))
3523     {
3524       chvc_head = chvc->next;
3525       GNUNET_PEERINFO_iterate_cancel (chvc->piter);
3526       GNUNET_free (chvc);
3527     }
3528   chvc_tail = NULL;
3529
3530   GNUNET_CONTAINER_multihashmap_iterate (validation_map,
3531                                          &abort_validation,
3532                                          NULL);
3533   GNUNET_CONTAINER_multihashmap_destroy (validation_map);
3534   validation_map = NULL;
3535   if (stats != NULL)
3536     {
3537       GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
3538       stats = NULL;
3539     }
3540 }
3541
3542
3543 /**
3544  * Initiate transport service.
3545  *
3546  * @param cls closure
3547  * @param s scheduler to use
3548  * @param serv the initialized server
3549  * @param c configuration to use
3550  */
3551 static void
3552 run (void *cls,
3553      struct GNUNET_SCHEDULER_Handle *s,
3554      struct GNUNET_SERVER_Handle *serv,
3555      const struct GNUNET_CONFIGURATION_Handle *c)
3556 {
3557   char *plugs;
3558   char *pos;
3559   int no_transports;
3560   unsigned long long tneigh;
3561   char *keyfile;
3562
3563   sched = s;
3564   cfg = c;
3565   stats = GNUNET_STATISTICS_create (sched, "transport", cfg);
3566   validation_map = GNUNET_CONTAINER_multihashmap_create (64);
3567   /* parse configuration */
3568   if ((GNUNET_OK !=
3569        GNUNET_CONFIGURATION_get_value_number (c,
3570                                               "TRANSPORT",
3571                                               "NEIGHBOUR_LIMIT",
3572                                               &tneigh)) ||
3573       (GNUNET_OK !=
3574        GNUNET_CONFIGURATION_get_value_filename (c,
3575                                                 "GNUNETD",
3576                                                 "HOSTKEY", &keyfile)))
3577     {
3578       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3579                   _
3580                   ("Transport service is lacking key configuration settings.  Exiting.\n"));
3581       GNUNET_SCHEDULER_shutdown (s);
3582       if (stats != NULL)
3583         {
3584           GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
3585           stats = NULL;
3586         }
3587       GNUNET_CONTAINER_multihashmap_destroy (validation_map);
3588       validation_map = NULL;
3589       return;
3590     }
3591   max_connect_per_transport = (uint32_t) tneigh;
3592   my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
3593   GNUNET_free (keyfile);
3594   if (my_private_key == NULL)
3595     {
3596       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3597                   _
3598                   ("Transport service could not access hostkey.  Exiting.\n"));
3599       GNUNET_SCHEDULER_shutdown (s);
3600       if (stats != NULL)
3601         {
3602           GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
3603           stats = NULL;
3604         }
3605       GNUNET_CONTAINER_multihashmap_destroy (validation_map);
3606       validation_map = NULL;
3607       return;
3608     }
3609   GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key);
3610   GNUNET_CRYPTO_hash (&my_public_key,
3611                       sizeof (my_public_key), &my_identity.hashPubKey);
3612   /* setup notification */
3613   server = serv;
3614   GNUNET_SERVER_disconnect_notify (server,
3615                                    &client_disconnect_notification, NULL);
3616   /* load plugins... */
3617   no_transports = 1;
3618   if (GNUNET_OK ==
3619       GNUNET_CONFIGURATION_get_value_string (c,
3620                                              "TRANSPORT", "PLUGINS", &plugs))
3621     {
3622       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3623                   _("Starting transport plugins `%s'\n"), plugs);
3624       pos = strtok (plugs, " ");
3625       while (pos != NULL)
3626         {
3627           start_transport (server, pos);
3628           no_transports = 0;
3629           pos = strtok (NULL, " ");
3630         }
3631       GNUNET_free (plugs);
3632     }
3633   GNUNET_SCHEDULER_add_delayed (sched,
3634                                 GNUNET_TIME_UNIT_FOREVER_REL,
3635                                 &shutdown_task, NULL);
3636   if (no_transports)
3637     refresh_hello ();
3638
3639 #if DEBUG_TRANSPORT
3640   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Transport service ready.\n"));
3641 #endif
3642   /* process client requests */
3643   GNUNET_SERVER_add_handlers (server, handlers);
3644 }
3645
3646
3647 /**
3648  * The main function for the transport service.
3649  *
3650  * @param argc number of arguments from the command line
3651  * @param argv command line arguments
3652  * @return 0 ok, 1 on error
3653  */
3654 int
3655 main (int argc, char *const *argv)
3656 {
3657   return (GNUNET_OK ==
3658           GNUNET_SERVICE_run (argc,
3659                               argv,
3660                               "transport",
3661                               GNUNET_SERVICE_OPTION_NONE,
3662                               &run, NULL)) ? 0 : 1;
3663 }
3664
3665 /* end of gnunet-service-transport.c */