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