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