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