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