28fd381261fe506399f9d37ea33dcde9405b0fad
[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   int sent;
1750   struct TransportPingMessage *ping;
1751   char * message_buf;
1752   int hello_size;
1753   int tsize;
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   tsize = sizeof(struct TransportPingMessage) + hello_size;
1784
1785   message_buf = GNUNET_malloc(tsize);
1786
1787   ping = GNUNET_malloc(sizeof(struct TransportPingMessage));
1788   ping->challenge = htonl(va->challenge);
1789   ping->header.size = htons(sizeof(struct TransportPingMessage));
1790   ping->header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_PING);
1791   memcpy(&ping->target, &id, sizeof(struct GNUNET_PeerIdentity));
1792
1793   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "hello size is %d, ping size is %d, total size is %d", hello_size, sizeof(struct TransportPingMessage), tsize);
1794
1795   memcpy(message_buf, our_hello, hello_size);
1796   memcpy(&message_buf[hello_size], ping, sizeof(struct TransportPingMessage));
1797
1798
1799
1800   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending ping message to address `%s' via `%s' for `%4s'\n",
1801                 GNUNET_a2s (addr, addrlen), tname, GNUNET_i2s (&id));
1802
1803
1804   sent = tp->api->send(tp->api->cls, &id, message_buf, tsize, GNUNET_SCHEDULER_PRIORITY_DEFAULT,
1805                 TRANSPORT_DEFAULT_TIMEOUT, addr, addrlen, GNUNET_YES, NULL, NULL);
1806
1807   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transport returned %d from send!\n", sent);
1808
1809   GNUNET_free(ping);
1810   GNUNET_free(message_buf);
1811   return GNUNET_OK;
1812 }
1813
1814 /*
1815  * @param cls handle to the plugin (for sending)
1816  * @param target the peer identity of the peer we are sending to
1817  * @param challenge the challenge number
1818  * @param timeout how long to await validation?
1819  * @param addr the address to validate
1820  * @param addrlen the length of the address
1821  *
1822  * Perform address validation, which means sending a PING PONG to
1823  * the address via the transport plugin.  If not validated, then
1824  * do not count this as a good peer/address...
1825  *
1826  * Currently this function is not used, ping/pongs get sent from the
1827  * run_validation function.  Haven't decided yet how to do this.
1828  */
1829 static void
1830 validate_address (void *cls, struct ValidationAddress *va,
1831                   const struct GNUNET_PeerIdentity *target,
1832                   struct GNUNET_TIME_Relative timeout,
1833                   const void *addr, size_t addrlen)
1834 {
1835   /* struct Plugin *plugin = cls;
1836   int challenge = va->challenge; */
1837
1838
1839   return;
1840 }
1841
1842
1843 /**
1844  * Check if addresses in validated hello "h" overlap with
1845  * those in "chvc->hello" and update "chvc->hello" accordingly,
1846  * removing those addresses that have already been validated.
1847  */
1848 static void
1849 check_hello_validated (void *cls,
1850                        const struct GNUNET_PeerIdentity *peer,
1851                        const struct GNUNET_HELLO_Message *h, uint32_t trust)
1852 {
1853   struct CheckHelloValidatedContext *chvc = cls;
1854   struct ValidationAddress *va;
1855   struct TransportPlugin *tp;
1856   int first_call;
1857   int count;
1858   struct GNUNET_PeerIdentity apeer;
1859
1860   first_call = GNUNET_NO;
1861   if (chvc->e == NULL)
1862     {
1863       chvc->piter = NULL;
1864       first_call = GNUNET_YES;
1865       chvc->e = GNUNET_malloc (sizeof (struct ValidationList));
1866       GNUNET_assert (GNUNET_OK ==
1867                      GNUNET_HELLO_get_key (h != NULL ? h : chvc->hello,
1868                                            &chvc->e->publicKey));
1869       chvc->e->timeout =
1870         GNUNET_TIME_relative_to_absolute (HELLO_VERIFICATION_TIMEOUT);
1871       chvc->e->next = pending_validations;
1872       pending_validations = chvc->e;
1873     }
1874   /* no existing HELLO, all addresses are new */
1875   GNUNET_HELLO_iterate_addresses (chvc->hello,
1876                                   GNUNET_NO, &run_validation, chvc->e);
1877 #if 0
1878   if (h != NULL)
1879     {
1880       GNUNET_HELLO_iterate_new_addresses (chvc->hello,
1881                                           h,
1882                                           GNUNET_TIME_absolute_get (),
1883                                           &run_validation, chvc->e);
1884     }
1885   else if (GNUNET_YES == first_call)
1886     {
1887       /* no existing HELLO, all addresses are new */
1888       GNUNET_HELLO_iterate_addresses (chvc->hello,
1889                                       GNUNET_NO, &run_validation, chvc->e);
1890     }
1891 #endif
1892   if (h != NULL)
1893     return;                     /* wait for next call */
1894   /* finally, transmit validation attempts */
1895   GNUNET_assert (GNUNET_OK == GNUNET_HELLO_get_id (chvc->hello, &apeer));
1896 #if DEBUG_TRANSPORT
1897   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1898               "Ready to validate addresses from `%s' message for peer `%4s'\n",
1899               "HELLO", GNUNET_i2s (&apeer));
1900 #endif
1901   va = chvc->e->addresses;
1902   count = 0;
1903   while (va != NULL)
1904     {
1905 #if DEBUG_TRANSPORT
1906       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1907                   "Establishing `%s' connection to validate `%s' address `%s' of `%4s'\n",
1908                   va->transport_name,
1909                   "HELLO",
1910                   GNUNET_a2s ((const struct sockaddr *) &va[1],
1911                               va->addr_len), GNUNET_i2s (&apeer));
1912 #endif
1913       tp = find_transport (va->transport_name);
1914       GNUNET_assert (tp != NULL);
1915       /* This validation should happen inside the transport, not from the plugin! */
1916       validate_address (tp->api->cls, va, &apeer,
1917                         HELLO_VERIFICATION_TIMEOUT,
1918                         &va[1], va->addr_len);
1919       /* va->ok = GNUNET_SYSERR; will be set by validate_address! */
1920       va = va->next;
1921       count++;
1922     }
1923
1924 #if DEBUG_TRANSPORT
1925       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1926                   "Found %d addresses in hello of size %d\n", count, GNUNET_HELLO_size(chvc->hello));
1927 #endif
1928   GNUNET_SCHEDULER_add_delayed (sched,
1929                                 GNUNET_TIME_absolute_get_remaining (chvc->
1930                                                                     e->timeout),
1931                                 &cleanup_validation, NULL);
1932   GNUNET_free (chvc);
1933 }
1934
1935
1936 /**
1937  * Process HELLO-message.
1938  *
1939  * @param plugin transport involved, may be NULL
1940  * @param message the actual message
1941  * @return GNUNET_OK if the HELLO was well-formed, GNUNET_SYSERR otherwise
1942  */
1943 static int
1944 process_hello (struct TransportPlugin *plugin,
1945                const struct GNUNET_MessageHeader *message)
1946 {
1947   struct ValidationList *e;
1948   uint16_t hsize;
1949   struct GNUNET_PeerIdentity target;
1950   const struct GNUNET_HELLO_Message *hello;
1951   struct CheckHelloValidatedContext *chvc;
1952   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded publicKey;
1953
1954   hsize = ntohs (message->size);
1955   if ((ntohs (message->type) != GNUNET_MESSAGE_TYPE_HELLO) ||
1956       (hsize < sizeof (struct GNUNET_MessageHeader)))
1957     {
1958       GNUNET_break (0);
1959       return GNUNET_SYSERR;
1960     }
1961   /* first, check if load is too high */
1962   if (GNUNET_OS_load_cpu_get (cfg) > 100)
1963     {
1964       /* TODO: call to stats? */
1965       return GNUNET_OK;
1966     }
1967   hello = (const struct GNUNET_HELLO_Message *) message;
1968   if (GNUNET_OK != GNUNET_HELLO_get_key (hello, &publicKey))
1969     {
1970       GNUNET_break_op (0);
1971       return GNUNET_SYSERR;
1972     }
1973   GNUNET_CRYPTO_hash (&publicKey,
1974                       sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1975                       &target.hashPubKey);
1976 #if DEBUG_TRANSPORT
1977   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1978               "Processing `%s' message for `%4s' of size %d (hsize is %d)\n",
1979               "HELLO", GNUNET_i2s (&target), GNUNET_HELLO_size(hello), hsize);
1980 #endif
1981   /* check if a HELLO for this peer is already on the validation list */
1982   e = pending_validations;
1983   while (e != NULL)
1984     {
1985       if (0 == memcmp (&e->publicKey,
1986                        &publicKey,
1987                        sizeof (struct
1988                                GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)))
1989         {
1990           /* TODO: call to stats? */
1991 #if DEBUG_TRANSPORT
1992           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1993                       "`%s' message for peer `%4s' is already pending; ignoring new message\n",
1994                       "HELLO", GNUNET_i2s (&target));
1995 #endif
1996           return GNUNET_OK;
1997         }
1998       e = e->next;
1999     }
2000   chvc = GNUNET_malloc (sizeof (struct CheckHelloValidatedContext) + hsize);
2001   chvc->plugin = plugin;
2002   chvc->hello = (struct GNUNET_HELLO_Message *) &chvc[1];
2003   memcpy (chvc->hello, hello, hsize);
2004   /* finally, check if HELLO was previously validated
2005      (continuation will then schedule actual validation) */
2006   chvc->piter = GNUNET_PEERINFO_iterate (cfg,
2007                                          sched,
2008                                          &target,
2009                                          0,
2010                                          HELLO_VERIFICATION_TIMEOUT,
2011                                          &check_hello_validated, chvc);
2012   return GNUNET_OK;
2013 }
2014
2015
2016 /**
2017  * The peer specified by the given neighbor has timed-out or a plugin
2018  * has disconnected.  We may either need to do nothing (other plugins
2019  * still up), or trigger a full disconnect and clean up.  This
2020  * function updates our state and do the necessary notifications.
2021  * Also notifies our clients that the neighbor is now officially
2022  * gone.
2023  *
2024  * @param n the neighbor list entry for the peer
2025  * @param check should we just check if all plugins
2026  *        disconnected or must we ask all plugins to
2027  *        disconnect?
2028  */
2029 static void
2030 disconnect_neighbor (struct NeighborList *n, int check)
2031 {
2032   struct ReadyList *rpos;
2033   struct NeighborList *npos;
2034   struct NeighborList *nprev;
2035   struct MessageQueue *mq;
2036
2037   if (GNUNET_YES == check)
2038     {
2039       rpos = n->plugins;
2040       while (NULL != rpos)
2041         {
2042           if (GNUNET_YES == rpos->connected)
2043             return;             /* still connected */
2044           rpos = rpos->next;
2045         }
2046     }
2047
2048 #if DEBUG_TRANSPORT
2049   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2050               "Disconnecting from `%4s'\n", GNUNET_i2s (&n->id));
2051 #endif
2052   /* remove n from neighbors list */
2053   nprev = NULL;
2054   npos = neighbors;
2055   while ((npos != NULL) && (npos != n))
2056     {
2057       nprev = npos;
2058       npos = npos->next;
2059     }
2060   GNUNET_assert (npos != NULL);
2061   if (nprev == NULL)
2062     neighbors = n->next;
2063   else
2064     nprev->next = n->next;
2065
2066   /* notify all clients about disconnect */
2067   notify_clients_disconnect (&n->id);
2068
2069   /* clean up all plugins, cancel connections and pending transmissions */
2070   while (NULL != (rpos = n->plugins))
2071     {
2072       n->plugins = rpos->next;
2073       GNUNET_assert (rpos->neighbor == n);
2074       if (GNUNET_YES == rpos->connected)
2075         rpos->plugin->api->disconnect (rpos->plugin->api->cls, &n->id);
2076       GNUNET_free (rpos);
2077     }
2078
2079   /* free all messages on the queue */
2080   while (NULL != (mq = n->messages))
2081     {
2082       n->messages = mq->next;
2083       GNUNET_assert (mq->neighbor == n);
2084       GNUNET_free (mq);
2085     }
2086   if (n->timeout_task != GNUNET_SCHEDULER_NO_TASK)
2087     GNUNET_SCHEDULER_cancel (sched, n->timeout_task);
2088   /* finally, free n itself */
2089   GNUNET_free (n);
2090 }
2091
2092
2093 /**
2094  * Add an entry for each of our transport plugins
2095  * (that are able to send) to the list of plugins
2096  * for this neighbor.
2097  *
2098  * @param neighbor to initialize
2099  */
2100 static void
2101 add_plugins (struct NeighborList *neighbor)
2102 {
2103   struct TransportPlugin *tp;
2104   struct ReadyList *rl;
2105
2106   neighbor->retry_plugins_time
2107     = GNUNET_TIME_relative_to_absolute (PLUGIN_RETRY_FREQUENCY);
2108   tp = plugins;
2109   while (tp != NULL)
2110     {
2111       if (tp->api->send != NULL)
2112         {
2113           rl = GNUNET_malloc (sizeof (struct ReadyList));
2114           rl->next = neighbor->plugins;
2115           neighbor->plugins = rl;
2116           rl->plugin = tp;
2117           rl->neighbor = neighbor;
2118           rl->transmit_ready = GNUNET_YES;
2119         }
2120       tp = tp->next;
2121     }
2122 }
2123
2124
2125 static void
2126 neighbor_timeout_task (void *cls,
2127                         const struct GNUNET_SCHEDULER_TaskContext *tc)
2128 {
2129   struct NeighborList *n = cls;
2130
2131 #if DEBUG_TRANSPORT
2132   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2133               "Neighbor `%4s' has timed out!\n", GNUNET_i2s (&n->id));
2134 #endif
2135   n->timeout_task = GNUNET_SCHEDULER_NO_TASK;
2136   disconnect_neighbor (n, GNUNET_NO);
2137 }
2138
2139
2140 /**
2141  * Create a fresh entry in our neighbor list for the given peer.
2142  * Will try to transmit our current HELLO to the new neighbor.  Also
2143  * notifies our clients about the new "connection".
2144  *
2145  * @param peer the peer for which we create the entry
2146  * @return the new neighbor list entry
2147  */
2148 static struct NeighborList *
2149 setup_new_neighbor (const struct GNUNET_PeerIdentity *peer, const char *addr, size_t sender_address_len)
2150 {
2151   struct NeighborList *n;
2152
2153 #if DEBUG_TRANSPORT
2154   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2155               "Setting up new neighbor `%4s', sending our HELLO to introduce ourselves\n",
2156               GNUNET_i2s (peer));
2157 #endif
2158   GNUNET_assert (our_hello != NULL);
2159   n = GNUNET_malloc (sizeof (struct NeighborList));
2160   n->next = neighbors;
2161   neighbors = n;
2162   n->id = *peer;
2163   n->last_quota_update = GNUNET_TIME_absolute_get ();
2164   n->peer_timeout =
2165     GNUNET_TIME_relative_to_absolute
2166     (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
2167   n->quota_in = (GNUNET_CONSTANTS_DEFAULT_BPM_IN_OUT + 59999) / (60 * 1000);
2168   add_plugins (n);
2169   n->timeout_task = GNUNET_SCHEDULER_add_delayed (sched,
2170                                                   GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
2171                                                   &neighbor_timeout_task, n);
2172   transmit_to_peer (NULL, 0,
2173                     (const struct GNUNET_MessageHeader *) our_hello,
2174                     GNUNET_YES, n);
2175   notify_clients_connect (peer, GNUNET_TIME_UNIT_FOREVER_REL);
2176   return n;
2177 }
2178
2179 /*
2180  * We have received a PING message from someone.  Need to send a PONG message
2181  * in response to the peer by any means necessary.  Of course, with something
2182  * like TCP where a connection exists, we may want to send it that way.  But
2183  * we may not be able to make that distinction...
2184  */
2185 static int handle_ping(void *cls, const struct GNUNET_MessageHeader *message,
2186                        const struct GNUNET_PeerIdentity *peer,
2187                        const char *sender_address,
2188                        size_t sender_address_len)
2189 {
2190   struct TransportPlugin *plugin = cls;
2191   struct TransportPingMessage *ping;
2192   struct TransportPongMessage *pong;
2193   uint16_t msize;
2194   struct NeighborList *n;
2195   pong = GNUNET_malloc(sizeof(struct TransportPongMessage));
2196
2197 #if DEBUG_TRANSPORT
2198     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2199                 "Processing `%s' from `%s'\n",
2200                "PING", GNUNET_a2s ((const struct sockaddr *)sender_address, sender_address_len));
2201 #endif
2202
2203   msize = ntohs (message->size);
2204   if (msize < sizeof (struct TransportPingMessage))
2205     {
2206       GNUNET_break_op (0);
2207       return GNUNET_SYSERR;
2208     }
2209   ping = (struct TransportPingMessage *) message;
2210   if (0 != memcmp (&ping->target,
2211                    plugin->env.my_identity,
2212                    sizeof (struct GNUNET_PeerIdentity)))
2213     {
2214       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2215                   _("Received `%s' message not destined for me!\n"), "PING");
2216       return GNUNET_SYSERR;
2217     }
2218
2219   msize -= sizeof (struct TransportPingMessage);
2220 /*
2221  * if (GNUNET_OK != tcp_plugin_address_suggested (plugin, &vcm[1], msize))
2222     {
2223       GNUNET_break_op (0);
2224       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2225       return;
2226     }
2227
2228   if (GNUNET_OK != GNUNET_SERVER_client_get_address (client, &addr, &addrlen))
2229     {
2230       GNUNET_break (0);
2231       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2232       return;
2233     }
2234 */
2235   pong = GNUNET_malloc (sizeof (struct TransportPongMessage) + sender_address_len);
2236   pong->header.size = htons (sizeof (struct TransportPongMessage) + sender_address_len);
2237   pong->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_PONG);
2238   pong->purpose.size =
2239     htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) +
2240            sizeof (uint32_t) +
2241            sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) + sender_address_len);
2242   pong->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_TCP_PING);
2243   pong->challenge = ping->challenge;
2244
2245   memcpy(&pong->signer, &my_public_key, sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
2246   memcpy (&pong[1], sender_address, sender_address_len);
2247   GNUNET_assert (GNUNET_OK ==
2248                  GNUNET_CRYPTO_rsa_sign (my_private_key,
2249                                          &pong->purpose, &pong->signature));
2250   /* Will this nonsense work, even for UDP?
2251    * The idea is that we need an address to send to for UDP, but we may not know
2252    * this peer yet.  So in that case, we need to create a new neighbor with the
2253    * current address, but is this address going to be correct, or will it have a
2254    * random high port or something? Another question is, why didn't we get a WELCOME
2255    * from this peer with its advertised addresses already?  We don't want to
2256    * differentiate based on transport... */
2257   n = find_neighbor(peer, NULL, 0);
2258   if (n == NULL)
2259     {
2260 #if DEBUG_TRANSPORT
2261     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2262                 "Didn't find peer in list, adding...\n");
2263 #endif
2264       setup_new_neighbor(peer, sender_address, sender_address_len);
2265       n = find_neighbor(peer, sender_address, sender_address_len);
2266       GNUNET_assert(n != NULL);
2267     }
2268   else if (n->addr == NULL)
2269     {
2270 #if DEBUG_TRANSPORT
2271     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2272                 "Found peer in list, but without address, adding!\n");
2273 #endif
2274       n->addr = GNUNET_malloc(sender_address_len);
2275       memcpy(n->addr, sender_address, sender_address_len);
2276       n->addr_len = sender_address_len;
2277     }
2278
2279   transmit_to_peer(NULL, TRANSPORT_DEFAULT_PRIORITY, &pong->header, GNUNET_NO, n);
2280
2281   GNUNET_free(pong);
2282   return GNUNET_OK;
2283 }
2284
2285 /**
2286  * Function called by the plugin for each received message.
2287  * Update data volumes, possibly notify plugins about
2288  * reducing the rate at which they read from the socket
2289  * and generally forward to our receive callback.
2290  *
2291  * @param cls the "struct TransportPlugin *" we gave to the plugin
2292  * @param message the message, NULL if peer was disconnected
2293  * @param distance the transport cost to this peer (not latency!)
2294  * @param sender_address the address that the sender reported
2295  *        (opaque to transport service)
2296  * @param sender_address_len the length of the sender address
2297  * @param peer (claimed) identity of the other peer
2298  * @return the new service_context that the plugin should use
2299  *         for future receive calls for messages from this
2300  *         particular peer
2301  *
2302  */
2303 static void
2304 plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
2305                     const struct GNUNET_MessageHeader *message,
2306                     unsigned int distance, const char *sender_address,
2307                     size_t sender_address_len)
2308 {
2309   const struct GNUNET_MessageHeader ack = {
2310     htons (sizeof (struct GNUNET_MessageHeader)),
2311     htons (GNUNET_MESSAGE_TYPE_TRANSPORT_ACK)
2312   };
2313   struct ReadyList *service_context;
2314   struct TransportPlugin *plugin = cls;
2315   struct TransportClient *cpos;
2316   struct InboundMessage *im;
2317   uint16_t msize;
2318   struct NeighborList *n;
2319
2320   n = find_neighbor (peer, sender_address, sender_address_len);
2321   if (n == NULL)
2322     {
2323       if (message == NULL)
2324         return;                 /* disconnect of peer already marked down */
2325       n = setup_new_neighbor (peer, sender_address, sender_address_len);
2326     }
2327   service_context = n->plugins;
2328   while ((service_context != NULL) && (plugin != service_context->plugin))
2329     service_context = service_context->next;
2330   GNUNET_assert ((plugin->api->send == NULL) || (service_context != NULL));
2331   if (message == NULL)
2332     {
2333 #if DEBUG_TRANSPORT
2334       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2335                   "Receive failed from `%4s', triggering disconnect\n",
2336                   GNUNET_i2s (&n->id));
2337 #endif
2338       /* TODO: call stats */
2339       if (service_context != NULL)
2340         service_context->connected = GNUNET_NO;
2341       disconnect_neighbor (n, GNUNET_YES);
2342       return;
2343     }
2344 #if DEBUG_TRANSPORT
2345   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2346               "Processing message of type `%u' received by plugin...\n",
2347               ntohs (message->type));
2348 #endif
2349   if (service_context != NULL)
2350     {
2351       if (service_context->connected == GNUNET_NO)
2352         {
2353           service_context->connected = GNUNET_YES;
2354           service_context->transmit_ready = GNUNET_YES;
2355           service_context->connect_attempts++;
2356         }
2357       service_context->timeout
2358         =
2359         GNUNET_TIME_relative_to_absolute
2360         (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
2361       /* service_context->latency = latency; */ /* This value should be set by us! */
2362     }
2363   /* update traffic received amount ... */
2364   msize = ntohs (message->size);
2365   n->last_received += msize;
2366   GNUNET_SCHEDULER_cancel (sched, n->timeout_task);
2367   n->peer_timeout =
2368     GNUNET_TIME_relative_to_absolute
2369     (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
2370   n->timeout_task =
2371     GNUNET_SCHEDULER_add_delayed (sched,
2372                                   GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
2373                                   &neighbor_timeout_task, n);
2374   update_quota (n);
2375   if (n->quota_violation_count > QUOTA_VIOLATION_DROP_THRESHOLD)
2376     {
2377       /* dropping message due to frequent inbound volume violations! */
2378       GNUNET_log (GNUNET_ERROR_TYPE_WARNING |
2379                   GNUNET_ERROR_TYPE_BULK,
2380                   _
2381                   ("Dropping incoming message due to repeated bandwidth quota violations.\n"));
2382       /* TODO: call stats */
2383       GNUNET_assert ((service_context == NULL) ||
2384                      (NULL != service_context->neighbor));
2385       return;
2386     }
2387   switch (ntohs (message->type))
2388     {
2389     case GNUNET_MESSAGE_TYPE_HELLO:
2390 #if DEBUG_TRANSPORT
2391       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2392                   "Receiving `%s' message from `%4s'.\n", "HELLO",
2393                   GNUNET_i2s (peer));
2394 #endif
2395       process_hello (plugin, message);
2396 #if DEBUG_TRANSPORT
2397       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2398                   "Sending `%s' message to connecting peer `%4s'.\n", "ACK",
2399                   GNUNET_i2s (peer));
2400 #endif
2401       transmit_to_peer (NULL, 0, &ack, GNUNET_YES, n);
2402       break;
2403     case GNUNET_MESSAGE_TYPE_TRANSPORT_PING:
2404       handle_ping(plugin, message, peer, sender_address, sender_address_len);
2405       break;
2406     case GNUNET_MESSAGE_TYPE_TRANSPORT_PONG:
2407       handle_pong(plugin, message, peer, sender_address, sender_address_len);
2408       break;
2409       //plugin_env_notify_validation();
2410     case GNUNET_MESSAGE_TYPE_TRANSPORT_ACK:
2411       n->saw_ack = GNUNET_YES;
2412       /* intentional fall-through! */
2413     default:
2414 #if DEBUG_TRANSPORT
2415       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2416                   "Received message of type %u from `%4s', sending to all clients.\n",
2417                   ntohs (message->type), GNUNET_i2s (peer));
2418 #endif
2419       /* transmit message to all clients */
2420       im = GNUNET_malloc (sizeof (struct InboundMessage) + msize);
2421       im->header.size = htons (sizeof (struct InboundMessage) + msize);
2422       im->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RECV);
2423       im->latency = n->latency;
2424       im->peer = *peer;
2425       memcpy (&im[1], message, msize);
2426
2427       cpos = clients;
2428       while (cpos != NULL)
2429         {
2430           transmit_to_client (cpos, &im->header, GNUNET_YES);
2431           cpos = cpos->next;
2432         }
2433       GNUNET_free (im);
2434     }
2435   GNUNET_assert ((service_context == NULL) ||
2436                  (NULL != service_context->neighbor));
2437 }
2438
2439
2440 /**
2441  * Handle START-message.  This is the first message sent to us
2442  * by any client which causes us to add it to our list.
2443  *
2444  * @param cls closure (always NULL)
2445  * @param client identification of the client
2446  * @param message the actual message
2447  */
2448 static void
2449 handle_start (void *cls,
2450               struct GNUNET_SERVER_Client *client,
2451               const struct GNUNET_MessageHeader *message)
2452 {
2453   struct TransportClient *c;
2454   struct ConnectInfoMessage cim;
2455   struct NeighborList *n;
2456   struct InboundMessage *im;
2457   struct GNUNET_MessageHeader *ack;
2458
2459 #if DEBUG_TRANSPORT
2460   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2461               "Received `%s' request from client\n", "START");
2462 #endif
2463   c = clients;
2464   while (c != NULL)
2465     {
2466       if (c->client == client)
2467         {
2468           /* client already on our list! */
2469           GNUNET_break (0);
2470           GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2471           return;
2472         }
2473       c = c->next;
2474     }
2475   c = GNUNET_malloc (sizeof (struct TransportClient));
2476   c->next = clients;
2477   clients = c;
2478   c->client = client;
2479   if (our_hello != NULL)
2480     {
2481 #if DEBUG_TRANSPORT
2482       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2483                   "Sending our own `%s' to new client\n", "HELLO");
2484 #endif
2485       transmit_to_client (c,
2486                           (const struct GNUNET_MessageHeader *) our_hello,
2487                           GNUNET_NO);
2488       /* tell new client about all existing connections */
2489       cim.header.size = htons (sizeof (struct ConnectInfoMessage));
2490       cim.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
2491       cim.quota_out =
2492         htonl (GNUNET_CONSTANTS_DEFAULT_BPM_IN_OUT / (60 * 1000));
2493       cim.latency = GNUNET_TIME_relative_hton (GNUNET_TIME_UNIT_ZERO);  /* FIXME? */
2494       im = GNUNET_malloc (sizeof (struct InboundMessage) +
2495                           sizeof (struct GNUNET_MessageHeader));
2496       im->header.size = htons (sizeof (struct InboundMessage) +
2497                                sizeof (struct GNUNET_MessageHeader));
2498       im->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RECV);
2499       im->latency = GNUNET_TIME_relative_hton (GNUNET_TIME_UNIT_ZERO);  /* FIXME? */
2500       ack = (struct GNUNET_MessageHeader *) &im[1];
2501       ack->size = htons (sizeof (struct GNUNET_MessageHeader));
2502       ack->type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_ACK);
2503       for (n = neighbors; n != NULL; n = n->next)
2504         {
2505           cim.id = n->id;
2506           transmit_to_client (c, &cim.header, GNUNET_NO);
2507           if (n->saw_ack)
2508             {
2509               im->peer = n->id;
2510               transmit_to_client (c, &im->header, GNUNET_NO);
2511             }
2512         }
2513       GNUNET_free (im);
2514     }
2515   else
2516     {
2517       fprintf(stderr, "Our hello is NULL!\n");
2518     }
2519   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2520 }
2521
2522
2523 /**
2524  * Handle HELLO-message.
2525  *
2526  * @param cls closure (always NULL)
2527  * @param client identification of the client
2528  * @param message the actual message
2529  */
2530 static void
2531 handle_hello (void *cls,
2532               struct GNUNET_SERVER_Client *client,
2533               const struct GNUNET_MessageHeader *message)
2534 {
2535   int ret;
2536
2537 #if DEBUG_TRANSPORT
2538   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2539               "Received `%s' request from client\n", "HELLO");
2540 #endif
2541   ret = process_hello (NULL, message);
2542   GNUNET_SERVER_receive_done (client, ret);
2543 }
2544
2545
2546 /**
2547  * Handle SEND-message.
2548  *
2549  * @param cls closure (always NULL)
2550  * @param client identification of the client
2551  * @param message the actual message
2552  */
2553 static void
2554 handle_send (void *cls,
2555              struct GNUNET_SERVER_Client *client,
2556              const struct GNUNET_MessageHeader *message)
2557 {
2558   struct TransportClient *tc;
2559   struct NeighborList *n;
2560   const struct OutboundMessage *obm;
2561   const struct GNUNET_MessageHeader *obmm;
2562   uint16_t size;
2563   uint16_t msize;
2564
2565   size = ntohs (message->size);
2566   if (size <
2567       sizeof (struct OutboundMessage) + sizeof (struct GNUNET_MessageHeader))
2568     {
2569       GNUNET_break (0);
2570       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2571       return;
2572     }
2573   obm = (const struct OutboundMessage *) message;
2574 #if DEBUG_TRANSPORT
2575   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2576               "Received `%s' request from client with target `%4s'\n",
2577               "SEND", GNUNET_i2s (&obm->peer));
2578 #endif
2579   obmm = (const struct GNUNET_MessageHeader *) &obm[1];
2580   msize = ntohs (obmm->size);
2581   if (size != msize + sizeof (struct OutboundMessage))
2582     {
2583       GNUNET_break (0);
2584       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2585       return;
2586     }
2587   n = find_neighbor (&obm->peer, NULL, 0);
2588   if (n == NULL)
2589     n = setup_new_neighbor (&obm->peer, NULL, 0);
2590   tc = clients;
2591   while ((tc != NULL) && (tc->client != client))
2592     tc = tc->next;
2593
2594 #if DEBUG_TRANSPORT
2595   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2596               "Client asked to transmit %u-byte message of type %u to `%4s'\n",
2597               ntohs (obmm->size),
2598               ntohs (obmm->type), GNUNET_i2s (&obm->peer));
2599 #endif
2600   transmit_to_peer (tc, ntohl (obm->priority), obmm, GNUNET_NO, n);
2601   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2602 }
2603
2604
2605 /**
2606  * Handle SET_QUOTA-message.
2607  *
2608  * @param cls closure (always NULL)
2609  * @param client identification of the client
2610  * @param message the actual message
2611  */
2612 static void
2613 handle_set_quota (void *cls,
2614                   struct GNUNET_SERVER_Client *client,
2615                   const struct GNUNET_MessageHeader *message)
2616 {
2617   const struct QuotaSetMessage *qsm =
2618     (const struct QuotaSetMessage *) message;
2619   struct NeighborList *n;
2620   struct TransportPlugin *p;
2621   struct ReadyList *rl;
2622
2623 #if DEBUG_TRANSPORT
2624   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2625               "Received `%s' request from client for peer `%4s'\n",
2626               "SET_QUOTA", GNUNET_i2s (&qsm->peer));
2627 #endif
2628   n = find_neighbor (&qsm->peer, NULL, 0);
2629   if (n == NULL)
2630     {
2631       GNUNET_SERVER_receive_done (client, GNUNET_OK);
2632       return;
2633     }
2634   update_quota (n);
2635   if (n->quota_in < ntohl (qsm->quota_in))
2636     n->last_quota_update = GNUNET_TIME_absolute_get ();
2637   n->quota_in = ntohl (qsm->quota_in);
2638   rl = n->plugins;
2639   while (rl != NULL)
2640     {
2641       p = rl->plugin;
2642       p->api->set_receive_quota (p->api->cls,
2643                                  &qsm->peer, ntohl (qsm->quota_in));
2644       rl = rl->next;
2645     }
2646   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2647 }
2648
2649
2650 /**
2651  * Handle TRY_CONNECT-message.
2652  *
2653  * @param cls closure (always NULL)
2654  * @param client identification of the client
2655  * @param message the actual message
2656  */
2657 static void
2658 handle_try_connect (void *cls,
2659                     struct GNUNET_SERVER_Client *client,
2660                     const struct GNUNET_MessageHeader *message)
2661 {
2662   const struct TryConnectMessage *tcm;
2663
2664   tcm = (const struct TryConnectMessage *) message;
2665 #if DEBUG_TRANSPORT
2666   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2667               "Received `%s' request from client %p asking to connect to `%4s'\n",
2668               "TRY_CONNECT", client, GNUNET_i2s (&tcm->peer));
2669 #endif
2670   if (NULL == find_neighbor (&tcm->peer, NULL, 0))
2671     setup_new_neighbor (&tcm->peer, NULL, 0); /* Can we set up a truly _new_ neighbor without
2672                                         knowing its address?  Should we ask the plugin
2673                                         for more information about this peer?  I don't
2674                                         think we can...  Or set up new peer should only
2675                                         happen when transport notifies us of an address,
2676                                         and this setup should check for an address in
2677                                         the existing list only */
2678 #if DEBUG_TRANSPORT
2679   else
2680     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2681                 "Client asked to connect to `%4s', but connection already exists\n",
2682                 "TRY_CONNECT", GNUNET_i2s (&tcm->peer));
2683 #endif
2684   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2685 }
2686
2687 static void
2688 transmit_address_to_client (void *cls, const char *address)
2689 {
2690   struct GNUNET_SERVER_TransmitContext *tc = cls;
2691   size_t slen;
2692
2693   if (NULL == address)
2694     slen = 0;
2695   else
2696     slen = strlen (address) + 1;
2697   GNUNET_SERVER_transmit_context_append_data (tc, address, slen,
2698                                               GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_REPLY);
2699   if (NULL == address)
2700     GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
2701 }
2702
2703 /**
2704  * Handle AddressLookup-message.
2705  *
2706  * @param cls closure (always NULL)
2707  * @param client identification of the client
2708  * @param message the actual message
2709  */
2710 static void
2711 handle_address_lookup (void *cls,
2712                        struct GNUNET_SERVER_Client *client,
2713                        const struct GNUNET_MessageHeader *message)
2714 {
2715   const struct AddressLookupMessage *alum;
2716   struct TransportPlugin *lsPlugin;
2717   const char *nameTransport;
2718   const char *address;
2719   uint16_t size;
2720   struct GNUNET_SERVER_TransmitContext *tc;
2721
2722   size = ntohs (message->size);
2723   if (size < sizeof (struct AddressLookupMessage))
2724     {
2725       GNUNET_break_op (0);
2726       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2727       return;
2728     }
2729   alum = (const struct AddressLookupMessage *) message;
2730   uint32_t addressLen = ntohl (alum->addrlen);
2731   if (size <= sizeof (struct AddressLookupMessage) + addressLen)
2732     {
2733       GNUNET_break_op (0);
2734       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2735       return;
2736     }
2737   address = (const char *) &alum[1];
2738   nameTransport = (const char *) &address[addressLen];
2739   if (nameTransport
2740       [size - sizeof (struct AddressLookupMessage) - addressLen - 1] != '\0')
2741     {
2742       GNUNET_break_op (0);
2743       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2744       return;
2745     }
2746   struct GNUNET_TIME_Absolute timeout =
2747     GNUNET_TIME_absolute_ntoh (alum->timeout);
2748   struct GNUNET_TIME_Relative rtimeout =
2749     GNUNET_TIME_absolute_get_remaining (timeout);
2750   lsPlugin = find_transport (nameTransport);
2751   if (NULL == lsPlugin)
2752     {
2753       tc = GNUNET_SERVER_transmit_context_create (client);
2754       GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
2755                                                   GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_REPLY);
2756       GNUNET_SERVER_transmit_context_run (tc, rtimeout);
2757       return;
2758     }
2759   tc = GNUNET_SERVER_transmit_context_create (client);
2760   lsPlugin->api->address_pretty_printer (cls, nameTransport,
2761                                          address, addressLen, GNUNET_YES,
2762                                          rtimeout,
2763                                          &transmit_address_to_client, tc);
2764 }
2765
2766 /**
2767  * List of handlers for the messages understood by this
2768  * service.
2769  */
2770 static struct GNUNET_SERVER_MessageHandler handlers[] = {
2771   {&handle_start, NULL,
2772    GNUNET_MESSAGE_TYPE_TRANSPORT_START, 0},
2773   {&handle_hello, NULL,
2774    GNUNET_MESSAGE_TYPE_HELLO, 0},
2775   {&handle_send, NULL,
2776    GNUNET_MESSAGE_TYPE_TRANSPORT_SEND, 0},
2777   {&handle_set_quota, NULL,
2778    GNUNET_MESSAGE_TYPE_TRANSPORT_SET_QUOTA, sizeof (struct QuotaSetMessage)},
2779   {&handle_try_connect, NULL,
2780    GNUNET_MESSAGE_TYPE_TRANSPORT_TRY_CONNECT,
2781    sizeof (struct TryConnectMessage)},
2782   {&handle_address_lookup, NULL,
2783    GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_LOOKUP,
2784    0},
2785   {NULL, NULL, 0, 0}
2786 };
2787
2788
2789 /**
2790  * Setup the environment for this plugin.
2791  */
2792 static void
2793 create_environment (struct TransportPlugin *plug)
2794 {
2795   plug->env.cfg = cfg;
2796   plug->env.sched = sched;
2797   plug->env.my_identity = &my_identity;
2798   plug->env.cls = plug;
2799   plug->env.receive = &plugin_env_receive;
2800   plug->env.notify_address = &plugin_env_notify_address;
2801   plug->env.default_quota_in =
2802     (GNUNET_CONSTANTS_DEFAULT_BPM_IN_OUT + 59999) / (60 * 1000);
2803   plug->env.max_connections = max_connect_per_transport;
2804 }
2805
2806
2807 /**
2808  * Start the specified transport (load the plugin).
2809  */
2810 static void
2811 start_transport (struct GNUNET_SERVER_Handle *server, const char *name)
2812 {
2813   struct TransportPlugin *plug;
2814   char *libname;
2815
2816   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2817               _("Loading `%s' transport plugin\n"), name);
2818   GNUNET_asprintf (&libname, "libgnunet_plugin_transport_%s", name);
2819   plug = GNUNET_malloc (sizeof (struct TransportPlugin));
2820   create_environment (plug);
2821   plug->short_name = GNUNET_strdup (name);
2822   plug->lib_name = libname;
2823   plug->next = plugins;
2824   plugins = plug;
2825   plug->api = GNUNET_PLUGIN_load (libname, &plug->env);
2826   if (plug->api == NULL)
2827     {
2828       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2829                   _("Failed to load transport plugin for `%s'\n"), name);
2830       GNUNET_free (plug->short_name);
2831       plugins = plug->next;
2832       GNUNET_free (libname);
2833       GNUNET_free (plug);
2834     }
2835 }
2836
2837
2838 /**
2839  * Called whenever a client is disconnected.  Frees our
2840  * resources associated with that client.
2841  *
2842  * @param cls closure
2843  * @param client identification of the client
2844  */
2845 static void
2846 client_disconnect_notification (void *cls,
2847                                 struct GNUNET_SERVER_Client *client)
2848 {
2849   struct TransportClient *pos;
2850   struct TransportClient *prev;
2851   struct ClientMessageQueueEntry *mqe;
2852
2853   if (client == NULL)
2854     return;
2855 #if DEBUG_TRANSPORT
2856   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2857               "Client disconnected, cleaning up.\n");
2858 #endif
2859   prev = NULL;
2860   pos = clients;
2861   while ((pos != NULL) && (pos->client != client))
2862     {
2863       prev = pos;
2864       pos = pos->next;
2865     }
2866   if (pos == NULL)
2867     return;
2868   while (NULL != (mqe = pos->message_queue_head))
2869     {
2870       pos->message_queue_head = mqe->next;
2871       GNUNET_free (mqe);
2872     }
2873   pos->message_queue_head = NULL;
2874   if (prev == NULL)
2875     clients = pos->next;
2876   else
2877     prev->next = pos->next;
2878   if (GNUNET_YES == pos->tcs_pending)
2879     {
2880       pos->client = NULL;
2881       return;
2882     }
2883   GNUNET_free (pos);
2884 }
2885
2886
2887 /**
2888  * Function called when the service shuts down.  Unloads our plugins.
2889  *
2890  * @param cls closure, unused
2891  * @param tc task context (unused)
2892  */
2893 static void
2894 unload_plugins (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2895 {
2896   struct TransportPlugin *plug;
2897   struct AddressList *al;
2898
2899 #if DEBUG_TRANSPORT
2900   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2901               "Transport service is unloading plugins...\n");
2902 #endif
2903   while (NULL != (plug = plugins))
2904     {
2905       plugins = plug->next;
2906       GNUNET_break (NULL == GNUNET_PLUGIN_unload (plug->lib_name, plug->api));
2907       GNUNET_free (plug->lib_name);
2908       GNUNET_free (plug->short_name);
2909       while (NULL != (al = plug->addresses))
2910         {
2911           plug->addresses = al->next;
2912           GNUNET_free (al);
2913         }
2914       GNUNET_free (plug);
2915     }
2916   if (my_private_key != NULL)
2917     GNUNET_CRYPTO_rsa_key_free (my_private_key);
2918   GNUNET_free_non_null (our_hello);
2919 }
2920
2921
2922 /**
2923  * Initiate transport service.
2924  *
2925  * @param cls closure
2926  * @param s scheduler to use
2927  * @param serv the initialized server
2928  * @param c configuration to use
2929  */
2930 static void
2931 run (void *cls,
2932      struct GNUNET_SCHEDULER_Handle *s,
2933      struct GNUNET_SERVER_Handle *serv,
2934      const struct GNUNET_CONFIGURATION_Handle *c)
2935 {
2936   char *plugs;
2937   char *pos;
2938   int no_transports;
2939   unsigned long long tneigh;
2940   char *keyfile;
2941
2942   sched = s;
2943   cfg = c;
2944   /* parse configuration */
2945   if ((GNUNET_OK !=
2946        GNUNET_CONFIGURATION_get_value_number (c,
2947                                               "TRANSPORT",
2948                                               "NEIGHBOUR_LIMIT",
2949                                               &tneigh)) ||
2950       (GNUNET_OK !=
2951        GNUNET_CONFIGURATION_get_value_filename (c,
2952                                                 "GNUNETD",
2953                                                 "HOSTKEY", &keyfile)))
2954     {
2955       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2956                   _
2957                   ("Transport service is lacking key configuration settings.  Exiting.\n"));
2958       GNUNET_SCHEDULER_shutdown (s);
2959       return;
2960     }
2961   max_connect_per_transport = (uint32_t) tneigh;
2962   my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
2963   GNUNET_free (keyfile);
2964   if (my_private_key == NULL)
2965     {
2966       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2967                   _
2968                   ("Transport service could not access hostkey.  Exiting.\n"));
2969       GNUNET_SCHEDULER_shutdown (s);
2970       return;
2971     }
2972   GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key);
2973   GNUNET_CRYPTO_hash (&my_public_key,
2974                       sizeof (my_public_key), &my_identity.hashPubKey);
2975   /* setup notification */
2976   server = serv;
2977   GNUNET_SERVER_disconnect_notify (server,
2978                                    &client_disconnect_notification, NULL);
2979   /* load plugins... */
2980   no_transports = 1;
2981   if (GNUNET_OK ==
2982       GNUNET_CONFIGURATION_get_value_string (c,
2983                                              "TRANSPORT", "PLUGINS", &plugs))
2984     {
2985       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2986                   _("Starting transport plugins `%s'\n"), plugs);
2987       pos = strtok (plugs, " ");
2988       while (pos != NULL)
2989         {
2990           start_transport (server, pos);
2991           no_transports = 0;
2992           pos = strtok (NULL, " ");
2993         }
2994       GNUNET_free (plugs);
2995     }
2996   GNUNET_SCHEDULER_add_delayed (sched,
2997                                 GNUNET_TIME_UNIT_FOREVER_REL,
2998                                 &unload_plugins, NULL);
2999   if (no_transports)
3000     refresh_hello ();
3001
3002 #if DEBUG_TRANSPORT
3003   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Transport service ready.\n"));
3004 #endif
3005   /* process client requests */
3006   GNUNET_SERVER_add_handlers (server, handlers);
3007 }
3008
3009
3010 /**
3011  * The main function for the transport service.
3012  *
3013  * @param argc number of arguments from the command line
3014  * @param argv command line arguments
3015  * @return 0 ok, 1 on error
3016  */
3017 int
3018 main (int argc, char *const *argv)
3019 {
3020   return (GNUNET_OK ==
3021           GNUNET_SERVICE_run (argc,
3022                               argv,
3023                               "transport",
3024                               GNUNET_SERVICE_OPTION_NONE,
3025                               &run, NULL)) ? 0 : 1;
3026 }
3027
3028 /* end of gnunet-service-transport.c */