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