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