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