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