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