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