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