e0802c75855cec31473bbbaa0f6330cc6fe44ea4
[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   const struct TransportPongMessage *pong = (const 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
2190 #if DEBUG_TRANSPORT
2191   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2192               "Notifying peerinfo about peer %s\n",
2193               GNUNET_i2s (&target));
2194 #endif
2195   /* For some reason the line below causes something to hang up... maybe peerinfo isn't ready yet? */
2196   /*GNUNET_PEERINFO_add_peer (cfg, sched, &target, hello); */
2197
2198   /* check if a HELLO for this peer is already on the validation list */
2199   e = pending_validations;
2200   while (e != NULL)
2201     {
2202       if (0 == memcmp (&e->publicKey,
2203                        &publicKey,
2204                        sizeof (struct
2205                                GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)))
2206         {
2207           /* TODO: call to stats? */
2208 #if DEBUG_TRANSPORT
2209           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2210                       "`%s' message for peer `%4s' is already pending; ignoring new message\n",
2211                       "HELLO", GNUNET_i2s (&target));
2212 #endif
2213           return GNUNET_OK;
2214         }
2215       e = e->next;
2216     }
2217   chvc = GNUNET_malloc (sizeof (struct CheckHelloValidatedContext) + hsize);
2218   chvc->plugin = plugin;
2219   chvc->hello = (struct GNUNET_HELLO_Message *) &chvc[1];
2220   chvc->e = NULL;
2221   memcpy (chvc->hello, hello, hsize);
2222   /* finally, check if HELLO was previously validated
2223      (continuation will then schedule actual validation) */
2224   chvc->piter = GNUNET_PEERINFO_iterate (cfg,
2225                                          sched,
2226                                          &target,
2227                                          0,
2228                                          HELLO_VERIFICATION_TIMEOUT,
2229                                          &check_hello_validated, chvc);
2230   return GNUNET_OK;
2231 }
2232
2233
2234 /**
2235  * The peer specified by the given neighbor has timed-out or a plugin
2236  * has disconnected.  We may either need to do nothing (other plugins
2237  * still up), or trigger a full disconnect and clean up.  This
2238  * function updates our state and does the necessary notifications.
2239  * Also notifies our clients that the neighbor is now officially
2240  * gone.
2241  *
2242  * @param n the neighbor list entry for the peer
2243  * @param check should we just check if all plugins
2244  *        disconnected or must we ask all plugins to
2245  *        disconnect?
2246  */
2247 static void
2248 disconnect_neighbor (struct NeighborList *current_handle, int check)
2249 {
2250   struct ReadyList *rpos;
2251   struct NeighborList *npos;
2252   struct NeighborList *nprev;
2253   struct NeighborList *n;
2254   struct MessageQueue *mq;
2255   struct PeerAddressList *peer_addresses;
2256
2257   if (neighbors == NULL)
2258     return; /* We don't have any neighbors, so client has an already removed handle! */
2259
2260   npos = neighbors;
2261   while ((npos != NULL) && (current_handle != npos))
2262     npos = npos->next;
2263
2264   if (npos == NULL)
2265     return; /* Couldn't find neighbor in existing list, must have been already removed! */
2266   else
2267     n = npos;
2268
2269   if (GNUNET_YES == check)
2270     {
2271       rpos = n->plugins;
2272       while (NULL != rpos)
2273         {
2274           peer_addresses = rpos->addresses;
2275           while (peer_addresses != NULL)
2276             {
2277               if (GNUNET_YES == peer_addresses->connected)
2278                 return;             /* still connected */
2279               peer_addresses = peer_addresses->next;
2280             }
2281           rpos = rpos->next;
2282         }
2283     }
2284
2285 #if DEBUG_TRANSPORT
2286   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2287               "Disconnecting from `%4s'\n", GNUNET_i2s (&n->id));
2288 #endif
2289   /* remove n from neighbors list */
2290   nprev = NULL;
2291   npos = neighbors;
2292   while ((npos != NULL) && (npos != n))
2293     {
2294       nprev = npos;
2295       npos = npos->next;
2296     }
2297   GNUNET_assert (npos != NULL);
2298   if (nprev == NULL)
2299     neighbors = n->next;
2300   else
2301     nprev->next = n->next;
2302
2303   /* notify all clients about disconnect */
2304   notify_clients_disconnect (&n->id);
2305
2306   /* clean up all plugins, cancel connections and pending transmissions */
2307   while (NULL != (rpos = n->plugins))
2308     {
2309       n->plugins = rpos->next;
2310       GNUNET_assert (rpos->neighbor == n);
2311       if (GNUNET_YES == rpos->connected)
2312         rpos->plugin->api->disconnect (rpos->plugin->api->cls, &n->id);
2313       GNUNET_free (rpos);
2314     }
2315
2316   /* free all messages on the queue */
2317   while (NULL != (mq = n->messages))
2318     {
2319       n->messages = mq->next;
2320       GNUNET_assert (0 == memcmp(mq->neighbor_id, &n->id, sizeof(struct GNUNET_PeerIdentity)));
2321       GNUNET_free (mq);
2322     }
2323   if (n->timeout_task != GNUNET_SCHEDULER_NO_TASK)
2324     GNUNET_SCHEDULER_cancel (sched, n->timeout_task);
2325   /* finally, free n itself */
2326   GNUNET_free (n);
2327 }
2328
2329
2330 /*
2331  * We have received a PING message from someone.  Need to send a PONG message
2332  * in response to the peer by any means necessary.  Of course, with something
2333  * like TCP where a connection exists, we may want to send it that way.  But
2334  * we may not be able to make that distinction...
2335  */
2336 static int handle_ping(void *cls, const struct GNUNET_MessageHeader *message,
2337                        const struct GNUNET_PeerIdentity *peer,
2338                        const char *sender_address,
2339                        size_t sender_address_len)
2340 {
2341   struct TransportPlugin *plugin = cls;
2342   struct TransportPingMessage *ping;
2343   struct TransportPongMessage *pong;
2344   struct PeerAddressList *peer_address;
2345   uint16_t msize;
2346   struct NeighborList *n;
2347
2348 #if DEBUG_TRANSPORT
2349     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2350                 "Processing `%s' from `%s'\n",
2351                "PING", GNUNET_a2s ((const struct sockaddr *)sender_address, sender_address_len));
2352 #endif
2353
2354   msize = ntohs (message->size);
2355   if (msize < sizeof (struct TransportPingMessage))
2356     {
2357       GNUNET_break_op (0);
2358       return GNUNET_SYSERR;
2359     }
2360   ping = (struct TransportPingMessage *) message;
2361   if (0 != memcmp (&ping->target,
2362                    plugin->env.my_identity,
2363                    sizeof (struct GNUNET_PeerIdentity)))
2364     {
2365       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2366                   _("Received `%s' message not destined for me!\n"), "PING");
2367       return GNUNET_SYSERR;
2368     }
2369
2370   msize -= sizeof (struct TransportPingMessage);
2371
2372   pong = GNUNET_malloc (sizeof (struct TransportPongMessage) + sender_address_len);
2373   pong->header.size = htons (sizeof (struct TransportPongMessage) + sender_address_len);
2374   pong->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_PONG);
2375   pong->purpose.size =
2376     htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) +
2377            sizeof (uint32_t) +
2378            sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) + sender_address_len);
2379   pong->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_TCP_PING);
2380   pong->challenge = ping->challenge;
2381   pong->addrlen = htons(sender_address_len);
2382
2383   memcpy(&pong->signer, &my_public_key, sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
2384   memcpy (&pong[1], sender_address, sender_address_len);
2385   GNUNET_assert (GNUNET_OK ==
2386                  GNUNET_CRYPTO_rsa_sign (my_private_key,
2387                                          &pong->purpose, &pong->signature));
2388
2389   n = find_neighbor(peer);
2390   if (n == NULL)
2391     n = setup_new_neighbor(peer);
2392
2393   peer_address = find_peer_address(n, sender_address, sender_address_len);
2394   if (peer_address == NULL)
2395     peer_address = add_peer_address(n, sender_address, sender_address_len);
2396
2397   peer_address->timeout = GNUNET_TIME_relative_to_absolute(GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
2398
2399   /* We don't use the peer_address because the address we received the message from may not
2400    * be a reliable way to send it back!  We add it to the list which should queue up a separate
2401    * ping to determine if the address is viable.
2402    */
2403   transmit_to_peer(NULL, NULL, TRANSPORT_DEFAULT_PRIORITY, (char *)pong, ntohs(pong->header.size), GNUNET_NO, n);
2404
2405   GNUNET_free(pong);
2406   return GNUNET_OK;
2407 }
2408
2409 /**
2410  * Function called by the plugin for each received message.
2411  * Update data volumes, possibly notify plugins about
2412  * reducing the rate at which they read from the socket
2413  * and generally forward to our receive callback.
2414  *
2415  * @param cls the "struct TransportPlugin *" we gave to the plugin
2416  * @param message the message, NULL if peer was disconnected
2417  * @param distance the transport cost to this peer (not latency!)
2418  * @param sender_address the address that the sender reported
2419  *        (opaque to transport service)
2420  * @param sender_address_len the length of the sender address
2421  * @param peer (claimed) identity of the other peer
2422  * @return the new service_context that the plugin should use
2423  *         for future receive calls for messages from this
2424  *         particular peer
2425  *
2426  */
2427 static void
2428 plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
2429                     const struct GNUNET_MessageHeader *message,
2430                     unsigned int distance, const char *sender_address,
2431                     size_t sender_address_len)
2432 {
2433   struct ReadyList *service_context;
2434   struct TransportPlugin *plugin = cls;
2435   struct TransportClient *cpos;
2436   struct InboundMessage *im;
2437   struct PeerAddressList *peer_address;
2438   uint16_t msize;
2439   struct NeighborList *n;
2440
2441   n = find_neighbor (peer);
2442   if (n == NULL)
2443     {
2444       if (message == NULL)
2445         return;                 /* disconnect of peer already marked down */
2446       n = setup_new_neighbor (peer);
2447
2448     }
2449
2450   peer_address = find_peer_address(n, sender_address, sender_address_len);
2451   if (peer_address == NULL)
2452     peer_address = add_peer_address(n, sender_address, sender_address_len);
2453
2454   service_context = n->plugins;
2455   while ((service_context != NULL) && (plugin != service_context->plugin))
2456     service_context = service_context->next;
2457   GNUNET_assert ((plugin->api->send == NULL) || (service_context != NULL));
2458   if (message == NULL)
2459     {
2460 #if DEBUG_TRANSPORT
2461       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2462                   "Receive failed from `%4s', triggering disconnect\n",
2463                   GNUNET_i2s (&n->id));
2464 #endif
2465       /* TODO: call stats */
2466       if (service_context != NULL)
2467         service_context->connected = GNUNET_NO;
2468       disconnect_neighbor (n, GNUNET_YES);
2469       return;
2470     }
2471 #if DEBUG_TRANSPORT
2472   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2473               "Processing message of type `%u' received by plugin...\n",
2474               ntohs (message->type));
2475 #endif
2476   if (service_context != NULL)
2477     {
2478       if (service_context->connected == GNUNET_NO)
2479         {
2480           /*service_context->connected = GNUNET_YES;*/
2481           /* FIXME: What to do here?  Should we use these as well, to specify some Address
2482            * in the AddressList should be available?
2483            */
2484           peer_address->transmit_ready = GNUNET_YES;
2485           peer_address->connect_attempts++;
2486         }
2487       peer_address->timeout
2488         =
2489         GNUNET_TIME_relative_to_absolute
2490         (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
2491     }
2492   /* update traffic received amount ... */
2493   msize = ntohs (message->size);
2494   n->last_received += msize;
2495   GNUNET_SCHEDULER_cancel (sched, n->timeout_task);
2496   n->peer_timeout =
2497     GNUNET_TIME_relative_to_absolute
2498     (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
2499   n->timeout_task =
2500     GNUNET_SCHEDULER_add_delayed (sched,
2501                                   GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
2502                                   &neighbor_timeout_task, n);
2503   update_quota (n);
2504   if (n->quota_violation_count > QUOTA_VIOLATION_DROP_THRESHOLD)
2505     {
2506       /* dropping message due to frequent inbound volume violations! */
2507       GNUNET_log (GNUNET_ERROR_TYPE_WARNING |
2508                   GNUNET_ERROR_TYPE_BULK,
2509                   _
2510                   ("Dropping incoming message due to repeated bandwidth quota violations.\n"));
2511       /* TODO: call stats */
2512       GNUNET_assert ((service_context == NULL) ||
2513                      (NULL != service_context->neighbor));
2514       return;
2515     }
2516   switch (ntohs (message->type))
2517     {
2518     case GNUNET_MESSAGE_TYPE_HELLO:
2519 #if DEBUG_TRANSPORT
2520       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2521                   "Receiving `%s' message from `%4s'.\n", "HELLO",
2522                   GNUNET_i2s (peer));
2523 #endif
2524       process_hello (plugin, message);
2525       break;
2526     case GNUNET_MESSAGE_TYPE_TRANSPORT_PING:
2527       handle_ping(plugin, message, peer, sender_address, sender_address_len);
2528       break;
2529     case GNUNET_MESSAGE_TYPE_TRANSPORT_PONG:
2530       handle_pong(plugin, message, peer, sender_address, sender_address_len);
2531       break;
2532     default:
2533 #if DEBUG_TRANSPORT
2534       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2535                   "Received REAL MESSAGE type %u from `%4s', sending to all clients.\n",
2536                   ntohs (message->type), GNUNET_i2s (peer));
2537 #endif
2538       /* transmit message to all clients */
2539       im = GNUNET_malloc (sizeof (struct InboundMessage) + msize);
2540       im->header.size = htons (sizeof (struct InboundMessage) + msize);
2541       im->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RECV);
2542       im->latency = n->latency;
2543       im->peer = *peer;
2544       memcpy (&im[1], message, msize);
2545
2546       cpos = clients;
2547       while (cpos != NULL)
2548         {
2549           transmit_to_client (cpos, &im->header, GNUNET_YES);
2550           cpos = cpos->next;
2551         }
2552       GNUNET_free (im);
2553     }
2554   GNUNET_assert ((service_context == NULL) ||
2555                  (NULL != service_context->neighbor));
2556 }
2557
2558
2559 /**
2560  * Handle START-message.  This is the first message sent to us
2561  * by any client which causes us to add it to our list.
2562  *
2563  * @param cls closure (always NULL)
2564  * @param client identification of the client
2565  * @param message the actual message
2566  */
2567 static void
2568 handle_start (void *cls,
2569               struct GNUNET_SERVER_Client *client,
2570               const struct GNUNET_MessageHeader *message)
2571 {
2572   struct TransportClient *c;
2573   struct ConnectInfoMessage cim;
2574   struct NeighborList *n;
2575   struct InboundMessage *im;
2576   struct GNUNET_MessageHeader *ack;
2577
2578 #if DEBUG_TRANSPORT
2579   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2580               "Received `%s' request from client\n", "START");
2581 #endif
2582   c = clients;
2583   while (c != NULL)
2584     {
2585       if (c->client == client)
2586         {
2587           /* client already on our list! */
2588           GNUNET_break (0);
2589           GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2590           return;
2591         }
2592       c = c->next;
2593     }
2594   c = GNUNET_malloc (sizeof (struct TransportClient));
2595   c->next = clients;
2596   clients = c;
2597   c->client = client;
2598   if (our_hello != NULL)
2599     {
2600 #if DEBUG_TRANSPORT
2601       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2602                   "Sending our own `%s' to new client\n", "HELLO");
2603 #endif
2604       transmit_to_client (c,
2605                           (const struct GNUNET_MessageHeader *) our_hello,
2606                           GNUNET_NO);
2607       /* tell new client about all existing connections */
2608       cim.header.size = htons (sizeof (struct ConnectInfoMessage));
2609       cim.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
2610       cim.quota_out =
2611         htonl (GNUNET_CONSTANTS_DEFAULT_BPM_IN_OUT / (60 * 1000));
2612       cim.latency = GNUNET_TIME_relative_hton (GNUNET_TIME_UNIT_ZERO);  /* FIXME? */
2613       im = GNUNET_malloc (sizeof (struct InboundMessage) +
2614                           sizeof (struct GNUNET_MessageHeader));
2615       im->header.size = htons (sizeof (struct InboundMessage) +
2616                                sizeof (struct GNUNET_MessageHeader));
2617       im->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RECV);
2618       im->latency = GNUNET_TIME_relative_hton (GNUNET_TIME_UNIT_ZERO);  /* FIXME? */
2619       ack = (struct GNUNET_MessageHeader *) &im[1];
2620       ack->size = htons (sizeof (struct GNUNET_MessageHeader));
2621       ack->type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_ACK);
2622       for (n = neighbors; n != NULL; n = n->next)
2623         {
2624           cim.id = n->id;
2625           transmit_to_client (c, &cim.header, GNUNET_NO);
2626           if (n->received_pong)
2627             {
2628               im->peer = n->id;
2629               transmit_to_client (c, &im->header, GNUNET_NO);
2630             }
2631         }
2632       GNUNET_free (im);
2633     }
2634   else
2635     {
2636       fprintf(stderr, "Our hello is NULL!\n");
2637     }
2638   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2639 }
2640
2641
2642 /**
2643  * Handle HELLO-message.
2644  *
2645  * @param cls closure (always NULL)
2646  * @param client identification of the client
2647  * @param message the actual message
2648  */
2649 static void
2650 handle_hello (void *cls,
2651               struct GNUNET_SERVER_Client *client,
2652               const struct GNUNET_MessageHeader *message)
2653 {
2654   int ret;
2655
2656 #if DEBUG_TRANSPORT
2657   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2658               "Received `%s' request from client\n", "HELLO");
2659 #endif
2660   ret = process_hello (NULL, message);
2661   GNUNET_SERVER_receive_done (client, ret);
2662 }
2663
2664
2665 /**
2666  * Handle SEND-message.
2667  *
2668  * @param cls closure (always NULL)
2669  * @param client identification of the client
2670  * @param message the actual message
2671  */
2672 static void
2673 handle_send (void *cls,
2674              struct GNUNET_SERVER_Client *client,
2675              const struct GNUNET_MessageHeader *message)
2676 {
2677   struct TransportClient *tc;
2678   struct NeighborList *n;
2679   const struct OutboundMessage *obm;
2680   const struct GNUNET_MessageHeader *obmm;
2681   uint16_t size;
2682   uint16_t msize;
2683
2684   size = ntohs (message->size);
2685   if (size <
2686       sizeof (struct OutboundMessage) + sizeof (struct GNUNET_MessageHeader))
2687     {
2688       GNUNET_break (0);
2689       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2690       return;
2691     }
2692   obm = (const struct OutboundMessage *) message;
2693 #if DEBUG_TRANSPORT
2694   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2695               "Received `%s' request from client with target `%4s'\n",
2696               "SEND", GNUNET_i2s (&obm->peer));
2697 #endif
2698   obmm = (const struct GNUNET_MessageHeader *) &obm[1];
2699   msize = ntohs (obmm->size);
2700   if (size != msize + sizeof (struct OutboundMessage))
2701     {
2702       GNUNET_break (0);
2703       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2704       return;
2705     }
2706   n = find_neighbor (&obm->peer);
2707   if (n == NULL)
2708     n = setup_new_neighbor (&obm->peer); /* But won't ever add address, we have none! */
2709   tc = clients;
2710   while ((tc != NULL) && (tc->client != client))
2711     tc = tc->next;
2712
2713 #if DEBUG_TRANSPORT
2714   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2715               "Client asked to transmit %u-byte message of type %u to `%4s'\n",
2716               ntohs (obmm->size),
2717               ntohs (obmm->type), GNUNET_i2s (&obm->peer));
2718 #endif
2719   transmit_to_peer (tc, NULL, ntohl (obm->priority), (char *)obmm, ntohs (obmm->size), GNUNET_NO, n);
2720   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2721 }
2722
2723
2724 /**
2725  * Handle SET_QUOTA-message.
2726  *
2727  * @param cls closure (always NULL)
2728  * @param client identification of the client
2729  * @param message the actual message
2730  */
2731 static void
2732 handle_set_quota (void *cls,
2733                   struct GNUNET_SERVER_Client *client,
2734                   const struct GNUNET_MessageHeader *message)
2735 {
2736   const struct QuotaSetMessage *qsm =
2737     (const struct QuotaSetMessage *) message;
2738   struct NeighborList *n;
2739   struct TransportPlugin *p;
2740   struct ReadyList *rl;
2741
2742 #if DEBUG_TRANSPORT
2743   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2744               "Received `%s' request from client for peer `%4s'\n",
2745               "SET_QUOTA", GNUNET_i2s (&qsm->peer));
2746 #endif
2747   n = find_neighbor (&qsm->peer);
2748   if (n == NULL)
2749     {
2750       GNUNET_SERVER_receive_done (client, GNUNET_OK);
2751       return;
2752     }
2753   update_quota (n);
2754   if (n->quota_in < ntohl (qsm->quota_in))
2755     n->last_quota_update = GNUNET_TIME_absolute_get ();
2756   n->quota_in = ntohl (qsm->quota_in);
2757   rl = n->plugins;
2758   while (rl != NULL)
2759     {
2760       p = rl->plugin;
2761       p->api->set_receive_quota (p->api->cls,
2762                                  &qsm->peer, ntohl (qsm->quota_in));
2763       rl = rl->next;
2764     }
2765   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2766 }
2767
2768
2769 /**
2770  * Handle TRY_CONNECT-message.
2771  *
2772  * @param cls closure (always NULL)
2773  * @param client identification of the client
2774  * @param message the actual message
2775  */
2776 static void
2777 handle_try_connect (void *cls,
2778                     struct GNUNET_SERVER_Client *client,
2779                     const struct GNUNET_MessageHeader *message)
2780 {
2781   const struct TryConnectMessage *tcm;
2782   struct NeighborList *neighbor;
2783   tcm = (const struct TryConnectMessage *) message;
2784 #if DEBUG_TRANSPORT
2785   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2786               "Received `%s' request from client %p asking to connect to `%4s'\n",
2787               "TRY_CONNECT", client, GNUNET_i2s (&tcm->peer));
2788 #endif
2789   neighbor = find_neighbor(&tcm->peer);
2790
2791   if (neighbor == NULL)
2792     setup_new_neighbor (&tcm->peer);
2793   else
2794     {
2795 #if DEBUG_TRANSPORT
2796       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2797                   "Client asked to connect to `%4s', but connection already exists\n",
2798                   "TRY_CONNECT", GNUNET_i2s (&tcm->peer));
2799 #endif
2800       transmit_to_peer (NULL, NULL, 0,
2801                         (const char *) our_hello, GNUNET_HELLO_size(our_hello),
2802                         GNUNET_YES, neighbor);
2803       notify_clients_connect (&tcm->peer, GNUNET_TIME_UNIT_FOREVER_REL);
2804     }
2805   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2806 }
2807
2808 static void
2809 transmit_address_to_client (void *cls, const char *address)
2810 {
2811   struct GNUNET_SERVER_TransmitContext *tc = cls;
2812   size_t slen;
2813
2814   if (NULL == address)
2815     slen = 0;
2816   else
2817     slen = strlen (address) + 1;
2818   GNUNET_SERVER_transmit_context_append_data (tc, address, slen,
2819                                               GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_REPLY);
2820   if (NULL == address)
2821     GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
2822 }
2823
2824 /**
2825  * Handle AddressLookup-message.
2826  *
2827  * @param cls closure (always NULL)
2828  * @param client identification of the client
2829  * @param message the actual message
2830  */
2831 static void
2832 handle_address_lookup (void *cls,
2833                        struct GNUNET_SERVER_Client *client,
2834                        const struct GNUNET_MessageHeader *message)
2835 {
2836   const struct AddressLookupMessage *alum;
2837   struct TransportPlugin *lsPlugin;
2838   const char *nameTransport;
2839   const char *address;
2840   uint16_t size;
2841   struct GNUNET_SERVER_TransmitContext *tc;
2842
2843   size = ntohs (message->size);
2844   if (size < sizeof (struct AddressLookupMessage))
2845     {
2846       GNUNET_break_op (0);
2847       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2848       return;
2849     }
2850   alum = (const struct AddressLookupMessage *) message;
2851   uint32_t addressLen = ntohl (alum->addrlen);
2852   if (size <= sizeof (struct AddressLookupMessage) + addressLen)
2853     {
2854       GNUNET_break_op (0);
2855       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2856       return;
2857     }
2858   address = (const char *) &alum[1];
2859   nameTransport = (const char *) &address[addressLen];
2860   if (nameTransport
2861       [size - sizeof (struct AddressLookupMessage) - addressLen - 1] != '\0')
2862     {
2863       GNUNET_break_op (0);
2864       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2865       return;
2866     }
2867   struct GNUNET_TIME_Absolute timeout =
2868     GNUNET_TIME_absolute_ntoh (alum->timeout);
2869   struct GNUNET_TIME_Relative rtimeout =
2870     GNUNET_TIME_absolute_get_remaining (timeout);
2871   lsPlugin = find_transport (nameTransport);
2872   if (NULL == lsPlugin)
2873     {
2874       tc = GNUNET_SERVER_transmit_context_create (client);
2875       GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
2876                                                   GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_REPLY);
2877       GNUNET_SERVER_transmit_context_run (tc, rtimeout);
2878       return;
2879     }
2880   tc = GNUNET_SERVER_transmit_context_create (client);
2881   lsPlugin->api->address_pretty_printer (cls, nameTransport,
2882                                          address, addressLen, GNUNET_YES,
2883                                          rtimeout,
2884                                          &transmit_address_to_client, tc);
2885 }
2886
2887 /**
2888  * List of handlers for the messages understood by this
2889  * service.
2890  */
2891 static struct GNUNET_SERVER_MessageHandler handlers[] = {
2892   {&handle_start, NULL,
2893    GNUNET_MESSAGE_TYPE_TRANSPORT_START, 0},
2894   {&handle_hello, NULL,
2895    GNUNET_MESSAGE_TYPE_HELLO, 0},
2896   {&handle_send, NULL,
2897    GNUNET_MESSAGE_TYPE_TRANSPORT_SEND, 0},
2898   {&handle_set_quota, NULL,
2899    GNUNET_MESSAGE_TYPE_TRANSPORT_SET_QUOTA, sizeof (struct QuotaSetMessage)},
2900   {&handle_try_connect, NULL,
2901    GNUNET_MESSAGE_TYPE_TRANSPORT_TRY_CONNECT,
2902    sizeof (struct TryConnectMessage)},
2903   {&handle_address_lookup, NULL,
2904    GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_LOOKUP,
2905    0},
2906   {NULL, NULL, 0, 0}
2907 };
2908
2909
2910 /**
2911  * Setup the environment for this plugin.
2912  */
2913 static void
2914 create_environment (struct TransportPlugin *plug)
2915 {
2916   plug->env.cfg = cfg;
2917   plug->env.sched = sched;
2918   plug->env.my_identity = &my_identity;
2919   plug->env.cls = plug;
2920   plug->env.receive = &plugin_env_receive;
2921   plug->env.notify_address = &plugin_env_notify_address;
2922   plug->env.default_quota_in =
2923     (GNUNET_CONSTANTS_DEFAULT_BPM_IN_OUT + 59999) / (60 * 1000);
2924   plug->env.max_connections = max_connect_per_transport;
2925 }
2926
2927
2928 /**
2929  * Start the specified transport (load the plugin).
2930  */
2931 static void
2932 start_transport (struct GNUNET_SERVER_Handle *server, const char *name)
2933 {
2934   struct TransportPlugin *plug;
2935   char *libname;
2936
2937   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2938               _("Loading `%s' transport plugin\n"), name);
2939   GNUNET_asprintf (&libname, "libgnunet_plugin_transport_%s", name);
2940   plug = GNUNET_malloc (sizeof (struct TransportPlugin));
2941   create_environment (plug);
2942   plug->short_name = GNUNET_strdup (name);
2943   plug->lib_name = libname;
2944   plug->next = plugins;
2945   plugins = plug;
2946   plug->api = GNUNET_PLUGIN_load (libname, &plug->env);
2947   if (plug->api == NULL)
2948     {
2949       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2950                   _("Failed to load transport plugin for `%s'\n"), name);
2951       GNUNET_free (plug->short_name);
2952       plugins = plug->next;
2953       GNUNET_free (libname);
2954       GNUNET_free (plug);
2955     }
2956 }
2957
2958
2959 /**
2960  * Called whenever a client is disconnected.  Frees our
2961  * resources associated with that client.
2962  *
2963  * @param cls closure
2964  * @param client identification of the client
2965  */
2966 static void
2967 client_disconnect_notification (void *cls,
2968                                 struct GNUNET_SERVER_Client *client)
2969 {
2970   struct TransportClient *pos;
2971   struct TransportClient *prev;
2972   struct ClientMessageQueueEntry *mqe;
2973
2974   if (client == NULL)
2975     return;
2976 #if DEBUG_TRANSPORT
2977   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2978               "Client disconnected, cleaning up.\n");
2979 #endif
2980   prev = NULL;
2981   pos = clients;
2982   while ((pos != NULL) && (pos->client != client))
2983     {
2984       prev = pos;
2985       pos = pos->next;
2986     }
2987   if (pos == NULL)
2988     return;
2989   while (NULL != (mqe = pos->message_queue_head))
2990     {
2991       pos->message_queue_head = mqe->next;
2992       GNUNET_free (mqe);
2993     }
2994   pos->message_queue_head = NULL;
2995   if (prev == NULL)
2996     clients = pos->next;
2997   else
2998     prev->next = pos->next;
2999   if (GNUNET_YES == pos->tcs_pending)
3000     {
3001       pos->client = NULL;
3002       return;
3003     }
3004   GNUNET_free (pos);
3005 }
3006
3007
3008 /**
3009  * Function called when the service shuts down.  Unloads our plugins.
3010  *
3011  * @param cls closure, unused
3012  * @param tc task context (unused)
3013  */
3014 static void
3015 unload_plugins (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
3016 {
3017   struct TransportPlugin *plug;
3018   struct AddressList *al;
3019
3020 #if DEBUG_TRANSPORT
3021   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3022               "Transport service is unloading plugins...\n");
3023 #endif
3024   while (NULL != (plug = plugins))
3025     {
3026       plugins = plug->next;
3027       GNUNET_break (NULL == GNUNET_PLUGIN_unload (plug->lib_name, plug->api));
3028       GNUNET_free (plug->lib_name);
3029       GNUNET_free (plug->short_name);
3030       while (NULL != (al = plug->addresses))
3031         {
3032           plug->addresses = al->next;
3033           GNUNET_free (al);
3034         }
3035       GNUNET_free (plug);
3036     }
3037   if (my_private_key != NULL)
3038     GNUNET_CRYPTO_rsa_key_free (my_private_key);
3039   GNUNET_free_non_null (our_hello);
3040 }
3041
3042
3043 /**
3044  * Initiate transport service.
3045  *
3046  * @param cls closure
3047  * @param s scheduler to use
3048  * @param serv the initialized server
3049  * @param c configuration to use
3050  */
3051 static void
3052 run (void *cls,
3053      struct GNUNET_SCHEDULER_Handle *s,
3054      struct GNUNET_SERVER_Handle *serv,
3055      const struct GNUNET_CONFIGURATION_Handle *c)
3056 {
3057   char *plugs;
3058   char *pos;
3059   int no_transports;
3060   unsigned long long tneigh;
3061   char *keyfile;
3062
3063   sched = s;
3064   cfg = c;
3065   /* parse configuration */
3066   if ((GNUNET_OK !=
3067        GNUNET_CONFIGURATION_get_value_number (c,
3068                                               "TRANSPORT",
3069                                               "NEIGHBOUR_LIMIT",
3070                                               &tneigh)) ||
3071       (GNUNET_OK !=
3072        GNUNET_CONFIGURATION_get_value_filename (c,
3073                                                 "GNUNETD",
3074                                                 "HOSTKEY", &keyfile)))
3075     {
3076       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3077                   _
3078                   ("Transport service is lacking key configuration settings.  Exiting.\n"));
3079       GNUNET_SCHEDULER_shutdown (s);
3080       return;
3081     }
3082   max_connect_per_transport = (uint32_t) tneigh;
3083   my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
3084   GNUNET_free (keyfile);
3085   if (my_private_key == NULL)
3086     {
3087       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3088                   _
3089                   ("Transport service could not access hostkey.  Exiting.\n"));
3090       GNUNET_SCHEDULER_shutdown (s);
3091       return;
3092     }
3093   GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key);
3094   GNUNET_CRYPTO_hash (&my_public_key,
3095                       sizeof (my_public_key), &my_identity.hashPubKey);
3096   /* setup notification */
3097   server = serv;
3098   GNUNET_SERVER_disconnect_notify (server,
3099                                    &client_disconnect_notification, NULL);
3100   /* load plugins... */
3101   no_transports = 1;
3102   if (GNUNET_OK ==
3103       GNUNET_CONFIGURATION_get_value_string (c,
3104                                              "TRANSPORT", "PLUGINS", &plugs))
3105     {
3106       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3107                   _("Starting transport plugins `%s'\n"), plugs);
3108       pos = strtok (plugs, " ");
3109       while (pos != NULL)
3110         {
3111           start_transport (server, pos);
3112           no_transports = 0;
3113           pos = strtok (NULL, " ");
3114         }
3115       GNUNET_free (plugs);
3116     }
3117   GNUNET_SCHEDULER_add_delayed (sched,
3118                                 GNUNET_TIME_UNIT_FOREVER_REL,
3119                                 &unload_plugins, NULL);
3120   if (no_transports)
3121     refresh_hello ();
3122
3123 #if DEBUG_TRANSPORT
3124   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Transport service ready.\n"));
3125 #endif
3126   /* process client requests */
3127   GNUNET_SERVER_add_handlers (server, handlers);
3128 }
3129
3130
3131 /**
3132  * The main function for the transport service.
3133  *
3134  * @param argc number of arguments from the command line
3135  * @param argv command line arguments
3136  * @return 0 ok, 1 on error
3137  */
3138 int
3139 main (int argc, char *const *argv)
3140 {
3141   return (GNUNET_OK ==
3142           GNUNET_SERVICE_run (argc,
3143                               argv,
3144                               "transport",
3145                               GNUNET_SERVICE_OPTION_NONE,
3146                               &run, NULL)) ? 0 : 1;
3147 }
3148
3149 /* end of gnunet-service-transport.c */