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