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