d239ce0ce7f9e6995414d33bc8a5a242aac611cb
[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, 30)
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     {
992       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
993                   "Setting transmit_ready on transport!\n");
994       rl->transmit_ready = GNUNET_YES;
995     }
996
997   if (mq->client != NULL)
998     {
999       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1000                   "Notifying client %p about failed transission to peer `%4s'.\n",
1001                   mq->client, GNUNET_i2s (target));
1002       send_ok_msg.header.size = htons (sizeof (send_ok_msg));
1003       send_ok_msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK);
1004       send_ok_msg.success = htonl (result);
1005       send_ok_msg.peer = n->id;
1006       transmit_to_client (mq->client, &send_ok_msg.header, GNUNET_NO);
1007     }
1008   GNUNET_free (mq->message);
1009   GNUNET_free (mq);
1010   /* one plugin just became ready again, try transmitting
1011      another message (if available) */
1012   if (result == GNUNET_OK)
1013     try_transmission_to_peer (n);
1014   else
1015     disconnect_neighbor (n, GNUNET_YES);
1016 }
1017
1018
1019 /**
1020  * Check the ready list for the given neighbor and
1021  * if a plugin is ready for transmission (and if we
1022  * have a message), do so!
1023  */
1024 static void
1025 try_transmission_to_peer (struct NeighborList *neighbor)
1026 {
1027   struct ReadyList *pos;
1028   struct GNUNET_TIME_Relative min_latency;
1029   struct ReadyList *rl;
1030   struct MessageQueue *mq;
1031   struct GNUNET_TIME_Absolute now;
1032
1033   if (neighbor->addr != NULL)
1034     {
1035       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1036           _("try_transmission_to_peer entry: at this point neighbor->addr is NOT NULL\n"));
1037     }
1038   else
1039     {
1040       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("try_transmission_to_peer entry: at this point neighbor->addr is NULL\n"));
1041     }
1042
1043   if (neighbor->messages == NULL)
1044     return;                     /* nothing to do */
1045   try_alternative_plugins (neighbor);
1046   min_latency = GNUNET_TIME_UNIT_FOREVER_REL;
1047   rl = NULL;
1048   mq = neighbor->messages;
1049   now = GNUNET_TIME_absolute_get ();
1050   pos = neighbor->plugins;
1051   while (pos != NULL)
1052     {
1053       /* set plugins that are inactive for a long time back to disconnected */
1054       if ((pos->timeout.value < now.value) && (pos->connected == GNUNET_YES))
1055         {
1056 #if DEBUG_TRANSPORT
1057           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1058                       "Marking long-time inactive connection to `%4s' as down.\n",
1059                       GNUNET_i2s (&neighbor->id));
1060 #endif
1061           pos->connected = GNUNET_NO;
1062         }
1063       if (GNUNET_YES == pos->transmit_ready)
1064         {
1065 #if DEBUG_TRANSPORT
1066           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1067                       "Found transmit_ready flag...\n");
1068 #endif
1069         }
1070       if (((GNUNET_YES == pos->transmit_ready) ||
1071            (mq->internal_msg)) &&
1072           (pos->connect_attempts < MAX_CONNECT_RETRY) &&
1073           ((rl == NULL) || (min_latency.value > pos->latency.value)))
1074         {
1075           rl = pos;
1076           min_latency = pos->latency;
1077         }
1078       pos = pos->next;
1079     }
1080   if (rl == NULL)
1081     {
1082 #if DEBUG_TRANSPORT
1083       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1084                   "No plugin ready to transmit message\n");
1085 #endif
1086       return;                   /* nobody ready */
1087     }
1088   if (GNUNET_NO == rl->connected)
1089     {
1090       rl->connect_attempts++;
1091       rl->connected = GNUNET_YES;
1092 #if DEBUG_TRANSPORT
1093       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1094                   "Establishing fresh connection with `%4s' via plugin `%s'\n",
1095                   GNUNET_i2s (&neighbor->id), rl->plugin->short_name);
1096 #endif
1097     }
1098   neighbor->messages = mq->next;
1099   mq->plugin = rl->plugin;
1100   if (!mq->internal_msg)
1101     rl->transmit_ready = GNUNET_NO;
1102 #if DEBUG_TRANSPORT
1103   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1104               "Giving message of type `%u' for `%4s' to plugin `%s'\n",
1105               ntohs (mq->message->type),
1106               GNUNET_i2s (&neighbor->id), rl->plugin->short_name);
1107 #endif
1108
1109   if (rl->neighbor->addr != NULL)
1110       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("try_transmission_to_peer pre-send: at this point rl->neighbor->addr is NOT NULL, addrlen is %d\n"), rl->neighbor->addr_len);
1111   else
1112     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("try_transmission_to_peer pre-send: at this point rl->neighbor->addr is NULL\n"));
1113   /* FIXME: Change MessageQueue to hold message buffer and size? */
1114   rl->plugin->api->send (rl->plugin->api->cls,
1115                          &neighbor->id,
1116                          (char *)mq->message,
1117                          ntohs(mq->message->size),
1118                          mq->priority,
1119                          GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
1120                          rl->neighbor->addr,
1121                          rl->neighbor->addr_len,
1122                          GNUNET_NO,
1123                          &transmit_send_continuation, mq);
1124 }
1125
1126
1127 /**
1128  * Send the specified message to the specified peer.
1129  *
1130  * @param client source of the transmission request (can be NULL)
1131  * @param priority how important is the message
1132  * @param msg message to send
1133  * @param is_internal is this an internal message
1134  * @param neighbor handle to the neighbor for transmission
1135  */
1136 static void
1137 transmit_to_peer (struct TransportClient *client,
1138                   unsigned int priority,
1139                   const struct GNUNET_MessageHeader *msg,
1140                   int is_internal, struct NeighborList *neighbor)
1141 {
1142   struct MessageQueue *mq;
1143   struct MessageQueue *mqe;
1144   struct GNUNET_MessageHeader *m;
1145
1146 #if DEBUG_TRANSPORT
1147   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1148               _("Sending message of type %u to peer `%4s'\n"),
1149               ntohs (msg->type), GNUNET_i2s (&neighbor->id));
1150   if (neighbor->addr != NULL)
1151     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("transmit_to_peer: at this point neighbor->addr is NOT NULL\n"));
1152 #endif
1153   if (client != NULL)
1154     {
1155       /* check for duplicate submission */
1156       mq = neighbor->messages;
1157       while (NULL != mq)
1158         {
1159           if (mq->client == client)
1160             {
1161               /* client transmitted to same peer twice
1162                  before getting SendOk! */
1163               GNUNET_break (0);
1164               return;
1165             }
1166           mq = mq->next;
1167         }
1168     }
1169   mq = GNUNET_malloc (sizeof (struct MessageQueue));
1170   mq->client = client;
1171   m = GNUNET_malloc (ntohs (msg->size));
1172   memcpy (m, msg, ntohs (msg->size));
1173   mq->message = m;
1174   mq->neighbor = neighbor;
1175   mq->internal_msg = is_internal;
1176   mq->priority = priority;
1177
1178   /* find tail */
1179   mqe = neighbor->messages;
1180   if (mqe != NULL)
1181     while (mqe->next != NULL)
1182       mqe = mqe->next;
1183   if (mqe == NULL)
1184     {
1185       /* new head */
1186       neighbor->messages = mq;
1187     }
1188   else
1189     {
1190       /* append */
1191       mqe->next = mq;
1192     }
1193   try_transmission_to_peer (neighbor);
1194 }
1195
1196
1197 /**
1198  * FIXME: document.
1199  */
1200 struct GeneratorContext
1201 {
1202   struct TransportPlugin *plug_pos;
1203   struct AddressList *addr_pos;
1204   struct GNUNET_TIME_Absolute expiration;
1205 };
1206
1207
1208 /**
1209  * FIXME: document.
1210  */
1211 static size_t
1212 address_generator (void *cls, size_t max, void *buf)
1213 {
1214   struct GeneratorContext *gc = cls;
1215   size_t ret;
1216
1217   while ((gc->addr_pos == NULL) && (gc->plug_pos != NULL))
1218     {
1219       gc->plug_pos = gc->plug_pos->next;
1220       gc->addr_pos = (gc->plug_pos != NULL) ? gc->plug_pos->addresses : NULL;
1221     }
1222   if (NULL == gc->plug_pos)
1223     {
1224 #if DEBUG_TRANSPORT
1225       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1226                   "In address_generator, gc->plug_pos is NULL!\n");
1227 #endif
1228       return 0;
1229     }
1230 #if DEBUG_TRANSPORT
1231       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1232                   "Should be adding an address...\n");
1233 #endif
1234   ret = GNUNET_HELLO_add_address (gc->plug_pos->short_name,
1235                                   gc->expiration,
1236                                   gc->addr_pos->addr,
1237                                   gc->addr_pos->addrlen, buf, max);
1238   gc->addr_pos = gc->addr_pos->next;
1239   return ret;
1240 }
1241
1242
1243 /**
1244  * Construct our HELLO message from all of the addresses of
1245  * all of the transports.
1246  */
1247 static void
1248 refresh_hello ()
1249 {
1250   struct GNUNET_HELLO_Message *hello;
1251   struct TransportClient *cpos;
1252   struct NeighborList *npos;
1253   struct GeneratorContext gc;
1254
1255 #if DEBUG_TRANSPORT
1256   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
1257               "Refreshing my `%s'\n", "HELLO");
1258 #endif
1259   gc.plug_pos = plugins;
1260   gc.addr_pos = plugins != NULL ? plugins->addresses : NULL;
1261   gc.expiration = GNUNET_TIME_relative_to_absolute (HELLO_ADDRESS_EXPIRATION);
1262   hello = GNUNET_HELLO_create (&my_public_key, &address_generator, &gc);
1263 #if DEBUG_TRANSPORT
1264   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
1265               "Refreshed my `%s', new size is %d\n", "HELLO", GNUNET_HELLO_size(hello));
1266 #endif
1267   cpos = clients;
1268   while (cpos != NULL)
1269     {
1270       transmit_to_client (cpos,
1271                           (const struct GNUNET_MessageHeader *) hello,
1272                           GNUNET_NO);
1273       cpos = cpos->next;
1274     }
1275
1276   GNUNET_free_non_null (our_hello);
1277   our_hello = hello;
1278   our_hello_version++;
1279   GNUNET_PEERINFO_add_peer (cfg, sched, &my_identity, our_hello);
1280   npos = neighbors;
1281   while (npos != NULL)
1282     {
1283 #if DEBUG_TRANSPORT
1284       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
1285                   "Transmitting updated `%s' to neighbor `%4s'\n",
1286                   "HELLO", GNUNET_i2s (&npos->id));
1287 #endif
1288       transmit_to_peer (NULL, 0,
1289                         (const struct GNUNET_MessageHeader *) our_hello,
1290                         GNUNET_YES, npos);
1291       npos = npos->next;
1292     }
1293 }
1294
1295
1296 /**
1297  * Task used to clean up expired addresses for a plugin.
1298  *
1299  * @param cls closure
1300  * @param tc context
1301  */
1302 static void
1303 expire_address_task (void *cls,
1304                      const struct GNUNET_SCHEDULER_TaskContext *tc);
1305
1306
1307 /**
1308  * Update the list of addresses for this plugin,
1309  * expiring those that are past their expiration date.
1310  *
1311  * @param plugin addresses of which plugin should be recomputed?
1312  * @param fresh set to GNUNET_YES if a new address was added
1313  *        and we need to regenerate the HELLO even if nobody
1314  *        expired
1315  */
1316 static void
1317 update_addresses (struct TransportPlugin *plugin, int fresh)
1318 {
1319   struct GNUNET_TIME_Relative min_remaining;
1320   struct GNUNET_TIME_Relative remaining;
1321   struct GNUNET_TIME_Absolute now;
1322   struct AddressList *pos;
1323   struct AddressList *prev;
1324   struct AddressList *next;
1325   int expired;
1326
1327   if (plugin->address_update_task != GNUNET_SCHEDULER_NO_TASK)
1328     GNUNET_SCHEDULER_cancel (plugin->env.sched, plugin->address_update_task);
1329   plugin->address_update_task = GNUNET_SCHEDULER_NO_TASK;
1330   now = GNUNET_TIME_absolute_get ();
1331   min_remaining = GNUNET_TIME_UNIT_FOREVER_REL;
1332   expired = GNUNET_NO;
1333   prev = NULL;
1334   pos = plugin->addresses;
1335   while (pos != NULL)
1336     {
1337       next = pos->next;
1338       if (pos->expires.value < now.value)
1339         {
1340           expired = GNUNET_YES;
1341           if (prev == NULL)
1342             plugin->addresses = pos->next;
1343           else
1344             prev->next = pos->next;
1345           GNUNET_free (pos);
1346         }
1347       else
1348         {
1349           remaining = GNUNET_TIME_absolute_get_remaining (pos->expires);
1350           if (remaining.value < min_remaining.value)
1351             min_remaining = remaining;
1352           prev = pos;
1353         }
1354       pos = next;
1355     }
1356
1357   if (expired || fresh)
1358     refresh_hello ();
1359   if (min_remaining.value < GNUNET_TIME_UNIT_FOREVER_REL.value)
1360     plugin->address_update_task
1361       = GNUNET_SCHEDULER_add_delayed (plugin->env.sched,
1362                                       min_remaining,
1363                                       &expire_address_task, plugin);
1364
1365 }
1366
1367
1368 /**
1369  * Task used to clean up expired addresses for a plugin.
1370  *
1371  * @param cls closure
1372  * @param tc context
1373  */
1374 static void
1375 expire_address_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1376 {
1377   struct TransportPlugin *plugin = cls;
1378   plugin->address_update_task = GNUNET_SCHEDULER_NO_TASK;
1379   update_addresses (plugin, GNUNET_NO);
1380 }
1381
1382
1383 /**
1384  * Function that must be called by each plugin to notify the
1385  * transport service about the addresses under which the transport
1386  * provided by the plugin can be reached.
1387  *
1388  * @param cls closure
1389  * @param name name of the transport that generated the address
1390  * @param addr one of the addresses of the host, NULL for the last address
1391  *        the specific address format depends on the transport
1392  * @param addrlen length of the address
1393  * @param expires when should this address automatically expire?
1394  */
1395 static void
1396 plugin_env_notify_address (void *cls,
1397                            const char *name,
1398                            const void *addr,
1399                            size_t addrlen,
1400                            struct GNUNET_TIME_Relative expires)
1401 {
1402   struct TransportPlugin *p = cls;
1403   struct AddressList *al;
1404   struct GNUNET_TIME_Absolute abex;
1405
1406   abex = GNUNET_TIME_relative_to_absolute (expires);
1407   GNUNET_assert (p == find_transport (name));
1408
1409   al = p->addresses;
1410   while (al != NULL)
1411     {
1412       if ((addrlen == al->addrlen) && (0 == memcmp (addr, &al[1], addrlen)))
1413         {
1414           if (al->expires.value < abex.value)
1415             al->expires = abex;
1416           return;
1417         }
1418       al = al->next;
1419     }
1420 #if DEBUG_TRANSPORT
1421   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1422               "Plugin `%s' informs us about a new address `%s'\n", name,
1423               GNUNET_a2s (addr, addrlen));
1424 #endif
1425   al = GNUNET_malloc (sizeof (struct AddressList) + addrlen);
1426   al->addr = &al[1];
1427   al->next = p->addresses;
1428   p->addresses = al;
1429   al->expires = abex;
1430   al->addrlen = addrlen;
1431   memcpy (&al[1], addr, addrlen);
1432   update_addresses (p, GNUNET_YES);
1433 }
1434
1435
1436 /**
1437  * Notify all of our clients about a peer connecting.
1438  */
1439 static void
1440 notify_clients_connect (const struct GNUNET_PeerIdentity *peer,
1441                         struct GNUNET_TIME_Relative latency)
1442 {
1443   struct ConnectInfoMessage cim;
1444   struct TransportClient *cpos;
1445
1446 #if DEBUG_TRANSPORT
1447   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1448               "Informing clients about peer `%4s' connecting to us\n",
1449               GNUNET_i2s (peer));
1450 #endif
1451   cim.header.size = htons (sizeof (struct ConnectInfoMessage));
1452   cim.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
1453   cim.quota_out = htonl (GNUNET_CONSTANTS_DEFAULT_BPM_IN_OUT / (60 * 1000));
1454   cim.latency = GNUNET_TIME_relative_hton (latency);
1455   memcpy (&cim.id, peer, sizeof (struct GNUNET_PeerIdentity));
1456   cpos = clients;
1457   while (cpos != NULL)
1458     {
1459       transmit_to_client (cpos, &cim.header, GNUNET_NO);
1460       cpos = cpos->next;
1461     }
1462 }
1463
1464
1465 /**
1466  * Notify all of our clients about a peer disconnecting.
1467  */
1468 static void
1469 notify_clients_disconnect (const struct GNUNET_PeerIdentity *peer)
1470 {
1471   struct DisconnectInfoMessage dim;
1472   struct TransportClient *cpos;
1473
1474 #if DEBUG_TRANSPORT
1475   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1476               "Informing clients about peer `%4s' disconnecting\n",
1477               GNUNET_i2s (peer));
1478 #endif
1479   dim.header.size = htons (sizeof (struct DisconnectInfoMessage));
1480   dim.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT);
1481   dim.reserved = htonl (0);
1482   memcpy (&dim.peer, peer, sizeof (struct GNUNET_PeerIdentity));
1483   cpos = clients;
1484   while (cpos != NULL)
1485     {
1486       transmit_to_client (cpos, &dim.header, GNUNET_NO);
1487       cpos = cpos->next;
1488     }
1489 }
1490
1491
1492 /**
1493  * Copy any validated addresses to buf.
1494  *
1495  * @return 0 once all addresses have been
1496  *         returned
1497  */
1498 static size_t
1499 list_validated_addresses (void *cls, size_t max, void *buf)
1500 {
1501   struct ValidationAddress **va = cls;
1502   size_t ret;
1503
1504   while ((NULL != *va) && ((*va)->ok != GNUNET_YES))
1505     *va = (*va)->next;
1506   if (NULL == *va)
1507     return 0;
1508   ret = GNUNET_HELLO_add_address ((*va)->transport_name,
1509                                   (*va)->expiration,
1510                                   &(*va)[1], (*va)->addr_len, buf, max);
1511   *va = (*va)->next;
1512   return ret;
1513 }
1514
1515
1516 /**
1517  * HELLO validation cleanup task.
1518  */
1519 static void
1520 cleanup_validation (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1521 {
1522   struct ValidationAddress *va;
1523   struct ValidationList *pos;
1524   struct ValidationList *prev;
1525   struct GNUNET_TIME_Absolute now;
1526   struct GNUNET_TIME_Absolute first;
1527   struct GNUNET_HELLO_Message *hello;
1528   struct GNUNET_PeerIdentity pid;
1529   struct NeighborList *n;
1530
1531 #if DEBUG_TRANSPORT
1532   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
1533               "HELLO validation cleanup background task running...\n");
1534 #endif
1535   now = GNUNET_TIME_absolute_get ();
1536   prev = NULL;
1537   pos = pending_validations;
1538   while (pos != NULL)
1539     {
1540       if (pos->timeout.value < now.value)
1541         {
1542           if (prev == NULL)
1543             pending_validations = pos->next;
1544           else
1545             prev->next = pos->next;
1546           va = pos->addresses;
1547           hello = GNUNET_HELLO_create (&pos->publicKey,
1548                                        &list_validated_addresses, &va);
1549           GNUNET_CRYPTO_hash (&pos->publicKey,
1550                               sizeof (struct
1551                                       GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1552                               &pid.hashPubKey);
1553 #if DEBUG_TRANSPORT
1554           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1555                       "Creating persistent `%s' message for peer `%4s' based on confirmed addresses.\n",
1556                       "HELLO", GNUNET_i2s (&pid));
1557 #endif
1558           GNUNET_PEERINFO_add_peer (cfg, sched, &pid, hello);
1559           n = find_neighbor (&pid, NULL, 0);
1560           if (NULL != n)
1561             {
1562               try_transmission_to_peer (n);
1563             }
1564           GNUNET_free (hello);
1565           while (NULL != (va = pos->addresses))
1566             {
1567               pos->addresses = va->next;
1568               GNUNET_free (va->transport_name);
1569               GNUNET_free (va);
1570             }
1571           GNUNET_free (pos);
1572           if (prev == NULL)
1573             pos = pending_validations;
1574           else
1575             pos = prev->next;
1576           continue;
1577         }
1578       prev = pos;
1579       pos = pos->next;
1580     }
1581
1582   /* finally, reschedule cleanup if needed; list is
1583      ordered by timeout, so we need the last element... */
1584   if (NULL != pending_validations)
1585     {
1586       first = pending_validations->timeout;
1587       pos = pending_validations;
1588       while (pos != NULL)
1589         {
1590           first = GNUNET_TIME_absolute_min (first, pos->timeout);
1591           pos = pos->next;
1592         }
1593       GNUNET_SCHEDULER_add_delayed (sched,
1594                                     GNUNET_TIME_absolute_get_remaining
1595                                     (first), &cleanup_validation, NULL);
1596     }
1597 }
1598
1599
1600 /**
1601  * Function that will be called if we receive a validation
1602  * of an address challenge that we transmitted to another
1603  * peer.  Note that the validation should only be considered
1604  * acceptable if the challenge matches AND if the sender
1605  * address is at least a plausible address for this peer
1606  * (otherwise we may be seeing a MiM attack).
1607  *
1608  * @param cls closure
1609  * @param name name of the transport that generated the address
1610  * @param peer who responded to our challenge
1611  * @param challenge the challenge number we presumably used
1612  * @param sender_addr string describing our sender address (as observed
1613  *         by the other peer in human-readable format)
1614  */
1615 static void
1616 handle_pong (void *cls, const struct GNUNET_MessageHeader *message,
1617              const struct GNUNET_PeerIdentity *peer,
1618              const char *sender_address,
1619              size_t sender_address_len)
1620 {
1621   unsigned int not_done;
1622   int matched;
1623   struct ValidationList *pos;
1624   struct ValidationAddress *va;
1625   struct GNUNET_PeerIdentity id;
1626   struct TransportPongMessage *pong = (struct TransportPongMessage *)message;
1627   int count = 0;
1628   unsigned int challenge = ntohl(pong->challenge);
1629   pos = pending_validations;
1630   while (pos != NULL)
1631     {
1632       GNUNET_CRYPTO_hash (&pos->publicKey,
1633                           sizeof (struct
1634                                   GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1635                           &id.hashPubKey);
1636       if (0 == memcmp (peer, &id, sizeof (struct GNUNET_PeerIdentity)))
1637         break;
1638       pos = pos->next;
1639       count++;
1640     }
1641   if (pos == NULL)
1642     {
1643       /* TODO: call statistics (unmatched PONG) */
1644       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1645                   _
1646                   ("Received validation response but have no record of any validation request for `%4s' (out of %d). Ignoring.\n"),
1647                   GNUNET_i2s (peer), count);
1648       return;
1649     }
1650   not_done = 0;
1651   matched = GNUNET_NO;
1652   va = pos->addresses;
1653   while (va != NULL)
1654     {
1655       if (va->challenge == challenge)
1656         {
1657 #if DEBUG_TRANSPORT
1658           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1659                       "Confirmed validity of address, peer `%4s' has address `%s'.\n",
1660                       GNUNET_i2s (peer),
1661                       GNUNET_a2s ((const struct sockaddr *) sender_address,
1662                                   sender_address_len));
1663 #endif
1664           GNUNET_log (GNUNET_ERROR_TYPE_INFO | GNUNET_ERROR_TYPE_BULK,
1665                       _
1666                       ("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"),
1667                       GNUNET_a2s ((const struct sockaddr *) &va[1],
1668                                                            va->addr_len));
1669           va->ok = GNUNET_YES;
1670           va->expiration =
1671             GNUNET_TIME_relative_to_absolute (HELLO_ADDRESS_EXPIRATION);
1672           matched = GNUNET_YES;
1673         }
1674       if (va->ok != GNUNET_YES)
1675         not_done++;
1676       va = va->next;
1677     }
1678   if (GNUNET_NO == matched)
1679     {
1680       /* TODO: call statistics (unmatched PONG) */
1681       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1682                   _
1683                   ("Received `%s' message but have no record of a matching `%s' message. Ignoring.\n"),
1684                   "PONG", "PING");
1685     }
1686   if (0 == not_done)
1687     {
1688 #if DEBUG_TRANSPORT
1689       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1690                   "All addresses validated, will now construct `%s' for `%4s'.\n",
1691                   "HELLO", GNUNET_i2s (peer));
1692 #endif
1693       pos->timeout.value = 0;
1694       GNUNET_SCHEDULER_add_with_priority (sched,
1695                                           GNUNET_SCHEDULER_PRIORITY_IDLE,
1696                                           &cleanup_validation, NULL);
1697     }
1698   else
1699     {
1700 #if DEBUG_TRANSPORT
1701       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1702                   "Still waiting for %u additional `%s' messages before constructing `%s' for `%4s'.\n",
1703                   not_done, "PONG", "HELLO", GNUNET_i2s (peer));
1704 #endif
1705     }
1706 }
1707
1708
1709 struct CheckHelloValidatedContext
1710 {
1711   /**
1712    * Plugin for which we are validating.
1713    */
1714   struct TransportPlugin *plugin;
1715
1716   /**
1717    * Hello that we are validating.
1718    */
1719   struct GNUNET_HELLO_Message *hello;
1720
1721   /**
1722    * Validation list being build.
1723    */
1724   struct ValidationList *e;
1725
1726   /**
1727    * Context for peerinfo iteration.
1728    * NULL after we are done processing peerinfo's information.
1729    */
1730   struct GNUNET_PEERINFO_IteratorContext *piter;
1731
1732 };
1733
1734
1735 /**
1736  * Append the given address to the list of entries
1737  * that need to be validated.
1738  */
1739 static int
1740 run_validation (void *cls,
1741                 const char *tname,
1742                 struct GNUNET_TIME_Absolute expiration,
1743                 const void *addr, size_t addrlen)
1744 {
1745   struct ValidationList *e = cls;
1746   struct TransportPlugin *tp;
1747   struct ValidationAddress *va;
1748   struct GNUNET_PeerIdentity id;
1749   char *pingMessage;
1750   int sent;
1751   struct TransportPingMessage *ping;
1752   char * message_buf;
1753   int hello_size;
1754
1755   tp = find_transport (tname);
1756   if (tp == NULL)
1757     {
1758       GNUNET_log (GNUNET_ERROR_TYPE_INFO |
1759                   GNUNET_ERROR_TYPE_BULK,
1760                   _
1761                   ("Transport `%s' not loaded, will not try to validate peer address using this transport.\n"),
1762                   tname);
1763       return GNUNET_OK;
1764     }
1765   GNUNET_CRYPTO_hash (&e->publicKey,
1766                       sizeof (struct
1767                               GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1768                       &id.hashPubKey);
1769   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1770               "Scheduling validation of address `%s' via `%s' for `%4s'\n",
1771               GNUNET_a2s (addr, addrlen), tname, GNUNET_i2s (&id));
1772
1773   va = GNUNET_malloc (sizeof (struct ValidationAddress) + addrlen);
1774   va->next = e->addresses;
1775   e->addresses = va;
1776   va->transport_name = GNUNET_strdup (tname);
1777   va->addr_len = addrlen;
1778   va->challenge = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1779                                             (unsigned int) -1);
1780   memcpy (&va[1], addr, addrlen);
1781
1782   hello_size = GNUNET_HELLO_size(our_hello);
1783   message_buf = GNUNET_malloc(sizeof(struct TransportPingMessage) + hello_size);
1784   memcpy(message_buf, &our_hello, hello_size);
1785
1786   ping = GNUNET_malloc(sizeof(struct TransportPingMessage));
1787   ping->challenge = htonl(va->challenge);
1788   ping->header.size = htons(sizeof(struct TransportPingMessage));
1789   ping->header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_PING);
1790   memcpy(&ping->target, &id, sizeof(struct GNUNET_PeerIdentity));
1791   memcpy(&message_buf[hello_size], ping, sizeof(struct TransportPingMessage));
1792
1793   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending ping message to address `%s' via `%s' for `%4s'\n",
1794                 GNUNET_a2s (addr, addrlen), tname, GNUNET_i2s (&id));
1795
1796
1797   sent = tp->api->send(tp->api->cls, &id, message_buf, sizeof(struct TransportPingMessage) + hello_size, GNUNET_SCHEDULER_PRIORITY_DEFAULT,
1798                 TRANSPORT_DEFAULT_TIMEOUT, addr, addrlen, GNUNET_YES, NULL, NULL);
1799
1800   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transport returned %d from send!\n", sent);
1801
1802   GNUNET_free(pingMessage);
1803
1804   return GNUNET_OK;
1805 }
1806
1807 /*
1808  * @param cls handle to the plugin (for sending)
1809  * @param target the peer identity of the peer we are sending to
1810  * @param challenge the challenge number
1811  * @param timeout how long to await validation?
1812  * @param addr the address to validate
1813  * @param addrlen the length of the address
1814  *
1815  * Perform address validation, which means sending a PING PONG to
1816  * the address via the transport plugin.  If not validated, then
1817  * do not count this as a good peer/address...
1818  *
1819  * Currently this function is not used, ping/pongs get sent from the
1820  * run_validation function.  Haven't decided yet how to do this.
1821  */
1822 static void
1823 validate_address (void *cls, struct ValidationAddress *va,
1824                   const struct GNUNET_PeerIdentity *target,
1825                   struct GNUNET_TIME_Relative timeout,
1826                   const void *addr, size_t addrlen)
1827 {
1828   /* struct Plugin *plugin = cls;
1829   int challenge = va->challenge; */
1830
1831
1832   return;
1833 }
1834
1835
1836 /**
1837  * Check if addresses in validated hello "h" overlap with
1838  * those in "chvc->hello" and update "chvc->hello" accordingly,
1839  * removing those addresses that have already been validated.
1840  */
1841 static void
1842 check_hello_validated (void *cls,
1843                        const struct GNUNET_PeerIdentity *peer,
1844                        const struct GNUNET_HELLO_Message *h, uint32_t trust)
1845 {
1846   struct CheckHelloValidatedContext *chvc = cls;
1847   struct ValidationAddress *va;
1848   struct TransportPlugin *tp;
1849   int first_call;
1850   int count;
1851   struct GNUNET_PeerIdentity apeer;
1852
1853   first_call = GNUNET_NO;
1854   if (chvc->e == NULL)
1855     {
1856       chvc->piter = NULL;
1857       first_call = GNUNET_YES;
1858       chvc->e = GNUNET_malloc (sizeof (struct ValidationList));
1859       GNUNET_assert (GNUNET_OK ==
1860                      GNUNET_HELLO_get_key (h != NULL ? h : chvc->hello,
1861                                            &chvc->e->publicKey));
1862       chvc->e->timeout =
1863         GNUNET_TIME_relative_to_absolute (HELLO_VERIFICATION_TIMEOUT);
1864       chvc->e->next = pending_validations;
1865       pending_validations = chvc->e;
1866     }
1867   /* no existing HELLO, all addresses are new */
1868   GNUNET_HELLO_iterate_addresses (chvc->hello,
1869                                   GNUNET_NO, &run_validation, chvc->e);
1870 #if 0
1871   if (h != NULL)
1872     {
1873       GNUNET_HELLO_iterate_new_addresses (chvc->hello,
1874                                           h,
1875                                           GNUNET_TIME_absolute_get (),
1876                                           &run_validation, chvc->e);
1877     }
1878   else if (GNUNET_YES == first_call)
1879     {
1880       /* no existing HELLO, all addresses are new */
1881       GNUNET_HELLO_iterate_addresses (chvc->hello,
1882                                       GNUNET_NO, &run_validation, chvc->e);
1883     }
1884 #endif
1885   if (h != NULL)
1886     return;                     /* wait for next call */
1887   /* finally, transmit validation attempts */
1888   GNUNET_assert (GNUNET_OK == GNUNET_HELLO_get_id (chvc->hello, &apeer));
1889 #if DEBUG_TRANSPORT
1890   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1891               "Ready to validate addresses from `%s' message for peer `%4s'\n",
1892               "HELLO", GNUNET_i2s (&apeer));
1893 #endif
1894   va = chvc->e->addresses;
1895   count = 0;
1896   while (va != NULL)
1897     {
1898 #if DEBUG_TRANSPORT
1899       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1900                   "Establishing `%s' connection to validate `%s' address `%s' of `%4s'\n",
1901                   va->transport_name,
1902                   "HELLO",
1903                   GNUNET_a2s ((const struct sockaddr *) &va[1],
1904                               va->addr_len), GNUNET_i2s (&apeer));
1905 #endif
1906       tp = find_transport (va->transport_name);
1907       GNUNET_assert (tp != NULL);
1908       /* This validation should happen inside the transport, not from the plugin! */
1909       validate_address (tp->api->cls, va, &apeer,
1910                         HELLO_VERIFICATION_TIMEOUT,
1911                         &va[1], va->addr_len);
1912       /* va->ok = GNUNET_SYSERR; will be set by validate_address! */
1913       va = va->next;
1914       count++;
1915     }
1916
1917 #if DEBUG_TRANSPORT
1918       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1919                   "Found %d addresses in hello of size %d\n", count, GNUNET_HELLO_size(chvc->hello));
1920 #endif
1921   GNUNET_SCHEDULER_add_delayed (sched,
1922                                 GNUNET_TIME_absolute_get_remaining (chvc->
1923                                                                     e->timeout),
1924                                 &cleanup_validation, NULL);
1925   GNUNET_free (chvc);
1926 }
1927
1928
1929 /**
1930  * Process HELLO-message.
1931  *
1932  * @param plugin transport involved, may be NULL
1933  * @param message the actual message
1934  * @return GNUNET_OK if the HELLO was well-formed, GNUNET_SYSERR otherwise
1935  */
1936 static int
1937 process_hello (struct TransportPlugin *plugin,
1938                const struct GNUNET_MessageHeader *message)
1939 {
1940   struct ValidationList *e;
1941   uint16_t hsize;
1942   struct GNUNET_PeerIdentity target;
1943   const struct GNUNET_HELLO_Message *hello;
1944   struct CheckHelloValidatedContext *chvc;
1945   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded publicKey;
1946
1947   hsize = ntohs (message->size);
1948   if ((ntohs (message->type) != GNUNET_MESSAGE_TYPE_HELLO) ||
1949       (hsize < sizeof (struct GNUNET_MessageHeader)))
1950     {
1951       GNUNET_break (0);
1952       return GNUNET_SYSERR;
1953     }
1954   /* first, check if load is too high */
1955   if (GNUNET_OS_load_cpu_get (cfg) > 100)
1956     {
1957       /* TODO: call to stats? */
1958       return GNUNET_OK;
1959     }
1960   hello = (const struct GNUNET_HELLO_Message *) message;
1961   if (GNUNET_OK != GNUNET_HELLO_get_key (hello, &publicKey))
1962     {
1963       GNUNET_break_op (0);
1964       return GNUNET_SYSERR;
1965     }
1966   GNUNET_CRYPTO_hash (&publicKey,
1967                       sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1968                       &target.hashPubKey);
1969 #if DEBUG_TRANSPORT
1970   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1971               "Processing `%s' message for `%4s' of size %d (hsize is %d)\n",
1972               "HELLO", GNUNET_i2s (&target), GNUNET_HELLO_size(hello), hsize);
1973 #endif
1974   /* check if a HELLO for this peer is already on the validation list */
1975   e = pending_validations;
1976   while (e != NULL)
1977     {
1978       if (0 == memcmp (&e->publicKey,
1979                        &publicKey,
1980                        sizeof (struct
1981                                GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)))
1982         {
1983           /* TODO: call to stats? */
1984 #if DEBUG_TRANSPORT
1985           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1986                       "`%s' message for peer `%4s' is already pending; ignoring new message\n",
1987                       "HELLO", GNUNET_i2s (&target));
1988 #endif
1989           return GNUNET_OK;
1990         }
1991       e = e->next;
1992     }
1993   chvc = GNUNET_malloc (sizeof (struct CheckHelloValidatedContext) + hsize);
1994   chvc->plugin = plugin;
1995   chvc->hello = (struct GNUNET_HELLO_Message *) &chvc[1];
1996   memcpy (chvc->hello, hello, hsize);
1997   /* finally, check if HELLO was previously validated
1998      (continuation will then schedule actual validation) */
1999   chvc->piter = GNUNET_PEERINFO_iterate (cfg,
2000                                          sched,
2001                                          &target,
2002                                          0,
2003                                          HELLO_VERIFICATION_TIMEOUT,
2004                                          &check_hello_validated, chvc);
2005   return GNUNET_OK;
2006 }
2007
2008
2009 /**
2010  * The peer specified by the given neighbor has timed-out or a plugin
2011  * has disconnected.  We may either need to do nothing (other plugins
2012  * still up), or trigger a full disconnect and clean up.  This
2013  * function updates our state and do the necessary notifications.
2014  * Also notifies our clients that the neighbor is now officially
2015  * gone.
2016  *
2017  * @param n the neighbor list entry for the peer
2018  * @param check should we just check if all plugins
2019  *        disconnected or must we ask all plugins to
2020  *        disconnect?
2021  */
2022 static void
2023 disconnect_neighbor (struct NeighborList *n, int check)
2024 {
2025   struct ReadyList *rpos;
2026   struct NeighborList *npos;
2027   struct NeighborList *nprev;
2028   struct MessageQueue *mq;
2029
2030   if (GNUNET_YES == check)
2031     {
2032       rpos = n->plugins;
2033       while (NULL != rpos)
2034         {
2035           if (GNUNET_YES == rpos->connected)
2036             return;             /* still connected */
2037           rpos = rpos->next;
2038         }
2039     }
2040
2041 #if DEBUG_TRANSPORT
2042   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2043               "Disconnecting from `%4s'\n", GNUNET_i2s (&n->id));
2044 #endif
2045   /* remove n from neighbors list */
2046   nprev = NULL;
2047   npos = neighbors;
2048   while ((npos != NULL) && (npos != n))
2049     {
2050       nprev = npos;
2051       npos = npos->next;
2052     }
2053   GNUNET_assert (npos != NULL);
2054   if (nprev == NULL)
2055     neighbors = n->next;
2056   else
2057     nprev->next = n->next;
2058
2059   /* notify all clients about disconnect */
2060   notify_clients_disconnect (&n->id);
2061
2062   /* clean up all plugins, cancel connections and pending transmissions */
2063   while (NULL != (rpos = n->plugins))
2064     {
2065       n->plugins = rpos->next;
2066       GNUNET_assert (rpos->neighbor == n);
2067       if (GNUNET_YES == rpos->connected)
2068         rpos->plugin->api->disconnect (rpos->plugin->api->cls, &n->id);
2069       GNUNET_free (rpos);
2070     }
2071
2072   /* free all messages on the queue */
2073   while (NULL != (mq = n->messages))
2074     {
2075       n->messages = mq->next;
2076       GNUNET_assert (mq->neighbor == n);
2077       GNUNET_free (mq);
2078     }
2079   if (n->timeout_task != GNUNET_SCHEDULER_NO_TASK)
2080     GNUNET_SCHEDULER_cancel (sched, n->timeout_task);
2081   /* finally, free n itself */
2082   GNUNET_free (n);
2083 }
2084
2085
2086 /**
2087  * Add an entry for each of our transport plugins
2088  * (that are able to send) to the list of plugins
2089  * for this neighbor.
2090  *
2091  * @param neighbor to initialize
2092  */
2093 static void
2094 add_plugins (struct NeighborList *neighbor)
2095 {
2096   struct TransportPlugin *tp;
2097   struct ReadyList *rl;
2098
2099   neighbor->retry_plugins_time
2100     = GNUNET_TIME_relative_to_absolute (PLUGIN_RETRY_FREQUENCY);
2101   tp = plugins;
2102   while (tp != NULL)
2103     {
2104       if (tp->api->send != NULL)
2105         {
2106           rl = GNUNET_malloc (sizeof (struct ReadyList));
2107           rl->next = neighbor->plugins;
2108           neighbor->plugins = rl;
2109           rl->plugin = tp;
2110           rl->neighbor = neighbor;
2111           rl->transmit_ready = GNUNET_YES;
2112         }
2113       tp = tp->next;
2114     }
2115 }
2116
2117
2118 static void
2119 neighbor_timeout_task (void *cls,
2120                         const struct GNUNET_SCHEDULER_TaskContext *tc)
2121 {
2122   struct NeighborList *n = cls;
2123
2124 #if DEBUG_TRANSPORT
2125   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2126               "Neighbor `%4s' has timed out!\n", GNUNET_i2s (&n->id));
2127 #endif
2128   n->timeout_task = GNUNET_SCHEDULER_NO_TASK;
2129   disconnect_neighbor (n, GNUNET_NO);
2130 }
2131
2132
2133 /**
2134  * Create a fresh entry in our neighbor list for the given peer.
2135  * Will try to transmit our current HELLO to the new neighbor.  Also
2136  * notifies our clients about the new "connection".
2137  *
2138  * @param peer the peer for which we create the entry
2139  * @return the new neighbor list entry
2140  */
2141 static struct NeighborList *
2142 setup_new_neighbor (const struct GNUNET_PeerIdentity *peer, const char *addr, size_t sender_address_len)
2143 {
2144   struct NeighborList *n;
2145
2146 #if DEBUG_TRANSPORT
2147   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2148               "Setting up new neighbor `%4s', sending our HELLO to introduce ourselves\n",
2149               GNUNET_i2s (peer));
2150 #endif
2151   GNUNET_assert (our_hello != NULL);
2152   n = GNUNET_malloc (sizeof (struct NeighborList));
2153   n->next = neighbors;
2154   neighbors = n;
2155   n->id = *peer;
2156   n->last_quota_update = GNUNET_TIME_absolute_get ();
2157   n->peer_timeout =
2158     GNUNET_TIME_relative_to_absolute
2159     (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
2160   n->quota_in = (GNUNET_CONSTANTS_DEFAULT_BPM_IN_OUT + 59999) / (60 * 1000);
2161   add_plugins (n);
2162   n->timeout_task = GNUNET_SCHEDULER_add_delayed (sched,
2163                                                   GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
2164                                                   &neighbor_timeout_task, n);
2165   transmit_to_peer (NULL, 0,
2166                     (const struct GNUNET_MessageHeader *) our_hello,
2167                     GNUNET_YES, n);
2168   notify_clients_connect (peer, GNUNET_TIME_UNIT_FOREVER_REL);
2169   return n;
2170 }
2171
2172 /*
2173  * We have received a PING message from someone.  Need to send a PONG message
2174  * in response to the peer by any means necessary.  Of course, with something
2175  * like TCP where a connection exists, we may want to send it that way.  But
2176  * we may not be able to make that distinction...
2177  */
2178 static int handle_ping(void *cls, const struct GNUNET_MessageHeader *message,
2179                        const struct GNUNET_PeerIdentity *peer,
2180                        const char *sender_address,
2181                        size_t sender_address_len)
2182 {
2183   struct TransportPlugin *plugin = cls;
2184   struct TransportPingMessage *ping;
2185   struct TransportPongMessage *pong;
2186   uint16_t msize;
2187   struct NeighborList *n;
2188   pong = GNUNET_malloc(sizeof(struct TransportPongMessage));
2189
2190 #if DEBUG_TRANSPORT
2191     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2192                 "Processing `%s' from `%s'\n",
2193                "PING", GNUNET_a2s ((const struct sockaddr *)sender_address, sender_address_len));
2194 #endif
2195
2196   msize = ntohs (message->size);
2197   if (msize < sizeof (struct TransportPingMessage))
2198     {
2199       GNUNET_break_op (0);
2200       return GNUNET_SYSERR;
2201     }
2202   ping = (struct TransportPingMessage *) message;
2203   if (0 != memcmp (&ping->target,
2204                    plugin->env.my_identity,
2205                    sizeof (struct GNUNET_PeerIdentity)))
2206     {
2207       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2208                   _("Received `%s' message not destined for me!\n"), "PING");
2209       return GNUNET_SYSERR;
2210     }
2211
2212   msize -= sizeof (struct TransportPingMessage);
2213 /*
2214  * if (GNUNET_OK != tcp_plugin_address_suggested (plugin, &vcm[1], msize))
2215     {
2216       GNUNET_break_op (0);
2217       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2218       return;
2219     }
2220
2221   if (GNUNET_OK != GNUNET_SERVER_client_get_address (client, &addr, &addrlen))
2222     {
2223       GNUNET_break (0);
2224       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2225       return;
2226     }
2227 */
2228   pong = GNUNET_malloc (sizeof (struct TransportPongMessage) + sender_address_len);
2229   pong->header.size = htons (sizeof (struct TransportPongMessage) + sender_address_len);
2230   pong->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_PONG);
2231   pong->purpose.size =
2232     htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) +
2233            sizeof (uint32_t) +
2234            sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) + sender_address_len);
2235   pong->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_TCP_PING);
2236   pong->challenge = ping->challenge;
2237
2238   memcpy(&pong->signer, &my_public_key, sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
2239   memcpy (&pong[1], sender_address, sender_address_len);
2240   GNUNET_assert (GNUNET_OK ==
2241                  GNUNET_CRYPTO_rsa_sign (my_private_key,
2242                                          &pong->purpose, &pong->signature));
2243   /* Will this nonsense work, even for UDP?
2244    * The idea is that we need an address to send to for UDP, but we may not know
2245    * this peer yet.  So in that case, we need to create a new neighbor with the
2246    * current address, but is this address going to be correct, or will it have a
2247    * random high port or something? Another question is, why didn't we get a WELCOME
2248    * from this peer with its advertised addresses already?  We don't want to
2249    * differentiate based on transport... */
2250   n = find_neighbor(peer, NULL, 0);
2251   if (n == NULL)
2252     {
2253 #if DEBUG_TRANSPORT
2254     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2255                 "Didn't find peer in list, adding...\n");
2256 #endif
2257       setup_new_neighbor(peer, sender_address, sender_address_len);
2258       n = find_neighbor(peer, sender_address, sender_address_len);
2259       GNUNET_assert(n != NULL);
2260     }
2261   else if (n->addr == NULL)
2262     {
2263 #if DEBUG_TRANSPORT
2264     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2265                 "Found peer in list, but without address, adding!\n");
2266 #endif
2267       n->addr = GNUNET_malloc(sender_address_len);
2268       memcpy(n->addr, sender_address, sender_address_len);
2269       n->addr_len = sender_address_len;
2270     }
2271
2272   transmit_to_peer(NULL, TRANSPORT_DEFAULT_PRIORITY, &pong->header, GNUNET_NO, n);
2273
2274   GNUNET_free(pong);
2275   return GNUNET_OK;
2276 }
2277
2278 /**
2279  * Function called by the plugin for each received message.
2280  * Update data volumes, possibly notify plugins about
2281  * reducing the rate at which they read from the socket
2282  * and generally forward to our receive callback.
2283  *
2284  * @param cls the "struct TransportPlugin *" we gave to the plugin
2285  * @param message the message, NULL if peer was disconnected
2286  * @param distance the transport cost to this peer (not latency!)
2287  * @param sender_address the address that the sender reported
2288  *        (opaque to transport service)
2289  * @param sender_address_len the length of the sender address
2290  * @param peer (claimed) identity of the other peer
2291  * @return the new service_context that the plugin should use
2292  *         for future receive calls for messages from this
2293  *         particular peer
2294  *
2295  */
2296 static void
2297 plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
2298                     const struct GNUNET_MessageHeader *message,
2299                     unsigned int distance, const char *sender_address,
2300                     size_t sender_address_len)
2301 {
2302   const struct GNUNET_MessageHeader ack = {
2303     htons (sizeof (struct GNUNET_MessageHeader)),
2304     htons (GNUNET_MESSAGE_TYPE_TRANSPORT_ACK)
2305   };
2306   struct ReadyList *service_context;
2307   struct TransportPlugin *plugin = cls;
2308   struct TransportClient *cpos;
2309   struct InboundMessage *im;
2310   uint16_t msize;
2311   struct NeighborList *n;
2312
2313   n = find_neighbor (peer, sender_address, sender_address_len);
2314   if (n == NULL)
2315     {
2316       if (message == NULL)
2317         return;                 /* disconnect of peer already marked down */
2318       n = setup_new_neighbor (peer, sender_address, sender_address_len);
2319     }
2320   service_context = n->plugins;
2321   while ((service_context != NULL) && (plugin != service_context->plugin))
2322     service_context = service_context->next;
2323   GNUNET_assert ((plugin->api->send == NULL) || (service_context != NULL));
2324   if (message == NULL)
2325     {
2326 #if DEBUG_TRANSPORT
2327       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2328                   "Receive failed from `%4s', triggering disconnect\n",
2329                   GNUNET_i2s (&n->id));
2330 #endif
2331       /* TODO: call stats */
2332       if (service_context != NULL)
2333         service_context->connected = GNUNET_NO;
2334       disconnect_neighbor (n, GNUNET_YES);
2335       return;
2336     }
2337 #if DEBUG_TRANSPORT
2338   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2339               "Processing message of type `%u' received by plugin...\n",
2340               ntohs (message->type));
2341 #endif
2342   if (service_context != NULL)
2343     {
2344       if (service_context->connected == GNUNET_NO)
2345         {
2346           service_context->connected = GNUNET_YES;
2347           service_context->transmit_ready = GNUNET_YES;
2348           service_context->connect_attempts++;
2349         }
2350       service_context->timeout
2351         =
2352         GNUNET_TIME_relative_to_absolute
2353         (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
2354       /* service_context->latency = latency; */ /* This value should be set by us! */
2355     }
2356   /* update traffic received amount ... */
2357   msize = ntohs (message->size);
2358   n->last_received += msize;
2359   GNUNET_SCHEDULER_cancel (sched, n->timeout_task);
2360   n->peer_timeout =
2361     GNUNET_TIME_relative_to_absolute
2362     (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
2363   n->timeout_task =
2364     GNUNET_SCHEDULER_add_delayed (sched,
2365                                   GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
2366                                   &neighbor_timeout_task, n);
2367   update_quota (n);
2368   if (n->quota_violation_count > QUOTA_VIOLATION_DROP_THRESHOLD)
2369     {
2370       /* dropping message due to frequent inbound volume violations! */
2371       GNUNET_log (GNUNET_ERROR_TYPE_WARNING |
2372                   GNUNET_ERROR_TYPE_BULK,
2373                   _
2374                   ("Dropping incoming message due to repeated bandwidth quota violations.\n"));
2375       /* TODO: call stats */
2376       GNUNET_assert ((service_context == NULL) ||
2377                      (NULL != service_context->neighbor));
2378       return;
2379     }
2380   switch (ntohs (message->type))
2381     {
2382     case GNUNET_MESSAGE_TYPE_HELLO:
2383 #if DEBUG_TRANSPORT
2384       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2385                   "Receiving `%s' message from `%4s'.\n", "HELLO",
2386                   GNUNET_i2s (peer));
2387 #endif
2388       process_hello (plugin, message);
2389 #if DEBUG_TRANSPORT
2390       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2391                   "Sending `%s' message to connecting peer `%4s'.\n", "ACK",
2392                   GNUNET_i2s (peer));
2393 #endif
2394       transmit_to_peer (NULL, 0, &ack, GNUNET_YES, n);
2395       break;
2396     case GNUNET_MESSAGE_TYPE_TRANSPORT_PING:
2397       handle_ping(plugin, message, peer, sender_address, sender_address_len);
2398       break;
2399     case GNUNET_MESSAGE_TYPE_TRANSPORT_PONG:
2400       handle_pong(plugin, message, peer, sender_address, sender_address_len);
2401       break;
2402       //plugin_env_notify_validation();
2403     case GNUNET_MESSAGE_TYPE_TRANSPORT_ACK:
2404       n->saw_ack = GNUNET_YES;
2405       /* intentional fall-through! */
2406     default:
2407 #if DEBUG_TRANSPORT
2408       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2409                   "Received message of type %u from `%4s', sending to all clients.\n",
2410                   ntohs (message->type), GNUNET_i2s (peer));
2411 #endif
2412       /* transmit message to all clients */
2413       im = GNUNET_malloc (sizeof (struct InboundMessage) + msize);
2414       im->header.size = htons (sizeof (struct InboundMessage) + msize);
2415       im->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RECV);
2416       im->latency = n->latency;
2417       im->peer = *peer;
2418       memcpy (&im[1], message, msize);
2419
2420       cpos = clients;
2421       while (cpos != NULL)
2422         {
2423           transmit_to_client (cpos, &im->header, GNUNET_YES);
2424           cpos = cpos->next;
2425         }
2426       GNUNET_free (im);
2427     }
2428   GNUNET_assert ((service_context == NULL) ||
2429                  (NULL != service_context->neighbor));
2430 }
2431
2432
2433 /**
2434  * Handle START-message.  This is the first message sent to us
2435  * by any client which causes us to add it to our list.
2436  *
2437  * @param cls closure (always NULL)
2438  * @param client identification of the client
2439  * @param message the actual message
2440  */
2441 static void
2442 handle_start (void *cls,
2443               struct GNUNET_SERVER_Client *client,
2444               const struct GNUNET_MessageHeader *message)
2445 {
2446   struct TransportClient *c;
2447   struct ConnectInfoMessage cim;
2448   struct NeighborList *n;
2449   struct InboundMessage *im;
2450   struct GNUNET_MessageHeader *ack;
2451
2452 #if DEBUG_TRANSPORT
2453   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2454               "Received `%s' request from client\n", "START");
2455 #endif
2456   c = clients;
2457   while (c != NULL)
2458     {
2459       if (c->client == client)
2460         {
2461           /* client already on our list! */
2462           GNUNET_break (0);
2463           GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2464           return;
2465         }
2466       c = c->next;
2467     }
2468   c = GNUNET_malloc (sizeof (struct TransportClient));
2469   c->next = clients;
2470   clients = c;
2471   c->client = client;
2472   if (our_hello != NULL)
2473     {
2474 #if DEBUG_TRANSPORT
2475       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2476                   "Sending our own `%s' to new client\n", "HELLO");
2477 #endif
2478       transmit_to_client (c,
2479                           (const struct GNUNET_MessageHeader *) our_hello,
2480                           GNUNET_NO);
2481       /* tell new client about all existing connections */
2482       cim.header.size = htons (sizeof (struct ConnectInfoMessage));
2483       cim.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
2484       cim.quota_out =
2485         htonl (GNUNET_CONSTANTS_DEFAULT_BPM_IN_OUT / (60 * 1000));
2486       cim.latency = GNUNET_TIME_relative_hton (GNUNET_TIME_UNIT_ZERO);  /* FIXME? */
2487       im = GNUNET_malloc (sizeof (struct InboundMessage) +
2488                           sizeof (struct GNUNET_MessageHeader));
2489       im->header.size = htons (sizeof (struct InboundMessage) +
2490                                sizeof (struct GNUNET_MessageHeader));
2491       im->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RECV);
2492       im->latency = GNUNET_TIME_relative_hton (GNUNET_TIME_UNIT_ZERO);  /* FIXME? */
2493       ack = (struct GNUNET_MessageHeader *) &im[1];
2494       ack->size = htons (sizeof (struct GNUNET_MessageHeader));
2495       ack->type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_ACK);
2496       for (n = neighbors; n != NULL; n = n->next)
2497         {
2498           cim.id = n->id;
2499           transmit_to_client (c, &cim.header, GNUNET_NO);
2500           if (n->saw_ack)
2501             {
2502               im->peer = n->id;
2503               transmit_to_client (c, &im->header, GNUNET_NO);
2504             }
2505         }
2506       GNUNET_free (im);
2507     }
2508   else
2509     {
2510       fprintf(stderr, "Our hello is NULL!\n");
2511     }
2512   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2513 }
2514
2515
2516 /**
2517  * Handle HELLO-message.
2518  *
2519  * @param cls closure (always NULL)
2520  * @param client identification of the client
2521  * @param message the actual message
2522  */
2523 static void
2524 handle_hello (void *cls,
2525               struct GNUNET_SERVER_Client *client,
2526               const struct GNUNET_MessageHeader *message)
2527 {
2528   int ret;
2529
2530 #if DEBUG_TRANSPORT
2531   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2532               "Received `%s' request from client\n", "HELLO");
2533 #endif
2534   ret = process_hello (NULL, message);
2535   GNUNET_SERVER_receive_done (client, ret);
2536 }
2537
2538
2539 /**
2540  * Handle SEND-message.
2541  *
2542  * @param cls closure (always NULL)
2543  * @param client identification of the client
2544  * @param message the actual message
2545  */
2546 static void
2547 handle_send (void *cls,
2548              struct GNUNET_SERVER_Client *client,
2549              const struct GNUNET_MessageHeader *message)
2550 {
2551   struct TransportClient *tc;
2552   struct NeighborList *n;
2553   const struct OutboundMessage *obm;
2554   const struct GNUNET_MessageHeader *obmm;
2555   uint16_t size;
2556   uint16_t msize;
2557
2558   size = ntohs (message->size);
2559   if (size <
2560       sizeof (struct OutboundMessage) + sizeof (struct GNUNET_MessageHeader))
2561     {
2562       GNUNET_break (0);
2563       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2564       return;
2565     }
2566   obm = (const struct OutboundMessage *) message;
2567 #if DEBUG_TRANSPORT
2568   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2569               "Received `%s' request from client with target `%4s'\n",
2570               "SEND", GNUNET_i2s (&obm->peer));
2571 #endif
2572   obmm = (const struct GNUNET_MessageHeader *) &obm[1];
2573   msize = ntohs (obmm->size);
2574   if (size != msize + sizeof (struct OutboundMessage))
2575     {
2576       GNUNET_break (0);
2577       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2578       return;
2579     }
2580   n = find_neighbor (&obm->peer, NULL, 0);
2581   if (n == NULL)
2582     n = setup_new_neighbor (&obm->peer, NULL, 0);
2583   tc = clients;
2584   while ((tc != NULL) && (tc->client != client))
2585     tc = tc->next;
2586
2587 #if DEBUG_TRANSPORT
2588   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2589               "Client asked to transmit %u-byte message of type %u to `%4s'\n",
2590               ntohs (obmm->size),
2591               ntohs (obmm->type), GNUNET_i2s (&obm->peer));
2592 #endif
2593   transmit_to_peer (tc, ntohl (obm->priority), obmm, GNUNET_NO, n);
2594   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2595 }
2596
2597
2598 /**
2599  * Handle SET_QUOTA-message.
2600  *
2601  * @param cls closure (always NULL)
2602  * @param client identification of the client
2603  * @param message the actual message
2604  */
2605 static void
2606 handle_set_quota (void *cls,
2607                   struct GNUNET_SERVER_Client *client,
2608                   const struct GNUNET_MessageHeader *message)
2609 {
2610   const struct QuotaSetMessage *qsm =
2611     (const struct QuotaSetMessage *) message;
2612   struct NeighborList *n;
2613   struct TransportPlugin *p;
2614   struct ReadyList *rl;
2615
2616 #if DEBUG_TRANSPORT
2617   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2618               "Received `%s' request from client for peer `%4s'\n",
2619               "SET_QUOTA", GNUNET_i2s (&qsm->peer));
2620 #endif
2621   n = find_neighbor (&qsm->peer, NULL, 0);
2622   if (n == NULL)
2623     {
2624       GNUNET_SERVER_receive_done (client, GNUNET_OK);
2625       return;
2626     }
2627   update_quota (n);
2628   if (n->quota_in < ntohl (qsm->quota_in))
2629     n->last_quota_update = GNUNET_TIME_absolute_get ();
2630   n->quota_in = ntohl (qsm->quota_in);
2631   rl = n->plugins;
2632   while (rl != NULL)
2633     {
2634       p = rl->plugin;
2635       p->api->set_receive_quota (p->api->cls,
2636                                  &qsm->peer, ntohl (qsm->quota_in));
2637       rl = rl->next;
2638     }
2639   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2640 }
2641
2642
2643 /**
2644  * Handle TRY_CONNECT-message.
2645  *
2646  * @param cls closure (always NULL)
2647  * @param client identification of the client
2648  * @param message the actual message
2649  */
2650 static void
2651 handle_try_connect (void *cls,
2652                     struct GNUNET_SERVER_Client *client,
2653                     const struct GNUNET_MessageHeader *message)
2654 {
2655   const struct TryConnectMessage *tcm;
2656
2657   tcm = (const struct TryConnectMessage *) message;
2658 #if DEBUG_TRANSPORT
2659   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2660               "Received `%s' request from client %p asking to connect to `%4s'\n",
2661               "TRY_CONNECT", client, GNUNET_i2s (&tcm->peer));
2662 #endif
2663   if (NULL == find_neighbor (&tcm->peer, NULL, 0))
2664     setup_new_neighbor (&tcm->peer, NULL, 0); /* Can we set up a truly _new_ neighbor without
2665                                         knowing its address?  Should we ask the plugin
2666                                         for more information about this peer?  I don't
2667                                         think we can...  Or set up new peer should only
2668                                         happen when transport notifies us of an address,
2669                                         and this setup should check for an address in
2670                                         the existing list only */
2671 #if DEBUG_TRANSPORT
2672   else
2673     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2674                 "Client asked to connect to `%4s', but connection already exists\n",
2675                 "TRY_CONNECT", GNUNET_i2s (&tcm->peer));
2676 #endif
2677   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2678 }
2679
2680 static void
2681 transmit_address_to_client (void *cls, const char *address)
2682 {
2683   struct GNUNET_SERVER_TransmitContext *tc = cls;
2684   size_t slen;
2685
2686   if (NULL == address)
2687     slen = 0;
2688   else
2689     slen = strlen (address) + 1;
2690   GNUNET_SERVER_transmit_context_append_data (tc, address, slen,
2691                                               GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_REPLY);
2692   if (NULL == address)
2693     GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
2694 }
2695
2696 /**
2697  * Handle AddressLookup-message.
2698  *
2699  * @param cls closure (always NULL)
2700  * @param client identification of the client
2701  * @param message the actual message
2702  */
2703 static void
2704 handle_address_lookup (void *cls,
2705                        struct GNUNET_SERVER_Client *client,
2706                        const struct GNUNET_MessageHeader *message)
2707 {
2708   const struct AddressLookupMessage *alum;
2709   struct TransportPlugin *lsPlugin;
2710   const char *nameTransport;
2711   const char *address;
2712   uint16_t size;
2713   struct GNUNET_SERVER_TransmitContext *tc;
2714
2715   size = ntohs (message->size);
2716   if (size < sizeof (struct AddressLookupMessage))
2717     {
2718       GNUNET_break_op (0);
2719       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2720       return;
2721     }
2722   alum = (const struct AddressLookupMessage *) message;
2723   uint32_t addressLen = ntohl (alum->addrlen);
2724   if (size <= sizeof (struct AddressLookupMessage) + addressLen)
2725     {
2726       GNUNET_break_op (0);
2727       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2728       return;
2729     }
2730   address = (const char *) &alum[1];
2731   nameTransport = (const char *) &address[addressLen];
2732   if (nameTransport
2733       [size - sizeof (struct AddressLookupMessage) - addressLen - 1] != '\0')
2734     {
2735       GNUNET_break_op (0);
2736       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2737       return;
2738     }
2739   struct GNUNET_TIME_Absolute timeout =
2740     GNUNET_TIME_absolute_ntoh (alum->timeout);
2741   struct GNUNET_TIME_Relative rtimeout =
2742     GNUNET_TIME_absolute_get_remaining (timeout);
2743   lsPlugin = find_transport (nameTransport);
2744   if (NULL == lsPlugin)
2745     {
2746       tc = GNUNET_SERVER_transmit_context_create (client);
2747       GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
2748                                                   GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_REPLY);
2749       GNUNET_SERVER_transmit_context_run (tc, rtimeout);
2750       return;
2751     }
2752   tc = GNUNET_SERVER_transmit_context_create (client);
2753   lsPlugin->api->address_pretty_printer (cls, nameTransport,
2754                                          address, addressLen, GNUNET_YES,
2755                                          rtimeout,
2756                                          &transmit_address_to_client, tc);
2757 }
2758
2759 /**
2760  * List of handlers for the messages understood by this
2761  * service.
2762  */
2763 static struct GNUNET_SERVER_MessageHandler handlers[] = {
2764   {&handle_start, NULL,
2765    GNUNET_MESSAGE_TYPE_TRANSPORT_START, 0},
2766   {&handle_hello, NULL,
2767    GNUNET_MESSAGE_TYPE_HELLO, 0},
2768   {&handle_send, NULL,
2769    GNUNET_MESSAGE_TYPE_TRANSPORT_SEND, 0},
2770   {&handle_set_quota, NULL,
2771    GNUNET_MESSAGE_TYPE_TRANSPORT_SET_QUOTA, sizeof (struct QuotaSetMessage)},
2772   {&handle_try_connect, NULL,
2773    GNUNET_MESSAGE_TYPE_TRANSPORT_TRY_CONNECT,
2774    sizeof (struct TryConnectMessage)},
2775   {&handle_address_lookup, NULL,
2776    GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_LOOKUP,
2777    0},
2778   {NULL, NULL, 0, 0}
2779 };
2780
2781
2782 /**
2783  * Setup the environment for this plugin.
2784  */
2785 static void
2786 create_environment (struct TransportPlugin *plug)
2787 {
2788   plug->env.cfg = cfg;
2789   plug->env.sched = sched;
2790   plug->env.my_identity = &my_identity;
2791   plug->env.cls = plug;
2792   plug->env.receive = &plugin_env_receive;
2793   plug->env.notify_address = &plugin_env_notify_address;
2794   plug->env.default_quota_in =
2795     (GNUNET_CONSTANTS_DEFAULT_BPM_IN_OUT + 59999) / (60 * 1000);
2796   plug->env.max_connections = max_connect_per_transport;
2797 }
2798
2799
2800 /**
2801  * Start the specified transport (load the plugin).
2802  */
2803 static void
2804 start_transport (struct GNUNET_SERVER_Handle *server, const char *name)
2805 {
2806   struct TransportPlugin *plug;
2807   char *libname;
2808
2809   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2810               _("Loading `%s' transport plugin\n"), name);
2811   GNUNET_asprintf (&libname, "libgnunet_plugin_transport_%s", name);
2812   plug = GNUNET_malloc (sizeof (struct TransportPlugin));
2813   create_environment (plug);
2814   plug->short_name = GNUNET_strdup (name);
2815   plug->lib_name = libname;
2816   plug->next = plugins;
2817   plugins = plug;
2818   plug->api = GNUNET_PLUGIN_load (libname, &plug->env);
2819   if (plug->api == NULL)
2820     {
2821       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2822                   _("Failed to load transport plugin for `%s'\n"), name);
2823       GNUNET_free (plug->short_name);
2824       plugins = plug->next;
2825       GNUNET_free (libname);
2826       GNUNET_free (plug);
2827     }
2828 }
2829
2830
2831 /**
2832  * Called whenever a client is disconnected.  Frees our
2833  * resources associated with that client.
2834  *
2835  * @param cls closure
2836  * @param client identification of the client
2837  */
2838 static void
2839 client_disconnect_notification (void *cls,
2840                                 struct GNUNET_SERVER_Client *client)
2841 {
2842   struct TransportClient *pos;
2843   struct TransportClient *prev;
2844   struct ClientMessageQueueEntry *mqe;
2845
2846   if (client == NULL)
2847     return;
2848 #if DEBUG_TRANSPORT
2849   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2850               "Client disconnected, cleaning up.\n");
2851 #endif
2852   prev = NULL;
2853   pos = clients;
2854   while ((pos != NULL) && (pos->client != client))
2855     {
2856       prev = pos;
2857       pos = pos->next;
2858     }
2859   if (pos == NULL)
2860     return;
2861   while (NULL != (mqe = pos->message_queue_head))
2862     {
2863       pos->message_queue_head = mqe->next;
2864       GNUNET_free (mqe);
2865     }
2866   pos->message_queue_head = NULL;
2867   if (prev == NULL)
2868     clients = pos->next;
2869   else
2870     prev->next = pos->next;
2871   if (GNUNET_YES == pos->tcs_pending)
2872     {
2873       pos->client = NULL;
2874       return;
2875     }
2876   GNUNET_free (pos);
2877 }
2878
2879
2880 /**
2881  * Function called when the service shuts down.  Unloads our plugins.
2882  *
2883  * @param cls closure, unused
2884  * @param tc task context (unused)
2885  */
2886 static void
2887 unload_plugins (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2888 {
2889   struct TransportPlugin *plug;
2890   struct AddressList *al;
2891
2892 #if DEBUG_TRANSPORT
2893   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2894               "Transport service is unloading plugins...\n");
2895 #endif
2896   while (NULL != (plug = plugins))
2897     {
2898       plugins = plug->next;
2899       GNUNET_break (NULL == GNUNET_PLUGIN_unload (plug->lib_name, plug->api));
2900       GNUNET_free (plug->lib_name);
2901       GNUNET_free (plug->short_name);
2902       while (NULL != (al = plug->addresses))
2903         {
2904           plug->addresses = al->next;
2905           GNUNET_free (al);
2906         }
2907       GNUNET_free (plug);
2908     }
2909   if (my_private_key != NULL)
2910     GNUNET_CRYPTO_rsa_key_free (my_private_key);
2911   GNUNET_free_non_null (our_hello);
2912 }
2913
2914
2915 /**
2916  * Initiate transport service.
2917  *
2918  * @param cls closure
2919  * @param s scheduler to use
2920  * @param serv the initialized server
2921  * @param c configuration to use
2922  */
2923 static void
2924 run (void *cls,
2925      struct GNUNET_SCHEDULER_Handle *s,
2926      struct GNUNET_SERVER_Handle *serv,
2927      const struct GNUNET_CONFIGURATION_Handle *c)
2928 {
2929   char *plugs;
2930   char *pos;
2931   int no_transports;
2932   unsigned long long tneigh;
2933   char *keyfile;
2934
2935   sched = s;
2936   cfg = c;
2937   /* parse configuration */
2938   if ((GNUNET_OK !=
2939        GNUNET_CONFIGURATION_get_value_number (c,
2940                                               "TRANSPORT",
2941                                               "NEIGHBOUR_LIMIT",
2942                                               &tneigh)) ||
2943       (GNUNET_OK !=
2944        GNUNET_CONFIGURATION_get_value_filename (c,
2945                                                 "GNUNETD",
2946                                                 "HOSTKEY", &keyfile)))
2947     {
2948       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2949                   _
2950                   ("Transport service is lacking key configuration settings.  Exiting.\n"));
2951       GNUNET_SCHEDULER_shutdown (s);
2952       return;
2953     }
2954   max_connect_per_transport = (uint32_t) tneigh;
2955   my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
2956   GNUNET_free (keyfile);
2957   if (my_private_key == NULL)
2958     {
2959       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2960                   _
2961                   ("Transport service could not access hostkey.  Exiting.\n"));
2962       GNUNET_SCHEDULER_shutdown (s);
2963       return;
2964     }
2965   GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key);
2966   GNUNET_CRYPTO_hash (&my_public_key,
2967                       sizeof (my_public_key), &my_identity.hashPubKey);
2968   /* setup notification */
2969   server = serv;
2970   GNUNET_SERVER_disconnect_notify (server,
2971                                    &client_disconnect_notification, NULL);
2972   /* load plugins... */
2973   no_transports = 1;
2974   if (GNUNET_OK ==
2975       GNUNET_CONFIGURATION_get_value_string (c,
2976                                              "TRANSPORT", "PLUGINS", &plugs))
2977     {
2978       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2979                   _("Starting transport plugins `%s'\n"), plugs);
2980       pos = strtok (plugs, " ");
2981       while (pos != NULL)
2982         {
2983           start_transport (server, pos);
2984           no_transports = 0;
2985           pos = strtok (NULL, " ");
2986         }
2987       GNUNET_free (plugs);
2988     }
2989   GNUNET_SCHEDULER_add_delayed (sched,
2990                                 GNUNET_TIME_UNIT_FOREVER_REL,
2991                                 &unload_plugins, NULL);
2992   if (no_transports)
2993     refresh_hello ();
2994
2995 #if DEBUG_TRANSPORT
2996   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Transport service ready.\n"));
2997 #endif
2998   /* process client requests */
2999   GNUNET_SERVER_add_handlers (server, handlers);
3000 }
3001
3002
3003 /**
3004  * The main function for the transport service.
3005  *
3006  * @param argc number of arguments from the command line
3007  * @param argv command line arguments
3008  * @return 0 ok, 1 on error
3009  */
3010 int
3011 main (int argc, char *const *argv)
3012 {
3013   return (GNUNET_OK ==
3014           GNUNET_SERVICE_run (argc,
3015                               argv,
3016                               "transport",
3017                               GNUNET_SERVICE_OPTION_NONE,
3018                               &run, NULL)) ? 0 : 1;
3019 }
3020
3021 /* end of gnunet-service-transport.c */