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