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