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