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