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