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