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