18b50b38a85b38128f4be854cb042665b782420b
[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       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
757                   "Transmission to client failed, closing connection.\n");
758       /* fatal error with client, free message queue! */
759       while (NULL != (q = client->message_queue_head))
760         {
761           client->message_queue_head = q->next;
762           GNUNET_free (q);
763         }
764       client->message_queue_tail = NULL;
765       client->message_count = 0;
766       return 0;
767     }
768   cbuf = buf;
769   tsize = 0;
770   while (NULL != (q = client->message_queue_head))
771     {
772       msg = (const struct GNUNET_MessageHeader *) &q[1];
773       msize = ntohs (msg->size);
774       if (msize + tsize > size)
775         break;
776       client->message_queue_head = q->next;
777       if (q->next == NULL)
778         client->message_queue_tail = NULL;
779       memcpy (&cbuf[tsize], msg, msize);
780       tsize += msize;
781       GNUNET_free (q);
782       client->message_count--;
783     }
784   GNUNET_assert (tsize > 0);
785   if (NULL != q)
786     {
787       th = GNUNET_SERVER_notify_transmit_ready (client->client,
788                                                 msize,
789                                                 GNUNET_TIME_UNIT_FOREVER_REL,
790                                                 &transmit_to_client_callback,
791                                                 client);
792       GNUNET_assert (th != NULL);
793     }
794   return tsize;
795 }
796
797
798 /**
799  * Send the specified message to the specified client.  Since multiple
800  * messages may be pending for the same client at a time, this code
801  * makes sure that no message is lost.
802  *
803  * @param client client to transmit the message to
804  * @param msg the message to send
805  * @param may_drop can this message be dropped if the
806  *        message queue for this client is getting far too large?
807  */
808 static void
809 transmit_to_client (struct TransportClient *client,
810                     const struct GNUNET_MessageHeader *msg, int may_drop)
811 {
812   struct ClientMessageQueueEntry *q;
813   uint16_t msize;
814   struct GNUNET_NETWORK_TransmitHandle *th;
815
816   if ((client->message_count >= MAX_PENDING) && (GNUNET_YES == may_drop))
817     {
818       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
819                   _
820                   ("Dropping message, have %u messages pending (%u is the soft limit)\n"),
821                   client->message_count, MAX_PENDING);
822       /* TODO: call to statistics... */
823       return;
824     }
825   client->message_count++;
826   msize = ntohs (msg->size);
827   q = GNUNET_malloc (sizeof (struct ClientMessageQueueEntry) + msize);
828   memcpy (&q[1], msg, msize);
829   /* append to message queue */
830   if (client->message_queue_tail == NULL)
831     {
832       client->message_queue_tail = q;
833     }
834   else
835     {
836       client->message_queue_tail->next = q;
837       client->message_queue_tail = q;
838     }
839   if (client->message_queue_head == NULL)
840     {
841       client->message_queue_head = q;
842       th = GNUNET_SERVER_notify_transmit_ready (client->client,
843                                                 msize,
844                                                 GNUNET_TIME_UNIT_FOREVER_REL,
845                                                 &transmit_to_client_callback,
846                                                 client);
847       GNUNET_assert (th != NULL);
848     }
849 }
850
851
852 /**
853  * Find alternative plugins for communication.
854  *
855  * @param neighbour for which neighbour should we try to find
856  *        more plugins?
857  */
858 static void
859 try_alternative_plugins (struct NeighbourList *neighbour)
860 {
861   struct ReadyList *rl;
862
863   if ((neighbour->plugins != NULL) &&
864       (neighbour->retry_plugins_time.value >
865        GNUNET_TIME_absolute_get ().value))
866     return;                     /* don't try right now */
867   neighbour->retry_plugins_time
868     = GNUNET_TIME_relative_to_absolute (PLUGIN_RETRY_FREQUENCY);
869
870   rl = neighbour->plugins;
871   while (rl != NULL)
872     {
873       if (rl->connect_attempts > 0)
874         rl->connect_attempts--; /* amnesty */
875       rl = rl->next;
876     }
877
878 }
879
880
881 /**
882  * Check the ready list for the given neighbour and
883  * if a plugin is ready for transmission (and if we
884  * have a message), do so!
885  *
886  * @param neighbour target peer for which to check the plugins
887  */
888 static void try_transmission_to_peer (struct NeighbourList *neighbour);
889
890
891 /**
892  * Function called by the GNUNET_TRANSPORT_TransmitFunction
893  * upon "completion" of a send request.  This tells the API
894  * that it is now legal to send another message to the given
895  * peer.
896  *
897  * @param cls closure, identifies the entry on the
898  *            message queue that was transmitted and the
899  *            client responsible for queueing the message
900  * @param rl identifies plugin used for the transmission for
901  *           this neighbour; needs to be re-enabled for
902  *           future transmissions
903  * @param target the peer receiving the message
904  * @param result GNUNET_OK on success, if the transmission
905  *           failed, we should not tell the client to transmit
906  *           more messages
907  */
908 static void
909 transmit_send_continuation (void *cls,
910                             struct ReadyList *rl,
911                             const struct GNUNET_PeerIdentity *target,
912                             int result)
913 {
914   struct MessageQueue *mq = cls;
915   struct SendOkMessage send_ok_msg;
916   struct NeighbourList *n;
917
918   GNUNET_assert (mq != NULL);
919   n = mq->neighbour;
920   GNUNET_assert (n != NULL);
921   GNUNET_assert (0 ==
922                  memcmp (&n->id, target,
923                          sizeof (struct GNUNET_PeerIdentity)));
924   if (rl == NULL)
925     {
926       rl = n->plugins;
927       while ((rl != NULL) && (rl->plugin != mq->plugin))
928         rl = rl->next;
929       GNUNET_assert (rl != NULL);
930     }
931   if (result == GNUNET_OK)
932     {
933       rl->timeout = GNUNET_TIME_relative_to_absolute (IDLE_CONNECTION_TIMEOUT);
934     }
935   else
936     {
937       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
938                   "Transmission failed, marking connection as down.\n");
939       rl->connected = GNUNET_NO;
940     }
941   if (!mq->internal_msg)
942     rl->transmit_ready = GNUNET_YES;
943   if (mq->client != NULL)
944     {
945       send_ok_msg.header.size = htons (sizeof (send_ok_msg));
946       send_ok_msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK);
947       send_ok_msg.success = htonl (result);
948       send_ok_msg.peer = n->id;
949       transmit_to_client (mq->client, &send_ok_msg.header, GNUNET_NO);
950     }
951   GNUNET_free (mq->message);
952   GNUNET_free (mq);
953   /* one plugin just became ready again, try transmitting
954      another message (if available) */
955   try_transmission_to_peer (n);
956 }
957
958
959
960
961 /**
962  * We could not use an existing (or validated) connection to
963  * talk to a peer.  Try addresses that have not yet been
964  * validated.
965  *
966  * @param n neighbour we want to communicate with
967  * @return plugin ready to talk, or NULL if none is available
968  */
969 static struct ReadyList *
970 try_unvalidated_addresses (struct NeighbourList *n)
971 {
972   struct ValidationList *vl;
973   struct ValidationAddress *va;
974   struct GNUNET_PeerIdentity id;
975   struct GNUNET_TIME_Absolute now;
976   unsigned int total;
977   unsigned int cnt;
978   struct ReadyList *rl;
979   struct TransportPlugin *plugin;
980
981 #if DEBUG_TRANSPORT
982   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
983               "Trying to connect to `%4s' using unvalidated addresses\n",
984               GNUNET_i2s (&n->id));
985 #endif
986   /* NOTE: this function needs to not only identify the
987      plugin but also setup "plugin_handle", binding it to the
988      right address using the plugin's "send_to" API */
989   now = GNUNET_TIME_absolute_get ();
990   vl = pending_validations;
991   while (vl != NULL)
992     {
993       GNUNET_CRYPTO_hash (&vl->publicKey,
994                           sizeof (struct
995                                   GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
996                           &id.hashPubKey);
997       if (0 == memcmp (&id, &n->id, sizeof (struct GNUNET_PeerIdentity)))
998         break;
999       vl = vl->next;
1000     }
1001   if (vl == NULL)
1002     {
1003 #if DEBUG_TRANSPORT
1004       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1005                   "No unvalidated address found for peer `%4s'\n",
1006                   GNUNET_i2s (&n->id));
1007 #endif
1008       return NULL;
1009     }
1010   total = 0;
1011   cnt = 0;
1012   va = vl->addresses;
1013   while (va != NULL)
1014     {
1015       cnt++;
1016       if (va->expiration.value > now.value)
1017         total++;
1018       va = va->next;
1019     }
1020   if (total == 0)
1021     {
1022 #if DEBUG_TRANSPORT
1023       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1024                   "All %u unvalidated addresses for peer have expired\n",
1025                   cnt);
1026 #endif
1027       return NULL;
1028     }
1029   total = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, total);
1030   for (va = vl->addresses; va != NULL; va = va->next)
1031     {
1032       if (va->expiration.value <= now.value)
1033         continue;
1034       if (total > 0)
1035         {
1036           total--;
1037           continue;
1038         }
1039 #if DEBUG_TRANSPORT
1040       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
1041                   "Trying unvalidated address of `%s' transport\n",
1042                   va->transport_name);
1043 #endif
1044       plugin = find_transport (va->transport_name);
1045       if (plugin == NULL)
1046         {
1047           GNUNET_break (0);
1048           break;
1049         }
1050       rl = GNUNET_malloc (sizeof (struct ReadyList));
1051       rl->next = n->plugins;
1052       n->plugins = rl;
1053       rl->plugin = plugin;
1054       rl->plugin_handle = plugin->api->send_to (plugin->api->cls,
1055                                                 &n->id,
1056                                                 NULL,
1057                                                 NULL,
1058                                                 GNUNET_TIME_UNIT_ZERO,
1059                                                 &va->msg[1], va->addr_len);
1060       rl->transmit_ready = GNUNET_YES;
1061       return rl;
1062     }
1063   return NULL;
1064 }
1065
1066
1067 /**
1068  * Check the ready list for the given neighbour and
1069  * if a plugin is ready for transmission (and if we
1070  * have a message), do so!
1071  */
1072 static void
1073 try_transmission_to_peer (struct NeighbourList *neighbour)
1074 {
1075   struct ReadyList *pos;
1076   struct GNUNET_TIME_Relative min_latency;
1077   struct ReadyList *rl;
1078   struct MessageQueue *mq;
1079   struct GNUNET_TIME_Absolute now;
1080
1081   if (neighbour->messages == NULL)
1082     return;                     /* nothing to do */
1083   try_alternative_plugins (neighbour);
1084   min_latency = GNUNET_TIME_UNIT_FOREVER_REL;
1085   rl = NULL;
1086   mq = neighbour->messages;
1087   now = GNUNET_TIME_absolute_get ();
1088   pos = neighbour->plugins;
1089   while (pos != NULL)
1090     {
1091       /* set plugins that are inactive for a long time back to disconnected */
1092       if ((pos->timeout.value < now.value) && (pos->connected == GNUNET_YES))
1093         {
1094 #if DEBUG_TRANSPORT
1095           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1096                       "Marking long-time inactive connection to `%4s' as down.\n",
1097                       GNUNET_i2s (&neighbour->id));
1098 #endif
1099           pos->connected = GNUNET_NO;
1100         }
1101       if (((GNUNET_YES == pos->transmit_ready) ||
1102            (mq->internal_msg)) &&
1103           (pos->connect_attempts < MAX_CONNECT_RETRY) &&
1104           ((rl == NULL) || (min_latency.value > pos->latency.value)))
1105         {
1106           rl = pos;
1107           min_latency = pos->latency;
1108         }
1109       pos = pos->next;
1110     }
1111   if (rl == NULL)
1112     rl = try_unvalidated_addresses (neighbour);
1113   if (rl == NULL)
1114     {
1115 #if DEBUG_TRANSPORT
1116       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1117                   "No plugin ready to transmit message\n");
1118 #endif
1119       return;                   /* nobody ready */
1120     }
1121   if (GNUNET_NO == rl->connected)
1122     {
1123       rl->connect_attempts++;
1124       rl->connected = GNUNET_YES;
1125     }
1126   neighbour->messages = mq->next;
1127   mq->plugin = rl->plugin;
1128   if (!mq->internal_msg)
1129     rl->transmit_ready = GNUNET_NO;
1130 #if DEBUG_TRANSPORT
1131   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1132               "Giving message of type `%u' for `%4s' to plugin `%s'\n",
1133               ntohs (mq->message->type),
1134               GNUNET_i2s (&neighbour->id), rl->plugin->short_name);
1135 #endif
1136   rl->plugin_handle
1137     = rl->plugin->api->send (rl->plugin->api->cls,
1138                              rl->plugin_handle,
1139                              rl,
1140                              &neighbour->id,
1141                              mq->message,
1142                              IDLE_CONNECTION_TIMEOUT,
1143                              &transmit_send_continuation, mq);
1144 }
1145
1146
1147 /**
1148  * Send the specified message to the specified peer.
1149  *
1150  * @param client source of the transmission request (can be NULL)
1151  * @param msg message to send
1152  * @param is_internal is this an internal message
1153  * @param neighbour handle to the neighbour for transmission
1154  */
1155 static void
1156 transmit_to_peer (struct TransportClient *client,
1157                   const struct GNUNET_MessageHeader *msg,
1158                   int is_internal, struct NeighbourList *neighbour)
1159 {
1160   struct MessageQueue *mq;
1161   struct MessageQueue *mqe;
1162   struct GNUNET_MessageHeader *m;
1163
1164 #if DEBUG_TRANSPORT
1165   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1166               _("Sending message of type %u to peer `%4s'\n"),
1167               ntohs (msg->type), GNUNET_i2s (&neighbour->id));
1168 #endif
1169   if (client != NULL)
1170     {
1171       /* check for duplicate submission */
1172       mq = neighbour->messages;
1173       while (NULL != mq)
1174         {
1175           if (mq->client == client)
1176             {
1177               /* client transmitted to same peer twice
1178                  before getting SendOk! */
1179               GNUNET_break (0);
1180               return;
1181             }
1182           mq = mq->next;
1183         }
1184     }
1185   mq = GNUNET_malloc (sizeof (struct MessageQueue));
1186   mq->client = client;
1187   m = GNUNET_malloc (ntohs (msg->size));
1188   memcpy (m, msg, ntohs (msg->size));
1189   mq->message = m;
1190   mq->neighbour = neighbour;
1191   mq->internal_msg = is_internal;
1192
1193   /* find tail */
1194   mqe = neighbour->messages;
1195   if (mqe != NULL)
1196     while (mqe->next != NULL)
1197       mqe = mqe->next;
1198   if (mqe == NULL)
1199     {
1200       /* new head */
1201       neighbour->messages = mq;
1202       try_transmission_to_peer (neighbour);
1203     }
1204   else
1205     {
1206       /* append */
1207       mqe->next = mq;
1208     }
1209 }
1210
1211
1212 struct GeneratorContext
1213 {
1214   struct TransportPlugin *plug_pos;
1215   struct AddressList *addr_pos;
1216   struct GNUNET_TIME_Absolute expiration;
1217 };
1218
1219
1220 static size_t
1221 address_generator (void *cls, size_t max, void *buf)
1222 {
1223   struct GeneratorContext *gc = cls;
1224   size_t ret;
1225
1226   while ((gc->addr_pos == NULL) && (gc->plug_pos != NULL))
1227     {
1228       gc->plug_pos = gc->plug_pos->next;
1229       gc->addr_pos = (gc->plug_pos != NULL) ? gc->plug_pos->addresses : NULL;
1230     }
1231   if (NULL == gc->plug_pos)
1232     return 0;
1233   ret = GNUNET_HELLO_add_address (gc->plug_pos->short_name,
1234                                   gc->expiration,
1235                                   gc->addr_pos->addr,
1236                                   gc->addr_pos->addrlen, buf, max);
1237   gc->addr_pos = gc->addr_pos->next;
1238   return ret;
1239 }
1240
1241
1242 /**
1243  * Construct our HELLO message from all of the addresses of
1244  * all of the transports.
1245  */
1246 static void
1247 refresh_hello ()
1248 {
1249   struct GNUNET_HELLO_Message *hello;
1250   struct TransportClient *cpos;
1251   struct NeighbourList *npos;
1252   struct GeneratorContext gc;
1253
1254 #if DEBUG_TRANSPORT
1255   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
1256               "Refreshing my HELLO\n");
1257 #endif
1258   gc.plug_pos = plugins;
1259   gc.addr_pos = plugins != NULL ? plugins->addresses : NULL;
1260   gc.expiration = GNUNET_TIME_relative_to_absolute (HELLO_ADDRESS_EXPIRATION);
1261   hello = GNUNET_HELLO_create (&my_public_key, &address_generator, &gc);
1262   cpos = clients;
1263   while (cpos != NULL)
1264     {
1265       transmit_to_client (cpos,
1266                           (const struct GNUNET_MessageHeader *) hello,
1267                           GNUNET_NO);
1268       cpos = cpos->next;
1269     }
1270
1271   GNUNET_free_non_null (our_hello);
1272   our_hello = hello;
1273   our_hello_version++;
1274   npos = neighbours;
1275   while (npos != NULL)
1276     {
1277       transmit_to_peer (NULL,
1278                         (const struct GNUNET_MessageHeader *) our_hello,
1279                         GNUNET_YES, npos);
1280       npos = npos->next;
1281     }
1282 }
1283
1284
1285 /**
1286  * Task used to clean up expired addresses for a plugin.
1287  *
1288  * @param cls closure
1289  * @param tc context
1290  */
1291 static void
1292 expire_address_task (void *cls,
1293                      const struct GNUNET_SCHEDULER_TaskContext *tc);
1294
1295
1296 /**
1297  * Update the list of addresses for this plugin,
1298  * expiring those that are past their expiration date.
1299  *
1300  * @param plugin addresses of which plugin should be recomputed?
1301  * @param fresh set to GNUNET_YES if a new address was added
1302  *        and we need to regenerate the HELLO even if nobody
1303  *        expired
1304  */
1305 static void
1306 update_addresses (struct TransportPlugin *plugin, int fresh)
1307 {
1308   struct GNUNET_TIME_Relative min_remaining;
1309   struct GNUNET_TIME_Relative remaining;
1310   struct GNUNET_TIME_Absolute now;
1311   struct AddressList *pos;
1312   struct AddressList *prev;
1313   struct AddressList *next;
1314   int expired;
1315
1316   if (plugin->address_update_task != GNUNET_SCHEDULER_NO_PREREQUISITE_TASK)
1317     GNUNET_SCHEDULER_cancel (plugin->env.sched, plugin->address_update_task);
1318   plugin->address_update_task = GNUNET_SCHEDULER_NO_PREREQUISITE_TASK;
1319   now = GNUNET_TIME_absolute_get ();
1320   min_remaining = GNUNET_TIME_UNIT_FOREVER_REL;
1321   expired = GNUNET_NO;
1322   prev = NULL;
1323   pos = plugin->addresses;
1324   while (pos != NULL)
1325     {
1326       next = pos->next;
1327       if (pos->expires.value < now.value)
1328         {
1329           expired = GNUNET_YES;
1330           if (prev == NULL)
1331             plugin->addresses = pos->next;
1332           else
1333             prev->next = pos->next;
1334           GNUNET_free (pos);
1335         }
1336       else
1337         {
1338           remaining = GNUNET_TIME_absolute_get_remaining (pos->expires);
1339           if (remaining.value < min_remaining.value)
1340             min_remaining = remaining;
1341           prev = pos;
1342         }
1343       pos = next;
1344     }
1345
1346   if (expired || fresh)
1347     refresh_hello ();
1348   if (min_remaining.value < GNUNET_TIME_UNIT_FOREVER_REL.value)
1349     plugin->address_update_task
1350       = GNUNET_SCHEDULER_add_delayed (plugin->env.sched,
1351                                       GNUNET_NO,
1352                                       GNUNET_SCHEDULER_PRIORITY_IDLE,
1353                                       GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
1354                                       min_remaining,
1355                                       &expire_address_task, plugin);
1356
1357 }
1358
1359
1360 /**
1361  * Task used to clean up expired addresses for a plugin.
1362  *
1363  * @param cls closure
1364  * @param tc context
1365  */
1366 static void
1367 expire_address_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1368 {
1369   struct TransportPlugin *plugin = cls;
1370   plugin->address_update_task = GNUNET_SCHEDULER_NO_PREREQUISITE_TASK;
1371   update_addresses (plugin, GNUNET_NO);
1372 }
1373
1374
1375 /**
1376  * Function that must be called by each plugin to notify the
1377  * transport service about the addresses under which the transport
1378  * provided by the plugin can be reached.
1379  *
1380  * @param cls closure
1381  * @param name name of the transport that generated the address
1382  * @param addr one of the addresses of the host, NULL for the last address
1383  *        the specific address format depends on the transport
1384  * @param addrlen length of the address
1385  * @param expires when should this address automatically expire?
1386  */
1387 static void
1388 plugin_env_notify_address (void *cls,
1389                            const char *name,
1390                            const void *addr,
1391                            size_t addrlen,
1392                            struct GNUNET_TIME_Relative expires)
1393 {
1394   struct TransportPlugin *p = cls;
1395   struct AddressList *al;
1396   struct GNUNET_TIME_Absolute abex;
1397
1398 #if DEBUG_TRANSPORT
1399   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1400               "Plugin `%s' informs us about a new address `%s'\n", name,
1401               GNUNET_a2s(addr, addrlen));
1402 #endif
1403   abex = GNUNET_TIME_relative_to_absolute (expires);
1404   GNUNET_assert (p == find_transport (name));
1405
1406   al = p->addresses;
1407   while (al != NULL)
1408     {
1409       if ((addrlen == al->addrlen) && (0 == memcmp (addr, &al[1], addrlen)))
1410         {
1411           if (al->expires.value < abex.value)
1412             al->expires = abex;
1413           return;
1414         }
1415       al = al->next;
1416     }
1417   al = GNUNET_malloc (sizeof (struct AddressList) + addrlen);
1418   al->addr = &al[1];
1419   al->next = p->addresses;
1420   p->addresses = al;
1421   al->expires = abex;
1422   al->addrlen = addrlen;
1423   memcpy (&al[1], addr, addrlen);
1424   update_addresses (p, GNUNET_YES);
1425 }
1426
1427
1428 struct LookupHelloContext
1429 {
1430   GNUNET_TRANSPORT_AddressCallback iterator;
1431
1432   void *iterator_cls;
1433 };
1434
1435
1436 static int
1437 lookup_address_callback (void *cls,
1438                          const char *tname,
1439                          struct GNUNET_TIME_Absolute expiration,
1440                          const void *addr, size_t addrlen)
1441 {
1442   struct LookupHelloContext *lhc = cls;
1443   lhc->iterator (lhc->iterator_cls, tname, addr, addrlen);
1444   return GNUNET_OK;
1445 }
1446
1447
1448 static void
1449 lookup_hello_callback (void *cls,
1450                        const struct GNUNET_PeerIdentity *peer,
1451                        const struct GNUNET_HELLO_Message *h, uint32_t trust)
1452 {
1453   struct LookupHelloContext *lhc = cls;
1454
1455   if (peer == NULL)
1456     {
1457       lhc->iterator (lhc->iterator_cls, NULL, NULL, 0);
1458       GNUNET_free (lhc);
1459       return;
1460     }
1461   if (h == NULL)
1462     return;
1463   GNUNET_HELLO_iterate_addresses (h,
1464                                   GNUNET_NO, &lookup_address_callback, lhc);
1465 }
1466
1467
1468 /**
1469  * Function that allows a transport to query the known
1470  * network addresses for a given peer.
1471  *
1472  * @param cls closure
1473  * @param timeout after how long should we time out?
1474  * @param target which peer are we looking for?
1475  * @param iter function to call for each known address
1476  * @param iter_cls closure for iter
1477  */
1478 static void
1479 plugin_env_lookup_address (void *cls,
1480                            struct GNUNET_TIME_Relative timeout,
1481                            const struct GNUNET_PeerIdentity *target,
1482                            GNUNET_TRANSPORT_AddressCallback iter,
1483                            void *iter_cls)
1484 {
1485   struct LookupHelloContext *lhc;
1486
1487   lhc = GNUNET_malloc (sizeof (struct LookupHelloContext));
1488   lhc->iterator = iter;
1489   lhc->iterator_cls = iter_cls;
1490   GNUNET_PEERINFO_for_all (cfg,
1491                            sched,
1492                            target, 0, timeout, &lookup_hello_callback, &lhc);
1493 }
1494
1495
1496 /**
1497  * Notify all of our clients about a peer connecting.
1498  */
1499 static void
1500 notify_clients_connect (const struct GNUNET_PeerIdentity *peer,
1501                         struct GNUNET_TIME_Relative latency)
1502 {
1503   struct ConnectInfoMessage cim;
1504   struct TransportClient *cpos;
1505
1506 #if DEBUG_TRANSPORT
1507   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1508               "Informing clients about peer `%4s' connecting to us\n",
1509               GNUNET_i2s (peer));
1510 #endif
1511   cim.header.size = htons (sizeof (struct ConnectInfoMessage));
1512   cim.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
1513   cim.quota_out = htonl (default_quota_out);
1514   cim.latency = GNUNET_TIME_relative_hton (latency);
1515   memcpy (&cim.id, peer, sizeof (struct GNUNET_PeerIdentity));
1516   cpos = clients;
1517   while (cpos != NULL)
1518     {
1519       transmit_to_client (cpos, &cim.header, GNUNET_NO);
1520       cpos = cpos->next;
1521     }
1522 }
1523
1524
1525 /**
1526  * Notify all of our clients about a peer disconnecting.
1527  */
1528 static void
1529 notify_clients_disconnect (const struct GNUNET_PeerIdentity *peer)
1530 {
1531   struct DisconnectInfoMessage dim;
1532   struct TransportClient *cpos;
1533
1534 #if DEBUG_TRANSPORT
1535   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1536               "Informing clients about peer `%4s' disconnecting\n",
1537               GNUNET_i2s (peer));
1538 #endif
1539   dim.header.size = htons (sizeof (struct DisconnectInfoMessage));
1540   dim.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT);
1541   dim.reserved = htonl (0);
1542   memcpy (&dim.peer, peer, sizeof (struct GNUNET_PeerIdentity));
1543   cpos = clients;
1544   while (cpos != NULL)
1545     {
1546       transmit_to_client (cpos, &dim.header, GNUNET_NO);
1547       cpos = cpos->next;
1548     }
1549 }
1550
1551
1552 /**
1553  * Copy any validated addresses to buf.
1554  *
1555  * @return 0 once all addresses have been
1556  *         returned
1557  */
1558 static size_t
1559 list_validated_addresses (void *cls, size_t max, void *buf)
1560 {
1561   struct ValidationAddress **va = cls;
1562   size_t ret;
1563
1564   while ((NULL != *va) && ((*va)->ok != GNUNET_YES))
1565     *va = (*va)->next;
1566   if (NULL == *va)
1567     return 0;
1568   ret = GNUNET_HELLO_add_address ((*va)->transport_name,
1569                                   (*va)->expiration,
1570                                   &(*va)->msg[1], (*va)->addr_len, buf, max);
1571   *va = (*va)->next;
1572   return ret;
1573 }
1574
1575
1576 /**
1577  * HELLO validation cleanup task.
1578  */
1579 static void
1580 cleanup_validation (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1581 {
1582   struct ValidationAddress *va;
1583   struct ValidationList *pos;
1584   struct ValidationList *prev;
1585   struct GNUNET_TIME_Absolute now;
1586   struct GNUNET_HELLO_Message *hello;
1587   struct GNUNET_PeerIdentity pid;
1588
1589 #if DEBUG_TRANSPORT
1590   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
1591               "HELLO validation cleanup background task running...\n");
1592 #endif
1593   now = GNUNET_TIME_absolute_get ();
1594   prev = NULL;
1595   pos = pending_validations;
1596   while (pos != NULL)
1597     {
1598       if (pos->timeout.value < now.value)
1599         {
1600           if (prev == NULL)
1601             pending_validations = pos->next;
1602           else
1603             prev->next = pos->next;
1604           va = pos->addresses;
1605           hello = GNUNET_HELLO_create (&pos->publicKey,
1606                                        &list_validated_addresses, &va);
1607           GNUNET_CRYPTO_hash (&pos->publicKey,
1608                               sizeof (struct
1609                                       GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1610                               &pid.hashPubKey);
1611 #if DEBUG_TRANSPORT
1612           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1613                       "Creating persistent `%s' message for peer `%4s' based on confirmed addresses.\n",
1614                       "HELLO", GNUNET_i2s (&pid));
1615 #endif
1616           GNUNET_PEERINFO_add_peer (cfg, sched, &pid, hello);
1617           GNUNET_free (hello);
1618           while (NULL != (va = pos->addresses))
1619             {
1620               pos->addresses = va->next;
1621               GNUNET_free (va->transport_name);
1622               GNUNET_free (va);
1623             }
1624           GNUNET_free (pos);
1625           if (prev == NULL)
1626             pos = pending_validations;
1627           else
1628             pos = prev->next;
1629           continue;
1630         }
1631       prev = pos;
1632       pos = pos->next;
1633     }
1634
1635   /* finally, reschedule cleanup if needed; list is
1636      ordered by timeout, so we need the last element... */
1637   pos = pending_validations;
1638   while ((pos != NULL) && (pos->next != NULL))
1639     pos = pos->next;
1640   if (NULL != pos)
1641     GNUNET_SCHEDULER_add_delayed (sched,
1642                                   GNUNET_NO,
1643                                   GNUNET_SCHEDULER_PRIORITY_IDLE,
1644                                   GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
1645                                   GNUNET_TIME_absolute_get_remaining
1646                                   (pos->timeout), &cleanup_validation, NULL);
1647 }
1648
1649
1650 struct CheckHelloValidatedContext
1651 {
1652   /**
1653    * Plugin for which we are validating.
1654    */
1655   struct TransportPlugin *plugin;
1656
1657   /**
1658    * Hello that we are validating.
1659    */
1660   struct GNUNET_HELLO_Message *hello;
1661
1662   /**
1663    * Validation list being build.
1664    */
1665   struct ValidationList *e;
1666
1667 };
1668
1669
1670 /**
1671  * Append the given address to the list of entries
1672  * that need to be validated.
1673  */
1674 static int
1675 run_validation (void *cls,
1676                 const char *tname,
1677                 struct GNUNET_TIME_Absolute expiration,
1678                 const void *addr, size_t addrlen)
1679 {
1680   struct ValidationList *e = cls;
1681   struct TransportPlugin *tp;
1682   struct ValidationAddress *va;
1683   struct ValidationChallengeMessage *vcm;
1684   struct GNUNET_PeerIdentity id;
1685
1686   tp = find_transport (tname);
1687   if (tp == NULL)
1688     {
1689       GNUNET_log (GNUNET_ERROR_TYPE_INFO |
1690                   GNUNET_ERROR_TYPE_BULK,
1691                   _
1692                   ("Transport `%s' not loaded, will not try to validate peer address using this transport.\n"),
1693                   tname);
1694       return GNUNET_OK;
1695     }
1696   GNUNET_CRYPTO_hash (&e->publicKey,
1697                       sizeof (struct
1698                               GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1699                       &id.hashPubKey);
1700   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1701               "Scheduling validation of address `%s' via `%s' for `%4s'\n",
1702               GNUNET_a2s(addr, addrlen),
1703               tname,
1704               GNUNET_i2s(&id));
1705
1706   va = GNUNET_malloc (sizeof (struct ValidationAddress) +
1707                       sizeof (struct ValidationChallengeMessage) + addrlen);
1708   va->next = e->addresses;
1709   e->addresses = va;
1710   vcm = (struct ValidationChallengeMessage *) &va[1];
1711   va->msg = vcm;
1712   va->transport_name = GNUNET_strdup (tname);
1713   va->addr_len = addrlen;
1714   vcm->header.size =
1715     htons (sizeof (struct ValidationChallengeMessage) + addrlen);
1716   vcm->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_PING);
1717   vcm->purpose.size =
1718     htonl (sizeof (struct ValidationChallengeMessage) + addrlen -
1719            sizeof (struct GNUNET_MessageHeader));
1720   vcm->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_HELLO);
1721   vcm->challenge = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1722                                              (unsigned int) -1);
1723   vcm->target = id;
1724   memcpy (&vcm[1], addr, addrlen);
1725   return GNUNET_OK;
1726 }
1727
1728
1729 /**
1730  * Check if addresses in validated hello "h" overlap with
1731  * those in "chvc->hello" and update "chvc->hello" accordingly,
1732  * removing those addresses that have already been validated.
1733  */
1734 static void
1735 check_hello_validated (void *cls,
1736                        const struct GNUNET_PeerIdentity *peer,
1737                        const struct GNUNET_HELLO_Message *h, uint32_t trust)
1738 {
1739   struct CheckHelloValidatedContext *chvc = cls;
1740   struct ValidationAddress *va;
1741   struct TransportPlugin *tp;
1742   int first_call;
1743
1744   first_call = GNUNET_NO;
1745   if (chvc->e == NULL)
1746     {
1747       first_call = GNUNET_YES;
1748       chvc->e = GNUNET_malloc (sizeof (struct ValidationList));
1749       GNUNET_assert (GNUNET_OK ==
1750                      GNUNET_HELLO_get_key (h != NULL ? h : chvc->hello,
1751                                            &chvc->e->publicKey));
1752       chvc->e->timeout =
1753         GNUNET_TIME_relative_to_absolute (HELLO_VERIFICATION_TIMEOUT);
1754       chvc->e->next = pending_validations;
1755       pending_validations = chvc->e;
1756     }
1757   if (h != NULL)
1758     {
1759       GNUNET_HELLO_iterate_new_addresses (chvc->hello,
1760                                           h,
1761                                           GNUNET_TIME_absolute_get (),
1762                                           &run_validation, chvc->e);
1763     }
1764   else if (GNUNET_YES == first_call)
1765     {
1766       /* no existing HELLO, all addresses are new */
1767       GNUNET_HELLO_iterate_addresses (chvc->hello,
1768                                       GNUNET_NO, &run_validation, chvc->e);
1769     }
1770   if (h != NULL)
1771     return;                     /* wait for next call */
1772   /* finally, transmit validation attempts */
1773   va = chvc->e->addresses;
1774   while (va != NULL)
1775     {
1776 #if DEBUG_TRANSPORT
1777       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1778                   "Establishing `%s' connection to validate `%s' of `%4s' (sending our `%s')\n",
1779                   va->transport_name,
1780                   "HELLO", GNUNET_i2s (&va->msg->target), "HELLO");
1781 #endif
1782       tp = find_transport (va->transport_name);
1783       GNUNET_assert (tp != NULL);
1784       if (NULL ==
1785           tp->api->send_to (tp->api->cls,
1786                             &va->msg->target,
1787                             (const struct GNUNET_MessageHeader *) our_hello,
1788                             &va->msg->header,
1789                             HELLO_VERIFICATION_TIMEOUT,
1790                             &va->msg[1], va->addr_len))
1791         va->ok = GNUNET_SYSERR;
1792       va = va->next;
1793     }
1794   if (chvc->e->next == NULL)
1795     GNUNET_SCHEDULER_add_delayed (sched,
1796                                   GNUNET_NO,
1797                                   GNUNET_SCHEDULER_PRIORITY_IDLE,
1798                                   GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
1799                                   GNUNET_TIME_absolute_get_remaining
1800                                   (chvc->e->timeout), &cleanup_validation,
1801                                   NULL);
1802   GNUNET_free (chvc);
1803 }
1804
1805
1806 /**
1807  * Process HELLO-message.
1808  *
1809  * @param plugin transport involved, may be NULL
1810  * @param message the actual message
1811  * @return GNUNET_OK if the HELLO was well-formed, GNUNET_SYSERR otherwise
1812  */
1813 static int
1814 process_hello (struct TransportPlugin *plugin,
1815                const struct GNUNET_MessageHeader *message)
1816 {
1817   struct ValidationList *e;
1818   uint16_t hsize;
1819   struct GNUNET_PeerIdentity target;
1820   const struct GNUNET_HELLO_Message *hello;
1821   struct CheckHelloValidatedContext *chvc;
1822   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded publicKey;
1823
1824   hsize = ntohs (message->size);
1825   if ((ntohs (message->type) != GNUNET_MESSAGE_TYPE_HELLO) ||
1826       (hsize < sizeof (struct GNUNET_MessageHeader)))
1827     {
1828       GNUNET_break (0);
1829       return GNUNET_SYSERR;
1830     }
1831   /* first, check if load is too high */
1832   if (GNUNET_OS_load_cpu_get (cfg) > 100)
1833     {
1834       /* TODO: call to stats? */
1835       return GNUNET_OK;
1836     }
1837   hello = (const struct GNUNET_HELLO_Message *) message;
1838   if (GNUNET_OK != GNUNET_HELLO_get_key (hello, &publicKey))
1839     {
1840       GNUNET_break_op (0);
1841       return GNUNET_SYSERR;
1842     }
1843   GNUNET_CRYPTO_hash (&publicKey,
1844                       sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1845                       &target.hashPubKey);
1846 #if DEBUG_TRANSPORT
1847   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1848               "Processing `%s' message for `%4s'\n",
1849               "HELLO", GNUNET_i2s (&target));
1850 #endif
1851   /* check if a HELLO for this peer is already on the validation list */
1852   e = pending_validations;
1853   while (e != NULL)
1854     {
1855       if (0 == memcmp (&e->publicKey,
1856                        &publicKey,
1857                        sizeof (struct
1858                                GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)))
1859         {
1860           /* TODO: call to stats? */
1861 #if DEBUG_TRANSPORT
1862           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1863                       "`%s' message for peer `%4s' is already pending; ignoring new message\n",
1864                       "HELLO", GNUNET_i2s (&target));
1865 #endif    
1866           return GNUNET_OK;
1867         }
1868       e = e->next;
1869     }
1870   chvc = GNUNET_malloc (sizeof (struct CheckHelloValidatedContext) + hsize);
1871   chvc->plugin = plugin;
1872   chvc->hello = (struct GNUNET_HELLO_Message *) &chvc[1];
1873   memcpy (chvc->hello, hello, hsize);
1874   /* finally, check if HELLO was previously validated
1875      (continuation will then schedule actual validation) */
1876   GNUNET_PEERINFO_for_all (cfg,
1877                            sched,
1878                            &target,
1879                            0,
1880                            HELLO_VERIFICATION_TIMEOUT,
1881                            &check_hello_validated, chvc);
1882   return GNUNET_OK;
1883 }
1884
1885
1886 /**
1887  * Handle PING-message.  If the plugin that gave us the message is
1888  * able to queue the PONG immediately, we only queue one PONG.
1889  * Otherwise we send at most TWO PONG messages, one via an unconfirmed
1890  * transport and one via a confirmed transport.  Both addresses are
1891  * selected randomly among those available.
1892  *
1893  * @param plugin plugin that gave us the message
1894  * @param sender claimed sender of the PING
1895  * @param plugin_context context that might be used to send response
1896  * @param message the actual message
1897  */
1898 static void
1899 process_ping (struct TransportPlugin *plugin,
1900               const struct GNUNET_PeerIdentity *sender,
1901               void *plugin_context,
1902               const struct GNUNET_MessageHeader *message)
1903 {
1904   const struct ValidationChallengeMessage *vcm;
1905   struct ValidationChallengeResponse vcr;
1906   uint16_t msize;
1907   struct NeighbourList *n;
1908
1909 #if DEBUG_TRANSPORT
1910   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
1911               "Processing PING\n");
1912 #endif
1913   msize = ntohs (message->size);
1914   if (msize < sizeof (struct ValidationChallengeMessage))
1915     {
1916       GNUNET_break_op (0);
1917       return;
1918     }
1919   vcm = (const struct ValidationChallengeMessage *) message;
1920   if (0 != memcmp (&vcm->target,
1921                    &my_identity, sizeof (struct GNUNET_PeerIdentity)))
1922     {
1923       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1924                   _("Received `%s' message not destined for me!\n"), "PING");
1925       /* TODO: call statistics */
1926       return;
1927     }
1928   if ((ntohl (vcm->purpose.size) !=
1929        msize - sizeof (struct GNUNET_MessageHeader))
1930       || (ntohl (vcm->purpose.purpose) !=
1931           GNUNET_SIGNATURE_PURPOSE_TRANSPORT_HELLO))
1932     {
1933       GNUNET_break_op (0);
1934       return;
1935     }
1936   msize -= sizeof (struct ValidationChallengeMessage);
1937   if (GNUNET_OK !=
1938       plugin->api->address_suggested (plugin->api->cls, &vcm[1], msize))
1939     {
1940       GNUNET_break_op (0);
1941       return;
1942     }
1943   vcr.header.size = htons (sizeof (struct ValidationChallengeResponse));
1944   vcr.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_PONG);
1945   vcr.challenge = vcm->challenge;
1946   vcr.sender = my_identity;
1947   GNUNET_assert (GNUNET_OK ==
1948                  GNUNET_CRYPTO_rsa_sign (my_private_key,
1949                                          &vcm->purpose, &vcr.signature));
1950 #if EXTRA_CHECKS
1951   GNUNET_assert (GNUNET_OK ==
1952                  GNUNET_CRYPTO_rsa_verify
1953                  (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_HELLO, &vcm->purpose,
1954                   &vcr.signature, &my_public_key));
1955 #endif
1956 #if DEBUG_TRANSPORT
1957   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
1958               "Trying to transmit PONG using inbound connection\n");
1959 #endif
1960   n = find_neighbour (sender);
1961   if (n == NULL)
1962     {
1963       GNUNET_break (0);
1964       return;
1965     }
1966   transmit_to_peer (NULL, &vcr.header, GNUNET_YES, n);
1967 }
1968
1969
1970 /**
1971  * Handle PONG-message.
1972  *
1973  * @param message the actual message
1974  */
1975 static void
1976 process_pong (struct TransportPlugin *plugin,
1977               const struct GNUNET_MessageHeader *message)
1978 {
1979   const struct ValidationChallengeResponse *vcr;
1980   struct ValidationList *pos;
1981   struct GNUNET_PeerIdentity peer;
1982   struct ValidationAddress *va;
1983   int all_done;
1984   int matched;
1985
1986 #if DEBUG_TRANSPORT
1987   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
1988               "Processing PONG\n");
1989 #endif
1990   vcr = (const struct ValidationChallengeResponse *) message;
1991   pos = pending_validations;
1992   while (pos != NULL)
1993     {
1994       GNUNET_CRYPTO_hash (&pos->publicKey,
1995                           sizeof (struct
1996                                   GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1997                           &peer.hashPubKey);
1998       if (0 ==
1999           memcmp (&peer, &vcr->sender, sizeof (struct GNUNET_PeerIdentity)))
2000         break;
2001       pos = pos->next;
2002     }
2003   if (pos == NULL)
2004     {
2005       /* TODO: call statistics (unmatched PONG) */
2006       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2007                   _
2008                   ("Received `%s' message but have no record of a matching `%s' message. Ignoring.\n"),
2009                   "PONG", "PING");
2010       return;
2011     }
2012   all_done = GNUNET_YES;
2013   matched = GNUNET_NO;
2014   va = pos->addresses;
2015   while (va != NULL)
2016     {
2017       if (va->msg->challenge == vcr->challenge)
2018         {
2019           if (GNUNET_OK !=
2020               GNUNET_CRYPTO_rsa_verify
2021               (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_HELLO, &va->msg->purpose,
2022                &vcr->signature, &pos->publicKey))
2023             {
2024               /* this could rarely happen if we used the same
2025                  challenge number for the peer for two different
2026                  transports / addresses, but the likelihood is
2027                  very small... */
2028               GNUNET_break_op (0);
2029             }
2030           else
2031             {
2032 #if DEBUG_TRANSPORT
2033               GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2034                           "Confirmed validity of peer address.\n");
2035 #endif
2036               va->ok = GNUNET_YES;
2037               va->expiration =
2038                 GNUNET_TIME_relative_to_absolute (HELLO_ADDRESS_EXPIRATION);
2039               matched = GNUNET_YES;
2040             }
2041         }
2042       if (va->ok != GNUNET_YES)
2043         all_done = GNUNET_NO;
2044       va = va->next;
2045     }
2046   if (GNUNET_NO == matched)
2047     {
2048       /* TODO: call statistics (unmatched PONG) */
2049       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2050                   _
2051                   ("Received `%s' message but have no record of a matching `%s' message. Ignoring.\n"),
2052                   "PONG", "PING");
2053     }
2054   if (GNUNET_YES == all_done)
2055     {
2056       pos->timeout.value = 0;
2057       GNUNET_SCHEDULER_add_delayed (sched,
2058                                     GNUNET_NO,
2059                                     GNUNET_SCHEDULER_PRIORITY_IDLE,
2060                                     GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
2061                                     GNUNET_TIME_UNIT_ZERO,
2062                                     &cleanup_validation, NULL);
2063     }
2064 }
2065
2066
2067 /**
2068  * The peer specified by the given neighbour has timed-out.  Update
2069  * our state and do the necessary notifications.  Also notifies
2070  * our clients that the neighbour is now officially gone.
2071  *
2072  * @param n the neighbour list entry for the peer
2073  */
2074 static void
2075 disconnect_neighbour (struct NeighbourList *n)
2076 {
2077   struct ReadyList *rpos;
2078   struct NeighbourList *npos;
2079   struct NeighbourList *nprev;
2080   struct MessageQueue *mq;
2081
2082 #if DEBUG_TRANSPORT
2083   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2084               "Disconnecting from neighbour\n");
2085 #endif
2086   /* remove n from neighbours list */
2087   nprev = NULL;
2088   npos = neighbours;
2089   while ((npos != NULL) && (npos != n))
2090     {
2091       nprev = npos;
2092       npos = npos->next;
2093     }
2094   GNUNET_assert (npos != NULL);
2095   if (nprev == NULL)
2096     neighbours = n->next;
2097   else
2098     nprev->next = n->next;
2099
2100   /* notify all clients about disconnect */
2101   notify_clients_disconnect (&n->id);
2102
2103   /* clean up all plugins, cancel connections & pending transmissions */
2104   while (NULL != (rpos = n->plugins))
2105     {
2106       n->plugins = rpos->next;
2107       GNUNET_assert (rpos->neighbour == n);
2108       rpos->plugin->api->cancel (rpos->plugin->api->cls,
2109                                  rpos->plugin_handle, rpos, &n->id);
2110       GNUNET_free (rpos);
2111     }
2112
2113   /* free all messages on the queue */
2114   while (NULL != (mq = n->messages))
2115     {
2116       n->messages = mq->next;
2117       GNUNET_assert (mq->neighbour == n);
2118       GNUNET_free (mq);
2119     }
2120
2121   /* finally, free n itself */
2122   GNUNET_free (n);
2123 }
2124
2125
2126 /**
2127  * Add an entry for each of our transport plugins
2128  * (that are able to send) to the list of plugins
2129  * for this neighbour.
2130  *
2131  * @param neighbour to initialize
2132  */
2133 static void
2134 add_plugins (struct NeighbourList *neighbour)
2135 {
2136   struct TransportPlugin *tp;
2137   struct ReadyList *rl;
2138
2139   neighbour->retry_plugins_time
2140     = GNUNET_TIME_relative_to_absolute (PLUGIN_RETRY_FREQUENCY);
2141   tp = plugins;
2142   while (tp != NULL)
2143     {
2144       if (tp->api->send != NULL)
2145         {
2146           rl = GNUNET_malloc (sizeof (struct ReadyList));
2147           rl->next = neighbour->plugins;
2148           neighbour->plugins = rl;
2149           rl->plugin = tp;
2150           rl->neighbour = neighbour;
2151           rl->transmit_ready = GNUNET_YES;
2152         }
2153       tp = tp->next;
2154     }
2155 }
2156
2157
2158 static void
2159 neighbour_timeout_task (void *cls,
2160                         const struct GNUNET_SCHEDULER_TaskContext *tc)
2161 {
2162   struct NeighbourList *n = cls;
2163
2164 #if DEBUG_TRANSPORT
2165   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2166               "Neighbour has timed out!\n");
2167 #endif
2168   n->timeout_task = GNUNET_SCHEDULER_NO_PREREQUISITE_TASK;
2169   disconnect_neighbour (n);
2170 }
2171
2172
2173
2174 /**
2175  * Create a fresh entry in our neighbour list for the given peer.
2176  * Will try to transmit our current HELLO to the new neighbour.  Also
2177  * notifies our clients about the new "connection".
2178  *
2179  * @param peer the peer for which we create the entry
2180  * @return the new neighbour list entry
2181  */
2182 static struct NeighbourList *
2183 setup_new_neighbour (const struct GNUNET_PeerIdentity *peer)
2184 {
2185   struct NeighbourList *n;
2186
2187 #if DEBUG_TRANSPORT
2188   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2189               "Setting up new neighbour `%4s', sending our HELLO to introduce ourselves\n",
2190               GNUNET_i2s (peer));
2191 #endif
2192   GNUNET_assert (our_hello != NULL);
2193   n = GNUNET_malloc (sizeof (struct NeighbourList));
2194   n->next = neighbours;
2195   neighbours = n;
2196   n->id = *peer;
2197   n->last_quota_update = GNUNET_TIME_absolute_get ();
2198   n->peer_timeout =
2199     GNUNET_TIME_relative_to_absolute (IDLE_CONNECTION_TIMEOUT);
2200   n->quota_in = default_quota_in;
2201   add_plugins (n);
2202   n->hello_version_sent = our_hello_version;
2203   n->timeout_task = GNUNET_SCHEDULER_add_delayed (sched,
2204                                                   GNUNET_NO,
2205                                                   GNUNET_SCHEDULER_PRIORITY_IDLE,
2206                                                   GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
2207                                                   IDLE_CONNECTION_TIMEOUT,
2208                                                   &neighbour_timeout_task, n);
2209   transmit_to_peer (NULL,
2210                     (const struct GNUNET_MessageHeader *) our_hello,
2211                     GNUNET_YES, n);
2212   notify_clients_connect (peer, GNUNET_TIME_UNIT_FOREVER_REL);
2213   return n;
2214 }
2215
2216
2217 /**
2218  * Function called by the plugin for each received message.
2219  * Update data volumes, possibly notify plugins about
2220  * reducing the rate at which they read from the socket
2221  * and generally forward to our receive callback.
2222  *
2223  * @param plugin_context value to pass to this plugin
2224  *        to respond to the given peer (use is optional,
2225  *        but may speed up processing)
2226  * @param service_context value passed to the transport-service
2227  *        to identify the neighbour; will be NULL on the first
2228  *        call for a given peer
2229  * @param latency estimated latency for communicating with the
2230  *             given peer
2231  * @param peer (claimed) identity of the other peer
2232  * @param message the message, NULL if peer was disconnected
2233  * @return the new service_context that the plugin should use
2234  *         for future receive calls for messages from this
2235  *         particular peer
2236  */
2237 static struct ReadyList *
2238 plugin_env_receive (void *cls,
2239                     void *plugin_context,
2240                     struct ReadyList *service_context,
2241                     struct GNUNET_TIME_Relative latency,
2242                     const struct GNUNET_PeerIdentity *peer,
2243                     const struct GNUNET_MessageHeader *message)
2244 {
2245   const struct GNUNET_MessageHeader ack = {
2246     htons (sizeof (struct GNUNET_MessageHeader)),
2247     htons (GNUNET_MESSAGE_TYPE_TRANSPORT_ACK)
2248   };
2249   struct TransportPlugin *plugin = cls;
2250   struct TransportClient *cpos;
2251   struct InboundMessage *im;
2252   uint16_t msize;
2253   struct NeighbourList *n;
2254
2255   if (service_context != NULL)
2256     {
2257       n = service_context->neighbour;
2258       GNUNET_assert (n != NULL);
2259     }
2260   else
2261     {
2262       n = find_neighbour (peer);
2263       if (n == NULL)
2264         {
2265           if (message == NULL)
2266             return NULL;        /* disconnect of peer already marked down */
2267           n = setup_new_neighbour (peer);
2268         }
2269       service_context = n->plugins;
2270       while ((service_context != NULL) && (plugin != service_context->plugin))
2271         service_context = service_context->next;
2272       GNUNET_assert ((plugin->api->send == NULL) ||
2273                      (service_context != NULL));
2274     }
2275   if (message == NULL)
2276     {
2277       if ((service_context != NULL) &&
2278           (service_context->plugin_handle == plugin_context))
2279         {
2280           service_context->connected = GNUNET_NO;
2281           service_context->plugin_handle = NULL;
2282         }
2283       /* TODO: call stats */
2284       return NULL;
2285     }
2286 #if DEBUG_TRANSPORT
2287   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2288               "Processing message of type `%u' received by plugin...\n",
2289               ntohs (message->type));
2290 #endif
2291   if (service_context != NULL)
2292     {
2293       if (service_context->connected == GNUNET_NO)
2294         {
2295           service_context->connected = GNUNET_YES;
2296           service_context->transmit_ready = GNUNET_YES;
2297           service_context->connect_attempts++;
2298         }
2299       service_context->timeout
2300         = GNUNET_TIME_relative_to_absolute (IDLE_CONNECTION_TIMEOUT);
2301       service_context->plugin_handle = plugin_context;
2302       service_context->latency = latency;
2303     }
2304   /* update traffic received amount ... */
2305   msize = ntohs (message->size);
2306   n->last_received += msize;
2307   GNUNET_SCHEDULER_cancel (sched, n->timeout_task);
2308   n->peer_timeout =
2309     GNUNET_TIME_relative_to_absolute (IDLE_CONNECTION_TIMEOUT);
2310   n->timeout_task =
2311     GNUNET_SCHEDULER_add_delayed (sched, GNUNET_NO,
2312                                   GNUNET_SCHEDULER_PRIORITY_IDLE,
2313                                   GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
2314                                   IDLE_CONNECTION_TIMEOUT,
2315                                   &neighbour_timeout_task, n);
2316   update_quota (n);
2317   if (n->quota_violation_count > QUOTA_VIOLATION_DROP_THRESHOLD)
2318     {
2319       /* dropping message due to frequent inbound volume violations! */
2320       GNUNET_log (GNUNET_ERROR_TYPE_WARNING |
2321                   GNUNET_ERROR_TYPE_BULK,
2322                   _
2323                   ("Dropping incoming message due to repeated bandwidth quota violations.\n"));
2324       /* TODO: call stats */
2325       GNUNET_assert (NULL != service_context->neighbour);
2326       return service_context;
2327     }
2328   switch (ntohs (message->type))
2329     {
2330     case GNUNET_MESSAGE_TYPE_HELLO:
2331 #if DEBUG_TRANSPORT
2332       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2333                   "Receiving `%s' message from other peer.\n", "HELLO");
2334 #endif
2335       process_hello (plugin, message);
2336 #if DEBUG_TRANSPORT
2337       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2338                   "Sending `%s' message to connecting peer.\n", "ACK");
2339 #endif
2340       transmit_to_peer (NULL, &ack, GNUNET_YES, n);
2341       break;
2342     case GNUNET_MESSAGE_TYPE_TRANSPORT_PING:
2343       process_ping (plugin, peer, plugin_context, message);
2344       break;
2345     case GNUNET_MESSAGE_TYPE_TRANSPORT_PONG:
2346       process_pong (plugin, message);
2347       break;
2348     case GNUNET_MESSAGE_TYPE_TRANSPORT_ACK:
2349       n->saw_ack = GNUNET_YES;
2350       /* intentional fall-through! */
2351     default:
2352 #if DEBUG_TRANSPORT
2353       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2354                   "Received message of type %u from other peer, sending to all clients.\n",
2355                   ntohs (message->type));
2356 #endif
2357       /* transmit message to all clients */
2358       im = GNUNET_malloc (sizeof (struct InboundMessage) + msize);
2359       im->header.size = htons (sizeof (struct InboundMessage) + msize);
2360       im->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RECV);
2361       im->latency = GNUNET_TIME_relative_hton (latency);
2362       im->peer = *peer;
2363       memcpy (&im[1], message, msize);
2364
2365       cpos = clients;
2366       while (cpos != NULL)
2367         {
2368           transmit_to_client (cpos, &im->header, GNUNET_YES);
2369           cpos = cpos->next;
2370         }
2371       GNUNET_free (im);
2372     }
2373   GNUNET_assert (NULL != service_context->neighbour);
2374   return service_context;
2375 }
2376
2377
2378 /**
2379  * Handle START-message.  This is the first message sent to us
2380  * by any client which causes us to add it to our list.
2381  *
2382  * @param cls closure (always NULL)
2383  * @param client identification of the client
2384  * @param message the actual message
2385  */
2386 static void
2387 handle_start (void *cls,
2388               struct GNUNET_SERVER_Client *client,
2389               const struct GNUNET_MessageHeader *message)
2390 {
2391   struct TransportClient *c;
2392   struct ConnectInfoMessage cim;
2393   struct NeighbourList *n;
2394   struct InboundMessage *im;
2395   struct GNUNET_MessageHeader *ack;
2396
2397 #if DEBUG_TRANSPORT
2398   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2399               "Received `%s' request from client\n", "START");
2400 #endif
2401   c = clients;
2402   while (c != NULL)
2403     {
2404       if (c->client == client)
2405         {
2406           /* client already on our list! */
2407           GNUNET_break (0);
2408           GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2409           return;
2410         }
2411       c = c->next;
2412     }
2413   c = GNUNET_malloc (sizeof (struct TransportClient));
2414   c->next = clients;
2415   clients = c;
2416   c->client = client;
2417   if (our_hello != NULL)
2418     {
2419 #if DEBUG_TRANSPORT
2420       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2421                   "Sending our own HELLO to new client\n");
2422 #endif
2423       transmit_to_client (c,
2424                           (const struct GNUNET_MessageHeader *) our_hello,
2425                           GNUNET_NO);
2426       /* tell new client about all existing connections */
2427       cim.header.size = htons (sizeof (struct ConnectInfoMessage));
2428       cim.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
2429       cim.quota_out = htonl (default_quota_out);
2430       cim.latency = GNUNET_TIME_relative_hton (GNUNET_TIME_UNIT_ZERO);  /* FIXME? */
2431       im = GNUNET_malloc (sizeof (struct InboundMessage) +
2432                           sizeof (struct GNUNET_MessageHeader));
2433       im->header.size = htons (sizeof (struct InboundMessage) +
2434                                sizeof (struct GNUNET_MessageHeader));
2435       im->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RECV);
2436       im->latency = GNUNET_TIME_relative_hton (GNUNET_TIME_UNIT_ZERO);  /* FIXME? */
2437       ack = (struct GNUNET_MessageHeader *) &im[1];
2438       ack->size = htons (sizeof (struct GNUNET_MessageHeader));
2439       ack->type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_ACK);
2440       for (n = neighbours; n != NULL; n = n->next)
2441         {
2442           cim.id = n->id;
2443           transmit_to_client (c, &cim.header, GNUNET_NO);
2444           if (n->saw_ack)
2445             {
2446               im->peer = n->id;
2447               transmit_to_client (c, &im->header, GNUNET_NO);
2448             }
2449         }
2450       GNUNET_free (im);
2451     }
2452   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2453 }
2454
2455
2456 /**
2457  * Handle HELLO-message.
2458  *
2459  * @param cls closure (always NULL)
2460  * @param client identification of the client
2461  * @param message the actual message
2462  */
2463 static void
2464 handle_hello (void *cls,
2465               struct GNUNET_SERVER_Client *client,
2466               const struct GNUNET_MessageHeader *message)
2467 {
2468   int ret;
2469
2470 #if DEBUG_TRANSPORT
2471   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2472               "Received `%s' request from client\n", "HELLO");
2473 #endif
2474   ret = process_hello (NULL, message);
2475   GNUNET_SERVER_receive_done (client, ret);
2476 }
2477
2478
2479 /**
2480  * Handle SEND-message.
2481  *
2482  * @param cls closure (always NULL)
2483  * @param client identification of the client
2484  * @param message the actual message
2485  */
2486 static void
2487 handle_send (void *cls,
2488              struct GNUNET_SERVER_Client *client,
2489              const struct GNUNET_MessageHeader *message)
2490 {
2491   struct TransportClient *tc;
2492   struct NeighbourList *n;
2493   const struct OutboundMessage *obm;
2494   const struct GNUNET_MessageHeader *obmm;
2495   uint16_t size;
2496   uint16_t msize;
2497
2498   size = ntohs (message->size);
2499   if (size <
2500       sizeof (struct OutboundMessage) + sizeof (struct GNUNET_MessageHeader))
2501     {
2502       GNUNET_break (0);
2503       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2504       return;
2505     }
2506   obm = (const struct OutboundMessage *) message;
2507 #if DEBUG_TRANSPORT
2508   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2509               "Received `%s' request from client with target `%4s'\n",
2510               "SEND", GNUNET_i2s (&obm->peer));
2511 #endif
2512   obmm = (const struct GNUNET_MessageHeader *) &obm[1];
2513   msize = ntohs (obmm->size);
2514   if (size != msize + sizeof (struct OutboundMessage))
2515     {
2516       GNUNET_break (0);
2517       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2518       return;
2519     }
2520   n = find_neighbour (&obm->peer);
2521   if (n == NULL)
2522     n = setup_new_neighbour (&obm->peer);
2523   tc = clients;
2524   while ((tc != NULL) && (tc->client != client))
2525     tc = tc->next;
2526
2527 #if DEBUG_TRANSPORT
2528   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2529               "Client asked to transmit %u-byte message of type %u to `%4s'\n",
2530               ntohs (obmm->size),
2531               ntohs (obmm->type), GNUNET_i2s (&obm->peer));
2532 #endif
2533   transmit_to_peer (tc, obmm, GNUNET_NO, n);
2534   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2535 }
2536
2537
2538 /**
2539  * Handle SET_QUOTA-message.
2540  *
2541  * @param cls closure (always NULL)
2542  * @param client identification of the client
2543  * @param message the actual message
2544  */
2545 static void
2546 handle_set_quota (void *cls,
2547                   struct GNUNET_SERVER_Client *client,
2548                   const struct GNUNET_MessageHeader *message)
2549 {
2550   const struct QuotaSetMessage *qsm =
2551     (const struct QuotaSetMessage *) message;
2552   struct NeighbourList *n;
2553   struct TransportPlugin *p;
2554   struct ReadyList *rl;
2555
2556 #if DEBUG_TRANSPORT
2557   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2558               "Received `%s' request from client for peer `%4s'\n",
2559               "SET_QUOTA", GNUNET_i2s (&qsm->peer));
2560 #endif
2561   n = find_neighbour (&qsm->peer);
2562   if (n == NULL)
2563     {
2564       GNUNET_SERVER_receive_done (client, GNUNET_OK);
2565       return;
2566     }
2567   update_quota (n);
2568   if (n->quota_in < ntohl (qsm->quota_in))
2569     n->last_quota_update = GNUNET_TIME_absolute_get ();
2570   n->quota_in = ntohl (qsm->quota_in);
2571   rl = n->plugins;
2572   while (rl != NULL)
2573     {
2574       p = rl->plugin;
2575       p->api->set_receive_quota (p->api->cls,
2576                                  &qsm->peer, ntohl (qsm->quota_in));
2577       rl = rl->next;
2578     }
2579   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2580 }
2581
2582
2583 /**
2584  * Handle TRY_CONNECT-message.
2585  *
2586  * @param cls closure (always NULL)
2587  * @param client identification of the client
2588  * @param message the actual message
2589  */
2590 static void
2591 handle_try_connect (void *cls,
2592                     struct GNUNET_SERVER_Client *client,
2593                     const struct GNUNET_MessageHeader *message)
2594 {
2595   const struct TryConnectMessage *tcm;
2596
2597   tcm = (const struct TryConnectMessage *) message;
2598 #if DEBUG_TRANSPORT
2599   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2600               "Received `%s' request from client asking to connect to `%4s'\n",
2601               "TRY_CONNECT", GNUNET_i2s (&tcm->peer));
2602 #endif
2603   if (NULL == find_neighbour (&tcm->peer))
2604     setup_new_neighbour (&tcm->peer);
2605   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2606 }
2607
2608
2609 /**
2610  * List of handlers for the messages understood by this
2611  * service.
2612  */
2613 static struct GNUNET_SERVER_MessageHandler handlers[] = {
2614   {&handle_start, NULL,
2615    GNUNET_MESSAGE_TYPE_TRANSPORT_START, 0},
2616   {&handle_hello, NULL,
2617    GNUNET_MESSAGE_TYPE_HELLO, 0},
2618   {&handle_send, NULL,
2619    GNUNET_MESSAGE_TYPE_TRANSPORT_SEND, 0},
2620   {&handle_set_quota, NULL,
2621    GNUNET_MESSAGE_TYPE_TRANSPORT_SET_QUOTA, sizeof (struct QuotaSetMessage)},
2622   {&handle_try_connect, NULL,
2623    GNUNET_MESSAGE_TYPE_TRANSPORT_TRY_CONNECT,
2624    sizeof (struct TryConnectMessage)},
2625   {NULL, NULL, 0, 0}
2626 };
2627
2628
2629 /**
2630  * Setup the environment for this plugin.
2631  */
2632 static void
2633 create_environment (struct TransportPlugin *plug)
2634 {
2635   plug->env.cfg = cfg;
2636   plug->env.sched = sched;
2637   plug->env.my_public_key = &my_public_key;
2638   plug->env.cls = plug;
2639   plug->env.receive = &plugin_env_receive;
2640   plug->env.lookup = &plugin_env_lookup_address;
2641   plug->env.notify_address = &plugin_env_notify_address;
2642   plug->env.default_quota_in = default_quota_in;
2643   plug->env.max_connections = max_connect_per_transport;
2644 }
2645
2646
2647 /**
2648  * Start the specified transport (load the plugin).
2649  */
2650 static void
2651 start_transport (struct GNUNET_SERVER_Handle *server, const char *name)
2652 {
2653   struct TransportPlugin *plug;
2654   char *libname;
2655
2656   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2657               _("Loading `%s' transport plugin\n"), name);
2658   GNUNET_asprintf (&libname, "libgnunet_plugin_transport_%s", name);
2659   plug = GNUNET_malloc (sizeof (struct TransportPlugin));
2660   create_environment (plug);
2661   plug->short_name = GNUNET_strdup (name);
2662   plug->lib_name = libname;
2663   plug->next = plugins;
2664   plugins = plug;
2665   plug->api = GNUNET_PLUGIN_load (libname, &plug->env);
2666   if (plug->api == NULL)
2667     {
2668       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2669                   _("Failed to load transport plugin for `%s'\n"), name);
2670       GNUNET_free (plug->short_name);
2671       plugins = plug->next;
2672       GNUNET_free (libname);
2673       GNUNET_free (plug);
2674     }
2675 }
2676
2677
2678 /**
2679  * Called whenever a client is disconnected.  Frees our
2680  * resources associated with that client.
2681  *
2682  * @param cls closure
2683  * @param client identification of the client
2684  */
2685 static void
2686 client_disconnect_notification (void *cls,
2687                                 struct GNUNET_SERVER_Client *client)
2688 {
2689   struct TransportClient *pos;
2690   struct TransportClient *prev;
2691   struct ClientMessageQueueEntry *mqe;
2692
2693 #if DEBUG_TRANSPORT
2694   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2695               "Client disconnected, cleaning up.\n");
2696 #endif
2697   prev = NULL;
2698   pos = clients;
2699   while ((pos != NULL) && (pos->client != client))
2700     {
2701       prev = pos;
2702       pos = pos->next;
2703     }
2704   if (pos == NULL)
2705     return;
2706   while (NULL != (mqe = pos->message_queue_head))
2707     {
2708       pos->message_queue_head = mqe->next;
2709       GNUNET_free (mqe);
2710     }
2711   pos->message_queue_head = NULL;
2712   if (prev == NULL)
2713     clients = pos->next;
2714   else
2715     prev->next = pos->next;
2716   if (GNUNET_YES == pos->tcs_pending)
2717     {
2718       pos->client = NULL;
2719       return;
2720     }
2721   GNUNET_free (pos);
2722 }
2723
2724
2725 /**
2726  * Initiate transport service.
2727  *
2728  * @param cls closure
2729  * @param s scheduler to use
2730  * @param serv the initialized server
2731  * @param c configuration to use
2732  */
2733 static void
2734 run (void *cls,
2735      struct GNUNET_SCHEDULER_Handle *s,
2736      struct GNUNET_SERVER_Handle *serv, struct GNUNET_CONFIGURATION_Handle *c)
2737 {
2738   char *plugs;
2739   char *pos;
2740   int no_transports;
2741   unsigned long long qin;
2742   unsigned long long qout;
2743   unsigned long long tneigh;
2744   char *keyfile;
2745
2746   sched = s;
2747   cfg = c;
2748   /* parse configuration */
2749   if ((GNUNET_OK !=
2750        GNUNET_CONFIGURATION_get_value_number (c,
2751                                               "TRANSPORT",
2752                                               "DEFAULT_QUOTA_IN",
2753                                               &qin)) ||
2754       (GNUNET_OK !=
2755        GNUNET_CONFIGURATION_get_value_number (c,
2756                                               "TRANSPORT",
2757                                               "DEFAULT_QUOTA_OUT",
2758                                               &qout)) ||
2759       (GNUNET_OK !=
2760        GNUNET_CONFIGURATION_get_value_number (c,
2761                                               "TRANSPORT",
2762                                               "NEIGHBOUR_LIMIT",
2763                                               &tneigh)) ||
2764       (GNUNET_OK !=
2765        GNUNET_CONFIGURATION_get_value_filename (c,
2766                                                 "GNUNETD",
2767                                                 "HOSTKEY", &keyfile)))
2768     {
2769       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2770                   _
2771                   ("Transport service is lacking key configuration settings.  Exiting.\n"));
2772       GNUNET_SCHEDULER_shutdown (s);
2773       return;
2774     }
2775   max_connect_per_transport = (uint32_t) tneigh;
2776   default_quota_in = (uint32_t) qin;
2777   default_quota_out = (uint32_t) qout;
2778   my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
2779   GNUNET_free (keyfile);
2780   if (my_private_key == NULL)
2781     {
2782       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2783                   _
2784                   ("Transport service could not access hostkey.  Exiting.\n"));
2785       GNUNET_SCHEDULER_shutdown (s);
2786       return;
2787     }
2788   GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key);
2789   GNUNET_CRYPTO_hash (&my_public_key,
2790                       sizeof (my_public_key), &my_identity.hashPubKey);
2791   /* setup notification */
2792   server = serv;
2793   GNUNET_SERVER_disconnect_notify (server,
2794                                    &client_disconnect_notification, NULL);
2795   /* load plugins... */
2796   no_transports = 1;
2797   if (GNUNET_OK ==
2798       GNUNET_CONFIGURATION_get_value_string (c,
2799                                              "TRANSPORT", "PLUGINS", &plugs))
2800     {
2801       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2802                   _("Starting transport plugins `%s'\n"), plugs);
2803       pos = strtok (plugs, " ");
2804       while (pos != NULL)
2805         {
2806           start_transport (server, pos);
2807           no_transports = 0;
2808           pos = strtok (NULL, " ");
2809         }
2810       GNUNET_free (plugs);
2811     }
2812   if (no_transports)
2813     refresh_hello ();
2814   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Transport service ready.\n"));
2815   /* process client requests */
2816   GNUNET_SERVER_add_handlers (server, handlers);
2817 }
2818
2819
2820 /**
2821  * Function called when the service shuts
2822  * down.  Unloads our plugins.
2823  *
2824  * @param cls closure
2825  * @param cfg configuration to use
2826  */
2827 static void
2828 unload_plugins (void *cls, struct GNUNET_CONFIGURATION_Handle *cfg)
2829 {
2830   struct TransportPlugin *plug;
2831   struct AddressList *al;
2832
2833 #if DEBUG_TRANSPORT
2834   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2835               "Transport service is unloading plugins...\n");
2836 #endif
2837   while (NULL != (plug = plugins))
2838     {
2839       plugins = plug->next;
2840       GNUNET_break (NULL == GNUNET_PLUGIN_unload (plug->lib_name, plug->api));
2841       GNUNET_free (plug->lib_name);
2842       GNUNET_free (plug->short_name);
2843       while (NULL != (al = plug->addresses))
2844         {
2845           plug->addresses = al->next;
2846           GNUNET_free (al);
2847         }
2848       GNUNET_free (plug);
2849     }
2850   if (my_private_key != NULL)
2851     GNUNET_CRYPTO_rsa_key_free (my_private_key);
2852 }
2853
2854
2855 /**
2856  * The main function for the transport service.
2857  *
2858  * @param argc number of arguments from the command line
2859  * @param argv command line arguments
2860  * @return 0 ok, 1 on error
2861  */
2862 int
2863 main (int argc, char *const *argv)
2864 {
2865   return (GNUNET_OK ==
2866           GNUNET_SERVICE_run (argc,
2867                               argv,
2868                               "transport",
2869                               &run, NULL, &unload_plugins, NULL)) ? 0 : 1;
2870 }
2871
2872 /* end of gnunet-service-transport.c */