-remove debug message
[oweals/gnunet.git] / src / transport / gnunet-service-tng.c
1 /*
2    This file is part of GNUnet.
3    Copyright (C) 2010-2016, 2018, 2019 GNUnet e.V.
4
5    GNUnet is free software: you can redistribute it and/or modify it
6    under the terms of the GNU Affero General Public License as published
7    by the Free Software Foundation, either version 3 of the License,
8    or (at your 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    Affero General Public License for more details.
14
15    You should have received a copy of the GNU Affero General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18      SPDX-License-Identifier: AGPL3.0-or-later
19  */
20 /**
21  * @file transport/gnunet-service-tng.c
22  * @brief main for gnunet-service-tng
23  * @author Christian Grothoff
24  *
25  * TODO:
26  * Implement next:
27  * - review retransmission logic, right now there is no smartness there!
28  *   => congestion control, etc [PERFORMANCE-BASICS]
29  *
30  * Optimizations-Statistics:
31  * - Track ACK losses based on ACK-counter [ROUTING]
32  * - Need to track total bandwidth per VirtualLink and adjust how frequently
33  *   we send FC messages based on bandwidth-delay-product (and relation
34  *   to the window size!). See OPTIMIZE-FC-BDP.
35  * - Consider more statistics in #check_connection_quality() [FIXME-CONQ-STATISTICS]
36  * - Adapt available_fc_window_size, using larger values for high-bandwidth
37  *   and high-latency links *if* we have the RAM [GOODPUT / utilization / stalls]
38  * - Set last_window_consum_limit promise properly based on
39  *   latency and bandwidth of the respective connection [GOODPUT / utilization / stalls]
40  *
41  * Optimizations-DV:
42  * - When forwarding DV learn messages, if a peer is reached that
43  *   has a *bidirectional* link to the origin beyond 1st hop,
44  *   do NOT forward it to peers _other_ than the origin, as
45  *   there is clearly a better path directly from the origin to
46  *   whatever else we could reach.
47  * - When we passively learned DV (with unconfirmed freshness), we
48  *   right now add the path to our list but with a zero path_valid_until
49  *   time and only use it for unconfirmed routes.  However, we could consider
50  *   triggering an explicit validation mechansim ourselves, specifically routing
51  *   a challenge-response message over the path [ROUTING]
52  * = if available, try to confirm unconfirmed DV paths when trying to establish
53  *   virtual link for a `struct IncomingRequest`. (i.e. if DVH is
54  *   unconfirmed, incoming requests cause us to try to validate a passively
55  *   learned path (requires new message type!))
56  *
57  * Optimizations-Fragmentation:
58  * - Fragments send over a reliable channel could do without the
59  *   AcknowledgementUUIDP altogether, as they won't be acked! [BANDWIDTH]
60  *   (-> have 2nd type of acknowledgment message; low priority, as we
61  *       do not have an MTU-limited *reliable* communicator) [FIXME-FRAG-REL-UUID]
62  * - if messages are below MTU, consider adding ACKs and other stuff
63  *   to the same transmission to avoid tiny messages (requires planning at
64  *   receiver, and additional MST-style demultiplex at receiver!) [PACKET COUNT]
65  *
66  * Optimizations-internals:
67  * - queue_send_msg by API design has to make a copy
68  *   of the payload, and route_message on top of that requires a malloc/free.
69  *   Change design to approximate "zero" copy better... [CPU]
70  * - could avoid copying body of message into each fragment and keep
71  *   fragments as just pointers into the original message and only
72  *   fully build fragments just before transmission (optimization, should
73  *   reduce CPU and memory use) [CPU, MEMORY]
74  */
75 #include "platform.h"
76 #include "gnunet_util_lib.h"
77 #include "gnunet_statistics_service.h"
78 #include "gnunet_transport_monitor_service.h"
79 #include "gnunet_peerstore_service.h"
80 #include "gnunet_hello_lib.h"
81 #include "gnunet_signatures.h"
82 #include "transport.h"
83
84 /**
85  * Maximum number of messages we acknowledge together in one
86  * cummulative ACK.  Larger values may save a bit of bandwidth.
87  */
88 #define MAX_CUMMULATIVE_ACKS 64
89
90 /**
91  * What is the 1:n chance that we send a Flow control response when
92  * receiving a flow control message that did not change anything for
93  * us? Basically, this is used in the case where both peers are stuck
94  * on flow control (no window changes), but one might continue sending
95  * flow control messages to the other peer as the first FC message
96  * when things stalled got lost, and then subsequently the other peer
97  * does *usually* not respond as nothing changed.  So to ensure that
98  * eventually the FC messages stop, we do send with 1/8th probability
99  * an FC message even if nothing changed.  That prevents one peer
100  * being stuck in sending (useless) FC messages "forever".
101  */
102 #define FC_NO_CHANGE_REPLY_PROBABILITY 8
103
104 /**
105  * What is the size we assume for a read operation in the
106  * absence of an MTU for the purpose of flow control?
107  */
108 #define IN_PACKET_SIZE_WITHOUT_MTU 128
109
110 /**
111  * Number of slots we keep of historic data for computation of
112  * goodput / message loss ratio.
113  */
114 #define GOODPUT_AGING_SLOTS 4
115
116 /**
117  * How big is the flow control window size by default;
118  * limits per-neighbour RAM utilization.
119  */
120 #define DEFAULT_WINDOW_SIZE (128 * 1024)
121
122 /**
123  * For how many incoming connections do we try to create a
124  * virtual link for (at the same time!).  This does NOT
125  * limit the number of incoming connections, just the number
126  * for which we are actively trying to find working addresses
127  * in the absence (!) of our own applications wanting the
128  * link to go up.
129  */
130 #define MAX_INCOMING_REQUEST 16
131
132 /**
133  * Maximum number of peers we select for forwarding DVInit
134  * messages at the same time (excluding initiator).
135  */
136 #define MAX_DV_DISCOVERY_SELECTION 16
137
138 /**
139  * Window size. How many messages to the same target do we pass
140  * to CORE without a RECV_OK in between? Small values limit
141  * thoughput, large values will increase latency.
142  *
143  * FIXME-OPTIMIZE: find out what good values are experimentally,
144  * maybe set adaptively (i.e. to observed available bandwidth).
145  */
146 #define RECV_WINDOW_SIZE 4
147
148 /**
149  * Minimum number of hops we should forward DV learn messages
150  * even if they are NOT useful for us in hope of looping
151  * back to the initiator?
152  *
153  * FIXME: allow initiator some control here instead?
154  */
155 #define MIN_DV_PATH_LENGTH_FOR_INITIATOR 3
156
157 /**
158  * Maximum DV distance allowed ever.
159  */
160 #define MAX_DV_HOPS_ALLOWED 16
161
162 /**
163  * Maximum number of DV learning activities we may
164  * have pending at the same time.
165  */
166 #define MAX_DV_LEARN_PENDING 64
167
168 /**
169  * Maximum number of DV paths we keep simultaneously to the same target.
170  */
171 #define MAX_DV_PATHS_TO_TARGET 3
172
173 /**
174  * If a queue delays the next message by more than this number
175  * of seconds we log a warning. Note: this is for testing,
176  * the value chosen here might be too aggressively low!
177  */
178 #define DELAY_WARN_THRESHOLD \
179   GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
180
181 /**
182  * If a DVBox could not be forwarded after this number of
183  * seconds we drop it.
184  */
185 #define DV_FORWARD_TIMEOUT \
186   GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
187
188 /**
189  * We only consider queues as "quality" connections when
190  * suppressing the generation of DV initiation messages if
191  * the latency of the queue is below this threshold.
192  */
193 #define DV_QUALITY_RTT_THRESHOLD \
194   GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
195
196 /**
197  * How long do we consider a DV path valid if we see no
198  * further updates on it? Note: the value chosen here might be too low!
199  */
200 #define DV_PATH_VALIDITY_TIMEOUT \
201   GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
202
203 /**
204  * How long do we cache backchannel (struct Backtalker) information
205  * after a backchannel goes inactive?
206  */
207 #define BACKCHANNEL_INACTIVITY_TIMEOUT \
208   GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
209
210 /**
211  * How long before paths expire would we like to (re)discover DV paths? Should
212  * be below #DV_PATH_VALIDITY_TIMEOUT.
213  */
214 #define DV_PATH_DISCOVERY_FREQUENCY \
215   GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 4)
216
217 /**
218  * How long are ephemeral keys valid?
219  */
220 #define EPHEMERAL_VALIDITY \
221   GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
222
223 /**
224  * How long do we keep partially reassembled messages around before giving up?
225  */
226 #define REASSEMBLY_EXPIRATION \
227   GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 4)
228
229 /**
230  * What is the fastest rate at which we send challenges *if* we keep learning
231  * an address (gossip, DHT, etc.)?
232  */
233 #define FAST_VALIDATION_CHALLENGE_FREQ \
234   GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 1)
235
236 /**
237  * What is the slowest rate at which we send challenges?
238  */
239 #define MAX_VALIDATION_CHALLENGE_FREQ \
240   GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_DAYS, 1)
241
242 /**
243  * How long until we forget about historic accumulators and thus
244  * reset the ACK counter? Should exceed the maximum time an
245  * active connection experiences without an ACK.
246  */
247 #define ACK_CUMMULATOR_TIMEOUT \
248   GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
249
250 /**
251  * What is the non-randomized base frequency at which we
252  * would initiate DV learn messages?
253  */
254 #define DV_LEARN_BASE_FREQUENCY GNUNET_TIME_UNIT_MINUTES
255
256 /**
257  * How many good connections (confirmed, bi-directional, not DV)
258  * do we need to have to suppress initiating DV learn messages?
259  */
260 #define DV_LEARN_QUALITY_THRESHOLD 100
261
262 /**
263  * When do we forget an invalid address for sure?
264  */
265 #define MAX_ADDRESS_VALID_UNTIL \
266   GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MONTHS, 1)
267
268 /**
269  * How long do we consider an address valid if we just checked?
270  */
271 #define ADDRESS_VALIDATION_LIFETIME \
272   GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
273
274 /**
275  * What is the maximum frequency at which we do address validation?
276  * A random value between 0 and this value is added when scheduling
277  * the #validation_task (both to ensure we do not validate too often,
278  * and to randomize a bit).
279  */
280 #define MIN_DELAY_ADDRESS_VALIDATION GNUNET_TIME_UNIT_MILLISECONDS
281
282 /**
283  * How many network RTTs before an address validation expires should we begin
284  * trying to revalidate? (Note that the RTT used here is the one that we
285  * experienced during the last validation, not necessarily the latest RTT
286  * observed).
287  */
288 #define VALIDATION_RTT_BUFFER_FACTOR 3
289
290 /**
291  * How many messages can we have pending for a given communicator
292  * process before we start to throttle that communicator?
293  *
294  * Used if a communicator might be CPU-bound and cannot handle the traffic.
295  */
296 #define COMMUNICATOR_TOTAL_QUEUE_LIMIT 512
297
298 /**
299  * How many messages can we have pending for a given queue (queue to
300  * a particular peer via a communicator) process before we start to
301  * throttle that queue?
302  */
303 #define QUEUE_LENGTH_LIMIT 32
304
305
306 GNUNET_NETWORK_STRUCT_BEGIN
307
308 /**
309  * Unique identifier we attach to a message.
310  */
311 struct MessageUUIDP
312 {
313   /**
314    * Unique value, generated by incrementing the
315    * `message_uuid_ctr` of `struct Neighbour`.
316    */
317   uint64_t uuid GNUNET_PACKED;
318 };
319
320
321 /**
322  * Unique identifier to map an acknowledgement to a transmission.
323  */
324 struct AcknowledgementUUIDP
325 {
326   /**
327    * The UUID value.
328    */
329   struct GNUNET_Uuid value;
330 };
331
332
333 /**
334  * Type of a nonce used for challenges.
335  */
336 struct ChallengeNonceP
337 {
338   /**
339    * The value of the nonce.  Note that this is NOT a hash.
340    */
341   struct GNUNET_ShortHashCode value;
342 };
343
344
345 /**
346  * Outer layer of an encapsulated backchannel message.
347  */
348 struct TransportBackchannelEncapsulationMessage
349 {
350   /**
351    * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION.
352    */
353   struct GNUNET_MessageHeader header;
354
355   /* Followed by *another* message header which is the message to
356      the communicator */
357
358   /* Followed by a 0-terminated name of the communicator */
359 };
360
361
362 /**
363  * Body by which a peer confirms that it is using an ephemeral key.
364  */
365 struct EphemeralConfirmationPS
366 {
367   /**
368    * Purpose is #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL
369    */
370   struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
371
372   /**
373    * How long is this signature over the ephemeral key valid?
374    *
375    * Note that the receiver MUST IGNORE the absolute time, and only interpret
376    * the value as a mononic time and reject "older" values than the last one
377    * observed.  This is necessary as we do not want to require synchronized
378    * clocks and may not have a bidirectional communication channel.
379    *
380    * Even with this, there is no real guarantee against replay achieved here,
381    * unless the latest timestamp is persisted.  While persistence should be
382    * provided via PEERSTORE, we do not consider the mechanism reliable!  Thus,
383    * communicators must protect against replay attacks when using backchannel
384    * communication!
385    */
386   struct GNUNET_TIME_AbsoluteNBO sender_monotonic_time;
387
388   /**
389    * Target's peer identity.
390    */
391   struct GNUNET_PeerIdentity target;
392
393   /**
394    * Ephemeral key setup by the sender for @e target, used
395    * to encrypt the payload.
396    */
397   struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
398 };
399
400
401 /**
402  * Plaintext of the variable-size payload that is encrypted
403  * within a `struct TransportBackchannelEncapsulationMessage`
404  */
405 struct TransportDVBoxPayloadP
406 {
407   /**
408    * Sender's peer identity.
409    */
410   struct GNUNET_PeerIdentity sender;
411
412   /**
413    * Signature of the sender over an
414    * #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL.
415    */
416   struct GNUNET_CRYPTO_EddsaSignature sender_sig;
417
418   /**
419    * Current monotonic time of the sending transport service.  Used to
420    * detect replayed messages.  Note that the receiver should remember
421    * a list of the recently seen timestamps and only reject messages
422    * if the timestamp is in the list, or the list is "full" and the
423    * timestamp is smaller than the lowest in the list.
424    *
425    * Like the @e ephemeral_validity, the list of timestamps per peer should be
426    * persisted to guard against replays after restarts.
427    */
428   struct GNUNET_TIME_AbsoluteNBO monotonic_time;
429
430   /* Followed by a `struct GNUNET_MessageHeader` with a message
431      for the target peer */
432 };
433
434
435 /**
436  * Outer layer of an encapsulated unfragmented application message sent
437  * over an unreliable channel.
438  */
439 struct TransportReliabilityBoxMessage
440 {
441   /**
442    * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX
443    */
444   struct GNUNET_MessageHeader header;
445
446   /**
447    * Number of messages still to be sent before a commulative
448    * ACK is requested.  Zero if an ACK is requested immediately.
449    * In NBO.  Note that the receiver may send the ACK faster
450    * if it believes that is reasonable.
451    */
452   uint32_t ack_countdown GNUNET_PACKED;
453
454   /**
455    * Unique ID of the message used for signalling receipt of
456    * messages sent over possibly unreliable channels.  Should
457    * be a random.
458    */
459   struct AcknowledgementUUIDP ack_uuid;
460 };
461
462
463 /**
464  * Acknowledgement payload.
465  */
466 struct TransportCummulativeAckPayloadP
467 {
468   /**
469    * How long was the ACK delayed for generating cummulative ACKs?
470    * Used to calculate the correct network RTT by taking the receipt
471    * time of the ack minus the transmission time of the sender minus
472    * this value.
473    */
474   struct GNUNET_TIME_RelativeNBO ack_delay;
475
476   /**
477    * UUID of a message being acknowledged.
478    */
479   struct AcknowledgementUUIDP ack_uuid;
480 };
481
482
483 /**
484  * Confirmation that the receiver got a
485  * #GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX. Note that the
486  * confirmation may be transmitted over a completely different queue,
487  * so ACKs are identified by a combination of PID of sender and
488  * message UUID, without the queue playing any role!
489  */
490 struct TransportReliabilityAckMessage
491 {
492   /**
493    * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_ACK
494    */
495   struct GNUNET_MessageHeader header;
496
497   /**
498    * Counter of ACKs transmitted by the sender to us. Incremented
499    * by one for each ACK, used to detect how many ACKs were lost.
500    */
501   uint32_t ack_counter GNUNET_PACKED;
502
503   /* followed by any number of `struct TransportCummulativeAckPayloadP`
504      messages providing ACKs */
505 };
506
507
508 /**
509  * Outer layer of an encapsulated fragmented application message.
510  */
511 struct TransportFragmentBoxMessage
512 {
513   /**
514    * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT
515    */
516   struct GNUNET_MessageHeader header;
517
518   /**
519    * Offset of this fragment in the overall message.
520    */
521   uint16_t frag_off GNUNET_PACKED;
522
523   /**
524    * Total size of the message that is being fragmented.
525    */
526   uint16_t msg_size GNUNET_PACKED;
527
528   /**
529    * Unique ID of this fragment (and fragment transmission!). Will
530    * change even if a fragement is retransmitted to make each
531    * transmission attempt unique! If a client receives a duplicate
532    * fragment (same @e frag_off for same @a msg_uuid, it must send
533    * #GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_ACK immediately.
534    */
535   struct AcknowledgementUUIDP ack_uuid;
536
537   /**
538    * Original message ID for of the message that all the fragments
539    * belong to.  Must be the same for all fragments.
540    */
541   struct MessageUUIDP msg_uuid;
542 };
543
544
545 /**
546  * Content signed by the initator during DV learning.
547  *
548  * The signature is required to prevent DDoS attacks. A peer sending out this
549  * message is potentially generating a lot of traffic that will go back to the
550  * initator, as peers receiving this message will try to let the initiator
551  * know that they got the message.
552  *
553  * Without this signature, an attacker could abuse this mechanism for traffic
554  * amplification, sending a lot of traffic to a peer by putting out this type
555  * of message with the victim's peer identity.
556  *
557  * Even with just a signature, traffic amplification would be possible via
558  * replay attacks. The @e monotonic_time limits such replay attacks, as every
559  * potential amplificator will check the @e monotonic_time and only respond
560  * (at most) once per message.
561  */
562 struct DvInitPS
563 {
564   /**
565    * Purpose is #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR
566    */
567   struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
568
569   /**
570    * Time at the initiator when generating the signature.
571    *
572    * Note that the receiver MUST IGNORE the absolute time, and only interpret
573    * the value as a mononic time and reject "older" values than the last one
574    * observed.  This is necessary as we do not want to require synchronized
575    * clocks and may not have a bidirectional communication channel.
576    *
577    * Even with this, there is no real guarantee against replay achieved here,
578    * unless the latest timestamp is persisted.  Persistence should be
579    * provided via PEERSTORE if possible.
580    */
581   struct GNUNET_TIME_AbsoluteNBO monotonic_time;
582
583   /**
584    * Challenge value used by the initiator to re-identify the path.
585    */
586   struct ChallengeNonceP challenge;
587 };
588
589
590 /**
591  * Content signed by each peer during DV learning.
592  *
593  * This assues the initiator of the DV learning operation that the hop from @e
594  * pred via the signing peer to @e succ actually exists.  This makes it
595  * impossible for an adversary to supply the network with bogus routes.
596  *
597  * The @e challenge is included to provide replay protection for the
598  * initiator. This way, the initiator knows that the hop existed after the
599  * original @e challenge was first transmitted, providing a freshness metric.
600  *
601  * Peers other than the initiator that passively learn paths by observing
602  * these messages do NOT benefit from this. Here, an adversary may indeed
603  * replay old messages.  Thus, passively learned paths should always be
604  * immediately marked as "potentially stale".
605  */
606 struct DvHopPS
607 {
608   /**
609    * Purpose is #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_HOP
610    */
611   struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
612
613   /**
614    * Identity of the previous peer on the path.
615    */
616   struct GNUNET_PeerIdentity pred;
617
618   /**
619    * Identity of the next peer on the path.
620    */
621   struct GNUNET_PeerIdentity succ;
622
623   /**
624    * Challenge value used by the initiator to re-identify the path.
625    */
626   struct ChallengeNonceP challenge;
627 };
628
629
630 /**
631  * An entry describing a peer on a path in a
632  * `struct TransportDVLearnMessage` message.
633  */
634 struct DVPathEntryP
635 {
636   /**
637    * Identity of a peer on the path.
638    */
639   struct GNUNET_PeerIdentity hop;
640
641   /**
642    * Signature of this hop over the path, of purpose
643    * #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_HOP
644    */
645   struct GNUNET_CRYPTO_EddsaSignature hop_sig;
646 };
647
648
649 /**
650  * Internal message used by transport for distance vector learning.
651  * If @e num_hops does not exceed the threshold, peers should append
652  * themselves to the peer list and flood the message (possibly only
653  * to a subset of their neighbours to limit discoverability of the
654  * network topology).  To the extend that the @e bidirectional bits
655  * are set, peers may learn the inverse paths even if they did not
656  * initiate.
657  *
658  * Unless received on a bidirectional queue and @e num_hops just
659  * zero, peers that can forward to the initator should always try to
660  * forward to the initiator.
661  */
662 struct TransportDVLearnMessage
663 {
664   /**
665    * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN
666    */
667   struct GNUNET_MessageHeader header;
668
669   /**
670    * Number of hops this messages has travelled, in NBO. Zero if
671    * sent by initiator.
672    */
673   uint16_t num_hops GNUNET_PACKED;
674
675   /**
676    * Bitmask of the last 16 hops indicating whether they are confirmed
677    * available (without DV) in both directions or not, in NBO.  Used
678    * to possibly instantly learn a path in both directions.  Each peer
679    * should shift this value by one to the left, and then set the
680    * lowest bit IF the current sender can be reached from it (without
681    * DV routing).
682    */
683   uint16_t bidirectional GNUNET_PACKED;
684
685   /**
686    * Peers receiving this message and delaying forwarding to other
687    * peers for any reason should increment this value by the non-network
688    * delay created by the peer.
689    */
690   struct GNUNET_TIME_RelativeNBO non_network_delay;
691
692   /**
693    * Time at the initiator when generating the signature.
694    *
695    * Note that the receiver MUST IGNORE the absolute time, and only interpret
696    * the value as a mononic time and reject "older" values than the last one
697    * observed.  This is necessary as we do not want to require synchronized
698    * clocks and may not have a bidirectional communication channel.
699    *
700    * Even with this, there is no real guarantee against replay achieved here,
701    * unless the latest timestamp is persisted.  Persistence should be
702    * provided via PEERSTORE if possible.
703    */
704   struct GNUNET_TIME_AbsoluteNBO monotonic_time;
705
706   /**
707    * Signature of this hop over the path, of purpose
708    * #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR
709    */
710   struct GNUNET_CRYPTO_EddsaSignature init_sig;
711
712   /**
713    * Identity of the peer that started this learning activity.
714    */
715   struct GNUNET_PeerIdentity initiator;
716
717   /**
718    * Challenge value used by the initiator to re-identify the path.
719    */
720   struct ChallengeNonceP challenge;
721
722   /* Followed by @e num_hops `struct DVPathEntryP` values,
723      excluding the initiator of the DV trace; the last entry is the
724      current sender; the current peer must not be included. */
725 };
726
727
728 /**
729  * Outer layer of an encapsulated message send over multiple hops.
730  * The path given only includes the identities of the subsequent
731  * peers, i.e. it will be empty if we are the receiver. Each
732  * forwarding peer should scan the list from the end, and if it can,
733  * forward to the respective peer. The list should then be shortened
734  * by all the entries up to and including that peer.  Each hop should
735  * also increment @e total_hops to allow the receiver to get a precise
736  * estimate on the number of hops the message travelled.  Senders must
737  * provide a learned path that thus should work, but intermediaries
738  * know of a shortcut, they are allowed to send the message via that
739  * shortcut.
740  *
741  * If a peer finds itself still on the list, it must drop the message.
742  *
743  * The payload of the box can only be decrypted and verified by the
744  * ultimate receiver. Intermediaries do not learn the sender's
745  * identity and the path the message has taken.  However, the first
746  * hop does learn the sender as @e total_hops would be zero and thus
747  * the predecessor must be the origin (so this is not really useful
748  * for anonymization).
749  */
750 struct TransportDVBoxMessage
751 {
752   /**
753    * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX
754    */
755   struct GNUNET_MessageHeader header;
756
757   /**
758    * Number of total hops this messages travelled. In NBO.
759    * @e origin sets this to zero, to be incremented at
760    * each hop.  Peers should limit the @e total_hops value
761    * they accept from other peers.
762    */
763   uint16_t total_hops GNUNET_PACKED;
764
765   /**
766    * Number of hops this messages includes. In NBO.  Reduced by one
767    * or more at each hop.  Peers should limit the @e num_hops value
768    * they accept from other peers.
769    */
770   uint16_t num_hops GNUNET_PACKED;
771
772   /**
773    * Ephemeral key setup by the sender for target, used to encrypt the
774    * payload.  Intermediaries must not change this value.
775    */
776   struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
777
778   /**
779    * We use an IV here as the @e ephemeral_key is re-used for
780    * #EPHEMERAL_VALIDITY time to avoid re-signing it all the time.
781    * Intermediaries must not change this value.
782    */
783   struct GNUNET_ShortHashCode iv;
784
785   /**
786    * HMAC over the ciphertext of the encrypted, variable-size body
787    * that follows.  Verified via DH of target and @e ephemeral_key.
788    * Intermediaries must not change this value.
789    */
790   struct GNUNET_HashCode hmac;
791
792   /* Followed by @e num_hops `struct GNUNET_PeerIdentity` values;
793      excluding the @e origin and the current peer, the last must be
794      the ultimate target; if @e num_hops is zero, the receiver of this
795      message is the ultimate target. */
796
797   /* Followed by encrypted, variable-size payload, which
798      must begin with a `struct TransportDVBoxPayloadP` */
799
800   /* Followed by the actual message, which itself must not be a
801      a DV_LEARN or DV_BOX message! */
802 };
803
804
805 /**
806  * Message send to another peer to validate that it can indeed
807  * receive messages at a particular address.
808  */
809 struct TransportValidationChallengeMessage
810 {
811   /**
812    * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_CHALLENGE
813    */
814   struct GNUNET_MessageHeader header;
815
816   /**
817    * Always zero.
818    */
819   uint32_t reserved GNUNET_PACKED;
820
821   /**
822    * Challenge to be signed by the receiving peer.
823    */
824   struct ChallengeNonceP challenge;
825
826   /**
827    * Timestamp of the sender, to be copied into the reply to allow
828    * sender to calculate RTT.  Must be monotonically increasing!
829    */
830   struct GNUNET_TIME_AbsoluteNBO sender_time;
831 };
832
833
834 /**
835  * Message signed by a peer to confirm that it can indeed
836  * receive messages at a particular address.
837  */
838 struct TransportValidationPS
839 {
840   /**
841    * Purpose is #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_CHALLENGE
842    */
843   struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
844
845   /**
846    * How long does the sender believe the address on
847    * which the challenge was received to remain valid?
848    */
849   struct GNUNET_TIME_RelativeNBO validity_duration;
850
851   /**
852    * Challenge signed by the receiving peer.
853    */
854   struct ChallengeNonceP challenge;
855 };
856
857
858 /**
859  * Message  send to a peer to respond to a
860  * #GNUNET_MESSAGE_TYPE_ADDRESS_VALIDATION_CHALLENGE
861  */
862 struct TransportValidationResponseMessage
863 {
864   /**
865    * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_RESPONSE
866    */
867   struct GNUNET_MessageHeader header;
868
869   /**
870    * Always zero.
871    */
872   uint32_t reserved GNUNET_PACKED;
873
874   /**
875    * The peer's signature matching the
876    * #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_CHALLENGE purpose.
877    */
878   struct GNUNET_CRYPTO_EddsaSignature signature;
879
880   /**
881    * The challenge that was signed by the receiving peer.
882    */
883   struct ChallengeNonceP challenge;
884
885   /**
886    * Original timestamp of the sender (was @code{sender_time}),
887    * copied into the reply to allow sender to calculate RTT.
888    */
889   struct GNUNET_TIME_AbsoluteNBO origin_time;
890
891   /**
892    * How long does the sender believe this address to remain
893    * valid?
894    */
895   struct GNUNET_TIME_RelativeNBO validity_duration;
896 };
897
898
899 /**
900  * Message for Transport-to-Transport Flow control. Specifies the size
901  * of the flow control window, including how much we believe to have
902  * consumed (at transmission time), how much we believe to be allowed
903  * (at transmission time), and how much the other peer is allowed to
904  * send to us, and how much data we already received from the other
905  * peer.
906  */
907 struct TransportFlowControlMessage
908 {
909   /**
910    * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_FLOW_CONTROL
911    */
912   struct GNUNET_MessageHeader header;
913
914   /**
915    * Sequence number of the flow control message. Incremented by one
916    * for each message.  Starts at zero when a virtual link goes up.
917    * Used to detect one-sided connection drops. On wrap-around, the
918    * flow control counters will be reset as if the connection had
919    * dropped.
920    */
921   uint32_t seq GNUNET_PACKED;
922
923   /**
924    * Flow control window size in bytes, in NBO.
925    * The receiver can send this many bytes at most.
926    */
927   uint64_t inbound_window_size GNUNET_PACKED;
928
929   /**
930    * How many bytes has the sender sent that count for flow control at
931    * this time.  Used to allow the receiver to estimate the packet
932    * loss rate.
933    */
934   uint64_t outbound_sent GNUNET_PACKED;
935
936   /**
937    * Latest flow control window size we learned from the other peer,
938    * in bytes, in NBO.  We are limited to sending at most this many
939    * bytes to the other peer.  May help the other peer detect when
940    * flow control messages were lost and should thus be retransmitted.
941    * In particular, if the delta to @e outbound_sent is too small,
942    * this signals that we are stalled.
943    */
944   uint64_t outbound_window_size GNUNET_PACKED;
945
946   /**
947    * Timestamp of the sender.  Must be monotonically increasing!
948    * Used to enable receiver to ignore out-of-order packets in
949    * combination with the @e seq. Note that @e seq will go down
950    * (back to zero) whenever either side believes the connection
951    * was dropped, allowing the peers to detect that they need to
952    * reset the counters for the number of bytes sent!
953    */
954   struct GNUNET_TIME_AbsoluteNBO sender_time;
955 };
956
957
958 GNUNET_NETWORK_STRUCT_END
959
960
961 /**
962  * What type of client is the `struct TransportClient` about?
963  */
964 enum ClientType
965 {
966   /**
967    * We do not know yet (client is fresh).
968    */
969   CT_NONE = 0,
970
971   /**
972    * Is the CORE service, we need to forward traffic to it.
973    */
974   CT_CORE = 1,
975
976   /**
977    * It is a monitor, forward monitor data.
978    */
979   CT_MONITOR = 2,
980
981   /**
982    * It is a communicator, use for communication.
983    */
984   CT_COMMUNICATOR = 3,
985
986   /**
987    * "Application" telling us where to connect (i.e. TOPOLOGY, DHT or CADET).
988    */
989   CT_APPLICATION = 4
990 };
991
992
993 /**
994  * Which transmission options are allowable for transmission?
995  * Interpreted bit-wise!
996  */
997 enum RouteMessageOptions
998 {
999   /**
1000    * Only confirmed, non-DV direct neighbours.
1001    */
1002   RMO_NONE = 0,
1003
1004   /**
1005    * We are allowed to use DV routing for this @a hdr
1006    */
1007   RMO_DV_ALLOWED = 1,
1008
1009   /**
1010    * We are allowed to use unconfirmed queues or DV routes for this message
1011    */
1012   RMO_UNCONFIRMED_ALLOWED = 2,
1013
1014   /**
1015    * Reliable and unreliable, DV and non-DV are all acceptable.
1016    */
1017   RMO_ANYTHING_GOES = (RMO_DV_ALLOWED | RMO_UNCONFIRMED_ALLOWED),
1018
1019   /**
1020    * If we have multiple choices, it is OK to send this message
1021    * over multiple channels at the same time to improve loss tolerance.
1022    * (We do at most 2 transmissions.)
1023    */
1024   RMO_REDUNDANT = 4
1025 };
1026
1027
1028 /**
1029  * When did we launch this DV learning activity?
1030  */
1031 struct LearnLaunchEntry
1032 {
1033   /**
1034    * Kept (also) in a DLL sorted by launch time.
1035    */
1036   struct LearnLaunchEntry *prev;
1037
1038   /**
1039    * Kept (also) in a DLL sorted by launch time.
1040    */
1041   struct LearnLaunchEntry *next;
1042
1043   /**
1044    * Challenge that uniquely identifies this activity.
1045    */
1046   struct ChallengeNonceP challenge;
1047
1048   /**
1049    * When did we transmit the DV learn message (used to calculate RTT) and
1050    * determine freshness of paths learned via this operation.
1051    */
1052   struct GNUNET_TIME_Absolute launch_time;
1053 };
1054
1055
1056 /**
1057  * Information we keep per #GOODPUT_AGING_SLOTS about historic
1058  * (or current) transmission performance.
1059  */
1060 struct TransmissionHistoryEntry
1061 {
1062   /**
1063    * Number of bytes actually sent in the interval.
1064    */
1065   uint64_t bytes_sent;
1066
1067   /**
1068    * Number of bytes received and acknowledged by the other peer in
1069    * the interval.
1070    */
1071   uint64_t bytes_received;
1072 };
1073
1074
1075 /**
1076  * Performance data for a transmission possibility.
1077  */
1078 struct PerformanceData
1079 {
1080   /**
1081    * Weighted average for the RTT.
1082    */
1083   struct GNUNET_TIME_Relative aged_rtt;
1084
1085   /**
1086    * Historic performance data, using a ring buffer of#GOODPUT_AGING_SLOTS
1087    * entries.
1088    */
1089   struct TransmissionHistoryEntry the[GOODPUT_AGING_SLOTS];
1090
1091   /**
1092    * What was the last age when we wrote to @e the? Used to clear
1093    * old entries when the age advances.
1094    */
1095   unsigned int last_age;
1096 };
1097
1098
1099 /**
1100  * Client connected to the transport service.
1101  */
1102 struct TransportClient;
1103
1104 /**
1105  * A neighbour that at least one communicator is connected to.
1106  */
1107 struct Neighbour;
1108
1109 /**
1110  * Entry in our #dv_routes table, representing a (set of) distance
1111  * vector routes to a particular peer.
1112  */
1113 struct DistanceVector;
1114
1115 /**
1116  * A queue is a message queue provided by a communicator
1117  * via which we can reach a particular neighbour.
1118  */
1119 struct Queue;
1120
1121 /**
1122  * Message awaiting transmission. See detailed comments below.
1123  */
1124 struct PendingMessage;
1125
1126 /**
1127  * One possible hop towards a DV target.
1128  */
1129 struct DistanceVectorHop;
1130
1131 /**
1132  * A virtual link is another reachable peer that is known to CORE.  It
1133  * can be either a `struct Neighbour` with at least one confirmed
1134  * `struct Queue`, or a `struct DistanceVector` with at least one
1135  * confirmed `struct DistanceVectorHop`.  With a virtual link we track
1136  * data that is per neighbour that is not specific to how the
1137  * connectivity is established.
1138  */
1139 struct VirtualLink;
1140
1141
1142 /**
1143  * Context from #handle_incoming_msg().  Closure for many
1144  * message handlers below.
1145  */
1146 struct CommunicatorMessageContext
1147 {
1148   /**
1149    * Kept in a DLL of `struct VirtualLink` if waiting for CORE
1150    * flow control to unchoke.
1151    */
1152   struct CommunicatorMessageContext *next;
1153
1154   /**
1155    * Kept in a DLL of `struct VirtualLink` if waiting for CORE
1156    * flow control to unchoke.
1157    */
1158   struct CommunicatorMessageContext *prev;
1159
1160   /**
1161    * Which communicator provided us with the message.
1162    */
1163   struct TransportClient *tc;
1164
1165   /**
1166    * Additional information for flow control and about the sender.
1167    */
1168   struct GNUNET_TRANSPORT_IncomingMessage im;
1169
1170   /**
1171    * Number of hops the message has travelled (if DV-routed).
1172    * FIXME: make use of this in ACK handling!
1173    */
1174   uint16_t total_hops;
1175 };
1176
1177
1178 /**
1179  * Closure for #core_env_sent_cb.
1180  */
1181 struct CoreSentContext
1182 {
1183   /**
1184    * Kept in a DLL to clear @e vl in case @e vl is lost.
1185    */
1186   struct CoreSentContext *next;
1187
1188   /**
1189    * Kept in a DLL to clear @e vl in case @e vl is lost.
1190    */
1191   struct CoreSentContext *prev;
1192
1193   /**
1194    * Virtual link this is about.
1195    */
1196   struct VirtualLink *vl;
1197
1198   /**
1199    * How big was the message.
1200    */
1201   uint16_t size;
1202
1203   /**
1204    * By how much should we increment @e vl's
1205    * incoming_fc_window_size_used once we are done sending to CORE?
1206    * Use to ensure we do not increment twice if there is more than one
1207    * CORE client.
1208    */
1209   uint16_t isize;
1210 };
1211
1212
1213 /**
1214  * A virtual link is another reachable peer that is known to CORE.  It
1215  * can be either a `struct Neighbour` with at least one confirmed
1216  * `struct Queue`, or a `struct DistanceVector` with at least one
1217  * confirmed `struct DistanceVectorHop`.  With a virtual link we track
1218  * data that is per neighbour that is not specific to how the
1219  * connectivity is established.
1220  */
1221 struct VirtualLink
1222 {
1223   /**
1224    * Identity of the peer at the other end of the link.
1225    */
1226   struct GNUNET_PeerIdentity target;
1227
1228   /**
1229    * Communicators blocked for receiving on @e target as we are waiting
1230    * on the @e core_recv_window to increase.
1231    */
1232   struct CommunicatorMessageContext *cmc_head;
1233
1234   /**
1235    * Communicators blocked for receiving on @e target as we are waiting
1236    * on the @e core_recv_window to increase.
1237    */
1238   struct CommunicatorMessageContext *cmc_tail;
1239
1240   /**
1241    * Head of list of messages pending for this VL.
1242    */
1243   struct PendingMessage *pending_msg_head;
1244
1245   /**
1246    * Tail of list of messages pending for this VL.
1247    */
1248   struct PendingMessage *pending_msg_tail;
1249
1250   /**
1251    * Kept in a DLL to clear @e vl in case @e vl is lost.
1252    */
1253   struct CoreSentContext *csc_tail;
1254
1255   /**
1256    * Kept in a DLL to clear @e vl in case @e vl is lost.
1257    */
1258   struct CoreSentContext *csc_head;
1259
1260   /**
1261    * Task scheduled to possibly notfiy core that this peer is no
1262    * longer counting as confirmed.  Runs the #core_visibility_check(),
1263    * which checks that some DV-path or a queue exists that is still
1264    * considered confirmed.
1265    */
1266   struct GNUNET_SCHEDULER_Task *visibility_task;
1267
1268   /**
1269    * Task scheduled to periodically retransmit FC messages (in
1270    * case one got lost).
1271    */
1272   struct GNUNET_SCHEDULER_Task *fc_retransmit_task;
1273
1274   /**
1275    * Neighbour used by this virtual link, NULL if @e dv is used.
1276    */
1277   struct Neighbour *n;
1278
1279   /**
1280    * Distance vector used by this virtual link, NULL if @e n is used.
1281    */
1282   struct DistanceVector *dv;
1283
1284   /**
1285    * Sender timestamp of @e n_challenge, used to generate out-of-order
1286    * challenges (as sender's timestamps must be monotonically
1287    * increasing).  FIXME: where do we need this?
1288    */
1289   struct GNUNET_TIME_Absolute n_challenge_time;
1290
1291   /**
1292    * When did we last send a
1293    * #GNUNET_MESSAGE_TYPE_TRANSPORT_FLOW_CONTROL message?
1294    * Used to determine whether it is time to re-transmit the message.
1295    */
1296   struct GNUNET_TIME_Absolute last_fc_transmission;
1297
1298   /**
1299    * Sender timestamp of the last
1300    * #GNUNET_MESSAGE_TYPE_TRANSPORT_FLOW_CONTROL message we have
1301    * received.  Note that we do not persist this monotonic time as we
1302    * do not really have to worry about ancient flow control window
1303    * sizes after restarts.
1304    */
1305   struct GNUNET_TIME_Absolute last_fc_timestamp;
1306
1307   /**
1308    * Expected RTT from the last FC transmission. (Zero if the last
1309    * attempt failed, but could theoretically be zero even on success.)
1310    */
1311   struct GNUNET_TIME_Relative last_fc_rtt;
1312
1313   /**
1314    * Used to generate unique UUIDs for messages that are being
1315    * fragmented.
1316    */
1317   uint64_t message_uuid_ctr;
1318
1319   /**
1320    * Memory allocated for this virtual link.  Expresses how much RAM
1321    * we are willing to allocate to this virtual link.  OPTIMIZE-ME:
1322    * Can be adapted to dedicate more RAM to links that need it, while
1323    * sticking to some overall RAM limit.  For now, set to
1324    * #DEFAULT_WINDOW_SIZE.
1325    */
1326   uint64_t available_fc_window_size;
1327
1328   /**
1329    * Memory actually used to buffer packets on this virtual link.
1330    * Expresses how much RAM we are currently using for virtual link.
1331    * Note that once CORE is done with a packet, we decrement the value
1332    * here.
1333    */
1334   uint64_t incoming_fc_window_size_ram;
1335
1336   /**
1337    * Last flow control window size we provided to the other peer, in
1338    * bytes.  We are allowing the other peer to send this
1339    * many bytes.
1340    */
1341   uint64_t incoming_fc_window_size;
1342
1343   /**
1344    * How much of the window did the other peer successfully use (and
1345    * we already passed it on to CORE)? Must be below @e
1346    * incoming_fc_window_size.   We should effectively signal the
1347    * other peer that the window is this much bigger at the next
1348    * opportunity / challenge.
1349    */
1350   uint64_t incoming_fc_window_size_used;
1351
1352   /**
1353    * What is our current estimate on the message loss rate for the sender?
1354    * Based on the difference between how much the sender sent according
1355    * to the last #GNUNET_MESSAGE_TYPE_TRANSPORT_FLOW_CONTROL message
1356    * (@e outbound_sent field) and how much we actually received at that
1357    * time (@e incoming_fc_window_size_used).  This delta is then
1358    * added onto the @e incoming_fc_window_size when determining the
1359    * @e outbound_window_size we send to the other peer.  Initially zero.
1360    * May be negative if we (due to out-of-order delivery) actually received
1361    * more than the sender claims to have sent in its last FC message.
1362    */
1363   int64_t incoming_fc_window_size_loss;
1364
1365   /**
1366    * Our current flow control window size in bytes.  We
1367    * are allowed to transmit this many bytes to @a n.
1368    */
1369   uint64_t outbound_fc_window_size;
1370
1371   /**
1372    * How much of our current flow control window size have we
1373    * used (in bytes).  Must be below
1374    * @e outbound_fc_window_size.
1375    */
1376   uint64_t outbound_fc_window_size_used;
1377
1378   /**
1379    * What is the most recent FC window the other peer sent us
1380    * in `outbound_window_size`? This is basically the window
1381    * size value the other peer has definitively received from
1382    * us. If it matches @e incoming_fc_window_size, we should
1383    * not send a FC message to increase the FC window. However,
1384    * we may still send an FC message to notify the other peer
1385    * that we received the other peer's FC message.
1386    */
1387   uint64_t last_outbound_window_size_received;
1388
1389   /**
1390    * Generator for the sequence numbers of
1391    * #GNUNET_MESSAGE_TYPE_TRANSPORT_FLOW_CONTROL messages we send.
1392    */
1393   uint32_t fc_seq_gen;
1394
1395   /**
1396    * Last sequence number of a
1397    * #GNUNET_MESSAGE_TYPE_TRANSPORT_FLOW_CONTROL message we have
1398    * received.
1399    */
1400   uint32_t last_fc_seq;
1401
1402   /**
1403    * How many more messages can we send to CORE before we exhaust
1404    * the receive window of CORE for this peer? If this hits zero,
1405    * we must tell communicators to stop providing us more messages
1406    * for this peer.  In fact, the window can go negative as we
1407    * have multiple communicators, so per communicator we can go
1408    * down by one into the negative range. Furthermore, we count
1409    * delivery per CORE client, so if we had multiple cores, that
1410    * might also cause a negative window size here (as one message
1411    * would decrement the window by one per CORE client).
1412    */
1413   int core_recv_window;
1414 };
1415
1416
1417 /**
1418  * Data structure kept when we are waiting for an acknowledgement.
1419  */
1420 struct PendingAcknowledgement
1421 {
1422   /**
1423    * If @e pm is non-NULL, this is the DLL in which this acknowledgement
1424    * is kept in relation to its pending message.
1425    */
1426   struct PendingAcknowledgement *next_pm;
1427
1428   /**
1429    * If @e pm is non-NULL, this is the DLL in which this acknowledgement
1430    * is kept in relation to its pending message.
1431    */
1432   struct PendingAcknowledgement *prev_pm;
1433
1434   /**
1435    * If @e queue is non-NULL, this is the DLL in which this acknowledgement
1436    * is kept in relation to the queue that was used to transmit the
1437    * @a pm.
1438    */
1439   struct PendingAcknowledgement *next_queue;
1440
1441   /**
1442    * If @e queue is non-NULL, this is the DLL in which this acknowledgement
1443    * is kept in relation to the queue that was used to transmit the
1444    * @a pm.
1445    */
1446   struct PendingAcknowledgement *prev_queue;
1447
1448   /**
1449    * If @e dvh is non-NULL, this is the DLL in which this acknowledgement
1450    * is kept in relation to the DVH that was used to transmit the
1451    * @a pm.
1452    */
1453   struct PendingAcknowledgement *next_dvh;
1454
1455   /**
1456    * If @e dvh is non-NULL, this is the DLL in which this acknowledgement
1457    * is kept in relation to the DVH that was used to transmit the
1458    * @a pm.
1459    */
1460   struct PendingAcknowledgement *prev_dvh;
1461
1462   /**
1463    * Pointers for the DLL of all pending acknowledgements.
1464    * This list is sorted by @e transmission time.  If the list gets too
1465    * long, the oldest entries are discarded.
1466    */
1467   struct PendingAcknowledgement *next_pa;
1468
1469   /**
1470    * Pointers for the DLL of all pending acknowledgements.
1471    * This list is sorted by @e transmission time.  If the list gets too
1472    * long, the oldest entries are discarded.
1473    */
1474   struct PendingAcknowledgement *prev_pa;
1475
1476   /**
1477    * Unique identifier for this transmission operation.
1478    */
1479   struct AcknowledgementUUIDP ack_uuid;
1480
1481   /**
1482    * Message that was transmitted, may be NULL if the message was ACKed
1483    * via another channel.
1484    */
1485   struct PendingMessage *pm;
1486
1487   /**
1488    * Distance vector path chosen for this transmission, NULL if transmission
1489    * was to a direct neighbour OR if the path was forgotten in the meantime.
1490    */
1491   struct DistanceVectorHop *dvh;
1492
1493   /**
1494    * Queue used for transmission, NULL if the queue has been destroyed
1495    * (which may happen before we get an acknowledgement).
1496    */
1497   struct Queue *queue;
1498
1499   /**
1500    * Time of the transmission, for RTT calculation.
1501    */
1502   struct GNUNET_TIME_Absolute transmission_time;
1503
1504   /**
1505    * Number of bytes of the original message (to calculate bandwidth).
1506    */
1507   uint16_t message_size;
1508 };
1509
1510
1511 /**
1512  * One possible hop towards a DV target.
1513  */
1514 struct DistanceVectorHop
1515 {
1516   /**
1517    * Kept in a MDLL, sorted by @e timeout.
1518    */
1519   struct DistanceVectorHop *next_dv;
1520
1521   /**
1522    * Kept in a MDLL, sorted by @e timeout.
1523    */
1524   struct DistanceVectorHop *prev_dv;
1525
1526   /**
1527    * Kept in a MDLL.
1528    */
1529   struct DistanceVectorHop *next_neighbour;
1530
1531   /**
1532    * Kept in a MDLL.
1533    */
1534   struct DistanceVectorHop *prev_neighbour;
1535
1536   /**
1537    * Head of DLL of PAs that used our @a path.
1538    */
1539   struct PendingAcknowledgement *pa_head;
1540
1541   /**
1542    * Tail of DLL of PAs that used our @a path.
1543    */
1544   struct PendingAcknowledgement *pa_tail;
1545
1546   /**
1547    * What would be the next hop to @e target?
1548    */
1549   struct Neighbour *next_hop;
1550
1551   /**
1552    * Distance vector entry this hop belongs with.
1553    */
1554   struct DistanceVector *dv;
1555
1556   /**
1557    * Array of @e distance hops to the target, excluding @e next_hop.
1558    * NULL if the entire path is us to @e next_hop to `target`. Allocated
1559    * at the end of this struct. Excludes the target itself!
1560    */
1561   const struct GNUNET_PeerIdentity *path;
1562
1563   /**
1564    * At what time do we forget about this path unless we see it again
1565    * while learning?
1566    */
1567   struct GNUNET_TIME_Absolute timeout;
1568
1569   /**
1570    * For how long is the validation of this path considered
1571    * valid?
1572    * Set to ZERO if the path is learned by snooping on DV learn messages
1573    * initiated by other peers, and to the time at which we generated the
1574    * challenge for DV learn operations this peer initiated.
1575    */
1576   struct GNUNET_TIME_Absolute path_valid_until;
1577
1578   /**
1579    * Performance data for this transmission possibility.
1580    */
1581   struct PerformanceData pd;
1582
1583   /**
1584    * Number of hops in total to the `target` (excluding @e next_hop and `target`
1585    * itself). Thus 0 still means a distance of 2 hops (to @e next_hop and then
1586    * to `target`).
1587    */
1588   unsigned int distance;
1589 };
1590
1591
1592 /**
1593  * Entry in our #dv_routes table, representing a (set of) distance
1594  * vector routes to a particular peer.
1595  */
1596 struct DistanceVector
1597 {
1598   /**
1599    * To which peer is this a route?
1600    */
1601   struct GNUNET_PeerIdentity target;
1602
1603   /**
1604    * Known paths to @e target.
1605    */
1606   struct DistanceVectorHop *dv_head;
1607
1608   /**
1609    * Known paths to @e target.
1610    */
1611   struct DistanceVectorHop *dv_tail;
1612
1613   /**
1614    * Task scheduled to purge expired paths from @e dv_head MDLL.
1615    */
1616   struct GNUNET_SCHEDULER_Task *timeout_task;
1617
1618   /**
1619    * Do we have a confirmed working queue and are thus visible to
1620    * CORE?  If so, this is the virtual link, otherwise NULL.
1621    */
1622   struct VirtualLink *vl;
1623
1624   /**
1625    * Signature affirming @e ephemeral_key of type
1626    * #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL
1627    */
1628   struct GNUNET_CRYPTO_EddsaSignature sender_sig;
1629
1630   /**
1631    * How long is @e sender_sig valid
1632    */
1633   struct GNUNET_TIME_Absolute ephemeral_validity;
1634
1635   /**
1636    * What time was @e sender_sig created
1637    */
1638   struct GNUNET_TIME_Absolute monotime;
1639
1640   /**
1641    * Our ephemeral key.
1642    */
1643   struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
1644
1645   /**
1646    * Our private ephemeral key.
1647    */
1648   struct GNUNET_CRYPTO_EcdhePrivateKey private_key;
1649 };
1650
1651
1652 /**
1653  * Entry identifying transmission in one of our `struct
1654  * Queue` which still awaits an ACK.  This is used to
1655  * ensure we do not overwhelm a communicator and limit the number of
1656  * messages outstanding per communicator (say in case communicator is
1657  * CPU bound) and per queue (in case bandwidth allocation exceeds
1658  * what the communicator can actually provide towards a particular
1659  * peer/target).
1660  */
1661 struct QueueEntry
1662 {
1663   /**
1664    * Kept as a DLL.
1665    */
1666   struct QueueEntry *next;
1667
1668   /**
1669    * Kept as a DLL.
1670    */
1671   struct QueueEntry *prev;
1672
1673   /**
1674    * Queue this entry is queued with.
1675    */
1676   struct Queue *queue;
1677
1678   /**
1679    * Pending message this entry is for, or NULL for none.
1680    */
1681   struct PendingMessage *pm;
1682
1683   /**
1684    * Message ID used for this message with the queue used for transmission.
1685    */
1686   uint64_t mid;
1687 };
1688
1689
1690 /**
1691  * A queue is a message queue provided by a communicator
1692  * via which we can reach a particular neighbour.
1693  */
1694 struct Queue
1695 {
1696   /**
1697    * Kept in a MDLL.
1698    */
1699   struct Queue *next_neighbour;
1700
1701   /**
1702    * Kept in a MDLL.
1703    */
1704   struct Queue *prev_neighbour;
1705
1706   /**
1707    * Kept in a MDLL.
1708    */
1709   struct Queue *prev_client;
1710
1711   /**
1712    * Kept in a MDLL.
1713    */
1714   struct Queue *next_client;
1715
1716   /**
1717    * Head of DLL of PAs that used this queue.
1718    */
1719   struct PendingAcknowledgement *pa_head;
1720
1721   /**
1722    * Tail of DLL of PAs that used this queue.
1723    */
1724   struct PendingAcknowledgement *pa_tail;
1725
1726   /**
1727    * Head of DLL of unacked transmission requests.
1728    */
1729   struct QueueEntry *queue_head;
1730
1731   /**
1732    * End of DLL of unacked transmission requests.
1733    */
1734   struct QueueEntry *queue_tail;
1735
1736   /**
1737    * Which neighbour is this queue for?
1738    */
1739   struct Neighbour *neighbour;
1740
1741   /**
1742    * Which communicator offers this queue?
1743    */
1744   struct TransportClient *tc;
1745
1746   /**
1747    * Address served by the queue.
1748    */
1749   const char *address;
1750
1751   /**
1752    * Task scheduled for the time when this queue can (likely) transmit the
1753    * next message.
1754    */
1755   struct GNUNET_SCHEDULER_Task *transmit_task;
1756
1757   /**
1758    * How long do *we* consider this @e address to be valid?  In the past or
1759    * zero if we have not yet validated it.  Can be updated based on
1760    * challenge-response validations (via address validation logic), or when we
1761    * receive ACKs that we can definitively map to transmissions via this
1762    * queue.
1763    */
1764   struct GNUNET_TIME_Absolute validated_until;
1765
1766   /**
1767    * Performance data for this queue.
1768    */
1769   struct PerformanceData pd;
1770
1771   /**
1772    * Message ID generator for transmissions on this queue to the
1773    * communicator.
1774    */
1775   uint64_t mid_gen;
1776
1777   /**
1778    * Unique identifier of this queue with the communicator.
1779    */
1780   uint32_t qid;
1781
1782   /**
1783    * Maximum transmission unit supported by this queue.
1784    */
1785   uint32_t mtu;
1786
1787   /**
1788    * Messages pending.
1789    */
1790   uint32_t num_msg_pending;
1791
1792   /**
1793    * Bytes pending.
1794    */
1795   uint32_t num_bytes_pending;
1796
1797   /**
1798    * Length of the DLL starting at @e queue_head.
1799    */
1800   unsigned int queue_length;
1801
1802   /**
1803    * Network type offered by this queue.
1804    */
1805   enum GNUNET_NetworkType nt;
1806
1807   /**
1808    * Connection status for this queue.
1809    */
1810   enum GNUNET_TRANSPORT_ConnectionStatus cs;
1811
1812   /**
1813    * Set to #GNUNET_YES if this queue is idle waiting for some
1814    * virtual link to give it a pending message.
1815    */
1816   int idle;
1817 };
1818
1819
1820 /**
1821  * Information we keep for a message that we are reassembling.
1822  */
1823 struct ReassemblyContext
1824 {
1825   /**
1826    * Original message ID for of the message that all the fragments
1827    * belong to.
1828    */
1829   struct MessageUUIDP msg_uuid;
1830
1831   /**
1832    * Which neighbour is this context for?
1833    */
1834   struct Neighbour *neighbour;
1835
1836   /**
1837    * Entry in the reassembly heap (sorted by expiration).
1838    */
1839   struct GNUNET_CONTAINER_HeapNode *hn;
1840
1841   /**
1842    * Bitfield with @e msg_size bits representing the positions
1843    * where we have received fragments.  When we receive a fragment,
1844    * we check the bits in @e bitfield before incrementing @e msg_missing.
1845    *
1846    * Allocated after the reassembled message.
1847    */
1848   uint8_t *bitfield;
1849
1850   /**
1851    * At what time will we give up reassembly of this message?
1852    */
1853   struct GNUNET_TIME_Absolute reassembly_timeout;
1854
1855   /**
1856    * Time we received the last fragment.  @e avg_ack_delay must be
1857    * incremented by now - @e last_frag multiplied by @e num_acks.
1858    */
1859   struct GNUNET_TIME_Absolute last_frag;
1860
1861   /**
1862    * How big is the message we are reassembling in total?
1863    */
1864   uint16_t msg_size;
1865
1866   /**
1867    * How many bytes of the message are still missing?  Defragmentation
1868    * is complete when @e msg_missing == 0.
1869    */
1870   uint16_t msg_missing;
1871
1872   /* Followed by @e msg_size bytes of the (partially) defragmented original
1873    * message */
1874
1875   /* Followed by @e bitfield data */
1876 };
1877
1878
1879 /**
1880  * A neighbour that at least one communicator is connected to.
1881  */
1882 struct Neighbour
1883 {
1884   /**
1885    * Which peer is this about?
1886    */
1887   struct GNUNET_PeerIdentity pid;
1888
1889   /**
1890    * Map with `struct ReassemblyContext` structs for fragments under
1891    * reassembly. May be NULL if we currently have no fragments from
1892    * this @e pid (lazy initialization).
1893    */
1894   struct GNUNET_CONTAINER_MultiHashMap32 *reassembly_map;
1895
1896   /**
1897    * Heap with `struct ReassemblyContext` structs for fragments under
1898    * reassembly. May be NULL if we currently have no fragments from
1899    * this @e pid (lazy initialization).
1900    */
1901   struct GNUNET_CONTAINER_Heap *reassembly_heap;
1902
1903   /**
1904    * Task to free old entries from the @e reassembly_heap and @e reassembly_map.
1905    */
1906   struct GNUNET_SCHEDULER_Task *reassembly_timeout_task;
1907
1908   /**
1909    * Head of MDLL of DV hops that have this neighbour as next hop. Must be
1910    * purged if this neighbour goes down.
1911    */
1912   struct DistanceVectorHop *dv_head;
1913
1914   /**
1915    * Tail of MDLL of DV hops that have this neighbour as next hop. Must be
1916    * purged if this neighbour goes down.
1917    */
1918   struct DistanceVectorHop *dv_tail;
1919
1920   /**
1921    * Head of DLL of queues to this peer.
1922    */
1923   struct Queue *queue_head;
1924
1925   /**
1926    * Tail of DLL of queues to this peer.
1927    */
1928   struct Queue *queue_tail;
1929
1930   /**
1931    * Handle for an operation to fetch @e last_dv_learn_monotime information from
1932    * the PEERSTORE, or NULL.
1933    */
1934   struct GNUNET_PEERSTORE_IterateContext *get;
1935
1936   /**
1937    * Handle to a PEERSTORE store operation to store this @e pid's @e
1938    * @e last_dv_learn_monotime.  NULL if no PEERSTORE operation is pending.
1939    */
1940   struct GNUNET_PEERSTORE_StoreContext *sc;
1941
1942   /**
1943    * Do we have a confirmed working queue and are thus visible to
1944    * CORE?  If so, this is the virtual link, otherwise NULL.
1945    */
1946   struct VirtualLink *vl;
1947
1948   /**
1949    * Latest DVLearn monotonic time seen from this peer.  Initialized only
1950    * if @e dl_monotime_available is #GNUNET_YES.
1951    */
1952   struct GNUNET_TIME_Absolute last_dv_learn_monotime;
1953
1954   /**
1955    * Do we have the lastest value for @e last_dv_learn_monotime from
1956    * PEERSTORE yet, or are we still waiting for a reply of PEERSTORE?
1957    */
1958   int dv_monotime_available;
1959 };
1960
1961
1962 /**
1963  * Another peer attempted to talk to us, we should try to establish
1964  * a connection in the other direction.
1965  */
1966 struct IncomingRequest
1967 {
1968   /**
1969    * Kept in a DLL.
1970    */
1971   struct IncomingRequest *next;
1972
1973   /**
1974    * Kept in a DLL.
1975    */
1976   struct IncomingRequest *prev;
1977
1978   /**
1979    * Handle for watching the peerstore for HELLOs for this peer.
1980    */
1981   struct GNUNET_PEERSTORE_WatchContext *wc;
1982
1983   /**
1984    * Which peer is this about?
1985    */
1986   struct GNUNET_PeerIdentity pid;
1987 };
1988
1989
1990 /**
1991  * A peer that an application (client) would like us to talk to directly.
1992  */
1993 struct PeerRequest
1994 {
1995   /**
1996    * Which peer is this about?
1997    */
1998   struct GNUNET_PeerIdentity pid;
1999
2000   /**
2001    * Client responsible for the request.
2002    */
2003   struct TransportClient *tc;
2004
2005   /**
2006    * Handle for watching the peerstore for HELLOs for this peer.
2007    */
2008   struct GNUNET_PEERSTORE_WatchContext *wc;
2009
2010   /**
2011    * What kind of performance preference does this @e tc have?
2012    *
2013    * TODO: use this!
2014    */
2015   enum GNUNET_MQ_PriorityPreferences pk;
2016
2017   /**
2018    * How much bandwidth would this @e tc like to see?
2019    */
2020   struct GNUNET_BANDWIDTH_Value32NBO bw;
2021 };
2022
2023
2024 /**
2025  * Types of different pending messages.
2026  */
2027 enum PendingMessageType
2028 {
2029   /**
2030    * Ordinary message received from the CORE service.
2031    */
2032   PMT_CORE = 0,
2033
2034   /**
2035    * Fragment box.
2036    */
2037   PMT_FRAGMENT_BOX = 1,
2038
2039   /**
2040    * Reliability box.
2041    */
2042   PMT_RELIABILITY_BOX = 2,
2043
2044   /**
2045    * Pending message created during #forward_dv_box().
2046    */
2047   PMT_DV_BOX = 3
2048 };
2049
2050
2051 /**
2052  * Transmission request that is awaiting delivery.  The original
2053  * transmission requests from CORE may be too big for some queues.
2054  * In this case, a *tree* of fragments is created.  At each
2055  * level of the tree, fragments are kept in a DLL ordered by which
2056  * fragment should be sent next (at the head).  The tree is searched
2057  * top-down, with the original message at the root.
2058  *
2059  * To select a node for transmission, first it is checked if the
2060  * current node's message fits with the MTU.  If it does not, we
2061  * either calculate the next fragment (based on @e frag_off) from the
2062  * current node, or, if all fragments have already been created,
2063  * descend to the @e head_frag.  Even though the node was already
2064  * fragmented, the fragment may be too big if the fragment was
2065  * generated for a queue with a larger MTU. In this case, the node
2066  * may be fragmented again, thus creating a tree.
2067  *
2068  * When acknowledgements for fragments are received, the tree
2069  * must be pruned, removing those parts that were already
2070  * acknowledged.  When fragments are sent over a reliable
2071  * channel, they can be immediately removed.
2072  *
2073  * If a message is ever fragmented, then the original "full" message
2074  * is never again transmitted (even if it fits below the MTU), and
2075  * only (remaining) fragments are sent.
2076  */
2077 struct PendingMessage
2078 {
2079   /**
2080    * Kept in a MDLL of messages for this @a vl.
2081    */
2082   struct PendingMessage *next_vl;
2083
2084   /**
2085    * Kept in a MDLL of messages for this @a vl.
2086    */
2087   struct PendingMessage *prev_vl;
2088
2089   /**
2090    * Kept in a MDLL of messages from this @a client (if @e pmt is #PMT_CORE)
2091    */
2092   struct PendingMessage *next_client;
2093
2094   /**
2095    * Kept in a MDLL of messages from this @a client  (if @e pmt is #PMT_CORE)
2096    */
2097   struct PendingMessage *prev_client;
2098
2099   /**
2100    * Kept in a MDLL of messages from this @a cpm (if @e pmt is
2101    * #PMT_FRAGMENT_BOx)
2102    */
2103   struct PendingMessage *next_frag;
2104
2105   /**
2106    * Kept in a MDLL of messages from this @a cpm  (if @e pmt is
2107    * #PMT_FRAGMENT_BOX)
2108    */
2109   struct PendingMessage *prev_frag;
2110
2111   /**
2112    * Head of DLL of PAs for this pending message.
2113    */
2114   struct PendingAcknowledgement *pa_head;
2115
2116   /**
2117    * Tail of DLL of PAs for this pending message.
2118    */
2119   struct PendingAcknowledgement *pa_tail;
2120
2121   /**
2122    * This message, reliability *or* DV-boxed. Only possibly available
2123    * if @e pmt is #PMT_CORE.
2124    */
2125   struct PendingMessage *bpm;
2126
2127   /**
2128    * Target of the request (always the ultimate destination!).
2129    */
2130   struct VirtualLink *vl;
2131
2132   /**
2133    * Set to non-NULL value if this message is currently being given to a
2134    * communicator and we are awaiting that communicator's acknowledgement.
2135    * Note that we must not retransmit a pending message while we're still
2136    * in the process of giving it to a communicator. If a pending message
2137    * is free'd while this entry is non-NULL, the @e qe reference to us
2138    * should simply be set to NULL.
2139    */
2140   struct QueueEntry *qe;
2141
2142   /**
2143    * Client that issued the transmission request, if @e pmt is #PMT_CORE.
2144    */
2145   struct TransportClient *client;
2146
2147   /**
2148    * Head of a MDLL of fragments created for this core message.
2149    */
2150   struct PendingMessage *head_frag;
2151
2152   /**
2153    * Tail of a MDLL of fragments created for this core message.
2154    */
2155   struct PendingMessage *tail_frag;
2156
2157   /**
2158    * Our parent in the fragmentation tree.
2159    */
2160   struct PendingMessage *frag_parent;
2161
2162   /**
2163    * At what time should we give up on the transmission (and no longer retry)?
2164    */
2165   struct GNUNET_TIME_Absolute timeout;
2166
2167   /**
2168    * What is the earliest time for us to retry transmission of this message?
2169    */
2170   struct GNUNET_TIME_Absolute next_attempt;
2171
2172   /**
2173    * UUID to use for this message (used for reassembly of fragments, only
2174    * initialized if @e msg_uuid_set is #GNUNET_YES).
2175    */
2176   struct MessageUUIDP msg_uuid;
2177
2178   /**
2179    * UUID we use to identify this message in our logs.
2180    * Generated by incrementing the "logging_uuid_gen".
2181    */
2182   unsigned long long logging_uuid;
2183
2184   /**
2185    * Type of the pending message.
2186    */
2187   enum PendingMessageType pmt;
2188
2189   /**
2190    * Preferences for this message.
2191    * TODO: actually use this!
2192    */
2193   enum GNUNET_MQ_PriorityPreferences prefs;
2194
2195   /**
2196    * Size of the original message.
2197    */
2198   uint16_t bytes_msg;
2199
2200   /**
2201    * Offset at which we should generate the next fragment.
2202    */
2203   uint16_t frag_off;
2204
2205   /**
2206    * #GNUNET_YES once @e msg_uuid was initialized
2207    */
2208   int16_t msg_uuid_set;
2209
2210   /* Followed by @e bytes_msg to transmit */
2211 };
2212
2213
2214 /**
2215  * Acknowledgement payload.
2216  */
2217 struct TransportCummulativeAckPayload
2218 {
2219   /**
2220    * When did we receive the message we are ACKing?  Used to calculate
2221    * the delay we introduced by cummulating ACKs.
2222    */
2223   struct GNUNET_TIME_Absolute receive_time;
2224
2225   /**
2226    * UUID of a message being acknowledged.
2227    */
2228   struct AcknowledgementUUIDP ack_uuid;
2229 };
2230
2231
2232 /**
2233  * Data structure in which we track acknowledgements still to
2234  * be sent to the
2235  */
2236 struct AcknowledgementCummulator
2237 {
2238   /**
2239    * Target peer for which we are accumulating ACKs here.
2240    */
2241   struct GNUNET_PeerIdentity target;
2242
2243   /**
2244    * ACK data being accumulated.  Only @e num_acks slots are valid.
2245    */
2246   struct TransportCummulativeAckPayload ack_uuids[MAX_CUMMULATIVE_ACKS];
2247
2248   /**
2249    * Task scheduled either to transmit the cummulative ACK message,
2250    * or to clean up this data structure after extended periods of
2251    * inactivity (if @e num_acks is zero).
2252    */
2253   struct GNUNET_SCHEDULER_Task *task;
2254
2255   /**
2256    * When is @e task run (only used if @e num_acks is non-zero)?
2257    */
2258   struct GNUNET_TIME_Absolute min_transmission_time;
2259
2260   /**
2261    * Counter to produce the `ack_counter` in the `struct
2262    * TransportReliabilityAckMessage`.  Allows the receiver to detect
2263    * lost ACK messages.  Incremented by @e num_acks upon transmission.
2264    */
2265   uint32_t ack_counter;
2266
2267   /**
2268    * Number of entries used in @e ack_uuids.  Reset to 0 upon transmission.
2269    */
2270   unsigned int num_acks;
2271 };
2272
2273
2274 /**
2275  * One of the addresses of this peer.
2276  */
2277 struct AddressListEntry
2278 {
2279   /**
2280    * Kept in a DLL.
2281    */
2282   struct AddressListEntry *next;
2283
2284   /**
2285    * Kept in a DLL.
2286    */
2287   struct AddressListEntry *prev;
2288
2289   /**
2290    * Which communicator provides this address?
2291    */
2292   struct TransportClient *tc;
2293
2294   /**
2295    * The actual address.
2296    */
2297   const char *address;
2298
2299   /**
2300    * Current context for storing this address in the peerstore.
2301    */
2302   struct GNUNET_PEERSTORE_StoreContext *sc;
2303
2304   /**
2305    * Task to periodically do @e st operation.
2306    */
2307   struct GNUNET_SCHEDULER_Task *st;
2308
2309   /**
2310    * What is a typical lifetime the communicator expects this
2311    * address to have? (Always from now.)
2312    */
2313   struct GNUNET_TIME_Relative expiration;
2314
2315   /**
2316    * Address identifier used by the communicator.
2317    */
2318   uint32_t aid;
2319
2320   /**
2321    * Network type offered by this address.
2322    */
2323   enum GNUNET_NetworkType nt;
2324 };
2325
2326
2327 /**
2328  * Client connected to the transport service.
2329  */
2330 struct TransportClient
2331 {
2332   /**
2333    * Kept in a DLL.
2334    */
2335   struct TransportClient *next;
2336
2337   /**
2338    * Kept in a DLL.
2339    */
2340   struct TransportClient *prev;
2341
2342   /**
2343    * Handle to the client.
2344    */
2345   struct GNUNET_SERVICE_Client *client;
2346
2347   /**
2348    * Message queue to the client.
2349    */
2350   struct GNUNET_MQ_Handle *mq;
2351
2352   /**
2353    * What type of client is this?
2354    */
2355   enum ClientType type;
2356
2357   union
2358   {
2359     /**
2360      * Information for @e type #CT_CORE.
2361      */
2362     struct
2363     {
2364       /**
2365        * Head of list of messages pending for this client, sorted by
2366        * transmission time ("next_attempt" + possibly internal prioritization).
2367        */
2368       struct PendingMessage *pending_msg_head;
2369
2370       /**
2371        * Tail of list of messages pending for this client.
2372        */
2373       struct PendingMessage *pending_msg_tail;
2374     } core;
2375
2376     /**
2377      * Information for @e type #CT_MONITOR.
2378      */
2379     struct
2380     {
2381       /**
2382        * Peer identity to monitor the addresses of.
2383        * Zero to monitor all neighbours.  Valid if
2384        * @e type is #CT_MONITOR.
2385        */
2386       struct GNUNET_PeerIdentity peer;
2387
2388       /**
2389        * Is this a one-shot monitor?
2390        */
2391       int one_shot;
2392     } monitor;
2393
2394
2395     /**
2396      * Information for @e type #CT_COMMUNICATOR.
2397      */
2398     struct
2399     {
2400       /**
2401        * If @e type is #CT_COMMUNICATOR, this communicator
2402        * supports communicating using these addresses.
2403        */
2404       char *address_prefix;
2405
2406       /**
2407        * Head of DLL of queues offered by this communicator.
2408        */
2409       struct Queue *queue_head;
2410
2411       /**
2412        * Tail of DLL of queues offered by this communicator.
2413        */
2414       struct Queue *queue_tail;
2415
2416       /**
2417        * Head of list of the addresses of this peer offered by this
2418        * communicator.
2419        */
2420       struct AddressListEntry *addr_head;
2421
2422       /**
2423        * Tail of list of the addresses of this peer offered by this
2424        * communicator.
2425        */
2426       struct AddressListEntry *addr_tail;
2427
2428       /**
2429        * Number of queue entries in all queues to this communicator. Used
2430        * throttle sending to a communicator if we see that the communicator
2431        * is globally unable to keep up.
2432        */
2433       unsigned int total_queue_length;
2434
2435       /**
2436        * Characteristics of this communicator.
2437        */
2438       enum GNUNET_TRANSPORT_CommunicatorCharacteristics cc;
2439     } communicator;
2440
2441     /**
2442      * Information for @e type #CT_APPLICATION
2443      */
2444     struct
2445     {
2446       /**
2447        * Map of requests for peers the given client application would like to
2448        * see connections for.  Maps from PIDs to `struct PeerRequest`.
2449        */
2450       struct GNUNET_CONTAINER_MultiPeerMap *requests;
2451     } application;
2452   } details;
2453 };
2454
2455
2456 /**
2457  * State we keep for validation activities.  Each of these
2458  * is both in the #validation_heap and the #validation_map.
2459  */
2460 struct ValidationState
2461 {
2462   /**
2463    * For which peer is @a address to be validated (or possibly valid)?
2464    * Serves as key in the #validation_map.
2465    */
2466   struct GNUNET_PeerIdentity pid;
2467
2468   /**
2469    * How long did the peer claim this @e address to be valid? Capped at
2470    * minimum of #MAX_ADDRESS_VALID_UNTIL relative to the time where we last
2471    * were told about the address and the value claimed by the other peer at
2472    * that time.  May be updated similarly when validation succeeds.
2473    */
2474   struct GNUNET_TIME_Absolute valid_until;
2475
2476   /**
2477    * How long do *we* consider this @e address to be valid?
2478    * In the past or zero if we have not yet validated it.
2479    */
2480   struct GNUNET_TIME_Absolute validated_until;
2481
2482   /**
2483    * When did we FIRST use the current @e challenge in a message?
2484    * Used to sanity-check @code{origin_time} in the response when
2485    * calculating the RTT. If the @code{origin_time} is not in
2486    * the expected range, the response is discarded as malicious.
2487    */
2488   struct GNUNET_TIME_Absolute first_challenge_use;
2489
2490   /**
2491    * When did we LAST use the current @e challenge in a message?
2492    * Used to sanity-check @code{origin_time} in the response when
2493    * calculating the RTT.  If the @code{origin_time} is not in
2494    * the expected range, the response is discarded as malicious.
2495    */
2496   struct GNUNET_TIME_Absolute last_challenge_use;
2497
2498   /**
2499    * Next time we will send the @e challenge to the peer, if this time is past
2500    * @e valid_until, this validation state is released at this time.  If the
2501    * address is valid, @e next_challenge is set to @e validated_until MINUS @e
2502    * validation_delay * #VALIDATION_RTT_BUFFER_FACTOR, such that we will try
2503    * to re-validate before the validity actually expires.
2504    */
2505   struct GNUNET_TIME_Absolute next_challenge;
2506
2507   /**
2508    * Current backoff factor we're applying for sending the @a challenge.
2509    * Reset to 0 if the @a challenge is confirmed upon validation.
2510    * Reduced to minimum of #FAST_VALIDATION_CHALLENGE_FREQ and half of the
2511    * existing value if we receive an unvalidated address again over
2512    * another channel (and thus should consider the information "fresh").
2513    * Maximum is #MAX_VALIDATION_CHALLENGE_FREQ.
2514    */
2515   struct GNUNET_TIME_Relative challenge_backoff;
2516
2517   /**
2518    * Initially set to "forever". Once @e validated_until is set, this value is
2519    * set to the RTT that tells us how long it took to receive the validation.
2520    */
2521   struct GNUNET_TIME_Relative validation_rtt;
2522
2523   /**
2524    * The challenge we sent to the peer to get it to validate the address. Note
2525    * that we rotate the challenge whenever we update @e validated_until to
2526    * avoid attacks where a peer simply replays an old challenge in the future.
2527    * (We must not rotate more often as otherwise we may discard valid answers
2528    * due to packet losses, latency and reorderings on the network).
2529    */
2530   struct ChallengeNonceP challenge;
2531
2532   /**
2533    * Claimed address of the peer.
2534    */
2535   char *address;
2536
2537   /**
2538    * Entry in the #validation_heap, which is sorted by @e next_challenge. The
2539    * heap is used to figure out when the next validation activity should be
2540    * run.
2541    */
2542   struct GNUNET_CONTAINER_HeapNode *hn;
2543
2544   /**
2545    * Handle to a PEERSTORE store operation for this @e address.  NULL if
2546    * no PEERSTORE operation is pending.
2547    */
2548   struct GNUNET_PEERSTORE_StoreContext *sc;
2549
2550   /**
2551    * Self-imposed limit on the previous flow control window. (May be zero,
2552    * if we never used data from the previous window or are establishing the
2553    * connection for the first time).
2554    */
2555   uint32_t last_window_consum_limit;
2556
2557   /**
2558    * We are technically ready to send the challenge, but we are waiting for
2559    * the respective queue to become available for transmission.
2560    */
2561   int awaiting_queue;
2562 };
2563
2564
2565 /**
2566  * A Backtalker is a peer sending us backchannel messages. We use this
2567  * struct to detect monotonic time violations, cache ephemeral key
2568  * material (to avoid repeatedly checking signatures), and to synchronize
2569  * monotonic time with the PEERSTORE.
2570  */
2571 struct Backtalker
2572 {
2573   /**
2574    * Peer this is about.
2575    */
2576   struct GNUNET_PeerIdentity pid;
2577
2578   /**
2579    * Last (valid) monotonic time received from this sender.
2580    */
2581   struct GNUNET_TIME_Absolute monotonic_time;
2582
2583   /**
2584    * When will this entry time out?
2585    */
2586   struct GNUNET_TIME_Absolute timeout;
2587
2588   /**
2589    * Last (valid) ephemeral key received from this sender.
2590    */
2591   struct GNUNET_CRYPTO_EcdhePublicKey last_ephemeral;
2592
2593   /**
2594    * Task associated with this backtalker. Can be for timeout,
2595    * or other asynchronous operations.
2596    */
2597   struct GNUNET_SCHEDULER_Task *task;
2598
2599   /**
2600    * Communicator context waiting on this backchannel's @e get, or NULL.
2601    */
2602   struct CommunicatorMessageContext *cmc;
2603
2604   /**
2605    * Handle for an operation to fetch @e monotonic_time information from the
2606    * PEERSTORE, or NULL.
2607    */
2608   struct GNUNET_PEERSTORE_IterateContext *get;
2609
2610   /**
2611    * Handle to a PEERSTORE store operation for this @e pid's @e
2612    * monotonic_time.  NULL if no PEERSTORE operation is pending.
2613    */
2614   struct GNUNET_PEERSTORE_StoreContext *sc;
2615
2616   /**
2617    * Number of bytes of the original message body that follows after this
2618    * struct.
2619    */
2620   size_t body_size;
2621 };
2622
2623
2624 /**
2625  * Head of linked list of all clients to this service.
2626  */
2627 static struct TransportClient *clients_head;
2628
2629 /**
2630  * Tail of linked list of all clients to this service.
2631  */
2632 static struct TransportClient *clients_tail;
2633
2634 /**
2635  * Statistics handle.
2636  */
2637 static struct GNUNET_STATISTICS_Handle *GST_stats;
2638
2639 /**
2640  * Configuration handle.
2641  */
2642 static const struct GNUNET_CONFIGURATION_Handle *GST_cfg;
2643
2644 /**
2645  * Our public key.
2646  */
2647 static struct GNUNET_PeerIdentity GST_my_identity;
2648
2649 /**
2650  * Our private key.
2651  */
2652 static struct GNUNET_CRYPTO_EddsaPrivateKey *GST_my_private_key;
2653
2654 /**
2655  * Map from PIDs to `struct Neighbour` entries.  A peer is
2656  * a neighbour if we have an MQ to it from some communicator.
2657  */
2658 static struct GNUNET_CONTAINER_MultiPeerMap *neighbours;
2659
2660 /**
2661  * Map from PIDs to `struct Backtalker` entries.  A peer is
2662  * a backtalker if it recently send us backchannel messages.
2663  */
2664 static struct GNUNET_CONTAINER_MultiPeerMap *backtalkers;
2665
2666 /**
2667  * Map from PIDs to `struct AcknowledgementCummulator`s.
2668  * Here we track the cummulative ACKs for transmission.
2669  */
2670 static struct GNUNET_CONTAINER_MultiPeerMap *ack_cummulators;
2671
2672 /**
2673  * Map of pending acknowledgements, mapping `struct AcknowledgementUUID` to
2674  * a `struct PendingAcknowledgement`.
2675  */
2676 static struct GNUNET_CONTAINER_MultiUuidmap *pending_acks;
2677
2678 /**
2679  * Map from PIDs to `struct DistanceVector` entries describing
2680  * known paths to the peer.
2681  */
2682 static struct GNUNET_CONTAINER_MultiPeerMap *dv_routes;
2683
2684 /**
2685  * Map from PIDs to `struct ValidationState` entries describing
2686  * addresses we are aware of and their validity state.
2687  */
2688 static struct GNUNET_CONTAINER_MultiPeerMap *validation_map;
2689
2690 /**
2691  * Map from PIDs to `struct VirtualLink` entries describing
2692  * links CORE knows to exist.
2693  */
2694 static struct GNUNET_CONTAINER_MultiPeerMap *links;
2695
2696 /**
2697  * Map from challenges to `struct LearnLaunchEntry` values.
2698  */
2699 static struct GNUNET_CONTAINER_MultiShortmap *dvlearn_map;
2700
2701 /**
2702  * Head of a DLL sorted by launch time.
2703  */
2704 static struct LearnLaunchEntry *lle_head;
2705
2706 /**
2707  * Tail of a DLL sorted by launch time.
2708  */
2709 static struct LearnLaunchEntry *lle_tail;
2710
2711 /**
2712  * MIN Heap sorted by "next_challenge" to `struct ValidationState` entries
2713  * sorting addresses we are aware of by when we should next try to (re)validate
2714  * (or expire) them.
2715  */
2716 static struct GNUNET_CONTAINER_Heap *validation_heap;
2717
2718 /**
2719  * Database for peer's HELLOs.
2720  */
2721 static struct GNUNET_PEERSTORE_Handle *peerstore;
2722
2723 /**
2724  * Task run to initiate DV learning.
2725  */
2726 static struct GNUNET_SCHEDULER_Task *dvlearn_task;
2727
2728 /**
2729  * Task to run address validation.
2730  */
2731 static struct GNUNET_SCHEDULER_Task *validation_task;
2732
2733 /**
2734  * The most recent PA we have created, head of DLL.
2735  * The length of the DLL is kept in #pa_count.
2736  */
2737 static struct PendingAcknowledgement *pa_head;
2738
2739 /**
2740  * The oldest PA we have created, tail of DLL.
2741  * The length of the DLL is kept in #pa_count.
2742  */
2743 static struct PendingAcknowledgement *pa_tail;
2744
2745 /**
2746  * List of incomming connections where we are trying
2747  * to get a connection back established. Length
2748  * kept in #ir_total.
2749  */
2750 static struct IncomingRequest *ir_head;
2751
2752 /**
2753  * Tail of DLL starting at #ir_head.
2754  */
2755 static struct IncomingRequest *ir_tail;
2756
2757 /**
2758  * Length of the DLL starting at #ir_head.
2759  */
2760 static unsigned int ir_total;
2761
2762 /**
2763  * Generator of `logging_uuid` in `struct PendingMessage`.
2764  */
2765 static unsigned long long logging_uuid_gen;
2766
2767 /**
2768  * Number of entries in the #pa_head/#pa_tail DLL.  Used to
2769  * limit the size of the data structure.
2770  */
2771 static unsigned int pa_count;
2772
2773 /**
2774  * Monotonic time we use for HELLOs generated at this time.  TODO: we
2775  * should increase this value from time to time (i.e. whenever a
2776  * `struct AddressListEntry` actually expires), but IF we do this, we
2777  * must also update *all* (remaining) addresses in the PEERSTORE at
2778  * that time! (So for now only increased when the peer is restarted,
2779  * which hopefully roughly matches whenever our addresses change.)
2780  */
2781 static struct GNUNET_TIME_Absolute hello_mono_time;
2782
2783
2784 /**
2785  * Get an offset into the transmission history buffer for `struct
2786  * PerformanceData`.  Note that the caller must perform the required
2787  * modulo #GOODPUT_AGING_SLOTS operation before indexing into the
2788  * array!
2789  *
2790  * An 'age' lasts 15 minute slots.
2791  *
2792  * @return current age of the world
2793  */
2794 static unsigned int
2795 get_age ()
2796 {
2797   struct GNUNET_TIME_Absolute now;
2798
2799   now = GNUNET_TIME_absolute_get ();
2800   return now.abs_value_us / GNUNET_TIME_UNIT_MINUTES.rel_value_us / 15;
2801 }
2802
2803
2804 /**
2805  * Release @a ir data structure.
2806  *
2807  * @param ir data structure to release
2808  */
2809 static void
2810 free_incoming_request (struct IncomingRequest *ir)
2811 {
2812   GNUNET_CONTAINER_DLL_remove (ir_head, ir_tail, ir);
2813   GNUNET_assert (ir_total > 0);
2814   ir_total--;
2815   GNUNET_PEERSTORE_watch_cancel (ir->wc);
2816   GNUNET_free (ir);
2817 }
2818
2819
2820 /**
2821  * Release @a pa data structure.
2822  *
2823  * @param pa data structure to release
2824  */
2825 static void
2826 free_pending_acknowledgement (struct PendingAcknowledgement *pa)
2827 {
2828   struct Queue *q = pa->queue;
2829   struct PendingMessage *pm = pa->pm;
2830   struct DistanceVectorHop *dvh = pa->dvh;
2831
2832   GNUNET_CONTAINER_MDLL_remove (pa, pa_head, pa_tail, pa);
2833   pa_count--;
2834   if (NULL != q)
2835   {
2836     GNUNET_CONTAINER_MDLL_remove (queue, q->pa_head, q->pa_tail, pa);
2837     pa->queue = NULL;
2838   }
2839   if (NULL != pm)
2840   {
2841     GNUNET_CONTAINER_MDLL_remove (pm, pm->pa_head, pm->pa_tail, pa);
2842     pa->pm = NULL;
2843   }
2844   if (NULL != dvh)
2845   {
2846     GNUNET_CONTAINER_MDLL_remove (dvh, dvh->pa_head, dvh->pa_tail, pa);
2847     pa->queue = NULL;
2848   }
2849   GNUNET_assert (GNUNET_YES ==
2850                  GNUNET_CONTAINER_multiuuidmap_remove (pending_acks,
2851                                                        &pa->ack_uuid.value,
2852                                                        pa));
2853   GNUNET_free (pa);
2854 }
2855
2856
2857 /**
2858  * Free fragment tree below @e root, excluding @e root itself.
2859  * FIXME: this does NOT seem to have the intended semantics
2860  * based on how this is called. Seems we generally DO expect
2861  * @a root to be free'ed itself as well!
2862  *
2863  * @param root root of the tree to free
2864  */
2865 static void
2866 free_fragment_tree (struct PendingMessage *root)
2867 {
2868   struct PendingMessage *frag;
2869
2870   while (NULL != (frag = root->head_frag))
2871   {
2872     struct PendingAcknowledgement *pa;
2873
2874     free_fragment_tree (frag);
2875     while (NULL != (pa = frag->pa_head))
2876     {
2877       GNUNET_CONTAINER_MDLL_remove (pm, frag->pa_head, frag->pa_tail, pa);
2878       pa->pm = NULL;
2879     }
2880     GNUNET_CONTAINER_MDLL_remove (frag, root->head_frag, root->tail_frag, frag);
2881     GNUNET_free (frag);
2882   }
2883 }
2884
2885
2886 /**
2887  * Release memory associated with @a pm and remove @a pm from associated
2888  * data structures.  @a pm must be a top-level pending message and not
2889  * a fragment in the tree.  The entire tree is freed (if applicable).
2890  *
2891  * @param pm the pending message to free
2892  */
2893 static void
2894 free_pending_message (struct PendingMessage *pm)
2895 {
2896   struct TransportClient *tc = pm->client;
2897   struct VirtualLink *vl = pm->vl;
2898   struct PendingAcknowledgement *pa;
2899
2900   if (NULL != tc)
2901   {
2902     GNUNET_CONTAINER_MDLL_remove (client,
2903                                   tc->details.core.pending_msg_head,
2904                                   tc->details.core.pending_msg_tail,
2905                                   pm);
2906   }
2907   if (NULL != vl)
2908   {
2909     GNUNET_CONTAINER_MDLL_remove (vl,
2910                                   vl->pending_msg_head,
2911                                   vl->pending_msg_tail,
2912                                   pm);
2913   }
2914   while (NULL != (pa = pm->pa_head))
2915   {
2916     GNUNET_CONTAINER_MDLL_remove (pm, pm->pa_head, pm->pa_tail, pa);
2917     pa->pm = NULL;
2918   }
2919
2920   free_fragment_tree (pm);
2921   if (NULL != pm->qe)
2922   {
2923     GNUNET_assert (pm == pm->qe->pm);
2924     pm->qe->pm = NULL;
2925   }
2926   if (NULL != pm->bpm)
2927   {
2928     free_fragment_tree (pm->bpm);
2929     GNUNET_free (pm->bpm);
2930   }
2931   GNUNET_free (pm);
2932 }
2933
2934
2935 /**
2936  * Free virtual link.
2937  *
2938  * @param vl link data to free
2939  */
2940 static void
2941 free_virtual_link (struct VirtualLink *vl)
2942 {
2943   struct PendingMessage *pm;
2944   struct CoreSentContext *csc;
2945
2946   while (NULL != (pm = vl->pending_msg_head))
2947     free_pending_message (pm);
2948   GNUNET_assert (GNUNET_YES ==
2949                  GNUNET_CONTAINER_multipeermap_remove (links, &vl->target, vl));
2950   if (NULL != vl->visibility_task)
2951   {
2952     GNUNET_SCHEDULER_cancel (vl->visibility_task);
2953     vl->visibility_task = NULL;
2954   }
2955   if (NULL != vl->fc_retransmit_task)
2956   {
2957     GNUNET_SCHEDULER_cancel (vl->fc_retransmit_task);
2958     vl->fc_retransmit_task = NULL;
2959   }
2960   while (NULL != (csc = vl->csc_head))
2961   {
2962     GNUNET_CONTAINER_DLL_remove (vl->csc_head, vl->csc_tail, csc);
2963     GNUNET_assert (vl == csc->vl);
2964     csc->vl = NULL;
2965   }
2966   GNUNET_break (NULL == vl->n);
2967   GNUNET_break (NULL == vl->dv);
2968   GNUNET_free (vl);
2969 }
2970
2971
2972 /**
2973  * Free validation state.
2974  *
2975  * @param vs validation state to free
2976  */
2977 static void
2978 free_validation_state (struct ValidationState *vs)
2979 {
2980   GNUNET_assert (
2981     GNUNET_YES ==
2982     GNUNET_CONTAINER_multipeermap_remove (validation_map, &vs->pid, vs));
2983   GNUNET_CONTAINER_heap_remove_node (vs->hn);
2984   vs->hn = NULL;
2985   if (NULL != vs->sc)
2986   {
2987     GNUNET_PEERSTORE_store_cancel (vs->sc);
2988     vs->sc = NULL;
2989   }
2990   GNUNET_free (vs->address);
2991   GNUNET_free (vs);
2992 }
2993
2994
2995 /**
2996  * Lookup neighbour for peer @a pid.
2997  *
2998  * @param pid neighbour to look for
2999  * @return NULL if we do not have this peer as a neighbour
3000  */
3001 static struct Neighbour *
3002 lookup_neighbour (const struct GNUNET_PeerIdentity *pid)
3003 {
3004   return GNUNET_CONTAINER_multipeermap_get (neighbours, pid);
3005 }
3006
3007
3008 /**
3009  * Lookup virtual link for peer @a pid.
3010  *
3011  * @param pid virtual link to look for
3012  * @return NULL if we do not have this peer as a virtual link
3013  */
3014 static struct VirtualLink *
3015 lookup_virtual_link (const struct GNUNET_PeerIdentity *pid)
3016 {
3017   return GNUNET_CONTAINER_multipeermap_get (links, pid);
3018 }
3019
3020
3021 /**
3022  * Details about what to notify monitors about.
3023  */
3024 struct MonitorEvent
3025 {
3026   /**
3027    * @deprecated To be discussed if we keep these...
3028    */
3029   struct GNUNET_TIME_Absolute last_validation;
3030   struct GNUNET_TIME_Absolute valid_until;
3031   struct GNUNET_TIME_Absolute next_validation;
3032
3033   /**
3034    * Current round-trip time estimate.
3035    */
3036   struct GNUNET_TIME_Relative rtt;
3037
3038   /**
3039    * Connection status.
3040    */
3041   enum GNUNET_TRANSPORT_ConnectionStatus cs;
3042
3043   /**
3044    * Messages pending.
3045    */
3046   uint32_t num_msg_pending;
3047
3048   /**
3049    * Bytes pending.
3050    */
3051   uint32_t num_bytes_pending;
3052 };
3053
3054
3055 /**
3056  * Free a @dvh. Callers MAY want to check if this was the last path to the
3057  * `target`, and if so call #free_dv_route to also free the associated DV
3058  * entry in #dv_routes (if not, the associated scheduler job should eventually
3059  * take care of it).
3060  *
3061  * @param dvh hop to free
3062  */
3063 static void
3064 free_distance_vector_hop (struct DistanceVectorHop *dvh)
3065 {
3066   struct Neighbour *n = dvh->next_hop;
3067   struct DistanceVector *dv = dvh->dv;
3068   struct PendingAcknowledgement *pa;
3069
3070   while (NULL != (pa = dvh->pa_head))
3071   {
3072     GNUNET_CONTAINER_MDLL_remove (dvh, dvh->pa_head, dvh->pa_tail, pa);
3073     pa->dvh = NULL;
3074   }
3075   GNUNET_CONTAINER_MDLL_remove (neighbour, n->dv_head, n->dv_tail, dvh);
3076   GNUNET_CONTAINER_MDLL_remove (dv, dv->dv_head, dv->dv_tail, dvh);
3077   GNUNET_free (dvh);
3078 }
3079
3080
3081 /**
3082  * Task run to check whether the hops of the @a cls still
3083  * are validated, or if we need to core about disconnection.
3084  *
3085  * @param cls a `struct VirtualLink`
3086  */
3087 static void
3088 check_link_down (void *cls);
3089
3090
3091 /**
3092  * Send message to CORE clients that we lost a connection.
3093  *
3094  * @param pid peer the connection was for
3095  */
3096 static void
3097 cores_send_disconnect_info (const struct GNUNET_PeerIdentity *pid)
3098 {
3099   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3100               "Informing CORE clients about disconnect from %s\n",
3101               GNUNET_i2s (pid));
3102   for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
3103   {
3104     struct GNUNET_MQ_Envelope *env;
3105     struct DisconnectInfoMessage *dim;
3106
3107     if (CT_CORE != tc->type)
3108       continue;
3109     env = GNUNET_MQ_msg (dim, GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT);
3110     dim->peer = *pid;
3111     GNUNET_MQ_send (tc->mq, env);
3112   }
3113 }
3114
3115
3116 /**
3117  * Free entry in #dv_routes.  First frees all hops to the target, and
3118  * if there are no entries left, frees @a dv as well.
3119  *
3120  * @param dv route to free
3121  */
3122 static void
3123 free_dv_route (struct DistanceVector *dv)
3124 {
3125   struct DistanceVectorHop *dvh;
3126
3127   while (NULL != (dvh = dv->dv_head))
3128     free_distance_vector_hop (dvh);
3129   if (NULL == dv->dv_head)
3130   {
3131     struct VirtualLink *vl;
3132
3133     GNUNET_assert (
3134       GNUNET_YES ==
3135       GNUNET_CONTAINER_multipeermap_remove (dv_routes, &dv->target, dv));
3136     if (NULL != (vl = dv->vl))
3137     {
3138       GNUNET_assert (dv == vl->dv);
3139       vl->dv = NULL;
3140       if (NULL == vl->n)
3141       {
3142         cores_send_disconnect_info (&dv->target);
3143         free_virtual_link (vl);
3144       }
3145       else
3146       {
3147         GNUNET_SCHEDULER_cancel (vl->visibility_task);
3148         vl->visibility_task = GNUNET_SCHEDULER_add_now (&check_link_down, vl);
3149       }
3150       dv->vl = NULL;
3151     }
3152
3153     if (NULL != dv->timeout_task)
3154     {
3155       GNUNET_SCHEDULER_cancel (dv->timeout_task);
3156       dv->timeout_task = NULL;
3157     }
3158     GNUNET_free (dv);
3159   }
3160 }
3161
3162
3163 /**
3164  * Notify monitor @a tc about an event.  That @a tc
3165  * cares about the event has already been checked.
3166  *
3167  * Send @a tc information in @a me about a @a peer's status with
3168  * respect to some @a address to all monitors that care.
3169  *
3170  * @param tc monitor to inform
3171  * @param peer peer the information is about
3172  * @param address address the information is about
3173  * @param nt network type associated with @a address
3174  * @param me detailed information to transmit
3175  */
3176 static void
3177 notify_monitor (struct TransportClient *tc,
3178                 const struct GNUNET_PeerIdentity *peer,
3179                 const char *address,
3180                 enum GNUNET_NetworkType nt,
3181                 const struct MonitorEvent *me)
3182 {
3183   struct GNUNET_MQ_Envelope *env;
3184   struct GNUNET_TRANSPORT_MonitorData *md;
3185   size_t addr_len = strlen (address) + 1;
3186
3187   env = GNUNET_MQ_msg_extra (md,
3188                              addr_len,
3189                              GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_DATA);
3190   md->nt = htonl ((uint32_t) nt);
3191   md->peer = *peer;
3192   md->last_validation = GNUNET_TIME_absolute_hton (me->last_validation);
3193   md->valid_until = GNUNET_TIME_absolute_hton (me->valid_until);
3194   md->next_validation = GNUNET_TIME_absolute_hton (me->next_validation);
3195   md->rtt = GNUNET_TIME_relative_hton (me->rtt);
3196   md->cs = htonl ((uint32_t) me->cs);
3197   md->num_msg_pending = htonl (me->num_msg_pending);
3198   md->num_bytes_pending = htonl (me->num_bytes_pending);
3199   memcpy (&md[1], address, addr_len);
3200   GNUNET_MQ_send (tc->mq, env);
3201 }
3202
3203
3204 /**
3205  * Send information in @a me about a @a peer's status with respect
3206  * to some @a address to all monitors that care.
3207  *
3208  * @param peer peer the information is about
3209  * @param address address the information is about
3210  * @param nt network type associated with @a address
3211  * @param me detailed information to transmit
3212  */
3213 static void
3214 notify_monitors (const struct GNUNET_PeerIdentity *peer,
3215                  const char *address,
3216                  enum GNUNET_NetworkType nt,
3217                  const struct MonitorEvent *me)
3218 {
3219   for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
3220   {
3221     if (CT_MONITOR != tc->type)
3222       continue;
3223     if (tc->details.monitor.one_shot)
3224       continue;
3225     if ((0 != GNUNET_is_zero (&tc->details.monitor.peer)) &&
3226         (0 != GNUNET_memcmp (&tc->details.monitor.peer, peer)))
3227       continue;
3228     notify_monitor (tc, peer, address, nt, me);
3229   }
3230 }
3231
3232
3233 /**
3234  * Called whenever a client connects.  Allocates our
3235  * data structures associated with that client.
3236  *
3237  * @param cls closure, NULL
3238  * @param client identification of the client
3239  * @param mq message queue for the client
3240  * @return our `struct TransportClient`
3241  */
3242 static void *
3243 client_connect_cb (void *cls,
3244                    struct GNUNET_SERVICE_Client *client,
3245                    struct GNUNET_MQ_Handle *mq)
3246 {
3247   struct TransportClient *tc;
3248
3249   (void) cls;
3250   tc = GNUNET_new (struct TransportClient);
3251   tc->client = client;
3252   tc->mq = mq;
3253   GNUNET_CONTAINER_DLL_insert (clients_head, clients_tail, tc);
3254   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", tc);
3255   return tc;
3256 }
3257
3258
3259 /**
3260  * Free @a rc
3261  *
3262  * @param rc data structure to free
3263  */
3264 static void
3265 free_reassembly_context (struct ReassemblyContext *rc)
3266 {
3267   struct Neighbour *n = rc->neighbour;
3268
3269   GNUNET_assert (rc == GNUNET_CONTAINER_heap_remove_node (rc->hn));
3270   GNUNET_assert (GNUNET_OK ==
3271                  GNUNET_CONTAINER_multihashmap32_remove (n->reassembly_map,
3272                                                          rc->msg_uuid.uuid,
3273                                                          rc));
3274   GNUNET_free (rc);
3275 }
3276
3277
3278 /**
3279  * Task run to clean up reassembly context of a neighbour that have expired.
3280  *
3281  * @param cls a `struct Neighbour`
3282  */
3283 static void
3284 reassembly_cleanup_task (void *cls)
3285 {
3286   struct Neighbour *n = cls;
3287   struct ReassemblyContext *rc;
3288
3289   n->reassembly_timeout_task = NULL;
3290   while (NULL != (rc = GNUNET_CONTAINER_heap_peek (n->reassembly_heap)))
3291   {
3292     if (0 == GNUNET_TIME_absolute_get_remaining (rc->reassembly_timeout)
3293         .rel_value_us)
3294     {
3295       free_reassembly_context (rc);
3296       continue;
3297     }
3298     GNUNET_assert (NULL == n->reassembly_timeout_task);
3299     n->reassembly_timeout_task =
3300       GNUNET_SCHEDULER_add_at (rc->reassembly_timeout,
3301                                &reassembly_cleanup_task,
3302                                n);
3303     return;
3304   }
3305 }
3306
3307
3308 /**
3309  * function called to #free_reassembly_context().
3310  *
3311  * @param cls NULL
3312  * @param key unused
3313  * @param value a `struct ReassemblyContext` to free
3314  * @return #GNUNET_OK (continue iteration)
3315  */
3316 static int
3317 free_reassembly_cb (void *cls, uint32_t key, void *value)
3318 {
3319   struct ReassemblyContext *rc = value;
3320
3321   (void) cls;
3322   (void) key;
3323   free_reassembly_context (rc);
3324   return GNUNET_OK;
3325 }
3326
3327
3328 /**
3329  * Release memory used by @a neighbour.
3330  *
3331  * @param neighbour neighbour entry to free
3332  */
3333 static void
3334 free_neighbour (struct Neighbour *neighbour)
3335 {
3336   struct DistanceVectorHop *dvh;
3337   struct VirtualLink *vl;
3338
3339   GNUNET_assert (NULL == neighbour->queue_head);
3340   GNUNET_assert (GNUNET_YES ==
3341                  GNUNET_CONTAINER_multipeermap_remove (neighbours,
3342                                                        &neighbour->pid,
3343                                                        neighbour));
3344   if (NULL != neighbour->reassembly_map)
3345   {
3346     GNUNET_CONTAINER_multihashmap32_iterate (neighbour->reassembly_map,
3347                                              &free_reassembly_cb,
3348                                              NULL);
3349     GNUNET_CONTAINER_multihashmap32_destroy (neighbour->reassembly_map);
3350     neighbour->reassembly_map = NULL;
3351     GNUNET_CONTAINER_heap_destroy (neighbour->reassembly_heap);
3352     neighbour->reassembly_heap = NULL;
3353   }
3354   while (NULL != (dvh = neighbour->dv_head))
3355   {
3356     struct DistanceVector *dv = dvh->dv;
3357
3358     free_distance_vector_hop (dvh);
3359     if (NULL == dv->dv_head)
3360       free_dv_route (dv);
3361   }
3362   if (NULL != neighbour->reassembly_timeout_task)
3363   {
3364     GNUNET_SCHEDULER_cancel (neighbour->reassembly_timeout_task);
3365     neighbour->reassembly_timeout_task = NULL;
3366   }
3367   if (NULL != neighbour->get)
3368   {
3369     GNUNET_PEERSTORE_iterate_cancel (neighbour->get);
3370     neighbour->get = NULL;
3371   }
3372   if (NULL != neighbour->sc)
3373   {
3374     GNUNET_PEERSTORE_store_cancel (neighbour->sc);
3375     neighbour->sc = NULL;
3376   }
3377   if (NULL != (vl = neighbour->vl))
3378   {
3379     GNUNET_assert (neighbour == vl->n);
3380     vl->n = NULL;
3381     if (NULL == vl->dv)
3382     {
3383       cores_send_disconnect_info (&vl->target);
3384       free_virtual_link (vl);
3385     }
3386     else
3387     {
3388       GNUNET_SCHEDULER_cancel (vl->visibility_task);
3389       vl->visibility_task = GNUNET_SCHEDULER_add_now (&check_link_down, vl);
3390     }
3391     neighbour->vl = NULL;
3392   }
3393   GNUNET_free (neighbour);
3394 }
3395
3396
3397 /**
3398  * Send message to CORE clients that we lost a connection.
3399  *
3400  * @param tc client to inform (must be CORE client)
3401  * @param pid peer the connection is for
3402  */
3403 static void
3404 core_send_connect_info (struct TransportClient *tc,
3405                         const struct GNUNET_PeerIdentity *pid)
3406 {
3407   struct GNUNET_MQ_Envelope *env;
3408   struct ConnectInfoMessage *cim;
3409
3410   GNUNET_assert (CT_CORE == tc->type);
3411   env = GNUNET_MQ_msg (cim, GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
3412   cim->id = *pid;
3413   GNUNET_MQ_send (tc->mq, env);
3414 }
3415
3416
3417 /**
3418  * Send message to CORE clients that we gained a connection
3419  *
3420  * @param pid peer the queue was for
3421  */
3422 static void
3423 cores_send_connect_info (const struct GNUNET_PeerIdentity *pid)
3424 {
3425   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3426               "Informing CORE clients about connection to %s\n",
3427               GNUNET_i2s (pid));
3428   for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
3429   {
3430     if (CT_CORE != tc->type)
3431       continue;
3432     core_send_connect_info (tc, pid);
3433   }
3434 }
3435
3436
3437 /**
3438  * We believe we are ready to transmit a message on a queue. Gives the
3439  * message to the communicator for transmission (updating the tracker,
3440  * and re-scheduling itself if applicable).
3441  *
3442  * @param cls the `struct Queue` to process transmissions for
3443  */
3444 static void
3445 transmit_on_queue (void *cls);
3446
3447
3448 /**
3449  * Called whenever something changed that might effect when we
3450  * try to do the next transmission on @a queue using #transmit_on_queue().
3451  *
3452  * @param queue the queue to do scheduling for
3453  * @param p task priority to use, if @a queue is scheduled
3454  */
3455 static void
3456 schedule_transmit_on_queue (struct Queue *queue,
3457                             enum GNUNET_SCHEDULER_Priority p)
3458 {
3459   if (queue->tc->details.communicator.total_queue_length >=
3460       COMMUNICATOR_TOTAL_QUEUE_LIMIT)
3461   {
3462     GNUNET_STATISTICS_update (
3463       GST_stats,
3464       "# Transmission throttled due to communicator queue limit",
3465       1,
3466       GNUNET_NO);
3467     queue->idle = GNUNET_NO;
3468     return;
3469   }
3470   if (queue->queue_length >= QUEUE_LENGTH_LIMIT)
3471   {
3472     GNUNET_STATISTICS_update (GST_stats,
3473                               "# Transmission throttled due to queue queue limit",
3474                               1,
3475                               GNUNET_NO);
3476     queue->idle = GNUNET_NO;
3477     return;
3478   }
3479   /* queue might indeed be ready, schedule it */
3480   if (NULL != queue->transmit_task)
3481     GNUNET_SCHEDULER_cancel (queue->transmit_task);
3482   queue->transmit_task =
3483     GNUNET_SCHEDULER_add_with_priority (p, &transmit_on_queue, queue);
3484   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3485               "Considering transmission on queue `%s' to %s\n",
3486               queue->address,
3487               GNUNET_i2s (&queue->neighbour->pid));
3488 }
3489
3490
3491 /**
3492  * Task run to check whether the hops of the @a cls still
3493  * are validated, or if we need to core about disconnection.
3494  *
3495  * @param cls a `struct VirtualLink`
3496  */
3497 static void
3498 check_link_down (void *cls)
3499 {
3500   struct VirtualLink *vl = cls;
3501   struct DistanceVector *dv = vl->dv;
3502   struct Neighbour *n = vl->n;
3503   struct GNUNET_TIME_Absolute dvh_timeout;
3504   struct GNUNET_TIME_Absolute q_timeout;
3505
3506   vl->visibility_task = NULL;
3507   dvh_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
3508   for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
3509        pos = pos->next_dv)
3510     dvh_timeout = GNUNET_TIME_absolute_max (dvh_timeout, pos->path_valid_until);
3511   if (0 == GNUNET_TIME_absolute_get_remaining (dvh_timeout).rel_value_us)
3512   {
3513     vl->dv->vl = NULL;
3514     vl->dv = NULL;
3515   }
3516   q_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
3517   for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
3518     q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
3519   if (0 == GNUNET_TIME_absolute_get_remaining (q_timeout).rel_value_us)
3520   {
3521     vl->n->vl = NULL;
3522     vl->n = NULL;
3523   }
3524   if ((NULL == vl->n) && (NULL == vl->dv))
3525   {
3526     cores_send_disconnect_info (&vl->target);
3527     free_virtual_link (vl);
3528     return;
3529   }
3530   vl->visibility_task =
3531     GNUNET_SCHEDULER_add_at (GNUNET_TIME_absolute_max (q_timeout, dvh_timeout),
3532                              &check_link_down,
3533                              vl);
3534 }
3535
3536
3537 /**
3538  * Free @a queue.
3539  *
3540  * @param queue the queue to free
3541  */
3542 static void
3543 free_queue (struct Queue *queue)
3544 {
3545   struct Neighbour *neighbour = queue->neighbour;
3546   struct TransportClient *tc = queue->tc;
3547   struct MonitorEvent me = { .cs = GNUNET_TRANSPORT_CS_DOWN,
3548                              .rtt = GNUNET_TIME_UNIT_FOREVER_REL };
3549   struct QueueEntry *qe;
3550   int maxxed;
3551   struct PendingAcknowledgement *pa;
3552   struct VirtualLink *vl;
3553
3554   if (NULL != queue->transmit_task)
3555   {
3556     GNUNET_SCHEDULER_cancel (queue->transmit_task);
3557     queue->transmit_task = NULL;
3558   }
3559   while (NULL != (pa = queue->pa_head))
3560   {
3561     GNUNET_CONTAINER_MDLL_remove (queue, queue->pa_head, queue->pa_tail, pa);
3562     pa->queue = NULL;
3563   }
3564
3565   GNUNET_CONTAINER_MDLL_remove (neighbour,
3566                                 neighbour->queue_head,
3567                                 neighbour->queue_tail,
3568                                 queue);
3569   GNUNET_CONTAINER_MDLL_remove (client,
3570                                 tc->details.communicator.queue_head,
3571                                 tc->details.communicator.queue_tail,
3572                                 queue);
3573   maxxed = (COMMUNICATOR_TOTAL_QUEUE_LIMIT >=
3574             tc->details.communicator.total_queue_length);
3575   while (NULL != (qe = queue->queue_head))
3576   {
3577     GNUNET_CONTAINER_DLL_remove (queue->queue_head, queue->queue_tail, qe);
3578     queue->queue_length--;
3579     tc->details.communicator.total_queue_length--;
3580     if (NULL != qe->pm)
3581     {
3582       GNUNET_assert (qe == qe->pm->qe);
3583       qe->pm->qe = NULL;
3584     }
3585     GNUNET_free (qe);
3586   }
3587   GNUNET_assert (0 == queue->queue_length);
3588   if ((maxxed) && (COMMUNICATOR_TOTAL_QUEUE_LIMIT <
3589                    tc->details.communicator.total_queue_length))
3590   {
3591     /* Communicator dropped below threshold, resume all _other_ queues */
3592     GNUNET_STATISTICS_update (
3593       GST_stats,
3594       "# Transmission throttled due to communicator queue limit",
3595       -1,
3596       GNUNET_NO);
3597     for (struct Queue *s = tc->details.communicator.queue_head; NULL != s;
3598          s = s->next_client)
3599       schedule_transmit_on_queue (s, GNUNET_SCHEDULER_PRIORITY_DEFAULT);
3600   }
3601   notify_monitors (&neighbour->pid, queue->address, queue->nt, &me);
3602   GNUNET_free (queue);
3603
3604   vl = lookup_virtual_link (&neighbour->pid);
3605   if ((NULL != vl) && (neighbour == vl->n))
3606   {
3607     GNUNET_SCHEDULER_cancel (vl->visibility_task);
3608     check_link_down (vl);
3609   }
3610   if (NULL == neighbour->queue_head)
3611   {
3612     free_neighbour (neighbour);
3613   }
3614 }
3615
3616
3617 /**
3618  * Free @a ale
3619  *
3620  * @param ale address list entry to free
3621  */
3622 static void
3623 free_address_list_entry (struct AddressListEntry *ale)
3624 {
3625   struct TransportClient *tc = ale->tc;
3626
3627   GNUNET_CONTAINER_DLL_remove (tc->details.communicator.addr_head,
3628                                tc->details.communicator.addr_tail,
3629                                ale);
3630   if (NULL != ale->sc)
3631   {
3632     GNUNET_PEERSTORE_store_cancel (ale->sc);
3633     ale->sc = NULL;
3634   }
3635   if (NULL != ale->st)
3636   {
3637     GNUNET_SCHEDULER_cancel (ale->st);
3638     ale->st = NULL;
3639   }
3640   GNUNET_free (ale);
3641 }
3642
3643
3644 /**
3645  * Stop the peer request in @a value.
3646  *
3647  * @param cls a `struct TransportClient` that no longer makes the request
3648  * @param pid the peer's identity
3649  * @param value a `struct PeerRequest`
3650  * @return #GNUNET_YES (always)
3651  */
3652 static int
3653 stop_peer_request (void *cls,
3654                    const struct GNUNET_PeerIdentity *pid,
3655                    void *value)
3656 {
3657   struct TransportClient *tc = cls;
3658   struct PeerRequest *pr = value;
3659
3660   GNUNET_PEERSTORE_watch_cancel (pr->wc);
3661   GNUNET_assert (
3662     GNUNET_YES ==
3663     GNUNET_CONTAINER_multipeermap_remove (tc->details.application.requests,
3664                                           pid,
3665                                           pr));
3666   GNUNET_free (pr);
3667
3668   return GNUNET_OK;
3669 }
3670
3671
3672 /**
3673  * Called whenever a client is disconnected.  Frees our
3674  * resources associated with that client.
3675  *
3676  * @param cls closure, NULL
3677  * @param client identification of the client
3678  * @param app_ctx our `struct TransportClient`
3679  */
3680 static void
3681 client_disconnect_cb (void *cls,
3682                       struct GNUNET_SERVICE_Client *client,
3683                       void *app_ctx)
3684 {
3685   struct TransportClient *tc = app_ctx;
3686
3687   (void) cls;
3688   (void) client;
3689   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3690               "Client %p disconnected, cleaning up.\n",
3691               tc);
3692   GNUNET_CONTAINER_DLL_remove (clients_head, clients_tail, tc);
3693   switch (tc->type)
3694   {
3695   case CT_NONE:
3696     break;
3697
3698   case CT_CORE: {
3699       struct PendingMessage *pm;
3700
3701       while (NULL != (pm = tc->details.core.pending_msg_head))
3702       {
3703         GNUNET_CONTAINER_MDLL_remove (client,
3704                                       tc->details.core.pending_msg_head,
3705                                       tc->details.core.pending_msg_tail,
3706                                       pm);
3707         pm->client = NULL;
3708       }
3709     }
3710     break;
3711
3712   case CT_MONITOR:
3713     break;
3714
3715   case CT_COMMUNICATOR: {
3716       struct Queue *q;
3717       struct AddressListEntry *ale;
3718
3719       while (NULL != (q = tc->details.communicator.queue_head))
3720         free_queue (q);
3721       while (NULL != (ale = tc->details.communicator.addr_head))
3722         free_address_list_entry (ale);
3723       GNUNET_free (tc->details.communicator.address_prefix);
3724     }
3725     break;
3726
3727   case CT_APPLICATION:
3728     GNUNET_CONTAINER_multipeermap_iterate (tc->details.application.requests,
3729                                            &stop_peer_request,
3730                                            tc);
3731     GNUNET_CONTAINER_multipeermap_destroy (tc->details.application.requests);
3732     break;
3733   }
3734   GNUNET_free (tc);
3735 }
3736
3737
3738 /**
3739  * Iterator telling new CORE client about all existing
3740  * connections to peers.
3741  *
3742  * @param cls the new `struct TransportClient`
3743  * @param pid a connected peer
3744  * @param value the `struct Neighbour` with more information
3745  * @return #GNUNET_OK (continue to iterate)
3746  */
3747 static int
3748 notify_client_connect_info (void *cls,
3749                             const struct GNUNET_PeerIdentity *pid,
3750                             void *value)
3751 {
3752   struct TransportClient *tc = cls;
3753
3754   (void) value;
3755   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3756               "Telling new CORE client about existing connection to %s\n",
3757               GNUNET_i2s (pid));
3758   core_send_connect_info (tc, pid);
3759   return GNUNET_OK;
3760 }
3761
3762
3763 /**
3764  * Initialize a "CORE" client.  We got a start message from this
3765  * client, so add it to the list of clients for broadcasting of
3766  * inbound messages.
3767  *
3768  * @param cls the client
3769  * @param start the start message that was sent
3770  */
3771 static void
3772 handle_client_start (void *cls, const struct StartMessage *start)
3773 {
3774   struct TransportClient *tc = cls;
3775   uint32_t options;
3776
3777   options = ntohl (start->options);
3778   if ((0 != (1 & options)) &&
3779       (0 != GNUNET_memcmp (&start->self, &GST_my_identity)))
3780   {
3781     /* client thinks this is a different peer, reject */
3782     GNUNET_break (0);
3783     GNUNET_SERVICE_client_drop (tc->client);
3784     return;
3785   }
3786   if (CT_NONE != tc->type)
3787   {
3788     GNUNET_break (0);
3789     GNUNET_SERVICE_client_drop (tc->client);
3790     return;
3791   }
3792   tc->type = CT_CORE;
3793   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3794               "New CORE client with PID %s registered\n",
3795               GNUNET_i2s (&start->self));
3796   GNUNET_CONTAINER_multipeermap_iterate (neighbours,
3797                                          &notify_client_connect_info,
3798                                          tc);
3799   GNUNET_SERVICE_client_continue (tc->client);
3800 }
3801
3802
3803 /**
3804  * Client asked for transmission to a peer.  Process the request.
3805  *
3806  * @param cls the client
3807  * @param obm the send message that was sent
3808  */
3809 static int
3810 check_client_send (void *cls, const struct OutboundMessage *obm)
3811 {
3812   struct TransportClient *tc = cls;
3813   uint16_t size;
3814   const struct GNUNET_MessageHeader *obmm;
3815
3816   if (CT_CORE != tc->type)
3817   {
3818     GNUNET_break (0);
3819     return GNUNET_SYSERR;
3820   }
3821   size = ntohs (obm->header.size) - sizeof(struct OutboundMessage);
3822   if (size < sizeof(struct GNUNET_MessageHeader))
3823   {
3824     GNUNET_break (0);
3825     return GNUNET_SYSERR;
3826   }
3827   obmm = (const struct GNUNET_MessageHeader *) &obm[1];
3828   if (size != ntohs (obmm->size))
3829   {
3830     GNUNET_break (0);
3831     return GNUNET_SYSERR;
3832   }
3833   return GNUNET_OK;
3834 }
3835
3836
3837 /**
3838  * Send a response to the @a pm that we have processed a "send"
3839  * request.  Sends a confirmation to the "core" client responsible for
3840  * the original request and free's @a pm.
3841  *
3842  * @param pm handle to the original pending message
3843  */
3844 static void
3845 client_send_response (struct PendingMessage *pm)
3846 {
3847   struct TransportClient *tc = pm->client;
3848   struct VirtualLink *vl = pm->vl;
3849
3850   if (NULL != tc)
3851   {
3852     struct GNUNET_MQ_Envelope *env;
3853     struct SendOkMessage *som;
3854
3855     env = GNUNET_MQ_msg (som, GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK);
3856     som->peer = vl->target;
3857     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3858                 "Confirming transmission of <%llu> to %s\n",
3859                 pm->logging_uuid,
3860                 GNUNET_i2s (&vl->target));
3861     GNUNET_MQ_send (tc->mq, env);
3862   }
3863   free_pending_message (pm);
3864 }
3865
3866
3867 /**
3868  * Pick @a hops_array_length random DV paths satisfying @a options
3869  *
3870  * @param dv data structure to pick paths from
3871  * @param options constraints to satisfy
3872  * @param hops_array[out] set to the result
3873  * @param hops_array_length length of the @a hops_array
3874  * @return number of entries set in @a hops_array
3875  */
3876 static unsigned int
3877 pick_random_dv_hops (const struct DistanceVector *dv,
3878                      enum RouteMessageOptions options,
3879                      struct DistanceVectorHop **hops_array,
3880                      unsigned int hops_array_length)
3881 {
3882   uint64_t choices[hops_array_length];
3883   uint64_t num_dv;
3884   unsigned int dv_count;
3885
3886   /* Pick random vectors, but weighted by distance, giving more weight
3887      to shorter vectors */
3888   num_dv = 0;
3889   dv_count = 0;
3890   for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
3891        pos = pos->next_dv)
3892   {
3893     if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) &&
3894         (GNUNET_TIME_absolute_get_remaining (pos->path_valid_until)
3895          .rel_value_us == 0))
3896       continue;   /* pos unconfirmed and confirmed required */
3897     num_dv += MAX_DV_HOPS_ALLOWED - pos->distance;
3898     dv_count++;
3899   }
3900   if (0 == dv_count)
3901     return 0;
3902   if (dv_count <= hops_array_length)
3903   {
3904     dv_count = 0;
3905     for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
3906          pos = pos->next_dv)
3907       hops_array[dv_count++] = pos;
3908     return dv_count;
3909   }
3910   for (unsigned int i = 0; i < hops_array_length; i++)
3911   {
3912     int ok = GNUNET_NO;
3913     while (GNUNET_NO == ok)
3914     {
3915       choices[i] =
3916         GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, num_dv);
3917       ok = GNUNET_YES;
3918       for (unsigned int j = 0; j < i; j++)
3919         if (choices[i] == choices[j])
3920         {
3921           ok = GNUNET_NO;
3922           break;
3923         }
3924     }
3925   }
3926   dv_count = 0;
3927   num_dv = 0;
3928   for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
3929        pos = pos->next_dv)
3930   {
3931     uint32_t delta = MAX_DV_HOPS_ALLOWED - pos->distance;
3932
3933     if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) &&
3934         (GNUNET_TIME_absolute_get_remaining (pos->path_valid_until)
3935          .rel_value_us == 0))
3936       continue;   /* pos unconfirmed and confirmed required */
3937     for (unsigned int i = 0; i < hops_array_length; i++)
3938       if ((num_dv <= choices[i]) && (num_dv + delta > choices[i]))
3939         hops_array[dv_count++] = pos;
3940     num_dv += delta;
3941   }
3942   return dv_count;
3943 }
3944
3945
3946 /**
3947  * Communicator started.  Test message is well-formed.
3948  *
3949  * @param cls the client
3950  * @param cam the send message that was sent
3951  */
3952 static int
3953 check_communicator_available (
3954   void *cls,
3955   const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
3956 {
3957   struct TransportClient *tc = cls;
3958   uint16_t size;
3959
3960   if (CT_NONE != tc->type)
3961   {
3962     GNUNET_break (0);
3963     return GNUNET_SYSERR;
3964   }
3965   tc->type = CT_COMMUNICATOR;
3966   size = ntohs (cam->header.size) - sizeof(*cam);
3967   if (0 == size)
3968     return GNUNET_OK; /* receive-only communicator */
3969   GNUNET_MQ_check_zero_termination (cam);
3970   return GNUNET_OK;
3971 }
3972
3973
3974 /**
3975  * Send ACK to communicator (if requested) and free @a cmc.
3976  *
3977  * @param cmc context for which we are done handling the message
3978  */
3979 static void
3980 finish_cmc_handling (struct CommunicatorMessageContext *cmc)
3981 {
3982   if (0 != ntohl (cmc->im.fc_on))
3983   {
3984     /* send ACK when done to communicator for flow control! */
3985     struct GNUNET_MQ_Envelope *env;
3986     struct GNUNET_TRANSPORT_IncomingMessageAck *ack;
3987
3988     env = GNUNET_MQ_msg (ack, GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG_ACK);
3989     ack->reserved = htonl (0);
3990     ack->fc_id = cmc->im.fc_id;
3991     ack->sender = cmc->im.sender;
3992     GNUNET_MQ_send (cmc->tc->mq, env);
3993   }
3994   GNUNET_SERVICE_client_continue (cmc->tc->client);
3995   GNUNET_free (cmc);
3996 }
3997
3998
3999 /**
4000  * Client confirms that it is done handling message(s) to a particular
4001  * peer. We may now provide more messages to CORE for this peer.
4002  *
4003  * Notifies the respective queues that more messages can now be received.
4004  *
4005  * @param cls the client
4006  * @param rom the message that was sent
4007  */
4008 static void
4009 handle_client_recv_ok (void *cls, const struct RecvOkMessage *rom)
4010 {
4011   struct TransportClient *tc = cls;
4012   struct VirtualLink *vl;
4013   uint32_t delta;
4014   struct CommunicatorMessageContext *cmc;
4015
4016   if (CT_CORE != tc->type)
4017   {
4018     GNUNET_break (0);
4019     GNUNET_SERVICE_client_drop (tc->client);
4020     return;
4021   }
4022   vl = lookup_virtual_link (&rom->peer);
4023   if (NULL == vl)
4024   {
4025     GNUNET_STATISTICS_update (GST_stats,
4026                               "# RECV_OK dropped: virtual link unknown",
4027                               1,
4028                               GNUNET_NO);
4029     GNUNET_SERVICE_client_continue (tc->client);
4030     return;
4031   }
4032   delta = ntohl (rom->increase_window_delta);
4033   vl->core_recv_window += delta;
4034   if (vl->core_recv_window <= 0)
4035     return;
4036   /* resume communicators */
4037   while (NULL != (cmc = vl->cmc_tail))
4038   {
4039     GNUNET_CONTAINER_DLL_remove (vl->cmc_head, vl->cmc_tail, cmc);
4040     finish_cmc_handling (cmc);
4041   }
4042 }
4043
4044
4045 /**
4046  * Communicator started.  Process the request.
4047  *
4048  * @param cls the client
4049  * @param cam the send message that was sent
4050  */
4051 static void
4052 handle_communicator_available (
4053   void *cls,
4054   const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
4055 {
4056   struct TransportClient *tc = cls;
4057   uint16_t size;
4058
4059   size = ntohs (cam->header.size) - sizeof(*cam);
4060   if (0 == size)
4061   {
4062     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4063                 "Receive-only communicator connected\n");
4064     return;   /* receive-only communicator */
4065   }
4066   tc->details.communicator.address_prefix =
4067     GNUNET_strdup ((const char *) &cam[1]);
4068   tc->details.communicator.cc =
4069     (enum GNUNET_TRANSPORT_CommunicatorCharacteristics) ntohl (cam->cc);
4070   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4071               "Communicator with prefix `%s' connected\n",
4072               tc->details.communicator.address_prefix);
4073   GNUNET_SERVICE_client_continue (tc->client);
4074 }
4075
4076
4077 /**
4078  * Communicator requests backchannel transmission.  Check the request.
4079  *
4080  * @param cls the client
4081  * @param cb the send message that was sent
4082  * @return #GNUNET_OK if message is well-formed
4083  */
4084 static int
4085 check_communicator_backchannel (
4086   void *cls,
4087   const struct GNUNET_TRANSPORT_CommunicatorBackchannel *cb)
4088 {
4089   const struct GNUNET_MessageHeader *inbox;
4090   const char *is;
4091   uint16_t msize;
4092   uint16_t isize;
4093
4094   (void) cls;
4095   msize = ntohs (cb->header.size) - sizeof(*cb);
4096   inbox = (const struct GNUNET_MessageHeader *) &cb[1];
4097   isize = ntohs (inbox->size);
4098   if (isize >= msize)
4099   {
4100     GNUNET_break (0);
4101     return GNUNET_SYSERR;
4102   }
4103   is = (const char *) inbox;
4104   is += isize;
4105   msize -= isize;
4106   GNUNET_assert (0 < msize);
4107   if ('\0' != is[msize - 1])
4108   {
4109     GNUNET_break (0);
4110     return GNUNET_SYSERR;
4111   }
4112   return GNUNET_OK;
4113 }
4114
4115
4116 /**
4117  * Ensure ephemeral keys in our @a dv are current. If no current one exists,
4118  * set it up.
4119  *
4120  * @param dv[in,out] virtual link to update ephemeral for
4121  */
4122 static void
4123 update_ephemeral (struct DistanceVector *dv)
4124 {
4125   struct EphemeralConfirmationPS ec;
4126
4127   if (0 !=
4128       GNUNET_TIME_absolute_get_remaining (dv->ephemeral_validity).rel_value_us)
4129     return;
4130   dv->monotime = GNUNET_TIME_absolute_get_monotonic (GST_cfg);
4131   dv->ephemeral_validity =
4132     GNUNET_TIME_absolute_add (dv->monotime, EPHEMERAL_VALIDITY);
4133   GNUNET_CRYPTO_ecdhe_key_create (&dv->private_key);
4134   GNUNET_CRYPTO_ecdhe_key_get_public (&dv->private_key, &dv->ephemeral_key);
4135   ec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL);
4136   ec.purpose.size = htonl (sizeof(ec));
4137   ec.target = dv->target;
4138   ec.ephemeral_key = dv->ephemeral_key;
4139   GNUNET_CRYPTO_eddsa_sign (GST_my_private_key,
4140                             &ec,
4141                             &dv->sender_sig);
4142 }
4143
4144
4145 /**
4146  * Send the message @a payload on @a queue.
4147  *
4148  * @param queue the queue to use for transmission
4149  * @param pm pending message to update once transmission is done, may be NULL!
4150  * @param payload the payload to send (encapsulated in a
4151  *        #GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG).
4152  * @param payload_size number of bytes in @a payload
4153  */
4154 static void
4155 queue_send_msg (struct Queue *queue,
4156                 struct PendingMessage *pm,
4157                 const void *payload,
4158                 size_t payload_size)
4159 {
4160   struct Neighbour *n = queue->neighbour;
4161   struct GNUNET_TRANSPORT_SendMessageTo *smt;
4162   struct GNUNET_MQ_Envelope *env;
4163
4164   queue->idle = GNUNET_NO;
4165   GNUNET_log (
4166     GNUNET_ERROR_TYPE_DEBUG,
4167     "Queueing %u bytes of payload for transmission <%llu> on queue %llu to %s\n",
4168     (unsigned int) payload_size,
4169     (NULL == pm) ? 0 : pm->logging_uuid,
4170     (unsigned long long) queue->qid,
4171     GNUNET_i2s (&queue->neighbour->pid));
4172   env = GNUNET_MQ_msg_extra (smt,
4173                              payload_size,
4174                              GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG);
4175   smt->qid = queue->qid;
4176   smt->mid = queue->mid_gen;
4177   smt->receiver = n->pid;
4178   memcpy (&smt[1], payload, payload_size);
4179   {
4180     /* Pass the env to the communicator of queue for transmission. */
4181     struct QueueEntry *qe;
4182
4183     qe = GNUNET_new (struct QueueEntry);
4184     qe->mid = queue->mid_gen++;
4185     qe->queue = queue;
4186     if (NULL != pm)
4187     {
4188       qe->pm = pm;
4189       GNUNET_assert (NULL == pm->qe);
4190       pm->qe = qe;
4191     }
4192     GNUNET_CONTAINER_DLL_insert (queue->queue_head, queue->queue_tail, qe);
4193     GNUNET_assert (CT_COMMUNICATOR == queue->tc->type);
4194     queue->queue_length++;
4195     queue->tc->details.communicator.total_queue_length++;
4196     if (COMMUNICATOR_TOTAL_QUEUE_LIMIT ==
4197         queue->tc->details.communicator.total_queue_length)
4198       queue->idle = GNUNET_NO;
4199     if (QUEUE_LENGTH_LIMIT == queue->queue_length)
4200       queue->idle = GNUNET_NO;
4201     GNUNET_MQ_send (queue->tc->mq, env);
4202   }
4203 }
4204
4205
4206 /**
4207  * Pick a queue of @a n under constraints @a options and schedule
4208  * transmission of @a hdr.
4209  *
4210  * @param n neighbour to send to
4211  * @param hdr message to send as payload
4212  * @param options whether queues must be confirmed or not,
4213  *        and whether we may pick multiple (2) queues
4214  * @return expected RTT for transmission, #GNUNET_TIME_UNIT_FOREVER_REL if sending failed
4215  */
4216 static struct GNUNET_TIME_Relative
4217 route_via_neighbour (const struct Neighbour *n,
4218                      const struct GNUNET_MessageHeader *hdr,
4219                      enum RouteMessageOptions options)
4220 {
4221   struct GNUNET_TIME_Absolute now;
4222   unsigned int candidates;
4223   unsigned int sel1;
4224   unsigned int sel2;
4225   struct GNUNET_TIME_Relative rtt;
4226
4227   /* Pick one or two 'random' queues from n (under constraints of options) */
4228   now = GNUNET_TIME_absolute_get ();
4229   /* FIXME-OPTIMIZE: give queues 'weights' and pick proportional to
4230      weight in the future; weight could be assigned by observed
4231      bandwidth (note: not sure if we should do this for this type
4232      of control traffic though). */
4233   candidates = 0;
4234   for (struct Queue *pos = n->queue_head; NULL != pos;
4235        pos = pos->next_neighbour)
4236   {
4237     if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) ||
4238         (pos->validated_until.abs_value_us > now.abs_value_us))
4239       candidates++;
4240   }
4241   if (0 == candidates)
4242   {
4243     /* This can happen rarely if the last confirmed queue timed
4244        out just as we were beginning to process this message. */
4245     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
4246                 "Could not route message of type %u to %s: no valid queue\n",
4247                 ntohs (hdr->type),
4248                 GNUNET_i2s (&n->pid));
4249     GNUNET_STATISTICS_update (GST_stats,
4250                               "# route selection failed (all no valid queue)",
4251                               1,
4252                               GNUNET_NO);
4253     return GNUNET_TIME_UNIT_FOREVER_REL;
4254   }
4255
4256   rtt = GNUNET_TIME_UNIT_FOREVER_REL;
4257   sel1 = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, candidates);
4258   if (0 == (options & RMO_REDUNDANT))
4259     sel2 = candidates; /* picks none! */
4260   else
4261     sel2 = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, candidates);
4262   candidates = 0;
4263   for (struct Queue *pos = n->queue_head; NULL != pos;
4264        pos = pos->next_neighbour)
4265   {
4266     if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) ||
4267         (pos->validated_until.abs_value_us > now.abs_value_us))
4268     {
4269       if ((sel1 == candidates) || (sel2 == candidates))
4270       {
4271         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4272                     "Routing message of type %u to %s using %s (#%u)\n",
4273                     ntohs (hdr->type),
4274                     GNUNET_i2s (&n->pid),
4275                     pos->address,
4276                     (sel1 == candidates) ? 1 : 2);
4277         rtt = GNUNET_TIME_relative_min (rtt, pos->pd.aged_rtt);
4278         queue_send_msg (pos, NULL, hdr, ntohs (hdr->size));
4279       }
4280       candidates++;
4281     }
4282   }
4283   return rtt;
4284 }
4285
4286
4287 /**
4288  * Structure of the key material used to encrypt backchannel messages.
4289  */
4290 struct DVKeyState
4291 {
4292   /**
4293    * State of our block cipher.
4294    */
4295   gcry_cipher_hd_t cipher;
4296
4297   /**
4298    * Actual key material.
4299    */
4300   struct
4301   {
4302     /**
4303      * Key used for HMAC calculations (via #GNUNET_CRYPTO_hmac()).
4304      */
4305     struct GNUNET_CRYPTO_AuthKey hmac_key;
4306
4307     /**
4308      * Symmetric key to use for encryption.
4309      */
4310     char aes_key[256 / 8];
4311
4312     /**
4313      * Counter value to use during setup.
4314      */
4315     char aes_ctr[128 / 8];
4316   } material;
4317 };
4318
4319
4320 /**
4321  * Given the key material in @a km and the initialization vector
4322  * @a iv, setup the key material for the backchannel in @a key.
4323  *
4324  * @param km raw master secret
4325  * @param iv initialization vector
4326  * @param key[out] symmetric cipher and HMAC state to generate
4327  */
4328 static void
4329 dv_setup_key_state_from_km (const struct GNUNET_HashCode *km,
4330                             const struct GNUNET_ShortHashCode *iv,
4331                             struct DVKeyState *key)
4332 {
4333   /* must match #dh_key_derive_eph_pub */
4334   GNUNET_assert (GNUNET_YES ==
4335                  GNUNET_CRYPTO_kdf (&key->material,
4336                                     sizeof(key->material),
4337                                     "transport-backchannel-key",
4338                                     strlen ("transport-backchannel-key"),
4339                                     &km,
4340                                     sizeof(km),
4341                                     iv,
4342                                     sizeof(*iv)));
4343   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4344               "Deriving backchannel key based on KM %s and IV %s\n",
4345               GNUNET_h2s (km),
4346               GNUNET_sh2s (iv));
4347   gcry_cipher_open (&key->cipher,
4348                     GCRY_CIPHER_AES256 /* low level: go for speed */,
4349                     GCRY_CIPHER_MODE_CTR,
4350                     0 /* flags */);
4351   gcry_cipher_setkey (key->cipher,
4352                       &key->material.aes_key,
4353                       sizeof(key->material.aes_key));
4354   gcry_cipher_setctr (key->cipher,
4355                       &key->material.aes_ctr,
4356                       sizeof(key->material.aes_ctr));
4357 }
4358
4359
4360 /**
4361  * Derive backchannel encryption key material from @a priv_ephemeral
4362  * and @a target and @a iv.
4363  *
4364  * @param priv_ephemeral ephemeral private key to use
4365  * @param target the target peer to encrypt to
4366  * @param iv unique IV to use
4367  * @param key[out] set to the key material
4368  */
4369 static void
4370 dh_key_derive_eph_pid (
4371   const struct GNUNET_CRYPTO_EcdhePrivateKey *priv_ephemeral,
4372   const struct GNUNET_PeerIdentity *target,
4373   const struct GNUNET_ShortHashCode *iv,
4374   struct DVKeyState *key)
4375 {
4376   struct GNUNET_HashCode km;
4377
4378   GNUNET_assert (GNUNET_YES == GNUNET_CRYPTO_ecdh_eddsa (priv_ephemeral,
4379                                                          &target->public_key,
4380                                                          &km));
4381   dv_setup_key_state_from_km (&km, iv, key);
4382 }
4383
4384
4385 /**
4386  * Derive backchannel encryption key material from #GST_my_private_key
4387  * and @a pub_ephemeral and @a iv.
4388  *
4389  * @param priv_ephemeral ephemeral private key to use
4390  * @param target the target peer to encrypt to
4391  * @param iv unique IV to use
4392  * @param key[out] set to the key material
4393  */
4394 static void
4395 dh_key_derive_eph_pub (const struct GNUNET_CRYPTO_EcdhePublicKey *pub_ephemeral,
4396                        const struct GNUNET_ShortHashCode *iv,
4397                        struct DVKeyState *key)
4398 {
4399   struct GNUNET_HashCode km;
4400
4401   GNUNET_assert (GNUNET_YES == GNUNET_CRYPTO_eddsa_ecdh (GST_my_private_key,
4402                                                          pub_ephemeral,
4403                                                          &km));
4404   dv_setup_key_state_from_km (&km, iv, key);
4405 }
4406
4407
4408 /**
4409  * Do HMAC calculation for backchannel messages over @a data using key
4410  * material from @a key.
4411  *
4412  * @param key key material (from DH)
4413  * @param hmac[out] set to the HMAC
4414  * @param data data to perform HMAC calculation over
4415  * @param data_size number of bytes in @a data
4416  */
4417 static void
4418 dv_hmac (const struct DVKeyState *key,
4419          struct GNUNET_HashCode *hmac,
4420          const void *data,
4421          size_t data_size)
4422 {
4423   GNUNET_CRYPTO_hmac (&key->material.hmac_key, data, data_size, hmac);
4424 }
4425
4426
4427 /**
4428  * Perform backchannel encryption using symmetric secret in @a key
4429  * to encrypt data from @a in to @a dst.
4430  *
4431  * @param key[in,out] key material to use
4432  * @param dst where to write the result
4433  * @param in input data to encrypt (plaintext)
4434  * @param in_size number of bytes of input in @a in and available at @a dst
4435  */
4436 static void
4437 dv_encrypt (struct DVKeyState *key, const void *in, void *dst, size_t in_size)
4438 {
4439   GNUNET_assert (0 ==
4440                  gcry_cipher_encrypt (key->cipher, dst, in_size, in, in_size));
4441 }
4442
4443
4444 /**
4445  * Perform backchannel encryption using symmetric secret in @a key
4446  * to encrypt data from @a in to @a dst.
4447  *
4448  * @param key[in,out] key material to use
4449  * @param ciph cipher text to decrypt
4450  * @param out[out] output data to generate (plaintext)
4451  * @param out_size number of bytes of input in @a ciph and available in @a out
4452  */
4453 static void
4454 dv_decrypt (struct DVKeyState *key,
4455             void *out,
4456             const void *ciph,
4457             size_t out_size)
4458 {
4459   GNUNET_assert (
4460     0 == gcry_cipher_decrypt (key->cipher, out, out_size, ciph, out_size));
4461 }
4462
4463
4464 /**
4465  * Clean up key material in @a key.
4466  *
4467  * @param key key material to clean up (memory must not be free'd!)
4468  */
4469 static void
4470 dv_key_clean (struct DVKeyState *key)
4471 {
4472   gcry_cipher_close (key->cipher);
4473   GNUNET_CRYPTO_zero_keys (&key->material, sizeof(key->material));
4474 }
4475
4476
4477 /**
4478  * Function to call to further operate on the now DV encapsulated
4479  * message @a hdr, forwarding it via @a next_hop under respect of
4480  * @a options.
4481  *
4482  * @param cls closure
4483  * @param next_hop next hop of the DV path
4484  * @param hdr encapsulated message, technically a `struct TransportDFBoxMessage`
4485  * @param options options of the original message
4486  */
4487 typedef void (*DVMessageHandler) (void *cls,
4488                                   struct Neighbour *next_hop,
4489                                   const struct GNUNET_MessageHeader *hdr,
4490                                   enum RouteMessageOptions options);
4491
4492 /**
4493  * Pick a path of @a dv under constraints @a options and schedule
4494  * transmission of @a hdr.
4495  *
4496  * @param target neighbour to ultimately send to
4497  * @param num_dvhs length of the @a dvhs array
4498  * @param dvhs array of hops to send the message to
4499  * @param hdr message to send as payload
4500  * @param use function to call with the encapsulated message
4501  * @param use_cls closure for @a use
4502  * @param options whether path must be confirmed or not, to be passed to @a use
4503  * @return expected RTT for transmission, #GNUNET_TIME_UNIT_FOREVER_REL if sending failed
4504  */
4505 static struct GNUNET_TIME_Relative
4506 encapsulate_for_dv (struct DistanceVector *dv,
4507                     unsigned int num_dvhs,
4508                     struct DistanceVectorHop **dvhs,
4509                     const struct GNUNET_MessageHeader *hdr,
4510                     DVMessageHandler use,
4511                     void *use_cls,
4512                     enum RouteMessageOptions options)
4513 {
4514   struct TransportDVBoxMessage box_hdr;
4515   struct TransportDVBoxPayloadP payload_hdr;
4516   uint16_t enc_body_size = ntohs (hdr->size);
4517   char enc[sizeof(struct TransportDVBoxPayloadP) + enc_body_size] GNUNET_ALIGN;
4518   struct TransportDVBoxPayloadP *enc_payload_hdr =
4519     (struct TransportDVBoxPayloadP *) enc;
4520   struct DVKeyState key;
4521   struct GNUNET_TIME_Relative rtt;
4522
4523   /* Encrypt payload */
4524   box_hdr.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX);
4525   box_hdr.total_hops = htons (0);
4526   update_ephemeral (dv);
4527   box_hdr.ephemeral_key = dv->ephemeral_key;
4528   payload_hdr.sender_sig = dv->sender_sig;
4529   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
4530                               &box_hdr.iv,
4531                               sizeof(box_hdr.iv));
4532   dh_key_derive_eph_pid (&dv->private_key, &dv->target, &box_hdr.iv, &key);
4533   payload_hdr.sender = GST_my_identity;
4534   payload_hdr.monotonic_time = GNUNET_TIME_absolute_hton (dv->monotime);
4535   dv_encrypt (&key, &payload_hdr, enc_payload_hdr, sizeof(payload_hdr));
4536   dv_encrypt (&key,
4537               hdr,
4538               &enc[sizeof(struct TransportDVBoxPayloadP)],
4539               enc_body_size);
4540   dv_hmac (&key, &box_hdr.hmac, enc, sizeof(enc));
4541   dv_key_clean (&key);
4542   rtt = GNUNET_TIME_UNIT_FOREVER_REL;
4543   /* For each selected path, take the pre-computed header and body
4544      and add the path in the middle of the message; then send it. */
4545   for (unsigned int i = 0; i < num_dvhs; i++)
4546   {
4547     struct DistanceVectorHop *dvh = dvhs[i];
4548     unsigned int num_hops = dvh->distance + 1;
4549     char buf[sizeof(struct TransportDVBoxMessage)
4550              + sizeof(struct GNUNET_PeerIdentity) * num_hops
4551              + sizeof(struct TransportDVBoxPayloadP)
4552              + enc_body_size] GNUNET_ALIGN;
4553     struct GNUNET_PeerIdentity *dhops;
4554
4555     box_hdr.header.size = htons (sizeof(buf));
4556     box_hdr.num_hops = htons (num_hops);
4557     memcpy (buf, &box_hdr, sizeof(box_hdr));
4558     dhops = (struct GNUNET_PeerIdentity *) &buf[sizeof(box_hdr)];
4559     memcpy (dhops,
4560             dvh->path,
4561             dvh->distance * sizeof(struct GNUNET_PeerIdentity));
4562     dhops[dvh->distance] = dv->target;
4563     if (GNUNET_EXTRA_LOGGING > 0)
4564     {
4565       char *path;
4566
4567       path = GNUNET_strdup (GNUNET_i2s (&GST_my_identity));
4568       for (unsigned int j = 0; j <= num_hops; j++)
4569       {
4570         char *tmp;
4571
4572         GNUNET_asprintf (&tmp, "%s-%s", path, GNUNET_i2s (&dhops[j]));
4573         GNUNET_free (path);
4574         path = tmp;
4575       }
4576       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4577                   "Routing message of type %u to %s using DV (#%u/%u) via %s\n",
4578                   ntohs (hdr->type),
4579                   GNUNET_i2s (&dv->target),
4580                   i + 1,
4581                   num_dvhs + 1,
4582                   path);
4583       GNUNET_free (path);
4584     }
4585     rtt = GNUNET_TIME_relative_min (rtt, dvh->pd.aged_rtt);
4586     memcpy (&dhops[num_hops], enc, sizeof(enc));
4587     use (use_cls,
4588          dvh->next_hop,
4589          (const struct GNUNET_MessageHeader *) buf,
4590          options);
4591   }
4592   return rtt;
4593 }
4594
4595
4596 /**
4597  * Wrapper around #route_via_neighbour() that matches the
4598  * #DVMessageHandler structure.
4599  *
4600  * @param cls unused
4601  * @param next_hop where to send next
4602  * @param hdr header of the message to send
4603  * @param options message options for queue selection
4604  */
4605 static void
4606 send_dv_to_neighbour (void *cls,
4607                       struct Neighbour *next_hop,
4608                       const struct GNUNET_MessageHeader *hdr,
4609                       enum RouteMessageOptions options)
4610 {
4611   (void) cls;
4612   (void) route_via_neighbour (next_hop, hdr, options);
4613 }
4614
4615
4616 /**
4617  * We need to transmit @a hdr to @a target.  If necessary, this may
4618  * involve DV routing.  This function routes without applying flow
4619  * control or congestion control and should only be used for control
4620  * traffic.
4621  *
4622  * @param target peer to receive @a hdr
4623  * @param hdr header of the message to route and #GNUNET_free()
4624  * @param options which transmission channels are allowed
4625  * @return expected RTT for transmission, #GNUNET_TIME_UNIT_FOREVER_REL if sending failed
4626  */
4627 static struct GNUNET_TIME_Relative
4628 route_control_message_without_fc (const struct GNUNET_PeerIdentity *target,
4629                                   const struct GNUNET_MessageHeader *hdr,
4630                                   enum RouteMessageOptions options)
4631 {
4632   struct VirtualLink *vl;
4633   struct Neighbour *n;
4634   struct DistanceVector *dv;
4635   struct GNUNET_TIME_Relative rtt1;
4636   struct GNUNET_TIME_Relative rtt2;
4637
4638   vl = lookup_virtual_link (target);
4639   GNUNET_assert (NULL != vl);
4640   n = vl->n;
4641   dv = (0 != (options & RMO_DV_ALLOWED)) ? vl->dv : NULL;
4642   if (0 == (options & RMO_UNCONFIRMED_ALLOWED))
4643   {
4644     /* if confirmed is required, and we do not have anything
4645        confirmed, drop respective options */
4646     if (NULL == n)
4647       n = lookup_neighbour (target);
4648     if ((NULL == dv) && (0 != (options & RMO_DV_ALLOWED)))
4649       dv = GNUNET_CONTAINER_multipeermap_get (dv_routes, target);
4650   }
4651   if ((NULL == n) && (NULL == dv))
4652   {
4653     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
4654                 "Cannot route message of type %u to %s: no route\n",
4655                 ntohs (hdr->type),
4656                 GNUNET_i2s (target));
4657     GNUNET_STATISTICS_update (GST_stats,
4658                               "# Messages dropped in routing: no acceptable method",
4659                               1,
4660                               GNUNET_NO);
4661     return GNUNET_TIME_UNIT_FOREVER_REL;
4662   }
4663   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4664               "Routing message of type %u to %s with options %X\n",
4665               ntohs (hdr->type),
4666               GNUNET_i2s (target),
4667               (unsigned int) options);
4668   /* If both dv and n are possible and we must choose:
4669      flip a coin for the choice between the two; for now 50/50 */
4670   if ((NULL != n) && (NULL != dv) && (0 == (options & RMO_REDUNDANT)))
4671   {
4672     if (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 2))
4673       n = NULL;
4674     else
4675       dv = NULL;
4676   }
4677   if ((NULL != n) && (NULL != dv))
4678     options &= ~RMO_REDUNDANT; /* We will do one DV and one direct, that's
4679                                   enough for redunancy, so clear the flag. */
4680   rtt1 = GNUNET_TIME_UNIT_FOREVER_REL;
4681   rtt2 = GNUNET_TIME_UNIT_FOREVER_REL;
4682   if (NULL != n)
4683   {
4684     rtt1 = route_via_neighbour (n, hdr, options);
4685   }
4686   if (NULL != dv)
4687   {
4688     struct DistanceVectorHop *hops[2];
4689     unsigned int res;
4690
4691     res = pick_random_dv_hops (dv,
4692                                options,
4693                                hops,
4694                                (0 == (options & RMO_REDUNDANT)) ? 1 : 2);
4695     if (0 == res)
4696     {
4697       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
4698                   "Failed to route message, could not determine DV path\n");
4699       return rtt1;
4700     }
4701     rtt2 = encapsulate_for_dv (dv,
4702                                res,
4703                                hops,
4704                                hdr,
4705                                &send_dv_to_neighbour,
4706                                NULL,
4707                                options & (~RMO_REDUNDANT));
4708   }
4709   return GNUNET_TIME_relative_min (rtt1, rtt2);
4710 }
4711
4712
4713 /**
4714  * Something changed on the virtual link with respect to flow
4715  * control. Consider retransmitting the FC window size.
4716  *
4717  * @param cls a `struct VirtualLink` to work with
4718  */
4719 static void
4720 consider_sending_fc (void *cls)
4721 {
4722   struct VirtualLink *vl = cls;
4723   struct GNUNET_TIME_Absolute monotime;
4724   struct TransportFlowControlMessage fc;
4725   struct GNUNET_TIME_Relative duration;
4726   struct GNUNET_TIME_Relative rtt;
4727
4728   duration = GNUNET_TIME_absolute_get_duration (vl->last_fc_transmission);
4729   /* OPTIMIZE-FC-BDP: decide sane criteria on when to do this, instead of doing
4730      it always! */
4731   /* For example, we should probably ONLY do this if a bit more than
4732      an RTT has passed, or if the window changed "significantly" since
4733      then. See vl->last_fc_rtt! NOTE: to do this properly, we also
4734      need an estimate for the bandwidth-delay-product for the entire
4735      VL, as that determines "significantly". We have the delay, but
4736      the bandwidth statistics need to be added for the VL!*/(void) duration;
4737
4738   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4739               "Sending FC seq %u to %s with new window %llu\n",
4740               (unsigned int) vl->fc_seq_gen,
4741               GNUNET_i2s (&vl->target),
4742               (unsigned long long) vl->incoming_fc_window_size);
4743   monotime = GNUNET_TIME_absolute_get_monotonic (GST_cfg);
4744   vl->last_fc_transmission = monotime;
4745   fc.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_FLOW_CONTROL);
4746   fc.header.size = htons (sizeof(fc));
4747   fc.seq = htonl (vl->fc_seq_gen++);
4748   fc.inbound_window_size = GNUNET_htonll (vl->incoming_fc_window_size);
4749   fc.outbound_sent = GNUNET_htonll (vl->outbound_fc_window_size_used);
4750   fc.outbound_window_size = GNUNET_htonll (vl->outbound_fc_window_size);
4751   fc.sender_time = GNUNET_TIME_absolute_hton (monotime);
4752   rtt = route_control_message_without_fc (&vl->target, &fc.header, RMO_NONE);
4753   if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == rtt.rel_value_us)
4754   {
4755     rtt = GNUNET_TIME_UNIT_SECONDS;
4756     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4757                 "FC retransmission to %s failed, will retry in %s\n",
4758                 GNUNET_i2s (&vl->target),
4759                 GNUNET_STRINGS_relative_time_to_string (rtt, GNUNET_YES));
4760     vl->last_fc_rtt = GNUNET_TIME_UNIT_ZERO;
4761   }
4762   else
4763   {
4764     /* OPTIMIZE-FC-BDP: rtt is not ideal, we can do better! */
4765     vl->last_fc_rtt = rtt;
4766   }
4767   if (NULL != vl->fc_retransmit_task)
4768     GNUNET_SCHEDULER_cancel (vl->fc_retransmit_task);
4769   vl->fc_retransmit_task =
4770     GNUNET_SCHEDULER_add_delayed (rtt, &consider_sending_fc, vl);
4771 }
4772
4773
4774 /**
4775  * There is a message at the head of the pending messages for @a vl
4776  * which may be ready for transmission. Check if a queue is ready to
4777  * take it.
4778  *
4779  * This function must (1) check for flow control to ensure that we can
4780  * right now send to @a vl, (2) check that the pending message in the
4781  * queue is actually eligible, (3) determine if any applicable queue
4782  * (direct neighbour or DVH path) is ready to accept messages, and
4783  * (4) prioritize based on the preferences associated with the
4784  * pending message.
4785  *
4786  * So yeah, easy.
4787  *
4788  * @param vl virtual link where we should check for transmission
4789  */
4790 static void
4791 check_vl_transmission (struct VirtualLink *vl)
4792 {
4793   struct Neighbour *n = vl->n;
4794   struct DistanceVector *dv = vl->dv;
4795   struct GNUNET_TIME_Absolute now;
4796   int elig;
4797
4798   /* Check that we have an eligible pending message!
4799      (cheaper than having #transmit_on_queue() find out!) */
4800   elig = GNUNET_NO;
4801   for (struct PendingMessage *pm = vl->pending_msg_head; NULL != pm;
4802        pm = pm->next_vl)
4803   {
4804     if (NULL != pm->qe)
4805       continue;   /* not eligible, is in a queue! */
4806     if (pm->bytes_msg + vl->outbound_fc_window_size_used >
4807         vl->outbound_fc_window_size)
4808     {
4809       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4810                   "Stalled transmision on VL %s due to flow control: %llu < %llu\n",
4811                   GNUNET_i2s (&vl->target),
4812                   (unsigned long long) vl->outbound_fc_window_size,
4813                   (unsigned long long) (pm->bytes_msg
4814                                         + vl->outbound_fc_window_size_used));
4815       consider_sending_fc (vl);
4816       return;     /* We have a message, but flow control says "nope" */
4817     }
4818     elig = GNUNET_YES;
4819     break;
4820   }
4821   if (GNUNET_NO == elig)
4822     return;
4823
4824   /* Notify queues at direct neighbours that we are interested */
4825   now = GNUNET_TIME_absolute_get ();
4826   if (NULL != n)
4827   {
4828     for (struct Queue *queue = n->queue_head; NULL != queue;
4829          queue = queue->next_neighbour)
4830       if ((GNUNET_YES == queue->idle) &&
4831           (queue->validated_until.abs_value_us > now.abs_value_us))
4832         schedule_transmit_on_queue (queue, GNUNET_SCHEDULER_PRIORITY_DEFAULT);
4833   }
4834   /* Notify queues via DV that we are interested */
4835   if (NULL != dv)
4836   {
4837     /* Do DV with lower scheduler priority, which effectively means that
4838        IF a neighbour exists and is available, we prefer it. */
4839     for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
4840          pos = pos->next_dv)
4841     {
4842       struct Neighbour *nh = pos->next_hop;
4843
4844       if (pos->path_valid_until.abs_value_us <= now.abs_value_us)
4845         continue;     /* skip this one: path not validated */
4846       for (struct Queue *queue = nh->queue_head; NULL != queue;
4847            queue = queue->next_neighbour)
4848         if ((GNUNET_YES == queue->idle) &&
4849             (queue->validated_until.abs_value_us > now.abs_value_us))
4850           schedule_transmit_on_queue (queue,
4851                                       GNUNET_SCHEDULER_PRIORITY_BACKGROUND);
4852     }
4853   }
4854 }
4855
4856
4857 /**
4858  * Client asked for transmission to a peer.  Process the request.
4859  *
4860  * @param cls the client
4861  * @param obm the send message that was sent
4862  */
4863 static void
4864 handle_client_send (void *cls, const struct OutboundMessage *obm)
4865 {
4866   struct TransportClient *tc = cls;
4867   struct PendingMessage *pm;
4868   const struct GNUNET_MessageHeader *obmm;
4869   uint32_t bytes_msg;
4870   struct VirtualLink *vl;
4871   enum GNUNET_MQ_PriorityPreferences pp;
4872
4873   GNUNET_assert (CT_CORE == tc->type);
4874   obmm = (const struct GNUNET_MessageHeader *) &obm[1];
4875   bytes_msg = ntohs (obmm->size);
4876   pp = (enum GNUNET_MQ_PriorityPreferences) ntohl (obm->priority);
4877   vl = lookup_virtual_link (&obm->peer);
4878   if (NULL == vl)
4879   {
4880     /* Failure: don't have this peer as a neighbour (anymore).
4881        Might have gone down asynchronously, so this is NOT
4882        a protocol violation by CORE. Still count the event,
4883        as this should be rare. */
4884     GNUNET_SERVICE_client_continue (tc->client);
4885     GNUNET_STATISTICS_update (GST_stats,
4886                               "# messages dropped (neighbour unknown)",
4887                               1,
4888                               GNUNET_NO);
4889     return;
4890   }
4891
4892   pm = GNUNET_malloc (sizeof(struct PendingMessage) + bytes_msg);
4893   pm->logging_uuid = logging_uuid_gen++;
4894   pm->prefs = pp;
4895   pm->client = tc;
4896   pm->vl = vl;
4897   pm->bytes_msg = bytes_msg;
4898   memcpy (&pm[1], obmm, bytes_msg);
4899   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4900               "Sending %u bytes as <%llu> to %s\n",
4901               bytes_msg,
4902               pm->logging_uuid,
4903               GNUNET_i2s (&obm->peer));
4904   GNUNET_CONTAINER_MDLL_insert (client,
4905                                 tc->details.core.pending_msg_head,
4906                                 tc->details.core.pending_msg_tail,
4907                                 pm);
4908   GNUNET_CONTAINER_MDLL_insert (vl,
4909                                 vl->pending_msg_head,
4910                                 vl->pending_msg_tail,
4911                                 pm);
4912   check_vl_transmission (vl);
4913 }
4914
4915
4916 /**
4917  * Communicator requests backchannel transmission.  Process the request.
4918  * Just repacks it into our `struct TransportBackchannelEncapsulationMessage *`
4919  * (which for now has exactly the same format, only a different message type)
4920  * and passes it on for routing.
4921  *
4922  * @param cls the client
4923  * @param cb the send message that was sent
4924  */
4925 static void
4926 handle_communicator_backchannel (
4927   void *cls,
4928   const struct GNUNET_TRANSPORT_CommunicatorBackchannel *cb)
4929 {
4930   struct TransportClient *tc = cls;
4931   const struct GNUNET_MessageHeader *inbox =
4932     (const struct GNUNET_MessageHeader *) &cb[1];
4933   uint16_t isize = ntohs (inbox->size);
4934   const char *is = ((const char *) &cb[1]) + isize;
4935   char
4936     mbuf[isize
4937          + sizeof(struct
4938                   TransportBackchannelEncapsulationMessage)] GNUNET_ALIGN;
4939   struct TransportBackchannelEncapsulationMessage *be =
4940     (struct TransportBackchannelEncapsulationMessage *) mbuf;
4941
4942   /* 0-termination of 'is' was checked already in
4943    #check_communicator_backchannel() */
4944   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4945               "Preparing backchannel transmission to %s:%s of type %u\n",
4946               GNUNET_i2s (&cb->pid),
4947               is,
4948               ntohs (inbox->size));
4949   /* encapsulate and encrypt message */
4950   be->header.type =
4951     htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION);
4952   be->header.size = htons (sizeof(mbuf));
4953   memcpy (&be[1], inbox, isize);
4954   memcpy (&mbuf[sizeof(struct TransportBackchannelEncapsulationMessage)
4955                 + isize],
4956           is,
4957           strlen (is) + 1);
4958   route_control_message_without_fc (&cb->pid, &be->header, RMO_DV_ALLOWED);
4959   GNUNET_SERVICE_client_continue (tc->client);
4960 }
4961
4962
4963 /**
4964  * Address of our peer added.  Test message is well-formed.
4965  *
4966  * @param cls the client
4967  * @param aam the send message that was sent
4968  * @return #GNUNET_OK if message is well-formed
4969  */
4970 static int
4971 check_add_address (void *cls,
4972                    const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
4973 {
4974   struct TransportClient *tc = cls;
4975
4976   if (CT_COMMUNICATOR != tc->type)
4977   {
4978     GNUNET_break (0);
4979     return GNUNET_SYSERR;
4980   }
4981   GNUNET_MQ_check_zero_termination (aam);
4982   return GNUNET_OK;
4983 }
4984
4985
4986 /**
4987  * Ask peerstore to store our address.
4988  *
4989  * @param cls an `struct AddressListEntry *`
4990  */
4991 static void
4992 store_pi (void *cls);
4993
4994
4995 /**
4996  * Function called when peerstore is done storing our address.
4997  *
4998  * @param cls a `struct AddressListEntry`
4999  * @param success #GNUNET_YES if peerstore was successful
5000  */
5001 static void
5002 peerstore_store_own_cb (void *cls, int success)
5003 {
5004   struct AddressListEntry *ale = cls;
5005
5006   ale->sc = NULL;
5007   if (GNUNET_YES != success)
5008     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
5009                 "Failed to store our own address `%s' in peerstore!\n",
5010                 ale->address);
5011   else
5012     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5013                 "Successfully stored our own address `%s' in peerstore!\n",
5014                 ale->address);
5015   /* refresh period is 1/4 of expiration time, that should be plenty
5016      without being excessive. */
5017   ale->st =
5018     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide (ale->expiration,
5019                                                                4ULL),
5020                                   &store_pi,
5021                                   ale);
5022 }
5023
5024
5025 /**
5026  * Ask peerstore to store our address.
5027  *
5028  * @param cls an `struct AddressListEntry *`
5029  */
5030 static void
5031 store_pi (void *cls)
5032 {
5033   struct AddressListEntry *ale = cls;
5034   void *addr;
5035   size_t addr_len;
5036   struct GNUNET_TIME_Absolute expiration;
5037
5038   ale->st = NULL;
5039   expiration = GNUNET_TIME_relative_to_absolute (ale->expiration);
5040   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5041               "Storing our address `%s' in peerstore until %s!\n",
5042               ale->address,
5043               GNUNET_STRINGS_absolute_time_to_string (expiration));
5044   GNUNET_HELLO_sign_address (ale->address,
5045                              ale->nt,
5046                              hello_mono_time,
5047                              GST_my_private_key,
5048                              &addr,
5049                              &addr_len);
5050   ale->sc = GNUNET_PEERSTORE_store (peerstore,
5051                                     "transport",
5052                                     &GST_my_identity,
5053                                     GNUNET_PEERSTORE_TRANSPORT_HELLO_KEY,
5054                                     addr,
5055                                     addr_len,
5056                                     expiration,
5057                                     GNUNET_PEERSTORE_STOREOPTION_MULTIPLE,
5058                                     &peerstore_store_own_cb,
5059                                     ale);
5060   GNUNET_free (addr);
5061   if (NULL == ale->sc)
5062   {
5063     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
5064                 "Failed to store our address `%s' with peerstore\n",
5065                 ale->address);
5066     ale->st =
5067       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &store_pi, ale);
5068   }
5069 }
5070
5071
5072 /**
5073  * Address of our peer added.  Process the request.
5074  *
5075  * @param cls the client
5076  * @param aam the send message that was sent
5077  */
5078 static void
5079 handle_add_address (void *cls,
5080                     const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
5081 {
5082   struct TransportClient *tc = cls;
5083   struct AddressListEntry *ale;
5084   size_t slen;
5085
5086   /* 0-termination of &aam[1] was checked in #check_add_address */
5087   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5088               "Communicator added address `%s'!\n",
5089               (const char *) &aam[1]);
5090   slen = ntohs (aam->header.size) - sizeof(*aam);
5091   ale = GNUNET_malloc (sizeof(struct AddressListEntry) + slen);
5092   ale->tc = tc;
5093   ale->address = (const char *) &ale[1];
5094   ale->expiration = GNUNET_TIME_relative_ntoh (aam->expiration);
5095   ale->aid = aam->aid;
5096   ale->nt = (enum GNUNET_NetworkType) ntohl (aam->nt);
5097   memcpy (&ale[1], &aam[1], slen);
5098   GNUNET_CONTAINER_DLL_insert (tc->details.communicator.addr_head,
5099                                tc->details.communicator.addr_tail,
5100                                ale);
5101   ale->st = GNUNET_SCHEDULER_add_now (&store_pi, ale);
5102   GNUNET_SERVICE_client_continue (tc->client);
5103 }
5104
5105
5106 /**
5107  * Address of our peer deleted.  Process the request.
5108  *
5109  * @param cls the client
5110  * @param dam the send message that was sent
5111  */
5112 static void
5113 handle_del_address (void *cls,
5114                     const struct GNUNET_TRANSPORT_DelAddressMessage *dam)
5115 {
5116   struct TransportClient *tc = cls;
5117   struct AddressListEntry *alen;
5118
5119   if (CT_COMMUNICATOR != tc->type)
5120   {
5121     GNUNET_break (0);
5122     GNUNET_SERVICE_client_drop (tc->client);
5123     return;
5124   }
5125   for (struct AddressListEntry *ale = tc->details.communicator.addr_head;
5126        NULL != ale;
5127        ale = alen)
5128   {
5129     alen = ale->next;
5130     if (dam->aid != ale->aid)
5131       continue;
5132     GNUNET_assert (ale->tc == tc);
5133     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5134                 "Communicator deleted address `%s'!\n",
5135                 ale->address);
5136     free_address_list_entry (ale);
5137     GNUNET_SERVICE_client_continue (tc->client);
5138   }
5139   GNUNET_break (0);
5140   GNUNET_SERVICE_client_drop (tc->client);
5141 }
5142
5143
5144 /**
5145  * Given an inbound message @a msg from a communicator @a cmc,
5146  * demultiplex it based on the type calling the right handler.
5147  *
5148  * @param cmc context for demultiplexing
5149  * @param msg message to demultiplex
5150  */
5151 static void
5152 demultiplex_with_cmc (struct CommunicatorMessageContext *cmc,
5153                       const struct GNUNET_MessageHeader *msg);
5154
5155
5156 /**
5157  * Function called when we are done giving a message of a certain
5158  * size to CORE and should thus decrement the number of bytes of
5159  * RAM reserved for that peer's MQ.
5160  *
5161  * @param cls a `struct CoreSentContext`
5162  */
5163 static void
5164 core_env_sent_cb (void *cls)
5165 {
5166   struct CoreSentContext *ctx = cls;
5167   struct VirtualLink *vl = ctx->vl;
5168
5169   if (NULL == vl)
5170   {
5171     /* lost the link in the meantime, ignore */
5172     GNUNET_free (ctx);
5173     return;
5174   }
5175   GNUNET_CONTAINER_DLL_remove (vl->csc_head, vl->csc_tail, ctx);
5176   GNUNET_assert (vl->incoming_fc_window_size_ram >= ctx->size);
5177   vl->incoming_fc_window_size_ram -= ctx->size;
5178   vl->incoming_fc_window_size_used += ctx->isize;
5179   consider_sending_fc (vl);
5180   GNUNET_free (ctx);
5181 }
5182
5183
5184 /**
5185  * Communicator gave us an unencapsulated message to pass as-is to
5186  * CORE.  Process the request.
5187  *
5188  * @param cls a `struct CommunicatorMessageContext` (must call
5189  * #finish_cmc_handling() when done)
5190  * @param mh the message that was received
5191  */
5192 static void
5193 handle_raw_message (void *cls, const struct GNUNET_MessageHeader *mh)
5194 {
5195   struct CommunicatorMessageContext *cmc = cls;
5196   struct VirtualLink *vl;
5197   uint16_t size = ntohs (mh->size);
5198   int have_core;
5199
5200   if ((size > UINT16_MAX - sizeof(struct InboundMessage)) ||
5201       (size < sizeof(struct GNUNET_MessageHeader)))
5202   {
5203     struct GNUNET_SERVICE_Client *client = cmc->tc->client;
5204
5205     GNUNET_break (0);
5206     finish_cmc_handling (cmc);
5207     GNUNET_SERVICE_client_drop (client);
5208     return;
5209   }
5210   vl = lookup_virtual_link (&cmc->im.sender);
5211   if (NULL == vl)
5212   {
5213     /* FIXME: sender is giving us messages for CORE but we don't have
5214        the link up yet! I *suspect* this can happen right now (i.e.
5215        sender has verified us, but we didn't verify sender), but if
5216        we pass this on, CORE would be confused (link down, messages
5217        arrive).  We should investigate more if this happens often,
5218        or in a persistent manner, and possibly do "something" about
5219        it. Thus logging as error for now. */GNUNET_break_op (0);
5220     GNUNET_STATISTICS_update (GST_stats,
5221                               "# CORE messages droped (virtual link still down)",
5222                               1,
5223                               GNUNET_NO);
5224
5225     finish_cmc_handling (cmc);
5226     return;
5227   }
5228   if (vl->incoming_fc_window_size_ram > UINT_MAX - size)
5229   {
5230     GNUNET_STATISTICS_update (GST_stats,
5231                               "# CORE messages droped (FC arithmetic overflow)",
5232                               1,
5233                               GNUNET_NO);
5234
5235     finish_cmc_handling (cmc);
5236     return;
5237   }
5238   if (vl->incoming_fc_window_size_ram + size > vl->available_fc_window_size)
5239   {
5240     GNUNET_STATISTICS_update (GST_stats,
5241                               "# CORE messages droped (FC window overflow)",
5242                               1,
5243                               GNUNET_NO);
5244     finish_cmc_handling (cmc);
5245     return;
5246   }
5247
5248   /* Forward to all CORE clients */
5249   have_core = GNUNET_NO;
5250   for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
5251   {
5252     struct GNUNET_MQ_Envelope *env;
5253     struct InboundMessage *im;
5254     struct CoreSentContext *ctx;
5255
5256     if (CT_CORE != tc->type)
5257       continue;
5258     vl->incoming_fc_window_size_ram += size;
5259     env = GNUNET_MQ_msg_extra (im, size, GNUNET_MESSAGE_TYPE_TRANSPORT_RECV);
5260     ctx = GNUNET_new (struct CoreSentContext);
5261     ctx->vl = vl;
5262     ctx->size = size;
5263     ctx->isize = (GNUNET_NO == have_core) ? size : 0;
5264     have_core = GNUNET_YES;
5265     GNUNET_CONTAINER_DLL_insert (vl->csc_head, vl->csc_tail, ctx);
5266     GNUNET_MQ_notify_sent (env, &core_env_sent_cb, ctx);
5267     im->peer = cmc->im.sender;
5268     memcpy (&im[1], mh, size);
5269     GNUNET_MQ_send (tc->mq, env);
5270     vl->core_recv_window--;
5271   }
5272   if (GNUNET_NO == have_core)
5273   {
5274     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
5275                 "Dropped message to CORE: no CORE client connected!\n");
5276     /* Nevertheless, count window as used, as it is from the
5277        perspective of the other peer! */
5278     vl->incoming_fc_window_size_used += size;
5279     /* TODO-M1 */
5280     finish_cmc_handling (cmc);
5281     return;
5282   }
5283   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5284               "Delivered message from %s of type %u to CORE\n",
5285               GNUNET_i2s (&cmc->im.sender),
5286               ntohs (mh->type));
5287   if (vl->core_recv_window > 0)
5288   {
5289     finish_cmc_handling (cmc);
5290     return;
5291   }
5292   /* Wait with calling #finish_cmc_handling(cmc) until the message
5293      was processed by CORE MQs (for CORE flow control)! */
5294   GNUNET_CONTAINER_DLL_insert (vl->cmc_head, vl->cmc_tail, cmc);
5295 }
5296
5297
5298 /**
5299  * Communicator gave us a fragment box.  Check the message.
5300  *
5301  * @param cls a `struct CommunicatorMessageContext`
5302  * @param fb the send message that was sent
5303  * @return #GNUNET_YES if message is well-formed
5304  */
5305 static int
5306 check_fragment_box (void *cls, const struct TransportFragmentBoxMessage *fb)
5307 {
5308   uint16_t size = ntohs (fb->header.size);
5309   uint16_t bsize = size - sizeof(*fb);
5310
5311   (void) cls;
5312   if (0 == bsize)
5313   {
5314     GNUNET_break_op (0);
5315     return GNUNET_SYSERR;
5316   }
5317   if (bsize + ntohs (fb->frag_off) > ntohs (fb->msg_size))
5318   {
5319     GNUNET_break_op (0);
5320     return GNUNET_SYSERR;
5321   }
5322   if (ntohs (fb->frag_off) >= ntohs (fb->msg_size))
5323   {
5324     GNUNET_break_op (0);
5325     return GNUNET_SYSERR;
5326   }
5327   return GNUNET_YES;
5328 }
5329
5330
5331 /**
5332  * Clean up an idle cummulative acknowledgement data structure.
5333  *
5334  * @param cls a `struct AcknowledgementCummulator *`
5335  */
5336 static void
5337 destroy_ack_cummulator (void *cls)
5338 {
5339   struct AcknowledgementCummulator *ac = cls;
5340
5341   ac->task = NULL;
5342   GNUNET_assert (0 == ac->num_acks);
5343   GNUNET_assert (
5344     GNUNET_YES ==
5345     GNUNET_CONTAINER_multipeermap_remove (ack_cummulators, &ac->target, ac));
5346   GNUNET_free (ac);
5347 }
5348
5349
5350 /**
5351  * Do the transmission of a cummulative acknowledgement now.
5352  *
5353  * @param cls a `struct AcknowledgementCummulator *`
5354  */
5355 static void
5356 transmit_cummulative_ack_cb (void *cls)
5357 {
5358   struct AcknowledgementCummulator *ac = cls;
5359   char buf[sizeof(struct TransportReliabilityAckMessage)
5360            + ac->ack_counter
5361            * sizeof(struct TransportCummulativeAckPayloadP)] GNUNET_ALIGN;
5362   struct TransportReliabilityAckMessage *ack =
5363     (struct TransportReliabilityAckMessage *) buf;
5364   struct TransportCummulativeAckPayloadP *ap;
5365
5366   ac->task = NULL;
5367   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5368               "Sending ACK with %u components to %s\n",
5369               ac->ack_counter,
5370               GNUNET_i2s (&ac->target));
5371   GNUNET_assert (0 < ac->ack_counter);
5372   ack->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_ACK);
5373   ack->header.size =
5374     htons (sizeof(*ack)
5375            + ac->ack_counter * sizeof(struct TransportCummulativeAckPayloadP));
5376   ack->ack_counter = htonl (ac->ack_counter++);
5377   ap = (struct TransportCummulativeAckPayloadP *) &ack[1];
5378   for (unsigned int i = 0; i < ac->ack_counter; i++)
5379   {
5380     ap[i].ack_uuid = ac->ack_uuids[i].ack_uuid;
5381     ap[i].ack_delay = GNUNET_TIME_relative_hton (
5382       GNUNET_TIME_absolute_get_duration (ac->ack_uuids[i].receive_time));
5383   }
5384   route_control_message_without_fc (&ac->target, &ack->header, RMO_DV_ALLOWED);
5385   ac->num_acks = 0;
5386   ac->task = GNUNET_SCHEDULER_add_delayed (ACK_CUMMULATOR_TIMEOUT,
5387                                            &destroy_ack_cummulator,
5388                                            ac);
5389 }
5390
5391
5392 /**
5393  * Transmit an acknowledgement for @a ack_uuid to @a pid delaying
5394  * transmission by at most @a ack_delay.
5395  *
5396  * @param pid target peer
5397  * @param ack_uuid UUID to ack
5398  * @param max_delay how long can the ACK wait
5399  */
5400 static void
5401 cummulative_ack (const struct GNUNET_PeerIdentity *pid,
5402                  const struct AcknowledgementUUIDP *ack_uuid,
5403                  struct GNUNET_TIME_Absolute max_delay)
5404 {
5405   struct AcknowledgementCummulator *ac;
5406
5407   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5408               "Scheduling ACK %s for transmission to %s\n",
5409               GNUNET_uuid2s (&ack_uuid->value),
5410               GNUNET_i2s (pid));
5411   ac = GNUNET_CONTAINER_multipeermap_get (ack_cummulators, pid);
5412   if (NULL == ac)
5413   {
5414     ac = GNUNET_new (struct AcknowledgementCummulator);
5415     ac->target = *pid;
5416     ac->min_transmission_time = max_delay;
5417     GNUNET_assert (GNUNET_YES ==
5418                    GNUNET_CONTAINER_multipeermap_put (
5419                      ack_cummulators,
5420                      &ac->target,
5421                      ac,
5422                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
5423   }
5424   else
5425   {
5426     if (MAX_CUMMULATIVE_ACKS == ac->num_acks)
5427     {
5428       /* must run immediately, ack buffer full! */
5429       GNUNET_SCHEDULER_cancel (ac->task);
5430       transmit_cummulative_ack_cb (ac);
5431     }
5432     GNUNET_SCHEDULER_cancel (ac->task);
5433     ac->min_transmission_time =
5434       GNUNET_TIME_absolute_min (ac->min_transmission_time, max_delay);
5435   }
5436   GNUNET_assert (ac->num_acks < MAX_CUMMULATIVE_ACKS);
5437   ac->ack_uuids[ac->num_acks].receive_time = GNUNET_TIME_absolute_get ();
5438   ac->ack_uuids[ac->num_acks].ack_uuid = *ack_uuid;
5439   ac->num_acks++;
5440   ac->task = GNUNET_SCHEDULER_add_at (ac->min_transmission_time,
5441                                       &transmit_cummulative_ack_cb,
5442                                       ac);
5443 }
5444
5445
5446 /**
5447  * Closure for #find_by_message_uuid.
5448  */
5449 struct FindByMessageUuidContext
5450 {
5451   /**
5452    * UUID to look for.
5453    */
5454   struct MessageUUIDP message_uuid;
5455
5456   /**
5457    * Set to the reassembly context if found.
5458    */
5459   struct ReassemblyContext *rc;
5460 };
5461
5462
5463 /**
5464  * Iterator called to find a reassembly context by the message UUID in the
5465  * multihashmap32.
5466  *
5467  * @param cls a `struct FindByMessageUuidContext`
5468  * @param key a key (unused)
5469  * @param value a `struct ReassemblyContext`
5470  * @return #GNUNET_YES if not found, #GNUNET_NO if found
5471  */
5472 static int
5473 find_by_message_uuid (void *cls, uint32_t key, void *value)
5474 {
5475   struct FindByMessageUuidContext *fc = cls;
5476   struct ReassemblyContext *rc = value;
5477
5478   (void) key;
5479   if (0 == GNUNET_memcmp (&fc->message_uuid, &rc->msg_uuid))
5480   {
5481     fc->rc = rc;
5482     return GNUNET_NO;
5483   }
5484   return GNUNET_YES;
5485 }
5486
5487
5488 /**
5489  * Communicator gave us a fragment.  Process the request.
5490  *
5491  * @param cls a `struct CommunicatorMessageContext` (must call
5492  * #finish_cmc_handling() when done)
5493  * @param fb the message that was received
5494  */
5495 static void
5496 handle_fragment_box (void *cls, const struct TransportFragmentBoxMessage *fb)
5497 {
5498   struct CommunicatorMessageContext *cmc = cls;
5499   struct Neighbour *n;
5500   struct ReassemblyContext *rc;
5501   const struct GNUNET_MessageHeader *msg;
5502   uint16_t msize;
5503   uint16_t fsize;
5504   uint16_t frag_off;
5505   char *target;
5506   struct GNUNET_TIME_Relative cdelay;
5507   struct FindByMessageUuidContext fc;
5508
5509   n = lookup_neighbour (&cmc->im.sender);
5510   if (NULL == n)
5511   {
5512     struct GNUNET_SERVICE_Client *client = cmc->tc->client;
5513
5514     GNUNET_break (0);
5515     finish_cmc_handling (cmc);
5516     GNUNET_SERVICE_client_drop (client);
5517     return;
5518   }
5519   if (NULL == n->reassembly_map)
5520   {
5521     n->reassembly_map = GNUNET_CONTAINER_multihashmap32_create (8);
5522     n->reassembly_heap =
5523       GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
5524     n->reassembly_timeout_task =
5525       GNUNET_SCHEDULER_add_delayed (REASSEMBLY_EXPIRATION,
5526                                     &reassembly_cleanup_task,
5527                                     n);
5528   }
5529   msize = ntohs (fb->msg_size);
5530   fc.message_uuid = fb->msg_uuid;
5531   fc.rc = NULL;
5532   (void) GNUNET_CONTAINER_multihashmap32_get_multiple (n->reassembly_map,
5533                                                        fb->msg_uuid.uuid,
5534                                                        &find_by_message_uuid,
5535                                                        &fc);
5536   if (NULL == (rc = fc.rc))
5537   {
5538     rc = GNUNET_malloc (sizeof(*rc) + msize    /* reassembly payload buffer */
5539                         + (msize + 7) / 8 * sizeof(uint8_t) /* bitfield */);
5540     rc->msg_uuid = fb->msg_uuid;
5541     rc->neighbour = n;
5542     rc->msg_size = msize;
5543     rc->reassembly_timeout =
5544       GNUNET_TIME_relative_to_absolute (REASSEMBLY_EXPIRATION);
5545     rc->last_frag = GNUNET_TIME_absolute_get ();
5546     rc->hn = GNUNET_CONTAINER_heap_insert (n->reassembly_heap,
5547                                            rc,
5548                                            rc->reassembly_timeout.abs_value_us);
5549     GNUNET_assert (GNUNET_OK ==
5550                    GNUNET_CONTAINER_multihashmap32_put (
5551                      n->reassembly_map,
5552                      rc->msg_uuid.uuid,
5553                      rc,
5554                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
5555     target = (char *) &rc[1];
5556     rc->bitfield = (uint8_t *) (target + rc->msg_size);
5557     rc->msg_missing = rc->msg_size;
5558     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5559                 "Received fragment at offset %u/%u from %s for NEW message %u\n",
5560                 ntohs (fb->frag_off),
5561                 msize,
5562                 GNUNET_i2s (&cmc->im.sender),
5563                 (unsigned int) fb->msg_uuid.uuid);
5564   }
5565   else
5566   {
5567     target = (char *) &rc[1];
5568     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5569                 "Received fragment at offset %u/%u from %s for message %u\n",
5570                 ntohs (fb->frag_off),
5571                 msize,
5572                 GNUNET_i2s (&cmc->im.sender),
5573                 (unsigned int) fb->msg_uuid.uuid);
5574   }
5575   if (msize != rc->msg_size)
5576   {
5577     GNUNET_break (0);
5578     finish_cmc_handling (cmc);
5579     return;
5580   }
5581
5582   /* reassemble */
5583   fsize = ntohs (fb->header.size) - sizeof(*fb);
5584   if (0 == fsize)
5585   {
5586     GNUNET_break (0);
5587     finish_cmc_handling (cmc);
5588     return;
5589   }
5590   frag_off = ntohs (fb->frag_off);
5591   if (frag_off + fsize > msize)
5592   {
5593     /* Fragment (plus fragment size) exceeds message size! */
5594     GNUNET_break_op (0);
5595     finish_cmc_handling (cmc);
5596     return;
5597   }
5598   memcpy (&target[frag_off], &fb[1], fsize);
5599   /* update bitfield and msg_missing */
5600   for (unsigned int i = frag_off; i < frag_off + fsize; i++)
5601   {
5602     if (0 == (rc->bitfield[i / 8] & (1 << (i % 8))))
5603     {
5604       rc->bitfield[i / 8] |= (1 << (i % 8));
5605       rc->msg_missing--;
5606     }
5607   }
5608
5609   /* Compute cummulative ACK */
5610   cdelay = GNUNET_TIME_absolute_get_duration (rc->last_frag);
5611   cdelay = GNUNET_TIME_relative_multiply (cdelay, rc->msg_missing / fsize);
5612   if (0 == rc->msg_missing)
5613     cdelay = GNUNET_TIME_UNIT_ZERO;
5614   cummulative_ack (&cmc->im.sender,
5615                    &fb->ack_uuid,
5616                    GNUNET_TIME_relative_to_absolute (cdelay));
5617   rc->last_frag = GNUNET_TIME_absolute_get ();
5618   /* is reassembly complete? */
5619   if (0 != rc->msg_missing)
5620   {
5621     finish_cmc_handling (cmc);
5622     return;
5623   }
5624   /* reassembly is complete, verify result */
5625   msg = (const struct GNUNET_MessageHeader *) &rc[1];
5626   if (ntohs (msg->size) != rc->msg_size)
5627   {
5628     GNUNET_break (0);
5629     free_reassembly_context (rc);
5630     finish_cmc_handling (cmc);
5631     return;
5632   }
5633   /* successful reassembly */
5634   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5635               "Fragment reassembly complete for message %u\n",
5636               (unsigned int) fb->msg_uuid.uuid);
5637   /* FIXME: check that the resulting msg is NOT a
5638      DV Box or Reliability Box, as that is NOT allowed! */
5639   demultiplex_with_cmc (cmc, msg);
5640   /* FIXME-OPTIMIZE: really free here? Might be bad if fragments are still
5641      en-route and we forget that we finished this reassembly immediately!
5642      -> keep around until timeout?
5643      -> shorten timeout based on ACK? */
5644   free_reassembly_context (rc);
5645 }
5646
5647
5648 /**
5649  * Communicator gave us a reliability box.  Check the message.
5650  *
5651  * @param cls a `struct CommunicatorMessageContext`
5652  * @param rb the send message that was sent
5653  * @return #GNUNET_YES if message is well-formed
5654  */
5655 static int
5656 check_reliability_box (void *cls,
5657                        const struct TransportReliabilityBoxMessage *rb)
5658 {
5659   (void) cls;
5660   GNUNET_MQ_check_boxed_message (rb);
5661   return GNUNET_YES;
5662 }
5663
5664
5665 /**
5666  * Communicator gave us a reliability box.  Process the request.
5667  *
5668  * @param cls a `struct CommunicatorMessageContext` (must call
5669  * #finish_cmc_handling() when done)
5670  * @param rb the message that was received
5671  */
5672 static void
5673 handle_reliability_box (void *cls,
5674                         const struct TransportReliabilityBoxMessage *rb)
5675 {
5676   struct CommunicatorMessageContext *cmc = cls;
5677   const struct GNUNET_MessageHeader *inbox =
5678     (const struct GNUNET_MessageHeader *) &rb[1];
5679   struct GNUNET_TIME_Relative rtt;
5680
5681   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5682               "Received reliability box from %s with UUID %s of type %u\n",
5683               GNUNET_i2s (&cmc->im.sender),
5684               GNUNET_uuid2s (&rb->ack_uuid.value),
5685               (unsigned int) ntohs (inbox->type));
5686   rtt = GNUNET_TIME_UNIT_SECONDS; /* FIXME: should base this on "RTT", but we
5687                                      do not really have an RTT for the
5688                                    * incoming* queue (should we have
5689                                      the sender add it to the rb message?) */
5690   cummulative_ack (
5691     &cmc->im.sender,
5692     &rb->ack_uuid,
5693     (0 == ntohl (rb->ack_countdown))
5694     ? GNUNET_TIME_UNIT_ZERO_ABS
5695     : GNUNET_TIME_relative_to_absolute (
5696       GNUNET_TIME_relative_divide (rtt, 8 /* FIXME: magic constant */)));
5697   /* continue with inner message */
5698   /* FIXME: check that inbox is NOT a DV Box, fragment or another
5699      reliability box (not allowed!) */
5700   demultiplex_with_cmc (cmc, inbox);
5701 }
5702
5703
5704 /**
5705  * Check if we have advanced to another age since the last time.  If
5706  * so, purge ancient statistics (more than GOODPUT_AGING_SLOTS before
5707  * the current age)
5708  *
5709  * @param pd[in,out] data to update
5710  * @param age current age
5711  */
5712 static void
5713 update_pd_age (struct PerformanceData *pd, unsigned int age)
5714 {
5715   unsigned int sage;
5716
5717   if (age == pd->last_age)
5718     return; /* nothing to do */
5719   sage = GNUNET_MAX (pd->last_age, age - 2 * GOODPUT_AGING_SLOTS);
5720   for (unsigned int i = sage; i <= age - GOODPUT_AGING_SLOTS; i++)
5721   {
5722     struct TransmissionHistoryEntry *the = &pd->the[i % GOODPUT_AGING_SLOTS];
5723
5724     the->bytes_sent = 0;
5725     the->bytes_received = 0;
5726   }
5727   pd->last_age = age;
5728 }
5729
5730
5731 /**
5732  * Update @a pd based on the latest @a rtt and the number of bytes
5733  * that were confirmed to be successfully transmitted.
5734  *
5735  * @param pd[in,out] data to update
5736  * @param rtt latest round-trip time
5737  * @param bytes_transmitted_ok number of bytes receiver confirmed as received
5738  */
5739 static void
5740 update_performance_data (struct PerformanceData *pd,
5741                          struct GNUNET_TIME_Relative rtt,
5742                          uint16_t bytes_transmitted_ok)
5743 {
5744   uint64_t nval = rtt.rel_value_us;
5745   uint64_t oval = pd->aged_rtt.rel_value_us;
5746   unsigned int age = get_age ();
5747   struct TransmissionHistoryEntry *the = &pd->the[age % GOODPUT_AGING_SLOTS];
5748
5749   if (oval == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
5750     pd->aged_rtt = rtt;
5751   else
5752     pd->aged_rtt.rel_value_us = (nval + 7 * oval) / 8;
5753   update_pd_age (pd, age);
5754   the->bytes_received += bytes_transmitted_ok;
5755 }
5756
5757
5758 /**
5759  * We have successfully transmitted data via @a q, update metrics.
5760  *
5761  * @param q queue to update
5762  * @param rtt round trip time observed
5763  * @param bytes_transmitted_ok number of bytes successfully transmitted
5764  */
5765 static void
5766 update_queue_performance (struct Queue *q,
5767                           struct GNUNET_TIME_Relative rtt,
5768                           uint16_t bytes_transmitted_ok)
5769 {
5770   update_performance_data (&q->pd, rtt, bytes_transmitted_ok);
5771 }
5772
5773
5774 /**
5775  * We have successfully transmitted data via @a dvh, update metrics.
5776  *
5777  * @param dvh distance vector path data to update
5778  * @param rtt round trip time observed
5779  * @param bytes_transmitted_ok number of bytes successfully transmitted
5780  */
5781 static void
5782 update_dvh_performance (struct DistanceVectorHop *dvh,
5783                         struct GNUNET_TIME_Relative rtt,
5784                         uint16_t bytes_transmitted_ok)
5785 {
5786   update_performance_data (&dvh->pd, rtt, bytes_transmitted_ok);
5787 }
5788
5789
5790 /**
5791  * We have completed transmission of @a pm, remove it from
5792  * the transmission queues (and if it is a fragment, continue
5793  * up the tree as necessary).
5794  *
5795  * @param pm pending message that was transmitted
5796  */
5797 static void
5798 completed_pending_message (struct PendingMessage *pm)
5799 {
5800   struct PendingMessage *pos;
5801
5802   switch (pm->pmt)
5803   {
5804   case PMT_CORE:
5805   case PMT_RELIABILITY_BOX:
5806     /* Full message sent, we are done */
5807     client_send_response (pm);
5808     return;
5809
5810   case PMT_FRAGMENT_BOX:
5811     /* Fragment sent over reliabile channel */
5812     free_fragment_tree (pm);
5813     pos = pm->frag_parent;
5814     GNUNET_CONTAINER_MDLL_remove (frag, pos->head_frag, pos->tail_frag, pm);
5815     GNUNET_free (pm);
5816     /* check if subtree is done */
5817     while ((NULL == pos->head_frag) && (pos->frag_off == pos->bytes_msg) &&
5818            (pos != pm))
5819     {
5820       pm = pos;
5821       pos = pm->frag_parent;
5822       GNUNET_CONTAINER_MDLL_remove (frag, pos->head_frag, pos->tail_frag, pm);
5823       GNUNET_free (pm);
5824     }
5825
5826     /* Was this the last applicable fragmment? */
5827     if ((NULL == pos->head_frag) && (NULL == pos->frag_parent) &&
5828         (pos->frag_off == pos->bytes_msg))
5829       client_send_response (pos);
5830     return;
5831
5832   case PMT_DV_BOX:
5833     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5834                 "Completed transmission of message %llu (DV Box)\n",
5835                 pm->logging_uuid);
5836     free_pending_message (pm);
5837     return;
5838   }
5839 }
5840
5841
5842 /**
5843  * The @a pa was acknowledged, process the acknowledgement.
5844  *
5845  * @param pa the pending acknowledgement that was satisfied
5846  * @param ack_delay artificial delay from cummulative acks created by the
5847  * other peer
5848  */
5849 static void
5850 handle_acknowledged (struct PendingAcknowledgement *pa,
5851                      struct GNUNET_TIME_Relative ack_delay)
5852 {
5853   struct GNUNET_TIME_Relative delay;
5854
5855   delay = GNUNET_TIME_absolute_get_duration (pa->transmission_time);
5856   if (delay.rel_value_us > ack_delay.rel_value_us)
5857     delay = GNUNET_TIME_UNIT_ZERO;
5858   else
5859     delay = GNUNET_TIME_relative_subtract (delay, ack_delay);
5860   if (NULL != pa->queue)
5861     update_queue_performance (pa->queue, delay, pa->message_size);
5862   if (NULL != pa->dvh)
5863     update_dvh_performance (pa->dvh, delay, pa->message_size);
5864   if (NULL != pa->pm)
5865     completed_pending_message (pa->pm);
5866   free_pending_acknowledgement (pa);
5867 }
5868
5869
5870 /**
5871  * Communicator gave us a reliability ack.  Check it is well-formed.
5872  *
5873  * @param cls a `struct CommunicatorMessageContext` (unused)
5874  * @param ra the message that was received
5875  * @return #GNUNET_Ok if @a ra is well-formed
5876  */
5877 static int
5878 check_reliability_ack (void *cls,
5879                        const struct TransportReliabilityAckMessage *ra)
5880 {
5881   unsigned int n_acks;
5882
5883   (void) cls;
5884   n_acks = (ntohs (ra->header.size) - sizeof(*ra))
5885            / sizeof(struct TransportCummulativeAckPayloadP);
5886   if (0 == n_acks)
5887   {
5888     GNUNET_break_op (0);
5889     return GNUNET_SYSERR;
5890   }
5891   if ((ntohs (ra->header.size) - sizeof(*ra)) !=
5892       n_acks * sizeof(struct TransportCummulativeAckPayloadP))
5893   {
5894     GNUNET_break_op (0);
5895     return GNUNET_SYSERR;
5896   }
5897   return GNUNET_OK;
5898 }
5899
5900
5901 /**
5902  * Communicator gave us a reliability ack.  Process the request.
5903  *
5904  * @param cls a `struct CommunicatorMessageContext` (must call
5905  * #finish_cmc_handling() when done)
5906  * @param ra the message that was received
5907  */
5908 static void
5909 handle_reliability_ack (void *cls,
5910                         const struct TransportReliabilityAckMessage *ra)
5911 {
5912   struct CommunicatorMessageContext *cmc = cls;
5913   const struct TransportCummulativeAckPayloadP *ack;
5914   unsigned int n_acks;
5915   uint32_t ack_counter;
5916
5917   n_acks = (ntohs (ra->header.size) - sizeof(*ra))
5918            / sizeof(struct TransportCummulativeAckPayloadP);
5919   ack = (const struct TransportCummulativeAckPayloadP *) &ra[1];
5920   for (unsigned int i = 0; i < n_acks; i++)
5921   {
5922     struct PendingAcknowledgement *pa =
5923       GNUNET_CONTAINER_multiuuidmap_get (pending_acks, &ack[i].ack_uuid.value);
5924     if (NULL == pa)
5925     {
5926       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
5927                   "Received ACK from %s with UUID %s which is unknown to us!\n",
5928                   GNUNET_i2s (&cmc->im.sender),
5929                   GNUNET_uuid2s (&ack[i].ack_uuid.value));
5930       GNUNET_STATISTICS_update (
5931         GST_stats,
5932         "# FRAGMENT_ACKS dropped, no matching pending message",
5933         1,
5934         GNUNET_NO);
5935       continue;
5936     }
5937     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5938                 "Received ACK from %s with UUID %s\n",
5939                 GNUNET_i2s (&cmc->im.sender),
5940                 GNUNET_uuid2s (&ack[i].ack_uuid.value));
5941     handle_acknowledged (pa, GNUNET_TIME_relative_ntoh (ack[i].ack_delay));
5942   }
5943
5944   ack_counter = htonl (ra->ack_counter);
5945   (void) ack_counter;  /* silence compiler warning for now */
5946   // FIXME-OPTIMIZE: track ACK losses based on ack_counter somewhere!
5947   // (DV and/or Neighbour?)
5948   finish_cmc_handling (cmc);
5949 }
5950
5951
5952 /**
5953  * Communicator gave us a backchannel encapsulation.  Check the message.
5954  *
5955  * @param cls a `struct CommunicatorMessageContext`
5956  * @param be the send message that was sent
5957  * @return #GNUNET_YES if message is well-formed
5958  */
5959 static int
5960 check_backchannel_encapsulation (
5961   void *cls,
5962   const struct TransportBackchannelEncapsulationMessage *be)
5963 {
5964   uint16_t size = ntohs (be->header.size) - sizeof(*be);
5965   const struct GNUNET_MessageHeader *inbox =
5966     (const struct GNUNET_MessageHeader *) &be[1];
5967   const char *is;
5968   uint16_t isize;
5969
5970   (void) cls;
5971   if (ntohs (inbox->size) >= size)
5972   {
5973     GNUNET_break_op (0);
5974     return GNUNET_SYSERR;
5975   }
5976   isize = ntohs (inbox->size);
5977   is = ((const char *) inbox) + isize;
5978   size -= isize;
5979   if ('\0' != is[size - 1])
5980   {
5981     GNUNET_break_op (0);
5982     return GNUNET_SYSERR;
5983   }
5984   return GNUNET_YES;
5985 }
5986
5987
5988 /**
5989  * Communicator gave us a backchannel encapsulation.  Process the request.
5990  * (We are the destination of the backchannel here.)
5991  *
5992  * @param cls a `struct CommunicatorMessageContext` (must call
5993  * #finish_cmc_handling() when done)
5994  * @param be the message that was received
5995  */
5996 static void
5997 handle_backchannel_encapsulation (
5998   void *cls,
5999   const struct TransportBackchannelEncapsulationMessage *be)
6000 {
6001   struct CommunicatorMessageContext *cmc = cls;
6002   struct GNUNET_TRANSPORT_CommunicatorBackchannelIncoming *cbi;
6003   struct GNUNET_MQ_Envelope *env;
6004   struct TransportClient *tc;
6005   const struct GNUNET_MessageHeader *inbox =
6006     (const struct GNUNET_MessageHeader *) &be[1];
6007   uint16_t isize = ntohs (inbox->size);
6008   const char *target_communicator = ((const char *) inbox) + isize;
6009
6010   /* Find client providing this communicator */
6011   for (tc = clients_head; NULL != tc; tc = tc->next)
6012     if ((CT_COMMUNICATOR == tc->type) &&
6013         (0 ==
6014          strcmp (tc->details.communicator.address_prefix, target_communicator)))
6015       break;
6016   if (NULL == tc)
6017   {
6018     char *stastr;
6019
6020     GNUNET_asprintf (
6021       &stastr,
6022       "# Backchannel message dropped: target communicator `%s' unknown",
6023       target_communicator);
6024     GNUNET_STATISTICS_update (GST_stats, stastr, 1, GNUNET_NO);
6025     GNUNET_free (stastr);
6026     return;
6027   }
6028   /* Finally, deliver backchannel message to communicator */
6029   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6030               "Delivering backchannel message from %s of type %u to %s\n",
6031               GNUNET_i2s (&cmc->im.sender),
6032               ntohs (inbox->type),
6033               target_communicator);
6034   env = GNUNET_MQ_msg_extra (
6035     cbi,
6036     isize,
6037     GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL_INCOMING);
6038   cbi->pid = cmc->im.sender;
6039   memcpy (&cbi[1], inbox, isize);
6040   GNUNET_MQ_send (tc->mq, env);
6041 }
6042
6043
6044 /**
6045  * Task called when we should check if any of the DV paths
6046  * we have learned to a target are due for garbage collection.
6047  *
6048  * Collects stale paths, and possibly frees the entire DV
6049  * entry if no paths are left. Otherwise re-schedules itself.
6050  *
6051  * @param cls a `struct DistanceVector`
6052  */
6053 static void
6054 path_cleanup_cb (void *cls)
6055 {
6056   struct DistanceVector *dv = cls;
6057   struct DistanceVectorHop *pos;
6058
6059   dv->timeout_task = NULL;
6060   while (NULL != (pos = dv->dv_head))
6061   {
6062     GNUNET_assert (dv == pos->dv);
6063     if (GNUNET_TIME_absolute_get_remaining (pos->timeout).rel_value_us > 0)
6064       break;
6065     free_distance_vector_hop (pos);
6066   }
6067   if (NULL == pos)
6068   {
6069     free_dv_route (dv);
6070     return;
6071   }
6072   dv->timeout_task =
6073     GNUNET_SCHEDULER_add_at (pos->timeout, &path_cleanup_cb, dv);
6074 }
6075
6076
6077 /**
6078  * The @a hop is a validated path to the respective target
6079  * peer and we should tell core about it -- and schedule
6080  * a job to revoke the state.
6081  *
6082  * @param hop a path to some peer that is the reason for activation
6083  */
6084 static void
6085 activate_core_visible_dv_path (struct DistanceVectorHop *hop)
6086 {
6087   struct DistanceVector *dv = hop->dv;
6088   struct VirtualLink *vl;
6089
6090   vl = lookup_virtual_link (&dv->target);
6091   if (NULL != vl)
6092   {
6093     /* Link was already up, remember dv is also now available and we are done */
6094     vl->dv = dv;
6095     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6096                 "Virtual link to %s could now also use DV!\n",
6097                 GNUNET_i2s (&dv->target));
6098     return;
6099   }
6100   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6101               "Creating new virtual link to %s using DV!\n",
6102               GNUNET_i2s (&dv->target));
6103   vl = GNUNET_new (struct VirtualLink);
6104   vl->message_uuid_ctr =
6105     GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX);
6106   vl->target = dv->target;
6107   vl->dv = dv;
6108   dv->vl = vl;
6109   vl->core_recv_window = RECV_WINDOW_SIZE;
6110   vl->available_fc_window_size = DEFAULT_WINDOW_SIZE;
6111   vl->visibility_task =
6112     GNUNET_SCHEDULER_add_at (hop->path_valid_until, &check_link_down, vl);
6113   GNUNET_break (GNUNET_YES ==
6114                 GNUNET_CONTAINER_multipeermap_put (
6115                   links,
6116                   &vl->target,
6117                   vl,
6118                   GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
6119   consider_sending_fc (vl);
6120   /* We lacked a confirmed connection to the target
6121      before, so tell CORE about it (finally!) */
6122   cores_send_connect_info (&dv->target);
6123 }
6124
6125
6126 /**
6127  * We have learned a @a path through the network to some other peer, add it to
6128  * our DV data structure (returning #GNUNET_YES on success).
6129  *
6130  * We do not add paths if we have a sufficient number of shorter
6131  * paths to this target already (returning #GNUNET_NO).
6132  *
6133  * We also do not add problematic paths, like those where we lack the first
6134  * hop in our neighbour list (i.e. due to a topology change) or where some
6135  * non-first hop is in our neighbour list (returning #GNUNET_SYSERR).
6136  *
6137  * @param path the path we learned, path[0] should be us,
6138  *             and then path contains a valid path from us to
6139  * `path[path_len-1]` path[1] should be a direct neighbour (we should check!)
6140  * @param path_len number of entries on the @a path, at least three!
6141  * @param network_latency how long does the message take from us to
6142  * `path[path_len-1]`? set to "forever" if unknown
6143  * @param path_valid_until how long is this path considered validated? Maybe
6144  * be zero.
6145  * @return #GNUNET_YES on success,
6146  *         #GNUNET_NO if we have better path(s) to the target
6147  *         #GNUNET_SYSERR if the path is useless and/or invalid
6148  *                         (i.e. path[1] not a direct neighbour
6149  *                        or path[i+1] is a direct neighbour for i>0)
6150  */
6151 static int
6152 learn_dv_path (const struct GNUNET_PeerIdentity *path,
6153                unsigned int path_len,
6154                struct GNUNET_TIME_Relative network_latency,
6155                struct GNUNET_TIME_Absolute path_valid_until)
6156 {
6157   struct DistanceVectorHop *hop;
6158   struct DistanceVector *dv;
6159   struct Neighbour *next_hop;
6160   unsigned int shorter_distance;
6161
6162   if (path_len < 3)
6163   {
6164     /* what a boring path! not allowed! */
6165     GNUNET_break (0);
6166     return GNUNET_SYSERR;
6167   }
6168   GNUNET_assert (0 == GNUNET_memcmp (&GST_my_identity, &path[0]));
6169   next_hop = lookup_neighbour (&path[1]);
6170   if (NULL == next_hop)
6171   {
6172     /* next hop must be a neighbour, otherwise this whole thing is useless! */
6173     GNUNET_break (0);
6174     return GNUNET_SYSERR;
6175   }
6176   for (unsigned int i = 2; i < path_len; i++)
6177     if (NULL != lookup_neighbour (&path[i]))
6178     {
6179       /* Useless path: we have a direct connection to some hop
6180          in the middle of the path, so this one is not even
6181          terribly useful for redundancy */
6182       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
6183                   "Path of %u hops useless: directly link to hop %u (%s)\n",
6184                   path_len,
6185                   i,
6186                   GNUNET_i2s (&path[i]));
6187       GNUNET_STATISTICS_update (GST_stats,
6188                                 "# Useless DV path ignored: hop is neighbour",
6189                                 1,
6190                                 GNUNET_NO);
6191       return GNUNET_SYSERR;
6192     }
6193   dv = GNUNET_CONTAINER_multipeermap_get (dv_routes, &path[path_len - 1]);
6194   if (NULL == dv)
6195   {
6196     dv = GNUNET_new (struct DistanceVector);
6197     dv->target = path[path_len - 1];
6198     dv->timeout_task = GNUNET_SCHEDULER_add_delayed (DV_PATH_VALIDITY_TIMEOUT,
6199                                                      &path_cleanup_cb,
6200                                                      dv);
6201     GNUNET_assert (GNUNET_OK ==
6202                    GNUNET_CONTAINER_multipeermap_put (
6203                      dv_routes,
6204                      &dv->target,
6205                      dv,
6206                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
6207   }
6208   /* Check if we have this path already! */
6209   shorter_distance = 0;
6210   for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
6211        pos = pos->next_dv)
6212   {
6213     if (pos->distance < path_len - 2)
6214       shorter_distance++;
6215     /* Note that the distances in 'pos' excludes us (path[0]) and
6216        the next_hop (path[1]), so we need to subtract two
6217        and check next_hop explicitly */
6218     if ((pos->distance == path_len - 2) && (pos->next_hop == next_hop))
6219     {
6220       int match = GNUNET_YES;
6221
6222       for (unsigned int i = 0; i < pos->distance; i++)
6223       {
6224         if (0 != GNUNET_memcmp (&pos->path[i], &path[i + 2]))
6225         {
6226           match = GNUNET_NO;
6227           break;
6228         }
6229       }
6230       if (GNUNET_YES == match)
6231       {
6232         struct GNUNET_TIME_Relative last_timeout;
6233
6234         /* Re-discovered known path, update timeout */
6235         GNUNET_STATISTICS_update (GST_stats,
6236                                   "# Known DV path refreshed",
6237                                   1,
6238                                   GNUNET_NO);
6239         last_timeout = GNUNET_TIME_absolute_get_remaining (pos->timeout);
6240         pos->timeout =
6241           GNUNET_TIME_relative_to_absolute (DV_PATH_VALIDITY_TIMEOUT);
6242         pos->path_valid_until =
6243           GNUNET_TIME_absolute_max (pos->path_valid_until, path_valid_until);
6244         GNUNET_CONTAINER_MDLL_remove (dv, dv->dv_head, dv->dv_tail, pos);
6245         GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, pos);
6246         if (0 <
6247             GNUNET_TIME_absolute_get_remaining (path_valid_until).rel_value_us)
6248           activate_core_visible_dv_path (pos);
6249         if (last_timeout.rel_value_us <
6250             GNUNET_TIME_relative_subtract (DV_PATH_VALIDITY_TIMEOUT,
6251                                            DV_PATH_DISCOVERY_FREQUENCY)
6252             .rel_value_us)
6253         {
6254           /* Some peer send DV learn messages too often, we are learning
6255              the same path faster than it would be useful; do not forward! */
6256           GNUNET_log (GNUNET_ERROR_TYPE_INFO,
6257                       "Rediscovered path too quickly, not forwarding further\n");
6258           return GNUNET_NO;
6259         }
6260         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6261                     "Refreshed known path to %s, forwarding further\n",
6262                     GNUNET_i2s (&dv->target));
6263         return GNUNET_YES;
6264       }
6265     }
6266   }
6267   /* Count how many shorter paths we have (incl. direct
6268      neighbours) before simply giving up on this one! */
6269   if (shorter_distance >= MAX_DV_PATHS_TO_TARGET)
6270   {
6271     /* We have a shorter path already! */
6272     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6273                 "Have many shorter DV paths %s, not forwarding further\n",
6274                 GNUNET_i2s (&dv->target));
6275     return GNUNET_NO;
6276   }
6277   /* create new DV path entry */
6278   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6279               "Discovered new DV path to %s\n",
6280               GNUNET_i2s (&dv->target));
6281   hop = GNUNET_malloc (sizeof(struct DistanceVectorHop)
6282                        + sizeof(struct GNUNET_PeerIdentity) * (path_len - 2));
6283   hop->next_hop = next_hop;
6284   hop->dv = dv;
6285   hop->path = (const struct GNUNET_PeerIdentity *) &hop[1];
6286   memcpy (&hop[1],
6287           &path[2],
6288           sizeof(struct GNUNET_PeerIdentity) * (path_len - 2));
6289   hop->timeout = GNUNET_TIME_relative_to_absolute (DV_PATH_VALIDITY_TIMEOUT);
6290   hop->path_valid_until = path_valid_until;
6291   hop->distance = path_len - 2;
6292   hop->pd.aged_rtt = network_latency;
6293   GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, hop);
6294   GNUNET_CONTAINER_MDLL_insert (neighbour,
6295                                 next_hop->dv_head,
6296                                 next_hop->dv_tail,
6297                                 hop);
6298   if (0 < GNUNET_TIME_absolute_get_remaining (path_valid_until).rel_value_us)
6299     activate_core_visible_dv_path (hop);
6300   return GNUNET_YES;
6301 }
6302
6303
6304 /**
6305  * Communicator gave us a DV learn message.  Check the message.
6306  *
6307  * @param cls a `struct CommunicatorMessageContext`
6308  * @param dvl the send message that was sent
6309  * @return #GNUNET_YES if message is well-formed
6310  */
6311 static int
6312 check_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
6313 {
6314   uint16_t size = ntohs (dvl->header.size);
6315   uint16_t num_hops = ntohs (dvl->num_hops);
6316   const struct DVPathEntryP *hops = (const struct DVPathEntryP *) &dvl[1];
6317
6318   (void) cls;
6319   if (size != sizeof(*dvl) + num_hops * sizeof(struct DVPathEntryP))
6320   {
6321     GNUNET_break_op (0);
6322     return GNUNET_SYSERR;
6323   }
6324   if (num_hops > MAX_DV_HOPS_ALLOWED)
6325   {
6326     GNUNET_break_op (0);
6327     return GNUNET_SYSERR;
6328   }
6329   for (unsigned int i = 0; i < num_hops; i++)
6330   {
6331     if (0 == GNUNET_memcmp (&dvl->initiator, &hops[i].hop))
6332     {
6333       GNUNET_break_op (0);
6334       return GNUNET_SYSERR;
6335     }
6336     if (0 == GNUNET_memcmp (&GST_my_identity, &hops[i].hop))
6337     {
6338       GNUNET_break_op (0);
6339       return GNUNET_SYSERR;
6340     }
6341   }
6342   return GNUNET_YES;
6343 }
6344
6345
6346 /**
6347  * Build and forward a DV learn message to @a next_hop.
6348  *
6349  * @param next_hop peer to send the message to
6350  * @param msg message received
6351  * @param bi_history bitmask specifying hops on path that were bidirectional
6352  * @param nhops length of the @a hops array
6353  * @param hops path the message traversed so far
6354  * @param in_time when did we receive the message, used to calculate network
6355  * delay
6356  */
6357 static void
6358 forward_dv_learn (const struct GNUNET_PeerIdentity *next_hop,
6359                   const struct TransportDVLearnMessage *msg,
6360                   uint16_t bi_history,
6361                   uint16_t nhops,
6362                   const struct DVPathEntryP *hops,
6363                   struct GNUNET_TIME_Absolute in_time)
6364 {
6365   struct DVPathEntryP *dhops;
6366   char buf[sizeof(struct TransportDVLearnMessage)
6367            + (nhops + 1) * sizeof(struct DVPathEntryP)] GNUNET_ALIGN;
6368   struct TransportDVLearnMessage *fwd = (struct TransportDVLearnMessage *) buf;
6369   struct GNUNET_TIME_Relative nnd;
6370
6371   /* compute message for forwarding */
6372   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6373               "Forwarding DV learn message originating from %s to %s\n",
6374               GNUNET_i2s (&msg->initiator),
6375               GNUNET_i2s2 (next_hop));
6376   GNUNET_assert (nhops < MAX_DV_HOPS_ALLOWED);
6377   fwd->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN);
6378   fwd->header.size = htons (sizeof(struct TransportDVLearnMessage)
6379                             + (nhops + 1) * sizeof(struct DVPathEntryP));
6380   fwd->num_hops = htons (nhops + 1);
6381   fwd->bidirectional = htons (bi_history);
6382   nnd = GNUNET_TIME_relative_add (GNUNET_TIME_absolute_get_duration (in_time),
6383                                   GNUNET_TIME_relative_ntoh (
6384                                     msg->non_network_delay));
6385   fwd->non_network_delay = GNUNET_TIME_relative_hton (nnd);
6386   fwd->init_sig = msg->init_sig;
6387   fwd->initiator = msg->initiator;
6388   fwd->challenge = msg->challenge;
6389   dhops = (struct DVPathEntryP *) &fwd[1];
6390   GNUNET_memcpy (dhops, hops, sizeof(struct DVPathEntryP) * nhops);
6391   dhops[nhops].hop = GST_my_identity;
6392   {
6393     struct DvHopPS dhp = {
6394       .purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_HOP),
6395       .purpose.size = htonl (sizeof(dhp)),
6396       .pred = dhops[nhops - 1].hop,
6397       .succ = *next_hop,
6398       .challenge = msg->challenge
6399     };
6400
6401     GNUNET_CRYPTO_eddsa_sign (GST_my_private_key,
6402                               &dhp,
6403                               &dhops[nhops].hop_sig);
6404   }
6405   route_control_message_without_fc (next_hop,
6406                                     &fwd->header,
6407                                     RMO_UNCONFIRMED_ALLOWED);
6408 }
6409
6410
6411 /**
6412  * Check signature of type #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR
6413  *
6414  * @param sender_monotonic_time monotonic time of the initiator
6415  * @param init the signer
6416  * @param challenge the challenge that was signed
6417  * @param init_sig signature presumably by @a init
6418  * @return #GNUNET_OK if the signature is valid
6419  */
6420 static int
6421 validate_dv_initiator_signature (
6422   struct GNUNET_TIME_AbsoluteNBO sender_monotonic_time,
6423   const struct GNUNET_PeerIdentity *init,
6424   const struct ChallengeNonceP *challenge,
6425   const struct GNUNET_CRYPTO_EddsaSignature *init_sig)
6426 {
6427   struct DvInitPS ip = { .purpose.purpose = htonl (
6428                            GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR),
6429                          .purpose.size = htonl (sizeof(ip)),
6430                          .monotonic_time = sender_monotonic_time,
6431                          .challenge = *challenge };
6432
6433   if (
6434     GNUNET_OK !=
6435     GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR,
6436                                 &ip,
6437                                 init_sig,
6438                                 &init->public_key))
6439   {
6440     GNUNET_break_op (0);
6441     return GNUNET_SYSERR;
6442   }
6443   return GNUNET_OK;
6444 }
6445
6446
6447 /**
6448  * Closure for #dv_neighbour_selection and #dv_neighbour_transmission.
6449  */
6450 struct NeighbourSelectionContext
6451 {
6452   /**
6453    * Original message we received.
6454    */
6455   const struct TransportDVLearnMessage *dvl;
6456
6457   /**
6458    * The hops taken.
6459    */
6460   const struct DVPathEntryP *hops;
6461
6462   /**
6463    * Time we received the message.
6464    */
6465   struct GNUNET_TIME_Absolute in_time;
6466
6467   /**
6468    * Offsets of the selected peers.
6469    */
6470   uint32_t selections[MAX_DV_DISCOVERY_SELECTION];
6471
6472   /**
6473    * Number of peers eligible for selection.
6474    */
6475   unsigned int num_eligible;
6476
6477   /**
6478    * Number of peers that were selected for forwarding.
6479    */
6480   unsigned int num_selections;
6481
6482   /**
6483    * Number of hops in @e hops
6484    */
6485   uint16_t nhops;
6486
6487   /**
6488    * Bitmap of bidirectional connections encountered.
6489    */
6490   uint16_t bi_history;
6491 };
6492
6493
6494 /**
6495  * Function called for each neighbour during #handle_dv_learn.
6496  *
6497  * @param cls a `struct NeighbourSelectionContext *`
6498  * @param pid identity of the peer
6499  * @param value a `struct Neighbour`
6500  * @return #GNUNET_YES (always)
6501  */
6502 static int
6503 dv_neighbour_selection (void *cls,
6504                         const struct GNUNET_PeerIdentity *pid,
6505                         void *value)
6506 {
6507   struct NeighbourSelectionContext *nsc = cls;
6508
6509   (void) value;
6510   if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator))
6511     return GNUNET_YES; /* skip initiator */
6512   for (unsigned int i = 0; i < nsc->nhops; i++)
6513     if (0 == GNUNET_memcmp (pid, &nsc->hops[i].hop))
6514       return GNUNET_YES;
6515   /* skip peers on path */
6516   nsc->num_eligible++;
6517   return GNUNET_YES;
6518 }
6519
6520
6521 /**
6522  * Function called for each neighbour during #handle_dv_learn.
6523  * We call #forward_dv_learn() on the neighbour(s) selected
6524  * during #dv_neighbour_selection().
6525  *
6526  * @param cls a `struct NeighbourSelectionContext *`
6527  * @param pid identity of the peer
6528  * @param value a `struct Neighbour`
6529  * @return #GNUNET_YES (always)
6530  */
6531 static int
6532 dv_neighbour_transmission (void *cls,
6533                            const struct GNUNET_PeerIdentity *pid,
6534                            void *value)
6535 {
6536   struct NeighbourSelectionContext *nsc = cls;
6537
6538   (void) value;
6539   if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator))
6540     return GNUNET_YES; /* skip initiator */
6541   for (unsigned int i = 0; i < nsc->nhops; i++)
6542     if (0 == GNUNET_memcmp (pid, &nsc->hops[i].hop))
6543       return GNUNET_YES;
6544   /* skip peers on path */
6545   for (unsigned int i = 0; i < nsc->num_selections; i++)
6546   {
6547     if (nsc->selections[i] == nsc->num_eligible)
6548     {
6549       forward_dv_learn (pid,
6550                         nsc->dvl,
6551                         nsc->bi_history,
6552                         nsc->nhops,
6553                         nsc->hops,
6554                         nsc->in_time);
6555       break;
6556     }
6557   }
6558   nsc->num_eligible++;
6559   return GNUNET_YES;
6560 }
6561
6562
6563 /**
6564  * Computes the number of neighbours we should forward a DVInit
6565  * message to given that it has so far taken @a hops_taken hops
6566  * though the network and that the number of neighbours we have
6567  * in total is @a neighbour_count, out of which @a eligible_count
6568  * are not yet on the path.
6569  *
6570  * NOTE: technically we might want to include NSE in the formula to
6571  * get a better grip on the overall network size. However, for now
6572  * using NSE here would create a dependency issue in the build system.
6573  * => Left for later, hardcoded to 50 for now.
6574  *
6575  * The goal of the fomula is that we want to reach a total of LOG(NSE)
6576  * peers via DV (`target_total`).  We want the reach to be spread out
6577  * over various distances to the origin, with a bias towards shorter
6578  * distances.
6579  *
6580  * We make the strong assumption that the network topology looks
6581  * "similar" at other hops, in particular the @a neighbour_count
6582  * should be comparable at other hops.
6583  *
6584  * If the local neighbourhood is densely connected, we expect that @a
6585  * eligible_count is close to @a neighbour_count minus @a hops_taken
6586  * as a lot of the path is already known. In that case, we should
6587  * forward to few(er) peers to try to find a path out of the
6588  * neighbourhood. OTOH, if @a eligible_count is close to @a
6589  * neighbour_count, we should forward to many peers as we are either
6590  * still close to the origin (i.e.  @a hops_taken is small) or because
6591  * we managed to get beyond a local cluster.  We express this as
6592  * the `boost_factor` using the square of the fraction of eligible
6593  * neighbours (so if only 50% are eligible, we boost by 1/4, but if
6594  * 99% are eligible, the 'boost' will be almost 1).
6595  *
6596  * Second, the more hops we have taken, the larger the problem of an
6597  * exponential traffic explosion gets.  So we take the `target_total`,
6598  * and compute our degree such that at each distance d 2^{-d} peers
6599  * are selected (corrected by the `boost_factor`).
6600  *
6601  * @param hops_taken number of hops DVInit has travelled so far
6602  * @param neighbour_count number of neighbours we have in total
6603  * @param eligible_count number of neighbours we could in
6604  *        theory forward to
6605  */
6606 static unsigned int
6607 calculate_fork_degree (unsigned int hops_taken,
6608                        unsigned int neighbour_count,
6609                        unsigned int eligible_count)
6610 {
6611   double target_total = 50.0; /* FIXME: use LOG(NSE)? */
6612   double eligible_ratio =
6613     ((double) eligible_count) / ((double) neighbour_count);
6614   double boost_factor = eligible_ratio * eligible_ratio;
6615   unsigned int rnd;
6616   double left;
6617
6618   if (hops_taken >= 64)
6619   {
6620     GNUNET_break (0);
6621     return 0;   /* precaution given bitshift below */
6622   }
6623   for (unsigned int i = 1; i < hops_taken; i++)
6624   {
6625     /* For each hop, subtract the expected number of targets
6626        reached at distance d (so what remains divided by 2^d) */
6627     target_total -= (target_total * boost_factor / (1LLU << i));
6628   }
6629   rnd =
6630     (unsigned int) floor (target_total * boost_factor / (1LLU << hops_taken));
6631   /* round up or down probabilistically depending on how close we were
6632      when floor()ing to rnd */
6633   left = target_total - (double) rnd;
6634   if (UINT32_MAX * left >
6635       GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX))
6636     rnd++; /* round up */
6637   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6638               "Forwarding DV learn message of %u hops %u(/%u/%u) times\n",
6639               hops_taken,
6640               rnd,
6641               eligible_count,
6642               neighbour_count);
6643   return rnd;
6644 }
6645
6646
6647 /**
6648  * Function called when peerstore is done storing a DV monotonic time.
6649  *
6650  * @param cls a `struct Neighbour`
6651  * @param success #GNUNET_YES if peerstore was successful
6652  */
6653 static void
6654 neighbour_store_dvmono_cb (void *cls, int success)
6655 {
6656   struct Neighbour *n = cls;
6657
6658   n->sc = NULL;
6659   if (GNUNET_YES != success)
6660     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
6661                 "Failed to store other peer's monotonic time in peerstore!\n");
6662 }
6663
6664
6665 /**
6666  * Communicator gave us a DV learn message.  Process the request.
6667  *
6668  * @param cls a `struct CommunicatorMessageContext` (must call
6669  * #finish_cmc_handling() when done)
6670  * @param dvl the message that was received
6671  */
6672 static void
6673 handle_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
6674 {
6675   struct CommunicatorMessageContext *cmc = cls;
6676   enum GNUNET_TRANSPORT_CommunicatorCharacteristics cc;
6677   int bi_hop;
6678   uint16_t nhops;
6679   uint16_t bi_history;
6680   const struct DVPathEntryP *hops;
6681   int do_fwd;
6682   int did_initiator;
6683   struct GNUNET_TIME_Absolute in_time;
6684   struct Neighbour *n;
6685
6686   nhops = ntohs (dvl->bidirectional);  /* 0 = sender is initiator */
6687   bi_history = ntohs (dvl->bidirectional);
6688   hops = (const struct DVPathEntryP *) &dvl[1];
6689   if (0 == nhops)
6690   {
6691     /* sanity check */
6692     if (0 != GNUNET_memcmp (&dvl->initiator, &cmc->im.sender))
6693     {
6694       GNUNET_break (0);
6695       finish_cmc_handling (cmc);
6696       return;
6697     }
6698   }
6699   else
6700   {
6701     /* sanity check */
6702     if (0 != GNUNET_memcmp (&hops[nhops - 1].hop, &cmc->im.sender))
6703     {
6704       GNUNET_break (0);
6705       finish_cmc_handling (cmc);
6706       return;
6707     }
6708   }
6709
6710   GNUNET_assert (CT_COMMUNICATOR == cmc->tc->type);
6711   cc = cmc->tc->details.communicator.cc;
6712   bi_hop = (GNUNET_TRANSPORT_CC_RELIABLE ==
6713             cc); // FIXME: add bi-directional flag to cc?
6714   in_time = GNUNET_TIME_absolute_get ();
6715
6716   /* continue communicator here, everything else can happen asynchronous! */
6717   finish_cmc_handling (cmc);
6718
6719   n = lookup_neighbour (&dvl->initiator);
6720   if (NULL != n)
6721   {
6722     if ((n->dv_monotime_available == GNUNET_YES) &&
6723         (GNUNET_TIME_absolute_ntoh (dvl->monotonic_time).abs_value_us <
6724          n->last_dv_learn_monotime.abs_value_us))
6725     {
6726       GNUNET_STATISTICS_update (GST_stats,
6727                                 "# DV learn discarded due to time travel",
6728                                 1,
6729                                 GNUNET_NO);
6730       return;
6731     }
6732     if (GNUNET_OK != validate_dv_initiator_signature (dvl->monotonic_time,
6733                                                       &dvl->initiator,
6734                                                       &dvl->challenge,
6735                                                       &dvl->init_sig))
6736     {
6737       GNUNET_break_op (0);
6738       return;
6739     }
6740     n->last_dv_learn_monotime = GNUNET_TIME_absolute_ntoh (dvl->monotonic_time);
6741     if (GNUNET_YES == n->dv_monotime_available)
6742     {
6743       if (NULL != n->sc)
6744         GNUNET_PEERSTORE_store_cancel (n->sc);
6745       n->sc =
6746         GNUNET_PEERSTORE_store (peerstore,
6747                                 "transport",
6748                                 &dvl->initiator,
6749                                 GNUNET_PEERSTORE_TRANSPORT_DVLEARN_MONOTIME,
6750                                 &dvl->monotonic_time,
6751                                 sizeof(dvl->monotonic_time),
6752                                 GNUNET_TIME_UNIT_FOREVER_ABS,
6753                                 GNUNET_PEERSTORE_STOREOPTION_REPLACE,
6754                                 &neighbour_store_dvmono_cb,
6755                                 n);
6756     }
6757   }
6758   /* OPTIMIZE-FIXME: asynchronously (!) verify signatures!,
6759      If signature verification load too high, implement random drop strategy */
6760   for (unsigned int i = 0; i < nhops; i++)
6761   {
6762     struct DvHopPS dhp = { .purpose.purpose =
6763                              htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_HOP),
6764                            .purpose.size = htonl (sizeof(dhp)),
6765                            .pred = (0 == i) ? dvl->initiator : hops[i - 1].hop,
6766                            .succ = (nhops == i + 1) ? GST_my_identity
6767                                    : hops[i + 1].hop,
6768                            .challenge = dvl->challenge };
6769
6770     if (GNUNET_OK !=
6771         GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_HOP,
6772                                     &dhp,
6773                                     &hops[i].hop_sig,
6774                                     &hops[i].hop.public_key))
6775     {
6776       GNUNET_break_op (0);
6777       return;
6778     }
6779   }
6780
6781   if (GNUNET_EXTRA_LOGGING > 0)
6782   {
6783     char *path;
6784
6785     path = GNUNET_strdup (GNUNET_i2s (&dvl->initiator));
6786     for (unsigned int i = 0; i < nhops; i++)
6787     {
6788       char *tmp;
6789
6790       GNUNET_asprintf (&tmp,
6791                        "%s%s%s",
6792                        path,
6793                        (bi_history & (1 << (nhops - i))) ? "<->" : "-->",
6794                        GNUNET_i2s (&hops[i].hop));
6795       GNUNET_free (path);
6796       path = tmp;
6797     }
6798     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6799                 "Received DVInit via %s%s%s\n",
6800                 path,
6801                 bi_hop ? "<->" : "-->",
6802                 GNUNET_i2s (&GST_my_identity));
6803     GNUNET_free (path);
6804   }
6805
6806   do_fwd = GNUNET_YES;
6807   if (0 == GNUNET_memcmp (&GST_my_identity, &dvl->initiator))
6808   {
6809     struct GNUNET_PeerIdentity path[nhops + 1];
6810     struct GNUNET_TIME_Relative host_latency_sum;
6811     struct GNUNET_TIME_Relative latency;
6812     struct GNUNET_TIME_Relative network_latency;
6813
6814     /* We initiated this, learn the forward path! */
6815     path[0] = GST_my_identity;
6816     path[1] = hops[0].hop;
6817     host_latency_sum = GNUNET_TIME_relative_ntoh (dvl->non_network_delay);
6818
6819     // Need also something to lookup initiation time
6820     // to compute RTT! -> add RTT argument here?
6821     latency = GNUNET_TIME_UNIT_FOREVER_REL;   // FIXME: initialize properly
6822     // (based on dvl->challenge, we can identify time of origin!)
6823
6824     network_latency = GNUNET_TIME_relative_subtract (latency, host_latency_sum);
6825     /* assumption: latency on all links is the same */
6826     network_latency = GNUNET_TIME_relative_divide (network_latency, nhops);
6827
6828     for (unsigned int i = 2; i <= nhops; i++)
6829     {
6830       struct GNUNET_TIME_Relative ilat;
6831
6832       /* assumption: linear latency increase per hop */
6833       ilat = GNUNET_TIME_relative_multiply (network_latency, i);
6834       path[i] = hops[i - 1].hop;
6835       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6836                   "Learned path with %u hops to %s with latency %s\n",
6837                   i,
6838                   GNUNET_i2s (&path[i]),
6839                   GNUNET_STRINGS_relative_time_to_string (ilat, GNUNET_YES));
6840       learn_dv_path (path,
6841                      i,
6842                      ilat,
6843                      GNUNET_TIME_relative_to_absolute (
6844                        ADDRESS_VALIDATION_LIFETIME));
6845     }
6846     /* as we initiated, do not forward again (would be circular!) */
6847     do_fwd = GNUNET_NO;
6848     return;
6849   }
6850   if (bi_hop)
6851   {
6852     /* last hop was bi-directional, we could learn something here! */
6853     struct GNUNET_PeerIdentity path[nhops + 2];
6854
6855     path[0] = GST_my_identity;
6856     path[1] = hops[nhops - 1].hop;   /* direct neighbour == predecessor! */
6857     for (unsigned int i = 0; i < nhops; i++)
6858     {
6859       int iret;
6860
6861       if (0 == (bi_history & (1 << i)))
6862         break;     /* i-th hop not bi-directional, stop learning! */
6863       if (i == nhops - 1)
6864       {
6865         path[i + 2] = dvl->initiator;
6866       }
6867       else
6868       {
6869         path[i + 2] = hops[nhops - i - 2].hop;
6870       }
6871
6872       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6873                   "Learned inverse path with %u hops to %s\n",
6874                   i + 1,
6875                   GNUNET_i2s (&path[i + 2]));
6876       iret = learn_dv_path (path,
6877                             i + 2,
6878                             GNUNET_TIME_UNIT_FOREVER_REL,
6879                             GNUNET_TIME_UNIT_ZERO_ABS);
6880       if (GNUNET_SYSERR == iret)
6881       {
6882         /* path invalid or too long to be interesting for US, thus should also
6883            not be interesting to our neighbours, cut path when forwarding to
6884            'i' hops, except of course for the one that goes back to the
6885            initiator */
6886         GNUNET_STATISTICS_update (GST_stats,
6887                                   "# DV learn not forwarded due invalidity of path",
6888                                   1,
6889                                   GNUNET_NO);
6890         do_fwd = GNUNET_NO;
6891         break;
6892       }
6893       if ((GNUNET_NO == iret) && (nhops == i + 1))
6894       {
6895         /* we have better paths, and this is the longest target,
6896            so there cannot be anything interesting later */
6897         GNUNET_STATISTICS_update (GST_stats,
6898                                   "# DV learn not forwarded, got better paths",
6899                                   1,
6900                                   GNUNET_NO);
6901         do_fwd = GNUNET_NO;
6902         break;
6903       }
6904     }
6905   }
6906
6907   if (MAX_DV_HOPS_ALLOWED == nhops)
6908   {
6909     /* At limit, we're out of here! */
6910     finish_cmc_handling (cmc);
6911     return;
6912   }
6913
6914   /* Forward to initiator, if path non-trivial and possible */
6915   bi_history = (bi_history << 1) | (bi_hop ? 1 : 0);
6916   did_initiator = GNUNET_NO;
6917   if ((1 < nhops) &&
6918       (GNUNET_YES ==
6919        GNUNET_CONTAINER_multipeermap_contains (neighbours, &dvl->initiator)))
6920   {
6921     /* send back to origin! */
6922     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6923                 "Sending DVL back to initiator %s\n",
6924                 GNUNET_i2s (&dvl->initiator));
6925     forward_dv_learn (&dvl->initiator, dvl, bi_history, nhops, hops, in_time);
6926     did_initiator = GNUNET_YES;
6927   }
6928   /* We forward under two conditions: either we still learned something
6929      ourselves (do_fwd), or the path was darn short and thus the initiator is
6930      likely to still be very interested in this (and we did NOT already
6931      send it back to the initiator) */
6932   if ((do_fwd) || ((nhops < MIN_DV_PATH_LENGTH_FOR_INITIATOR) &&
6933                    (GNUNET_NO == did_initiator)))
6934   {
6935     /* Pick random neighbours that are not yet on the path */
6936     struct NeighbourSelectionContext nsc;
6937     unsigned int n_cnt;
6938
6939     n_cnt = GNUNET_CONTAINER_multipeermap_size (neighbours);
6940     nsc.nhops = nhops;
6941     nsc.dvl = dvl;
6942     nsc.bi_history = bi_history;
6943     nsc.hops = hops;
6944     nsc.in_time = in_time;
6945     nsc.num_eligible = 0;
6946     GNUNET_CONTAINER_multipeermap_iterate (neighbours,
6947                                            &dv_neighbour_selection,
6948                                            &nsc);
6949     if (0 == nsc.num_eligible)
6950       return;   /* done here, cannot forward to anyone else */
6951     nsc.num_selections = calculate_fork_degree (nhops, n_cnt, nsc.num_eligible);
6952     nsc.num_selections =
6953       GNUNET_MIN (MAX_DV_DISCOVERY_SELECTION, nsc.num_selections);
6954     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6955                 "Forwarding DVL to %u other peers\n",
6956                 nsc.num_selections);
6957     for (unsigned int i = 0; i < nsc.num_selections; i++)
6958       nsc.selections[i] =
6959         (nsc.num_selections == n_cnt)
6960         ? i   /* all were selected, avoid collisions by chance */
6961         : GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, n_cnt);
6962     nsc.num_eligible = 0;
6963     GNUNET_CONTAINER_multipeermap_iterate (neighbours,
6964                                            &dv_neighbour_transmission,
6965                                            &nsc);
6966   }
6967 }
6968
6969
6970 /**
6971  * Communicator gave us a DV box.  Check the message.
6972  *
6973  * @param cls a `struct CommunicatorMessageContext`
6974  * @param dvb the send message that was sent
6975  * @return #GNUNET_YES if message is well-formed
6976  */
6977 static int
6978 check_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
6979 {
6980   uint16_t size = ntohs (dvb->header.size);
6981   uint16_t num_hops = ntohs (dvb->num_hops);
6982   const struct GNUNET_PeerIdentity *hops =
6983     (const struct GNUNET_PeerIdentity *) &dvb[1];
6984
6985   (void) cls;
6986   if (size < sizeof(*dvb) + num_hops * sizeof(struct GNUNET_PeerIdentity)
6987       + sizeof(struct GNUNET_MessageHeader))
6988   {
6989     GNUNET_break_op (0);
6990     return GNUNET_SYSERR;
6991   }
6992   /* This peer must not be on the path */
6993   for (unsigned int i = 0; i < num_hops; i++)
6994     if (0 == GNUNET_memcmp (&hops[i], &GST_my_identity))
6995     {
6996       GNUNET_break_op (0);
6997       return GNUNET_SYSERR;
6998     }
6999   return GNUNET_YES;
7000 }
7001
7002
7003 /**
7004  * Create a DV Box message and queue it for transmission to
7005  * @ea next_hop.
7006  *
7007  * @param next_hop peer to receive the message next
7008  * @param total_hops how many hops did the message take so far
7009  * @param num_hops length of the @a hops array
7010  * @param origin origin of the message
7011  * @param hops next peer(s) to the destination, including destination
7012  * @param payload payload of the box
7013  * @param payload_size number of bytes in @a payload
7014  */
7015 static void
7016 forward_dv_box (struct Neighbour *next_hop,
7017                 const struct TransportDVBoxMessage *hdr,
7018                 uint16_t total_hops,
7019                 uint16_t num_hops,
7020                 const struct GNUNET_PeerIdentity *hops,
7021                 const void *enc_payload,
7022                 uint16_t enc_payload_size)
7023 {
7024   struct VirtualLink *vl = next_hop->vl;
7025   struct PendingMessage *pm;
7026   size_t msg_size;
7027   char *buf;
7028   struct GNUNET_PeerIdentity *dhops;
7029
7030   GNUNET_assert (NULL != vl);
7031   msg_size = sizeof(struct TransportDVBoxMessage)
7032              + num_hops * sizeof(struct GNUNET_PeerIdentity) + enc_payload_size;
7033   pm = GNUNET_malloc (sizeof(struct PendingMessage) + msg_size);
7034   pm->pmt = PMT_DV_BOX;
7035   pm->vl = vl;
7036   pm->timeout = GNUNET_TIME_relative_to_absolute (DV_FORWARD_TIMEOUT);
7037   pm->logging_uuid = logging_uuid_gen++;
7038   pm->prefs = GNUNET_MQ_PRIO_BACKGROUND;
7039   pm->bytes_msg = msg_size;
7040   buf = (char *) &pm[1];
7041   memcpy (buf, hdr, sizeof(*hdr));
7042   dhops =
7043     (struct GNUNET_PeerIdentity *) &buf[sizeof(struct TransportDVBoxMessage)];
7044   memcpy (dhops, hops, num_hops * sizeof(struct GNUNET_PeerIdentity));
7045   memcpy (&dhops[num_hops], enc_payload, enc_payload_size);
7046   GNUNET_CONTAINER_MDLL_insert (vl,
7047                                 vl->pending_msg_head,
7048                                 vl->pending_msg_tail,
7049                                 pm);
7050   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7051               "Created pending message %llu for DV Box with next hop %s (%u/%u)\n",
7052               pm->logging_uuid,
7053               GNUNET_i2s (&next_hop->pid),
7054               (unsigned int) num_hops,
7055               (unsigned int) total_hops);
7056   check_vl_transmission (vl);
7057 }
7058
7059
7060 /**
7061  * Free data structures associated with @a b.
7062  *
7063  * @param b data structure to release
7064  */
7065 static void
7066 free_backtalker (struct Backtalker *b)
7067 {
7068   if (NULL != b->get)
7069   {
7070     GNUNET_PEERSTORE_iterate_cancel (b->get);
7071     b->get = NULL;
7072     GNUNET_assert (NULL != b->cmc);
7073     finish_cmc_handling (b->cmc);
7074     b->cmc = NULL;
7075   }
7076   if (NULL != b->task)
7077   {
7078     GNUNET_SCHEDULER_cancel (b->task);
7079     b->task = NULL;
7080   }
7081   if (NULL != b->sc)
7082   {
7083     GNUNET_PEERSTORE_store_cancel (b->sc);
7084     b->sc = NULL;
7085   }
7086   GNUNET_assert (
7087     GNUNET_YES ==
7088     GNUNET_CONTAINER_multipeermap_remove (backtalkers, &b->pid, b));
7089   GNUNET_free (b);
7090 }
7091
7092
7093 /**
7094  * Callback to free backtalker records.
7095  *
7096  * @param cls NULL
7097  * @param pid unused
7098  * @param value a `struct Backtalker`
7099  * @return #GNUNET_OK (always)
7100  */
7101 static int
7102 free_backtalker_cb (void *cls,
7103                     const struct GNUNET_PeerIdentity *pid,
7104                     void *value)
7105 {
7106   struct Backtalker *b = value;
7107
7108   (void) cls;
7109   (void) pid;
7110   free_backtalker (b);
7111   return GNUNET_OK;
7112 }
7113
7114
7115 /**
7116  * Function called when it is time to clean up a backtalker.
7117  *
7118  * @param cls a `struct Backtalker`
7119  */
7120 static void
7121 backtalker_timeout_cb (void *cls)
7122 {
7123   struct Backtalker *b = cls;
7124
7125   b->task = NULL;
7126   if (0 != GNUNET_TIME_absolute_get_remaining (b->timeout).rel_value_us)
7127   {
7128     b->task = GNUNET_SCHEDULER_add_at (b->timeout, &backtalker_timeout_cb, b);
7129     return;
7130   }
7131   GNUNET_assert (NULL == b->sc);
7132   free_backtalker (b);
7133 }
7134
7135
7136 /**
7137  * Function called with the monotonic time of a backtalker
7138  * by PEERSTORE. Updates the time and continues processing.
7139  *
7140  * @param cls a `struct Backtalker`
7141  * @param record the information found, NULL for the last call
7142  * @param emsg error message
7143  */
7144 static void
7145 backtalker_monotime_cb (void *cls,
7146                         const struct GNUNET_PEERSTORE_Record *record,
7147                         const char *emsg)
7148 {
7149   struct Backtalker *b = cls;
7150   struct GNUNET_TIME_AbsoluteNBO *mtbe;
7151   struct GNUNET_TIME_Absolute mt;
7152
7153   (void) emsg;
7154   if (NULL == record)
7155   {
7156     /* we're done with #backtalker_monotime_cb() invocations,
7157        continue normal processing */
7158     b->get = NULL;
7159     GNUNET_assert (NULL != b->cmc);
7160     if (0 != b->body_size)
7161       demultiplex_with_cmc (b->cmc,
7162                             (const struct GNUNET_MessageHeader *) &b[1]);
7163     else
7164       finish_cmc_handling (b->cmc);
7165     b->cmc = NULL;
7166     return;
7167   }
7168   if (sizeof(*mtbe) != record->value_size)
7169   {
7170     GNUNET_break (0);
7171     return;
7172   }
7173   mtbe = record->value;
7174   mt = GNUNET_TIME_absolute_ntoh (*mtbe);
7175   if (mt.abs_value_us > b->monotonic_time.abs_value_us)
7176   {
7177     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7178                 "Backtalker message from %s dropped, monotime in the past\n",
7179                 GNUNET_i2s (&b->pid));
7180     GNUNET_STATISTICS_update (
7181       GST_stats,
7182       "# Backchannel messages dropped: monotonic time not increasing",
7183       1,
7184       GNUNET_NO);
7185     b->monotonic_time = mt;
7186     /* Setting body_size to 0 prevents call to #forward_backchannel_payload()
7187      */
7188     b->body_size = 0;
7189     return;
7190   }
7191 }
7192
7193
7194 /**
7195  * Function called by PEERSTORE when the store operation of
7196  * a backtalker's monotonic time is complete.
7197  *
7198  * @param cls the `struct Backtalker`
7199  * @param success #GNUNET_OK on success
7200  */
7201 static void
7202 backtalker_monotime_store_cb (void *cls, int success)
7203 {
7204   struct Backtalker *b = cls;
7205
7206   if (GNUNET_OK != success)
7207   {
7208     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
7209                 "Failed to store backtalker's monotonic time in PEERSTORE!\n");
7210   }
7211   b->sc = NULL;
7212   b->task = GNUNET_SCHEDULER_add_at (b->timeout, &backtalker_timeout_cb, b);
7213 }
7214
7215
7216 /**
7217  * The backtalker @a b monotonic time changed. Update PEERSTORE.
7218  *
7219  * @param b a backtalker with updated monotonic time
7220  */
7221 static void
7222 update_backtalker_monotime (struct Backtalker *b)
7223 {
7224   struct GNUNET_TIME_AbsoluteNBO mtbe;
7225
7226   if (NULL != b->sc)
7227   {
7228     GNUNET_PEERSTORE_store_cancel (b->sc);
7229     b->sc = NULL;
7230   }
7231   else
7232   {
7233     GNUNET_SCHEDULER_cancel (b->task);
7234     b->task = NULL;
7235   }
7236   mtbe = GNUNET_TIME_absolute_hton (b->monotonic_time);
7237   b->sc =
7238     GNUNET_PEERSTORE_store (peerstore,
7239                             "transport",
7240                             &b->pid,
7241                             GNUNET_PEERSTORE_TRANSPORT_BACKCHANNEL_MONOTIME,
7242                             &mtbe,
7243                             sizeof(mtbe),
7244                             GNUNET_TIME_UNIT_FOREVER_ABS,
7245                             GNUNET_PEERSTORE_STOREOPTION_REPLACE,
7246                             &backtalker_monotime_store_cb,
7247                             b);
7248 }
7249
7250
7251 /**
7252  * Communicator gave us a DV box.  Process the request.
7253  *
7254  * @param cls a `struct CommunicatorMessageContext` (must call
7255  * #finish_cmc_handling() when done)
7256  * @param dvb the message that was received
7257  */
7258 static void
7259 handle_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
7260 {
7261   struct CommunicatorMessageContext *cmc = cls;
7262   uint16_t size = ntohs (dvb->header.size) - sizeof(*dvb);
7263   uint16_t num_hops = ntohs (dvb->num_hops);
7264   const struct GNUNET_PeerIdentity *hops =
7265     (const struct GNUNET_PeerIdentity *) &dvb[1];
7266   const char *enc_payload = (const char *) &hops[num_hops];
7267   uint16_t enc_payload_size =
7268     size - (num_hops * sizeof(struct GNUNET_PeerIdentity));
7269   struct DVKeyState key;
7270   struct GNUNET_HashCode hmac;
7271   const char *hdr;
7272   size_t hdr_len;
7273
7274   if (GNUNET_EXTRA_LOGGING > 0)
7275   {
7276     char *path;
7277
7278     path = GNUNET_strdup (GNUNET_i2s (&GST_my_identity));
7279     for (unsigned int i = 0; i < num_hops; i++)
7280     {
7281       char *tmp;
7282
7283       GNUNET_asprintf (&tmp, "%s->%s", path, GNUNET_i2s (&hops[i]));
7284       GNUNET_free (path);
7285       path = tmp;
7286     }
7287     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7288                 "Received DVBox with remainig path %s\n",
7289                 path);
7290     GNUNET_free (path);
7291   }
7292
7293   if (num_hops > 0)
7294   {
7295     /* We're trying from the end of the hops array, as we may be
7296        able to find a shortcut unknown to the origin that way */
7297     for (int i = num_hops - 1; i >= 0; i--)
7298     {
7299       struct Neighbour *n;
7300
7301       if (0 == GNUNET_memcmp (&hops[i], &GST_my_identity))
7302       {
7303         GNUNET_break_op (0);
7304         finish_cmc_handling (cmc);
7305         return;
7306       }
7307       n = lookup_neighbour (&hops[i]);
7308       if (NULL == n)
7309         continue;
7310       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7311                   "Skipping %u/%u hops ahead while routing DV Box\n",
7312                   i,
7313                   num_hops);
7314       forward_dv_box (n,
7315                       dvb,
7316                       ntohs (dvb->total_hops) + 1,
7317                       num_hops - i - 1,    /* number of hops left */
7318                       &hops[i + 1],    /* remaining hops */
7319                       enc_payload,
7320                       enc_payload_size);
7321       GNUNET_STATISTICS_update (GST_stats,
7322                                 "# DV hops skipped routing boxes",
7323                                 i,
7324                                 GNUNET_NO);
7325       GNUNET_STATISTICS_update (GST_stats,
7326                                 "# DV boxes routed (total)",
7327                                 1,
7328                                 GNUNET_NO);
7329       finish_cmc_handling (cmc);
7330       return;
7331     }
7332     /* Woopsie, next hop not in neighbours, drop! */
7333     GNUNET_STATISTICS_update (GST_stats,
7334                               "# DV Boxes dropped: next hop unknown",
7335                               1,
7336                               GNUNET_NO);
7337     finish_cmc_handling (cmc);
7338     return;
7339   }
7340   /* We are the target. Unbox and handle message. */
7341   GNUNET_STATISTICS_update (GST_stats,
7342                             "# DV boxes opened (ultimate target)",
7343                             1,
7344                             GNUNET_NO);
7345   cmc->total_hops = ntohs (dvb->total_hops);
7346
7347   dh_key_derive_eph_pub (&dvb->ephemeral_key, &dvb->iv, &key);
7348   hdr = (const char *) &dvb[1];
7349   hdr_len = ntohs (dvb->header.size) - sizeof(*dvb);
7350   dv_hmac (&key, &hmac, hdr, hdr_len);
7351   if (0 != GNUNET_memcmp (&hmac, &dvb->hmac))
7352   {
7353     /* HMAC missmatch, disard! */
7354     GNUNET_break_op (0);
7355     finish_cmc_handling (cmc);
7356     return;
7357   }
7358   /* begin actual decryption */
7359   {
7360     struct Backtalker *b;
7361     struct GNUNET_TIME_Absolute monotime;
7362     struct TransportDVBoxPayloadP ppay;
7363     char body[hdr_len - sizeof(ppay)] GNUNET_ALIGN;
7364     const struct GNUNET_MessageHeader *mh =
7365       (const struct GNUNET_MessageHeader *) body;
7366
7367     GNUNET_assert (hdr_len >=
7368                    sizeof(ppay) + sizeof(struct GNUNET_MessageHeader));
7369     dv_decrypt (&key, &ppay, hdr, sizeof(ppay));
7370     dv_decrypt (&key, &body, &hdr[sizeof(ppay)], hdr_len - sizeof(ppay));
7371     dv_key_clean (&key);
7372     if (ntohs (mh->size) != sizeof(body))
7373     {
7374       GNUNET_break_op (0);
7375       finish_cmc_handling (cmc);
7376       return;
7377     }
7378     /* need to prevent box-in-a-box (and DV_LEARN) so check inbox type! */
7379     switch (ntohs (mh->type))
7380     {
7381     case GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX:
7382       GNUNET_break_op (0);
7383       finish_cmc_handling (cmc);
7384       return;
7385
7386     case GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN:
7387       GNUNET_break_op (0);
7388       finish_cmc_handling (cmc);
7389       return;
7390
7391     default:
7392       /* permitted, continue */
7393       break;
7394     }
7395     monotime = GNUNET_TIME_absolute_ntoh (ppay.monotonic_time);
7396     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7397                 "Decrypted backtalk from %s\n",
7398                 GNUNET_i2s (&ppay.sender));
7399     b = GNUNET_CONTAINER_multipeermap_get (backtalkers, &ppay.sender);
7400     if ((NULL != b) && (monotime.abs_value_us < b->monotonic_time.abs_value_us))
7401     {
7402       GNUNET_STATISTICS_update (
7403         GST_stats,
7404         "# Backchannel messages dropped: monotonic time not increasing",
7405         1,
7406         GNUNET_NO);
7407       finish_cmc_handling (cmc);
7408       return;
7409     }
7410     if ((NULL == b) ||
7411         (0 != GNUNET_memcmp (&b->last_ephemeral, &dvb->ephemeral_key)))
7412     {
7413       /* Check signature */
7414       struct EphemeralConfirmationPS ec;
7415
7416       ec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL);
7417       ec.purpose.size = htonl (sizeof(ec));
7418       ec.target = GST_my_identity;
7419       ec.ephemeral_key = dvb->ephemeral_key;
7420       if (
7421         GNUNET_OK !=
7422         GNUNET_CRYPTO_eddsa_verify (
7423           GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL,
7424           &ec,
7425           &ppay.sender_sig,
7426           &ppay.sender.public_key))
7427       {
7428         /* Signature invalid, disard! */
7429         GNUNET_break_op (0);
7430         finish_cmc_handling (cmc);
7431         return;
7432       }
7433     }
7434     /* Update sender, we now know the real origin! */
7435     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7436                 "DVBox received for me from %s via %s\n",
7437                 GNUNET_i2s2 (&ppay.sender),
7438                 GNUNET_i2s (&cmc->im.sender));
7439     cmc->im.sender = ppay.sender;
7440
7441     if (NULL != b)
7442     {
7443       /* update key cache and mono time */
7444       b->last_ephemeral = dvb->ephemeral_key;
7445       b->monotonic_time = monotime;
7446       update_backtalker_monotime (b);
7447       b->timeout =
7448         GNUNET_TIME_relative_to_absolute (BACKCHANNEL_INACTIVITY_TIMEOUT);
7449
7450       demultiplex_with_cmc (cmc, mh);
7451       return;
7452     }
7453     /* setup data structure to cache signature AND check
7454        monotonic time with PEERSTORE before forwarding backchannel payload */
7455     b = GNUNET_malloc (sizeof(struct Backtalker) + sizeof(body));
7456     b->pid = ppay.sender;
7457     b->body_size = sizeof(body);
7458     memcpy (&b[1], body, sizeof(body));
7459     GNUNET_assert (GNUNET_YES ==
7460                    GNUNET_CONTAINER_multipeermap_put (
7461                      backtalkers,
7462                      &b->pid,
7463                      b,
7464                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
7465     b->monotonic_time = monotime; /* NOTE: to be checked still! */
7466     b->cmc = cmc;
7467     b->timeout =
7468       GNUNET_TIME_relative_to_absolute (BACKCHANNEL_INACTIVITY_TIMEOUT);
7469     b->task = GNUNET_SCHEDULER_add_at (b->timeout, &backtalker_timeout_cb, b);
7470     b->get =
7471       GNUNET_PEERSTORE_iterate (peerstore,
7472                                 "transport",
7473                                 &b->pid,
7474                                 GNUNET_PEERSTORE_TRANSPORT_BACKCHANNEL_MONOTIME,
7475                                 &backtalker_monotime_cb,
7476                                 b);
7477   } /* end actual decryption */
7478 }
7479
7480
7481 /**
7482  * Client notified us about transmission from a peer.  Process the request.
7483  *
7484  * @param cls a `struct TransportClient` which sent us the message
7485  * @param obm the send message that was sent
7486  * @return #GNUNET_YES if message is well-formed
7487  */
7488 static int
7489 check_incoming_msg (void *cls,
7490                     const struct GNUNET_TRANSPORT_IncomingMessage *im)
7491 {
7492   struct TransportClient *tc = cls;
7493
7494   if (CT_COMMUNICATOR != tc->type)
7495   {
7496     GNUNET_break (0);
7497     return GNUNET_SYSERR;
7498   }
7499   GNUNET_MQ_check_boxed_message (im);
7500   return GNUNET_OK;
7501 }
7502
7503
7504 /**
7505  * Closure for #check_known_address.
7506  */
7507 struct CheckKnownAddressContext
7508 {
7509   /**
7510    * Set to the address we are looking for.
7511    */
7512   const char *address;
7513
7514   /**
7515    * Set to a matching validation state, if one was found.
7516    */
7517   struct ValidationState *vs;
7518 };
7519
7520
7521 /**
7522  * Test if the validation state in @a value matches the
7523  * address from @a cls.
7524  *
7525  * @param cls a `struct CheckKnownAddressContext`
7526  * @param pid unused (must match though)
7527  * @param value a `struct ValidationState`
7528  * @return #GNUNET_OK if not matching, #GNUNET_NO if match found
7529  */
7530 static int
7531 check_known_address (void *cls,
7532                      const struct GNUNET_PeerIdentity *pid,
7533                      void *value)
7534 {
7535   struct CheckKnownAddressContext *ckac = cls;
7536   struct ValidationState *vs = value;
7537
7538   (void) pid;
7539   if (0 != strcmp (vs->address, ckac->address))
7540     return GNUNET_OK;
7541   ckac->vs = vs;
7542   return GNUNET_NO;
7543 }
7544
7545
7546 /**
7547  * Task run periodically to validate some address based on #validation_heap.
7548  *
7549  * @param cls NULL
7550  */
7551 static void
7552 validation_start_cb (void *cls);
7553
7554
7555 /**
7556  * Set the time for next_challenge of @a vs to @a new_time.
7557  * Updates the heap and if necessary reschedules the job.
7558  *
7559  * @param vs validation state to update
7560  * @param new_time new time for revalidation
7561  */
7562 static void
7563 update_next_challenge_time (struct ValidationState *vs,
7564                             struct GNUNET_TIME_Absolute new_time)
7565 {
7566   struct GNUNET_TIME_Relative delta;
7567
7568   if (new_time.abs_value_us == vs->next_challenge.abs_value_us)
7569     return; /* be lazy */
7570   vs->next_challenge = new_time;
7571   if (NULL == vs->hn)
7572     vs->hn =
7573       GNUNET_CONTAINER_heap_insert (validation_heap, vs, new_time.abs_value_us);
7574   else
7575     GNUNET_CONTAINER_heap_update_cost (vs->hn, new_time.abs_value_us);
7576   if ((vs != GNUNET_CONTAINER_heap_peek (validation_heap)) &&
7577       (NULL != validation_task))
7578     return;
7579   if (NULL != validation_task)
7580     GNUNET_SCHEDULER_cancel (validation_task);
7581   /* randomize a bit */
7582   delta.rel_value_us =
7583     GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
7584                               MIN_DELAY_ADDRESS_VALIDATION.rel_value_us);
7585   new_time = GNUNET_TIME_absolute_add (new_time, delta);
7586   validation_task =
7587     GNUNET_SCHEDULER_add_at (new_time, &validation_start_cb, NULL);
7588 }
7589
7590
7591 /**
7592  * Start address validation.
7593  *
7594  * @param pid peer the @a address is for
7595  * @param address an address to reach @a pid (presumably)
7596  */
7597 static void
7598 start_address_validation (const struct GNUNET_PeerIdentity *pid,
7599                           const char *address)
7600 {
7601   struct GNUNET_TIME_Absolute now;
7602   struct ValidationState *vs;
7603   struct CheckKnownAddressContext ckac = { .address = address, .vs = NULL };
7604
7605   (void) GNUNET_CONTAINER_multipeermap_get_multiple (validation_map,
7606                                                      pid,
7607                                                      &check_known_address,
7608                                                      &ckac);
7609   if (NULL != (vs = ckac.vs))
7610   {
7611     /* if 'vs' is not currently valid, we need to speed up retrying the
7612      * validation */
7613     if (vs->validated_until.abs_value_us < vs->next_challenge.abs_value_us)
7614     {
7615       /* reduce backoff as we got a fresh advertisement */
7616       vs->challenge_backoff =
7617         GNUNET_TIME_relative_min (FAST_VALIDATION_CHALLENGE_FREQ,
7618                                   GNUNET_TIME_relative_divide (
7619                                     vs->challenge_backoff,
7620                                     2));
7621       update_next_challenge_time (vs,
7622                                   GNUNET_TIME_relative_to_absolute (
7623                                     vs->challenge_backoff));
7624     }
7625     return;
7626   }
7627   now = GNUNET_TIME_absolute_get ();
7628   vs = GNUNET_new (struct ValidationState);
7629   vs->pid = *pid;
7630   vs->valid_until =
7631     GNUNET_TIME_relative_to_absolute (ADDRESS_VALIDATION_LIFETIME);
7632   vs->first_challenge_use = now;
7633   vs->validation_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
7634   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
7635                               &vs->challenge,
7636                               sizeof(vs->challenge));
7637   vs->address = GNUNET_strdup (address);
7638   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7639               "Starting address validation `%s' of peer %s using challenge %s\n",
7640               address,
7641               GNUNET_i2s (pid),
7642               GNUNET_sh2s (&vs->challenge.value));
7643   GNUNET_assert (GNUNET_YES ==
7644                  GNUNET_CONTAINER_multipeermap_put (
7645                    validation_map,
7646                    &vs->pid,
7647                    vs,
7648                    GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
7649   update_next_challenge_time (vs, now);
7650 }
7651
7652
7653 /**
7654  * Function called by PEERSTORE for each matching record.
7655  *
7656  * @param cls closure, a `struct IncomingRequest`
7657  * @param record peerstore record information
7658  * @param emsg error message, or NULL if no errors
7659  */
7660 static void
7661 handle_hello_for_incoming (void *cls,
7662                            const struct GNUNET_PEERSTORE_Record *record,
7663                            const char *emsg)
7664 {
7665   struct IncomingRequest *ir = cls;
7666   const char *val;
7667
7668   if (NULL != emsg)
7669   {
7670     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
7671                 "Got failure from PEERSTORE: %s\n",
7672                 emsg);
7673     return;
7674   }
7675   val = record->value;
7676   if ((0 == record->value_size) || ('\0' != val[record->value_size - 1]))
7677   {
7678     GNUNET_break (0);
7679     return;
7680   }
7681   start_address_validation (&ir->pid, (const char *) record->value);
7682 }
7683
7684
7685 /**
7686  * Communicator gave us a transport address validation challenge.  Process the
7687  * request.
7688  *
7689  * @param cls a `struct CommunicatorMessageContext` (must call
7690  * #finish_cmc_handling() when done)
7691  * @param tvc the message that was received
7692  */
7693 static void
7694 handle_validation_challenge (
7695   void *cls,
7696   const struct TransportValidationChallengeMessage *tvc)
7697 {
7698   struct CommunicatorMessageContext *cmc = cls;
7699   struct TransportValidationResponseMessage tvr;
7700   struct VirtualLink *vl;
7701   struct GNUNET_TIME_RelativeNBO validity_duration;
7702   struct IncomingRequest *ir;
7703   struct Neighbour *n;
7704   struct GNUNET_PeerIdentity sender;
7705
7706   /* DV-routed messages are not allowed for validation challenges */
7707   if (cmc->total_hops > 0)
7708   {
7709     GNUNET_break_op (0);
7710     finish_cmc_handling (cmc);
7711     return;
7712   }
7713   validity_duration = cmc->im.expected_address_validity;
7714   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7715               "Received address validation challenge %s\n",
7716               GNUNET_sh2s (&tvc->challenge.value));
7717   /* If we have a virtual link, we use this mechanism to signal the
7718      size of the flow control window, and to allow the sender
7719      to ask for increases. If for us the virtual link is still down,
7720      we will always give a window size of zero. */
7721   tvr.header.type =
7722     htons (GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_RESPONSE);
7723   tvr.header.size = htons (sizeof(tvr));
7724   tvr.reserved = htonl (0);
7725   tvr.challenge = tvc->challenge;
7726   tvr.origin_time = tvc->sender_time;
7727   tvr.validity_duration = validity_duration;
7728   {
7729     /* create signature */
7730     struct TransportValidationPS tvp = {
7731       .purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_CHALLENGE),
7732       .purpose.size = htonl (sizeof(tvp)),
7733       .validity_duration = validity_duration,
7734       .challenge = tvc->challenge
7735     };
7736
7737     GNUNET_CRYPTO_eddsa_sign (GST_my_private_key,
7738                               &tvp,
7739                               &tvr.signature);
7740   }
7741   route_control_message_without_fc (&cmc->im.sender,
7742                                     &tvr.header,
7743                                     RMO_ANYTHING_GOES | RMO_REDUNDANT);
7744   sender = cmc->im.sender;
7745   finish_cmc_handling (cmc);
7746   vl = lookup_virtual_link (&sender);
7747   if (NULL != vl)
7748     return;
7749
7750   /* For us, the link is still down, but we need bi-directional
7751      connections (for flow-control and for this to be useful for
7752      CORE), so we must try to bring the link up! */
7753
7754   /* (1) Check existing queues, if any, we may be lucky! */
7755   n = lookup_neighbour (&sender);
7756   if (NULL != n)
7757     for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
7758       start_address_validation (&sender, q->address);
7759   /* (2) Also try to see if we have addresses in PEERSTORE for this peer
7760      we could use */
7761   for (ir = ir_head; NULL != ir; ir = ir->next)
7762     if (0 == GNUNET_memcmp (&ir->pid, &sender))
7763       return;
7764   /* we are already trying */
7765   ir = GNUNET_new (struct IncomingRequest);
7766   ir->pid = sender;
7767   GNUNET_CONTAINER_DLL_insert (ir_head, ir_tail, ir);
7768   ir->wc = GNUNET_PEERSTORE_watch (peerstore,
7769                                    "transport",
7770                                    &ir->pid,
7771                                    GNUNET_PEERSTORE_TRANSPORT_URLADDRESS_KEY,
7772                                    &handle_hello_for_incoming,
7773                                    ir);
7774   ir_total++;
7775   /* Bound attempts we do in parallel here, might otherwise get excessive */
7776   while (ir_total > MAX_INCOMING_REQUEST)
7777     free_incoming_request (ir_head);
7778 }
7779
7780
7781 /**
7782  * Closure for #check_known_challenge.
7783  */
7784 struct CheckKnownChallengeContext
7785 {
7786   /**
7787    * Set to the challenge we are looking for.
7788    */
7789   const struct ChallengeNonceP *challenge;
7790
7791   /**
7792    * Set to a matching validation state, if one was found.
7793    */
7794   struct ValidationState *vs;
7795 };
7796
7797
7798 /**
7799  * Test if the validation state in @a value matches the
7800  * challenge from @a cls.
7801  *
7802  * @param cls a `struct CheckKnownChallengeContext`
7803  * @param pid unused (must match though)
7804  * @param value a `struct ValidationState`
7805  * @return #GNUNET_OK if not matching, #GNUNET_NO if match found
7806  */
7807 static int
7808 check_known_challenge (void *cls,
7809                        const struct GNUNET_PeerIdentity *pid,
7810                        void *value)
7811 {
7812   struct CheckKnownChallengeContext *ckac = cls;
7813   struct ValidationState *vs = value;
7814
7815   (void) pid;
7816   if (0 != GNUNET_memcmp (&vs->challenge, ckac->challenge))
7817     return GNUNET_OK;
7818   ckac->vs = vs;
7819   return GNUNET_NO;
7820 }
7821
7822
7823 /**
7824  * Function called when peerstore is done storing a
7825  * validated address.
7826  *
7827  * @param cls a `struct ValidationState`
7828  * @param success #GNUNET_YES on success
7829  */
7830 static void
7831 peerstore_store_validation_cb (void *cls, int success)
7832 {
7833   struct ValidationState *vs = cls;
7834
7835   vs->sc = NULL;
7836   if (GNUNET_YES == success)
7837     return;
7838   GNUNET_STATISTICS_update (GST_stats,
7839                             "# Peerstore failed to store foreign address",
7840                             1,
7841                             GNUNET_NO);
7842 }
7843
7844
7845 /**
7846  * Find the queue matching @a pid and @a address.
7847  *
7848  * @param pid peer the queue must go to
7849  * @param address address the queue must use
7850  * @return NULL if no such queue exists
7851  */
7852 static struct Queue *
7853 find_queue (const struct GNUNET_PeerIdentity *pid, const char *address)
7854 {
7855   struct Neighbour *n;
7856
7857   n = lookup_neighbour (pid);
7858   if (NULL == n)
7859     return NULL;
7860   for (struct Queue *pos = n->queue_head; NULL != pos;
7861        pos = pos->next_neighbour)
7862   {
7863     if (0 == strcmp (pos->address, address))
7864       return pos;
7865   }
7866   return NULL;
7867 }
7868
7869
7870 /**
7871  * Communicator gave us a transport address validation response.  Process the
7872  * request.
7873  *
7874  * @param cls a `struct CommunicatorMessageContext` (must call
7875  * #finish_cmc_handling() when done)
7876  * @param tvr the message that was received
7877  */
7878 static void
7879 handle_validation_response (
7880   void *cls,
7881   const struct TransportValidationResponseMessage *tvr)
7882 {
7883   struct CommunicatorMessageContext *cmc = cls;
7884   struct ValidationState *vs;
7885   struct CheckKnownChallengeContext ckac = { .challenge = &tvr->challenge,
7886                                              .vs = NULL };
7887   struct GNUNET_TIME_Absolute origin_time;
7888   struct Queue *q;
7889   struct Neighbour *n;
7890   struct VirtualLink *vl;
7891
7892   /* check this is one of our challenges */
7893   (void) GNUNET_CONTAINER_multipeermap_get_multiple (validation_map,
7894                                                      &cmc->im.sender,
7895                                                      &check_known_challenge,
7896                                                      &ckac);
7897   if (NULL == (vs = ckac.vs))
7898   {
7899     /* This can happen simply if we 'forgot' the challenge by now,
7900        i.e. because we received the validation response twice */
7901     GNUNET_STATISTICS_update (GST_stats,
7902                               "# Validations dropped, challenge unknown",
7903                               1,
7904                               GNUNET_NO);
7905     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7906                 "Validation response %s dropped, challenge unknown\n",
7907                 GNUNET_sh2s (&tvr->challenge.value));
7908     finish_cmc_handling (cmc);
7909     return;
7910   }
7911
7912   /* sanity check on origin time */
7913   origin_time = GNUNET_TIME_absolute_ntoh (tvr->origin_time);
7914   if ((origin_time.abs_value_us < vs->first_challenge_use.abs_value_us) ||
7915       (origin_time.abs_value_us > vs->last_challenge_use.abs_value_us))
7916   {
7917     GNUNET_break_op (0);
7918     finish_cmc_handling (cmc);
7919     return;
7920   }
7921
7922   {
7923     /* check signature */
7924     struct TransportValidationPS tvp = {
7925       .purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_CHALLENGE),
7926       .purpose.size = htonl (sizeof(tvp)),
7927       .validity_duration = tvr->validity_duration,
7928       .challenge = tvr->challenge
7929     };
7930
7931     if (
7932       GNUNET_OK !=
7933       GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_CHALLENGE,
7934                                   &tvp,
7935                                   &tvr->signature,
7936                                   &cmc->im.sender.public_key))
7937     {
7938       GNUNET_break_op (0);
7939       finish_cmc_handling (cmc);
7940       return;
7941     }
7942   }
7943
7944   /* validity is capped by our willingness to keep track of the
7945      validation entry and the maximum the other peer allows */
7946   vs->valid_until = GNUNET_TIME_relative_to_absolute (
7947     GNUNET_TIME_relative_min (GNUNET_TIME_relative_ntoh (
7948                                 tvr->validity_duration),
7949                               MAX_ADDRESS_VALID_UNTIL));
7950   vs->validated_until =
7951     GNUNET_TIME_absolute_min (vs->valid_until,
7952                               GNUNET_TIME_relative_to_absolute (
7953                                 ADDRESS_VALIDATION_LIFETIME));
7954   vs->validation_rtt = GNUNET_TIME_absolute_get_duration (origin_time);
7955   vs->challenge_backoff = GNUNET_TIME_UNIT_ZERO;
7956   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
7957                               &vs->challenge,
7958                               sizeof(vs->challenge));
7959   vs->first_challenge_use = GNUNET_TIME_absolute_subtract (
7960     vs->validated_until,
7961     GNUNET_TIME_relative_multiply (vs->validation_rtt,
7962                                    VALIDATION_RTT_BUFFER_FACTOR));
7963   vs->last_challenge_use =
7964     GNUNET_TIME_UNIT_ZERO_ABS; /* challenge was not yet used */
7965   update_next_challenge_time (vs, vs->first_challenge_use);
7966   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7967               "Validation response %s accepted, address valid until %s\n",
7968               GNUNET_sh2s (&tvr->challenge.value),
7969               GNUNET_STRINGS_absolute_time_to_string (vs->valid_until));
7970   vs->sc = GNUNET_PEERSTORE_store (peerstore,
7971                                    "transport",
7972                                    &cmc->im.sender,
7973                                    GNUNET_PEERSTORE_TRANSPORT_URLADDRESS_KEY,
7974                                    vs->address,
7975                                    strlen (vs->address) + 1,
7976                                    vs->valid_until,
7977                                    GNUNET_PEERSTORE_STOREOPTION_MULTIPLE,
7978                                    &peerstore_store_validation_cb,
7979                                    vs);
7980   finish_cmc_handling (cmc);
7981
7982   /* Finally, we now possibly have a confirmed (!) working queue,
7983      update queue status (if queue still is around) */
7984   q = find_queue (&vs->pid, vs->address);
7985   if (NULL == q)
7986   {
7987     GNUNET_STATISTICS_update (GST_stats,
7988                               "# Queues lost at time of successful validation",
7989                               1,
7990                               GNUNET_NO);
7991     return;
7992   }
7993   q->validated_until = vs->validated_until;
7994   q->pd.aged_rtt = vs->validation_rtt;
7995   n = q->neighbour;
7996   vl = lookup_virtual_link (&vs->pid);
7997   if (NULL != vl)
7998   {
7999     /* Link was already up, remember n is also now available and we are done */
8000     if (NULL == vl->n)
8001     {
8002       vl->n = n;
8003       n->vl = vl;
8004       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8005                   "Virtual link to %s could now also direct neighbour!\n",
8006                   GNUNET_i2s (&vs->pid));
8007     }
8008     else
8009     {
8010       GNUNET_assert (n == vl->n);
8011     }
8012     return;
8013   }
8014   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8015               "Creating new virtual link to %s using direct neighbour!\n",
8016               GNUNET_i2s (&vs->pid));
8017   vl = GNUNET_new (struct VirtualLink);
8018   vl->target = n->pid;
8019   vl->n = n;
8020   n->vl = vl;
8021   vl->core_recv_window = RECV_WINDOW_SIZE;
8022   vl->available_fc_window_size = DEFAULT_WINDOW_SIZE;
8023   vl->visibility_task =
8024     GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl);
8025   GNUNET_break (GNUNET_YES ==
8026                 GNUNET_CONTAINER_multipeermap_put (
8027                   links,
8028                   &vl->target,
8029                   vl,
8030                   GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
8031   consider_sending_fc (vl);
8032   /* We lacked a confirmed connection to the target
8033      before, so tell CORE about it (finally!) */
8034   cores_send_connect_info (&n->pid);
8035 }
8036
8037
8038 /**
8039  * Incoming meessage.  Process the request.
8040  *
8041  * @param im the send message that was received
8042  */
8043 static void
8044 handle_incoming_msg (void *cls,
8045                      const struct GNUNET_TRANSPORT_IncomingMessage *im)
8046 {
8047   struct TransportClient *tc = cls;
8048   struct CommunicatorMessageContext *cmc =
8049     GNUNET_new (struct CommunicatorMessageContext);
8050
8051   cmc->tc = tc;
8052   cmc->im = *im;
8053   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8054               "Received message via communicator from peer %s\n",
8055               GNUNET_i2s (&im->sender));
8056   demultiplex_with_cmc (cmc, (const struct GNUNET_MessageHeader *) &im[1]);
8057 }
8058
8059
8060 /**
8061  * Communicator gave us a transport address validation response.  Process the
8062  * request.
8063  *
8064  * @param cls a `struct CommunicatorMessageContext` (must call
8065  * #finish_cmc_handling() when done)
8066  * @param fc the message that was received
8067  */
8068 static void
8069 handle_flow_control (void *cls, const struct TransportFlowControlMessage *fc)
8070 {
8071   struct CommunicatorMessageContext *cmc = cls;
8072   struct VirtualLink *vl;
8073   uint32_t seq;
8074   struct GNUNET_TIME_Absolute st;
8075   uint64_t os;
8076   uint64_t wnd;
8077
8078   vl = lookup_virtual_link (&cmc->im.sender);
8079   if (NULL == vl)
8080   {
8081     GNUNET_STATISTICS_update (GST_stats,
8082                               "# FC dropped: virtual link unknown",
8083                               1,
8084                               GNUNET_NO);
8085     finish_cmc_handling (cmc);
8086     return;
8087   }
8088   st = GNUNET_TIME_absolute_ntoh (fc->sender_time);
8089   if (st.abs_value_us < vl->last_fc_timestamp.abs_value_us)
8090   {
8091     /* out of order, drop */
8092     GNUNET_STATISTICS_update (GST_stats,
8093                               "# FC dropped: message out of order",
8094                               1,
8095                               GNUNET_NO);
8096     finish_cmc_handling (cmc);
8097     return;
8098   }
8099   seq = ntohl (fc->seq);
8100   if (seq < vl->last_fc_seq)
8101   {
8102     /* Wrap-around/reset of other peer; start all counters from zero */
8103     vl->outbound_fc_window_size_used = 0;
8104   }
8105   vl->last_fc_seq = seq;
8106   vl->last_fc_timestamp = st;
8107   vl->outbound_fc_window_size = GNUNET_ntohll (fc->inbound_window_size);
8108   os = GNUNET_ntohll (fc->outbound_sent);
8109   vl->incoming_fc_window_size_loss =
8110     (int64_t) (os - vl->incoming_fc_window_size_used);
8111   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8112               "Received FC from %s, seq %u, new window %llu (loss at %lld)\n",
8113               GNUNET_i2s (&vl->target),
8114               (unsigned int) seq,
8115               (unsigned long long) vl->outbound_fc_window_size,
8116               (long long) vl->incoming_fc_window_size_loss);
8117   wnd = GNUNET_ntohll (fc->outbound_window_size);
8118   if ((wnd < vl->incoming_fc_window_size) ||
8119       (vl->last_outbound_window_size_received != wnd) ||
8120       (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX)
8121        % FC_NO_CHANGE_REPLY_PROBABILITY))
8122   {
8123     /* Consider re-sending our FC message, as clearly the
8124        other peer's idea of the window is not up-to-date */
8125     consider_sending_fc (vl);
8126   }
8127   if ((wnd == vl->incoming_fc_window_size) &&
8128       (vl->last_outbound_window_size_received == wnd) &&
8129       (NULL != vl->fc_retransmit_task))
8130   {
8131     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8132                 "Stopping FC retransmission to %s: peer is current at window %llu\n",
8133                 GNUNET_i2s (&vl->target),
8134                 (unsigned long long) wnd);
8135     GNUNET_SCHEDULER_cancel (vl->fc_retransmit_task);
8136     vl->fc_retransmit_task = NULL;
8137   }
8138   vl->last_outbound_window_size_received = wnd;
8139   /* FC window likely increased, check transmission possibilities! */
8140   check_vl_transmission (vl);
8141   finish_cmc_handling (cmc);
8142 }
8143
8144
8145 /**
8146  * Given an inbound message @a msg from a communicator @a cmc,
8147  * demultiplex it based on the type calling the right handler.
8148  *
8149  * @param cmc context for demultiplexing
8150  * @param msg message to demultiplex
8151  */
8152 static void
8153 demultiplex_with_cmc (struct CommunicatorMessageContext *cmc,
8154                       const struct GNUNET_MessageHeader *msg)
8155 {
8156   struct GNUNET_MQ_MessageHandler handlers[] =
8157   { GNUNET_MQ_hd_var_size (fragment_box,
8158                            GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT,
8159                            struct TransportFragmentBoxMessage,
8160                            &cmc),
8161     GNUNET_MQ_hd_var_size (reliability_box,
8162                            GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX,
8163                            struct TransportReliabilityBoxMessage,
8164                            &cmc),
8165     GNUNET_MQ_hd_var_size (reliability_ack,
8166                            GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_ACK,
8167                            struct TransportReliabilityAckMessage,
8168                            &cmc),
8169     GNUNET_MQ_hd_var_size (backchannel_encapsulation,
8170                            GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION,
8171                            struct TransportBackchannelEncapsulationMessage,
8172                            &cmc),
8173     GNUNET_MQ_hd_var_size (dv_learn,
8174                            GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN,
8175                            struct TransportDVLearnMessage,
8176                            &cmc),
8177     GNUNET_MQ_hd_var_size (dv_box,
8178                            GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX,
8179                            struct TransportDVBoxMessage,
8180                            &cmc),
8181     GNUNET_MQ_hd_fixed_size (
8182       validation_challenge,
8183       GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_CHALLENGE,
8184       struct TransportValidationChallengeMessage,
8185       &cmc),
8186     GNUNET_MQ_hd_fixed_size (flow_control,
8187                              GNUNET_MESSAGE_TYPE_TRANSPORT_FLOW_CONTROL,
8188                              struct TransportFlowControlMessage,
8189                              &cmc),
8190     GNUNET_MQ_hd_fixed_size (
8191       validation_response,
8192       GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_RESPONSE,
8193       struct TransportValidationResponseMessage,
8194       &cmc),
8195     GNUNET_MQ_handler_end () };
8196   int ret;
8197
8198   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8199               "Handling message of type %u with %u bytes\n",
8200               (unsigned int) ntohs (msg->type),
8201               (unsigned int) ntohs (msg->size));
8202   ret = GNUNET_MQ_handle_message (handlers, msg);
8203   if (GNUNET_SYSERR == ret)
8204   {
8205     GNUNET_break (0);
8206     GNUNET_SERVICE_client_drop (cmc->tc->client);
8207     GNUNET_free (cmc);
8208     return;
8209   }
8210   if (GNUNET_NO == ret)
8211   {
8212     /* unencapsulated 'raw' message */
8213     handle_raw_message (&cmc, msg);
8214   }
8215 }
8216
8217
8218 /**
8219  * New queue became available.  Check message.
8220  *
8221  * @param cls the client
8222  * @param aqm the send message that was sent
8223  */
8224 static int
8225 check_add_queue_message (void *cls,
8226                          const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
8227 {
8228   struct TransportClient *tc = cls;
8229
8230   if (CT_COMMUNICATOR != tc->type)
8231   {
8232     GNUNET_break (0);
8233     return GNUNET_SYSERR;
8234   }
8235   GNUNET_MQ_check_zero_termination (aqm);
8236   return GNUNET_OK;
8237 }
8238
8239
8240 /**
8241  * If necessary, generates the UUID for a @a pm
8242  *
8243  * @param pm pending message to generate UUID for.
8244  */
8245 static void
8246 set_pending_message_uuid (struct PendingMessage *pm)
8247 {
8248   if (pm->msg_uuid_set)
8249     return;
8250   pm->msg_uuid.uuid = pm->vl->message_uuid_ctr++;
8251   pm->msg_uuid_set = GNUNET_YES;
8252 }
8253
8254
8255 /**
8256  * Setup data structure waiting for acknowledgements.
8257  *
8258  * @param queue queue the @a pm will be sent over
8259  * @param dvh path the message will take, may be NULL
8260  * @param pm the pending message for transmission
8261  * @return corresponding fresh pending acknowledgement
8262  */
8263 static struct PendingAcknowledgement *
8264 prepare_pending_acknowledgement (struct Queue *queue,
8265                                  struct DistanceVectorHop *dvh,
8266                                  struct PendingMessage *pm)
8267 {
8268   struct PendingAcknowledgement *pa;
8269
8270   pa = GNUNET_new (struct PendingAcknowledgement);
8271   pa->queue = queue;
8272   pa->dvh = dvh;
8273   pa->pm = pm;
8274   do
8275   {
8276     GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
8277                                 &pa->ack_uuid,
8278                                 sizeof(pa->ack_uuid));
8279   }
8280   while (GNUNET_YES != GNUNET_CONTAINER_multiuuidmap_put (
8281            pending_acks,
8282            &pa->ack_uuid.value,
8283            pa,
8284            GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
8285   GNUNET_CONTAINER_MDLL_insert (queue, queue->pa_head, queue->pa_tail, pa);
8286   GNUNET_CONTAINER_MDLL_insert (pm, pm->pa_head, pm->pa_tail, pa);
8287   if (NULL != dvh)
8288     GNUNET_CONTAINER_MDLL_insert (dvh, dvh->pa_head, dvh->pa_tail, pa);
8289   pa->transmission_time = GNUNET_TIME_absolute_get ();
8290   pa->message_size = pm->bytes_msg;
8291   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8292               "Waiting for ACKnowledgment `%s' for <%llu>\n",
8293               GNUNET_uuid2s (&pa->ack_uuid.value),
8294               pm->logging_uuid);
8295   return pa;
8296 }
8297
8298
8299 /**
8300  * Fragment the given @a pm to the given @a mtu.  Adds
8301  * additional fragments to the neighbour as well. If the
8302  * @a mtu is too small, generates and error for the @a pm
8303  * and returns NULL.
8304  *
8305  * @param queue which queue to fragment for
8306  * @param dvh path the message will take, or NULL
8307  * @param pm pending message to fragment for transmission
8308  * @return new message to transmit
8309  */
8310 static struct PendingMessage *
8311 fragment_message (struct Queue *queue,
8312                   struct DistanceVectorHop *dvh,
8313                   struct PendingMessage *pm)
8314 {
8315   struct PendingAcknowledgement *pa;
8316   struct PendingMessage *ff;
8317   uint16_t mtu;
8318
8319   mtu = (0 == queue->mtu)
8320         ? UINT16_MAX - sizeof(struct GNUNET_TRANSPORT_SendMessageTo)
8321         : queue->mtu;
8322   set_pending_message_uuid (pm);
8323   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8324               "Fragmenting message %llu <%llu> to %s for MTU %u\n",
8325               (unsigned long long) pm->msg_uuid.uuid,
8326               pm->logging_uuid,
8327               GNUNET_i2s (&pm->vl->target),
8328               (unsigned int) mtu);
8329   pa = prepare_pending_acknowledgement (queue, dvh, pm);
8330
8331   /* This invariant is established in #handle_add_queue_message() */
8332   GNUNET_assert (mtu > sizeof(struct TransportFragmentBoxMessage));
8333
8334   /* select fragment for transmission, descending the tree if it has
8335      been expanded until we are at a leaf or at a fragment that is small
8336      enough
8337    */
8338   ff = pm;
8339   while (((ff->bytes_msg > mtu) || (pm == ff)) &&
8340          (ff->frag_off == ff->bytes_msg) && (NULL != ff->head_frag))
8341   {
8342     ff = ff->head_frag;   /* descent into fragmented fragments */
8343   }
8344
8345   if (((ff->bytes_msg > mtu) || (pm == ff)) && (pm->frag_off < pm->bytes_msg))
8346   {
8347     /* Did not yet calculate all fragments, calculate next fragment */
8348     struct PendingMessage *frag;
8349     struct TransportFragmentBoxMessage tfb;
8350     const char *orig;
8351     char *msg;
8352     uint16_t fragmax;
8353     uint16_t fragsize;
8354     uint16_t msize;
8355     uint16_t xoff = 0;
8356
8357     orig = (const char *) &ff[1];
8358     msize = ff->bytes_msg;
8359     if (pm != ff)
8360     {
8361       const struct TransportFragmentBoxMessage *tfbo;
8362
8363       tfbo = (const struct TransportFragmentBoxMessage *) orig;
8364       orig += sizeof(struct TransportFragmentBoxMessage);
8365       msize -= sizeof(struct TransportFragmentBoxMessage);
8366       xoff = ntohs (tfbo->frag_off);
8367     }
8368     fragmax = mtu - sizeof(struct TransportFragmentBoxMessage);
8369     fragsize = GNUNET_MIN (msize - ff->frag_off, fragmax);
8370     frag =
8371       GNUNET_malloc (sizeof(struct PendingMessage)
8372                      + sizeof(struct TransportFragmentBoxMessage) + fragsize);
8373     frag->logging_uuid = logging_uuid_gen++;
8374     frag->vl = pm->vl;
8375     frag->frag_parent = ff;
8376     frag->timeout = pm->timeout;
8377     frag->bytes_msg = sizeof(struct TransportFragmentBoxMessage) + fragsize;
8378     frag->pmt = PMT_FRAGMENT_BOX;
8379     msg = (char *) &frag[1];
8380     tfb.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT);
8381     tfb.header.size =
8382       htons (sizeof(struct TransportFragmentBoxMessage) + fragsize);
8383     tfb.ack_uuid = pa->ack_uuid;
8384     tfb.msg_uuid = pm->msg_uuid;
8385     tfb.frag_off = htons (ff->frag_off + xoff);
8386     tfb.msg_size = htons (pm->bytes_msg);
8387     memcpy (msg, &tfb, sizeof(tfb));
8388     memcpy (&msg[sizeof(tfb)], &orig[ff->frag_off], fragsize);
8389     GNUNET_CONTAINER_MDLL_insert (frag, ff->head_frag, ff->tail_frag, frag);
8390     ff->frag_off += fragsize;
8391     ff = frag;
8392   }
8393
8394   /* Move head to the tail and return it */
8395   GNUNET_CONTAINER_MDLL_remove (frag,
8396                                 ff->frag_parent->head_frag,
8397                                 ff->frag_parent->tail_frag,
8398                                 ff);
8399   GNUNET_CONTAINER_MDLL_insert_tail (frag,
8400                                      ff->frag_parent->head_frag,
8401                                      ff->frag_parent->tail_frag,
8402                                      ff);
8403   return ff;
8404 }
8405
8406
8407 /**
8408  * Reliability-box the given @a pm. On error (can there be any), NULL
8409  * may be returned, otherwise the "replacement" for @a pm (which
8410  * should then be added to the respective neighbour's queue instead of
8411  * @a pm).  If the @a pm is already fragmented or reliability boxed,
8412  * or itself an ACK, this function simply returns @a pm.
8413  *
8414  * @param queue which queue to prepare transmission for
8415  * @param dvh path the message will take, or NULL
8416  * @param pm pending message to box for transmission over unreliabile queue
8417  * @return new message to transmit
8418  */
8419 static struct PendingMessage *
8420 reliability_box_message (struct Queue *queue,
8421                          struct DistanceVectorHop *dvh,
8422                          struct PendingMessage *pm)
8423 {
8424   struct TransportReliabilityBoxMessage rbox;
8425   struct PendingAcknowledgement *pa;
8426   struct PendingMessage *bpm;
8427   char *msg;
8428
8429   if (PMT_CORE != pm->pmt)
8430     return pm; /* already fragmented or reliability boxed, or control message:
8431                   do nothing */
8432   if (NULL != pm->bpm)
8433     return pm->bpm; /* already computed earlier: do nothing */
8434   GNUNET_assert (NULL == pm->head_frag);
8435   if (pm->bytes_msg + sizeof(rbox) > UINT16_MAX)
8436   {
8437     /* failed hard */
8438     GNUNET_break (0);
8439     client_send_response (pm);
8440     return NULL;
8441   }
8442   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8443               "Preparing reliability box for message <%llu> to %s on queue %s\n",
8444               pm->logging_uuid,
8445               GNUNET_i2s (&pm->vl->target),
8446               queue->address);
8447   pa = prepare_pending_acknowledgement (queue, dvh, pm);
8448
8449   bpm = GNUNET_malloc (sizeof(struct PendingMessage) + sizeof(rbox)
8450                        + pm->bytes_msg);
8451   bpm->logging_uuid = logging_uuid_gen++;
8452   bpm->vl = pm->vl;
8453   bpm->frag_parent = pm;
8454   GNUNET_CONTAINER_MDLL_insert (frag, pm->head_frag, pm->tail_frag, bpm);
8455   bpm->timeout = pm->timeout;
8456   bpm->pmt = PMT_RELIABILITY_BOX;
8457   bpm->bytes_msg = pm->bytes_msg + sizeof(rbox);
8458   set_pending_message_uuid (bpm);
8459   rbox.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX);
8460   rbox.header.size = htons (sizeof(rbox) + pm->bytes_msg);
8461   rbox.ack_countdown = htonl (0);  // FIXME: implement ACK countdown support
8462
8463   rbox.ack_uuid = pa->ack_uuid;
8464   msg = (char *) &bpm[1];
8465   memcpy (msg, &rbox, sizeof(rbox));
8466   memcpy (&msg[sizeof(rbox)], &pm[1], pm->bytes_msg);
8467   pm->bpm = bpm;
8468   return bpm;
8469 }
8470
8471
8472 /**
8473  * Change the value of the `next_attempt` field of @a pm
8474  * to @a next_attempt and re-order @a pm in the transmission
8475  * list as required by the new timestmap.
8476  *
8477  * @param pm a pending message to update
8478  * @param next_attempt timestamp to use
8479  */
8480 static void
8481 update_pm_next_attempt (struct PendingMessage *pm,
8482                         struct GNUNET_TIME_Absolute next_attempt)
8483 {
8484   struct VirtualLink *vl = pm->vl;
8485
8486   pm->next_attempt = next_attempt;
8487   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8488               "Next attempt for message <%llu> set to %s\n",
8489               pm->logging_uuid,
8490               GNUNET_STRINGS_absolute_time_to_string (next_attempt));
8491
8492   if (NULL == pm->frag_parent)
8493   {
8494     struct PendingMessage *pos;
8495
8496     /* re-insert sort in neighbour list */
8497     GNUNET_CONTAINER_MDLL_remove (vl,
8498                                   vl->pending_msg_head,
8499                                   vl->pending_msg_tail,
8500                                   pm);
8501     pos = vl->pending_msg_tail;
8502     while ((NULL != pos) &&
8503            (next_attempt.abs_value_us > pos->next_attempt.abs_value_us))
8504       pos = pos->prev_vl;
8505     GNUNET_CONTAINER_MDLL_insert_after (vl,
8506                                         vl->pending_msg_head,
8507                                         vl->pending_msg_tail,
8508                                         pos,
8509                                         pm);
8510   }
8511   else
8512   {
8513     /* re-insert sort in fragment list */
8514     struct PendingMessage *fp = pm->frag_parent;
8515     struct PendingMessage *pos;
8516
8517     GNUNET_CONTAINER_MDLL_remove (frag, fp->head_frag, fp->tail_frag, pm);
8518     pos = fp->tail_frag;
8519     while ((NULL != pos) &&
8520            (next_attempt.abs_value_us > pos->next_attempt.abs_value_us))
8521       pos = pos->prev_frag;
8522     GNUNET_CONTAINER_MDLL_insert_after (frag,
8523                                         fp->head_frag,
8524                                         fp->tail_frag,
8525                                         pos,
8526                                         pm);
8527   }
8528 }
8529
8530
8531 /**
8532  * Context for #select_best_pending_from_link().
8533  */
8534 struct PendingMessageScoreContext
8535 {
8536   /**
8537    * Set to the best message that was found, NULL for none.
8538    */
8539   struct PendingMessage *best;
8540
8541   /**
8542    * DVH that @e best should take, or NULL for direct transmission.
8543    */
8544   struct DistanceVectorHop *dvh;
8545
8546   /**
8547    * What is the estimated total overhead for this message?
8548    */
8549   size_t real_overhead;
8550
8551   /**
8552    * Number of pending messages we seriously considered this time.
8553    */
8554   unsigned int consideration_counter;
8555
8556   /**
8557    * Did we have to fragment?
8558    */
8559   int frag;
8560
8561   /**
8562    * Did we have to reliability box?
8563    */
8564   int relb;
8565 };
8566
8567
8568 /**
8569  * Select the best pending message from @a vl for transmission
8570  * via @a queue.
8571  *
8572  * @param sc[in,out] best message so far (NULL for none), plus scoring data
8573  * @param queue the queue that will be used for transmission
8574  * @param vl the virtual link providing the messages
8575  * @param dvh path we are currently considering, or NULL for none
8576  * @param overhead number of bytes of overhead to be expected
8577  *        from DV encapsulation (0 for without DV)
8578  */
8579 static void
8580 select_best_pending_from_link (struct PendingMessageScoreContext *sc,
8581                                struct Queue *queue,
8582                                struct VirtualLink *vl,
8583                                struct DistanceVectorHop *dvh,
8584                                size_t overhead)
8585 {
8586   struct GNUNET_TIME_Absolute now;
8587
8588   now = GNUNET_TIME_absolute_get ();
8589   for (struct PendingMessage *pos = vl->pending_msg_head; NULL != pos;
8590        pos = pos->next_vl)
8591   {
8592     size_t real_overhead = overhead;
8593     int frag;
8594     int relb;
8595
8596     if ((NULL != dvh) && (PMT_DV_BOX == pos->pmt))
8597       continue;   /* DV messages must not be DV-routed to next hop! */
8598     if (pos->next_attempt.abs_value_us > now.abs_value_us)
8599       break;   /* too early for all messages, they are sorted by next_attempt */
8600     if (NULL != pos->qe)
8601       continue;   /* not eligible */
8602     sc->consideration_counter++;
8603     /* determine if we have to fragment, if so add fragmentation
8604        overhead! */
8605     frag = GNUNET_NO;
8606     if (((0 != queue->mtu) &&
8607          (pos->bytes_msg + real_overhead > queue->mtu)) ||
8608         (pos->bytes_msg > UINT16_MAX - sizeof(struct
8609                                               GNUNET_TRANSPORT_SendMessageTo))
8610         ||
8611         (NULL != pos->head_frag /* fragments already exist, should
8612                                      respect that even if MTU is 0 for
8613                                      this queue */))
8614     {
8615       frag = GNUNET_YES;
8616       if (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc)
8617       {
8618         /* FIXME-FRAG-REL-UUID: we could use an optimized, shorter fragmentation
8619            header without the ACK UUID when using a *reliable* channel! */
8620       }
8621       real_overhead = overhead + sizeof(struct TransportFragmentBoxMessage);
8622     }
8623     /* determine if we have to reliability-box, if so add reliability box
8624        overhead */
8625     relb = GNUNET_NO;
8626     if ((GNUNET_NO == frag) &&
8627         (0 == (pos->prefs & GNUNET_MQ_PREF_UNRELIABLE)) &&
8628         (GNUNET_TRANSPORT_CC_RELIABLE != queue->tc->details.communicator.cc))
8629     {
8630       relb = GNUNET_YES;
8631       real_overhead += sizeof(struct TransportReliabilityBoxMessage);
8632     }
8633
8634     /* Finally, compare to existing 'best' in sc to see if this 'pos' pending
8635        message would beat it! */
8636     if (NULL != sc->best)
8637     {
8638       /* CHECK if pos fits queue BETTER (=smaller) than pm, if not: continue;
8639          OPTIMIZE-ME: This is a heuristic, which so far has NOT been
8640          experimentally validated. There may be some huge potential for
8641          improvement here. Also, we right now only compare how well the
8642          given message fits _this_ queue, and do not consider how well other
8643          queues might suit the message. Taking other queues into consideration
8644          may further improve the result, but could also be expensive
8645          in terms of CPU time.  */long long sc_score = sc->frag * 40 + sc->relb * 20 + sc->real_overhead;
8646       long long pm_score = frag * 40 + relb * 20 + real_overhead;
8647       long long time_delta =
8648         (sc->best->next_attempt.abs_value_us - pos->next_attempt.abs_value_us)
8649         / 1000LL;
8650
8651       /* "time_delta" considers which message has been 'ready' for transmission
8652          for longer, if a message has a preference for low latency, increase
8653          the weight of the time_delta by 10x if it is favorable for that message */
8654       if ((0 != (pos->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
8655           (0 != (sc->best->prefs & GNUNET_MQ_PREF_LOW_LATENCY)))
8656         time_delta *= 10;     /* increase weight (always, both are low latency) */
8657       else if ((0 != (pos->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
8658                (time_delta > 0))
8659         time_delta *=
8660           10;     /* increase weight, favors 'pos', which is low latency */
8661       else if ((0 != (sc->best->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
8662                (time_delta < 0))
8663         time_delta *=
8664           10;     /* increase weight, favors 'sc->best', which is low latency */
8665       if (0 != queue->mtu)
8666       {
8667         /* Grant bonus if we are bellow MTU, larger bonus the closer we will
8668            be to the MTU */
8669         if (queue->mtu > sc->real_overhead + sc->best->bytes_msg)
8670           sc_score -= queue->mtu - (sc->real_overhead + sc->best->bytes_msg);
8671         if (queue->mtu > real_overhead + pos->bytes_msg)
8672           pm_score -= queue->mtu - (real_overhead + pos->bytes_msg);
8673       }
8674       if (sc_score + time_delta > pm_score)
8675         continue;     /* sc_score larger, keep sc->best */
8676     }
8677     sc->best = pos;
8678     sc->dvh = dvh;
8679     sc->frag = frag;
8680     sc->relb = relb;
8681   }
8682 }
8683
8684
8685 /**
8686  * Function to call to further operate on the now DV encapsulated
8687  * message @a hdr, forwarding it via @a next_hop under respect of
8688  * @a options.
8689  *
8690  * @param cls a `struct PendingMessageScoreContext`
8691  * @param next_hop next hop of the DV path
8692  * @param hdr encapsulated message, technically a `struct TransportDFBoxMessage`
8693  * @param options options of the original message
8694  */
8695 static void
8696 extract_box_cb (void *cls,
8697                 struct Neighbour *next_hop,
8698                 const struct GNUNET_MessageHeader *hdr,
8699                 enum RouteMessageOptions options)
8700 {
8701   struct PendingMessageScoreContext *sc = cls;
8702   struct PendingMessage *pm = sc->best;
8703   struct PendingMessage *bpm;
8704   uint16_t bsize = ntohs (hdr->size);
8705
8706   GNUNET_assert (NULL == pm->bpm);
8707   bpm = GNUNET_malloc (sizeof(struct PendingMessage) + bsize);
8708   bpm->logging_uuid = logging_uuid_gen++;
8709   bpm->pmt = PMT_DV_BOX;
8710   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8711               "Creating DV Box %llu for original message %llu (next hop is %s)\n",
8712               bpm->logging_uuid,
8713               pm->logging_uuid,
8714               GNUNET_i2s (&next_hop->pid));
8715   memcpy (&bpm[1], hdr, bsize);
8716   pm->bpm = bpm;
8717 }
8718
8719
8720 /**
8721  * We believe we are ready to transmit a `struct PendingMessage` on a
8722  * queue, the big question is which one!  We need to see if there is
8723  * one pending that is allowed by flow control and congestion control
8724  * and (ideally) matches our queue's performance profile.
8725  *
8726  * If such a message is found, we give the message to the communicator
8727  * for transmission (updating the tracker, and re-scheduling ourselves
8728  * if applicable).
8729  *
8730  * If no such message is found, the queue's `idle` field must be set
8731  * to #GNUNET_YES.
8732  *
8733  * @param cls the `struct Queue` to process transmissions for
8734  */
8735 static void
8736 transmit_on_queue (void *cls)
8737 {
8738   struct Queue *queue = cls;
8739   struct Neighbour *n = queue->neighbour;
8740   struct PendingMessageScoreContext sc;
8741   struct PendingMessage *pm;
8742
8743   queue->transmit_task = NULL;
8744   if (NULL == n->vl)
8745   {
8746     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8747                 "Virtual link `%s' is down, cannot have PM for queue `%s'\n",
8748                 GNUNET_i2s (&n->pid),
8749                 queue->address);
8750     queue->idle = GNUNET_YES;
8751     return;
8752   }
8753   memset (&sc, 0, sizeof(sc));
8754   select_best_pending_from_link (&sc, queue, n->vl, NULL, 0);
8755   if (NULL == sc.best)
8756   {
8757     /* Also look at DVH that have the n as first hop! */
8758     for (struct DistanceVectorHop *dvh = n->dv_head; NULL != dvh;
8759          dvh = dvh->next_neighbour)
8760     {
8761       select_best_pending_from_link (&sc,
8762                                      queue,
8763                                      dvh->dv->vl,
8764                                      dvh,
8765                                      sizeof(struct GNUNET_PeerIdentity)
8766                                      * (1 + dvh->distance)
8767                                      + sizeof(struct TransportDVBoxMessage)
8768                                      + sizeof(struct TransportDVBoxPayloadP));
8769     }
8770   }
8771   if (NULL == sc.best)
8772   {
8773     /* no message pending, nothing to do here! */
8774     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8775                 "No pending messages, queue `%s' to %s now idle\n",
8776                 queue->address,
8777                 GNUNET_i2s (&n->pid));
8778     queue->idle = GNUNET_YES;
8779     return;
8780   }
8781
8782   /* Given selection in `sc`, do transmission */
8783   pm = sc.best;
8784   if (NULL != sc.dvh)
8785   {
8786     GNUNET_assert (PMT_DV_BOX != pm->pmt);
8787     if (NULL != sc.best->bpm)
8788     {
8789       /* We did this boxing before, but possibly for a different path!
8790          Discard old DV box!  OPTIMIZE-ME: we might want to check if
8791          it is the same and then not re-build the message... */
8792       free_pending_message (sc.best->bpm);
8793       sc.best->bpm = NULL;
8794     }
8795     encapsulate_for_dv (sc.dvh->dv,
8796                         1,
8797                         &sc.dvh,
8798                         (const struct GNUNET_MessageHeader *) &sc.best[1],
8799                         &extract_box_cb,
8800                         &sc,
8801                         RMO_NONE);
8802     GNUNET_assert (NULL != sc.best->bpm);
8803     pm = sc.best->bpm;
8804   }
8805   if (GNUNET_YES == sc.frag)
8806   {
8807     pm = fragment_message (queue, sc.dvh, pm);
8808     if (NULL == pm)
8809     {
8810       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8811                   "Fragmentation failed queue %s to %s for <%llu>, trying again\n",
8812                   queue->address,
8813                   GNUNET_i2s (&n->pid),
8814                   sc.best->logging_uuid);
8815       schedule_transmit_on_queue (queue, GNUNET_SCHEDULER_PRIORITY_DEFAULT);
8816       return;
8817     }
8818   }
8819   else if (GNUNET_YES == sc.relb)
8820   {
8821     pm = reliability_box_message (queue, sc.dvh, pm);
8822     if (NULL == pm)
8823     {
8824       /* Reliability boxing failed, try next message... */
8825       GNUNET_log (
8826         GNUNET_ERROR_TYPE_DEBUG,
8827         "Reliability boxing failed queue %s to %s for <%llu>, trying again\n",
8828         queue->address,
8829         GNUNET_i2s (&n->pid),
8830         sc.best->logging_uuid);
8831       schedule_transmit_on_queue (queue, GNUNET_SCHEDULER_PRIORITY_DEFAULT);
8832       return;
8833     }
8834   }
8835
8836   /* Pass 'pm' for transission to the communicator */
8837   GNUNET_log (
8838     GNUNET_ERROR_TYPE_DEBUG,
8839     "Passing message <%llu> to queue %s for peer %s (considered %u others)\n",
8840     pm->logging_uuid,
8841     queue->address,
8842     GNUNET_i2s (&n->pid),
8843     sc.consideration_counter);
8844
8845   /* Flow control: increment amount of traffic sent; if we are routing
8846      via DV (and thus the ultimate target of the pending message is for
8847      a different virtual link than the one of the queue), then we need
8848      to use up not only the window of the direct link but also the
8849      flow control window for the DV link! */pm->vl->outbound_fc_window_size_used += pm->bytes_msg;
8850
8851   if (pm->vl != queue->neighbour->vl)
8852   {
8853     /* If the virtual link of the queue differs, this better be distance
8854        vector routing! */
8855     GNUNET_assert (NULL != sc.dvh);
8856     /* If we do distance vector routing, we better not do this for a
8857        message that was itself DV-routed */
8858     GNUNET_assert (PMT_DV_BOX != sc.best->pmt);
8859     /* We use the size of the unboxed message here, to avoid counting
8860        the DV-Box header which is eaten up on the way by intermediaries */
8861     queue->neighbour->vl->outbound_fc_window_size_used += sc.best->bytes_msg;
8862   }
8863   else
8864   {
8865     GNUNET_assert (NULL == sc.dvh);
8866   }
8867
8868   queue_send_msg (queue, pm, &pm[1], pm->bytes_msg);
8869
8870   /* Check if this transmission somehow conclusively finished handing 'pm'
8871      even without any explicit ACKs */
8872   if ((PMT_CORE == pm->pmt) ||
8873       (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc))
8874   {
8875     completed_pending_message (pm);
8876   }
8877   else
8878   {
8879     /* Message not finished, waiting for acknowledgement.
8880        Update time by which we might retransmit 's' based on queue
8881        characteristics (i.e. RTT); it takes one RTT for the message to
8882        arrive and the ACK to come back in the best case; but the other
8883        side is allowed to delay ACKs by 2 RTTs, so we use 4 RTT before
8884        retransmitting.
8885
8886        OPTIMIZE: Note that in the future this heuristic should likely
8887        be improved further (measure RTT stability, consider message
8888        urgency and size when delaying ACKs, etc.) */update_pm_next_attempt (pm,
8889                             GNUNET_TIME_relative_to_absolute (
8890                               GNUNET_TIME_relative_multiply (queue->pd.aged_rtt,
8891                                                              4)));
8892   }
8893   /* finally, re-schedule queue transmission task itself */
8894   schedule_transmit_on_queue (queue, GNUNET_SCHEDULER_PRIORITY_DEFAULT);
8895 }
8896
8897
8898 /**
8899  * Queue to a peer went down.  Process the request.
8900  *
8901  * @param cls the client
8902  * @param dqm the send message that was sent
8903  */
8904 static void
8905 handle_del_queue_message (void *cls,
8906                           const struct GNUNET_TRANSPORT_DelQueueMessage *dqm)
8907 {
8908   struct TransportClient *tc = cls;
8909
8910   if (CT_COMMUNICATOR != tc->type)
8911   {
8912     GNUNET_break (0);
8913     GNUNET_SERVICE_client_drop (tc->client);
8914     return;
8915   }
8916   for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
8917        queue = queue->next_client)
8918   {
8919     struct Neighbour *neighbour = queue->neighbour;
8920
8921     if ((dqm->qid != queue->qid) ||
8922         (0 != GNUNET_memcmp (&dqm->receiver, &neighbour->pid)))
8923       continue;
8924     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8925                 "Dropped queue %s to peer %s\n",
8926                 queue->address,
8927                 GNUNET_i2s (&neighbour->pid));
8928     free_queue (queue);
8929     GNUNET_SERVICE_client_continue (tc->client);
8930     return;
8931   }
8932   GNUNET_break (0);
8933   GNUNET_SERVICE_client_drop (tc->client);
8934 }
8935
8936
8937 /**
8938  * Message was transmitted.  Process the request.
8939  *
8940  * @param cls the client
8941  * @param sma the send message that was sent
8942  */
8943 static void
8944 handle_send_message_ack (void *cls,
8945                          const struct GNUNET_TRANSPORT_SendMessageToAck *sma)
8946 {
8947   struct TransportClient *tc = cls;
8948   struct QueueEntry *qe;
8949   struct PendingMessage *pm;
8950
8951   if (CT_COMMUNICATOR != tc->type)
8952   {
8953     GNUNET_break (0);
8954     GNUNET_SERVICE_client_drop (tc->client);
8955     return;
8956   }
8957
8958   /* find our queue entry matching the ACK */
8959   qe = NULL;
8960   for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
8961        queue = queue->next_client)
8962   {
8963     if (0 != GNUNET_memcmp (&queue->neighbour->pid, &sma->receiver))
8964       continue;
8965     for (struct QueueEntry *qep = queue->queue_head; NULL != qep;
8966          qep = qep->next)
8967     {
8968       if (qep->mid != sma->mid)
8969         continue;
8970       qe = qep;
8971       break;
8972     }
8973     break;
8974   }
8975   if (NULL == qe)
8976   {
8977     /* this should never happen */
8978     GNUNET_break (0);
8979     GNUNET_SERVICE_client_drop (tc->client);
8980     return;
8981   }
8982   GNUNET_CONTAINER_DLL_remove (qe->queue->queue_head,
8983                                qe->queue->queue_tail,
8984                                qe);
8985   qe->queue->queue_length--;
8986   tc->details.communicator.total_queue_length--;
8987   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8988               "Received ACK on queue %s to peer %s (new length: %u/%u)\n",
8989               qe->queue->address,
8990               GNUNET_i2s (&qe->queue->neighbour->pid),
8991               qe->queue->queue_length,
8992               tc->details.communicator.total_queue_length);
8993   GNUNET_SERVICE_client_continue (tc->client);
8994
8995   /* if applicable, resume transmissions that waited on ACK */
8996   if (COMMUNICATOR_TOTAL_QUEUE_LIMIT - 1 ==
8997       tc->details.communicator.total_queue_length)
8998   {
8999     /* Communicator dropped below threshold, resume all queues
9000        incident with this client! */
9001     GNUNET_STATISTICS_update (
9002       GST_stats,
9003       "# Transmission throttled due to communicator queue limit",
9004       -1,
9005       GNUNET_NO);
9006     for (struct Queue *queue = tc->details.communicator.queue_head;
9007          NULL != queue;
9008          queue = queue->next_client)
9009       schedule_transmit_on_queue (queue, GNUNET_SCHEDULER_PRIORITY_DEFAULT);
9010   }
9011   else if (QUEUE_LENGTH_LIMIT - 1 == qe->queue->queue_length)
9012   {
9013     /* queue dropped below threshold; only resume this one queue */
9014     GNUNET_STATISTICS_update (GST_stats,
9015                               "# Transmission throttled due to queue queue limit",
9016                               -1,
9017                               GNUNET_NO);
9018     schedule_transmit_on_queue (qe->queue, GNUNET_SCHEDULER_PRIORITY_DEFAULT);
9019   }
9020
9021   if (NULL != (pm = qe->pm))
9022   {
9023     struct VirtualLink *vl;
9024
9025     GNUNET_assert (qe == pm->qe);
9026     pm->qe = NULL;
9027     /* If waiting for this communicator may have blocked transmission
9028        of pm on other queues for this neighbour, force schedule
9029        transmit on queue for queues of the neighbour */
9030     vl = pm->vl;
9031     if (vl->pending_msg_head == pm)
9032       check_vl_transmission (vl);
9033   }
9034   GNUNET_free (qe);
9035 }
9036
9037
9038 /**
9039  * Iterator telling new MONITOR client about all existing
9040  * queues to peers.
9041  *
9042  * @param cls the new `struct TransportClient`
9043  * @param pid a connected peer
9044  * @param value the `struct Neighbour` with more information
9045  * @return #GNUNET_OK (continue to iterate)
9046  */
9047 static int
9048 notify_client_queues (void *cls,
9049                       const struct GNUNET_PeerIdentity *pid,
9050                       void *value)
9051 {
9052   struct TransportClient *tc = cls;
9053   struct Neighbour *neighbour = value;
9054
9055   GNUNET_assert (CT_MONITOR == tc->type);
9056   for (struct Queue *q = neighbour->queue_head; NULL != q;
9057        q = q->next_neighbour)
9058   {
9059     struct MonitorEvent me = { .rtt = q->pd.aged_rtt,
9060                                .cs = q->cs,
9061                                .num_msg_pending = q->num_msg_pending,
9062                                .num_bytes_pending = q->num_bytes_pending };
9063
9064     notify_monitor (tc, pid, q->address, q->nt, &me);
9065   }
9066   return GNUNET_OK;
9067 }
9068
9069
9070 /**
9071  * Initialize a monitor client.
9072  *
9073  * @param cls the client
9074  * @param start the start message that was sent
9075  */
9076 static void
9077 handle_monitor_start (void *cls,
9078                       const struct GNUNET_TRANSPORT_MonitorStart *start)
9079 {
9080   struct TransportClient *tc = cls;
9081
9082   if (CT_NONE != tc->type)
9083   {
9084     GNUNET_break (0);
9085     GNUNET_SERVICE_client_drop (tc->client);
9086     return;
9087   }
9088   tc->type = CT_MONITOR;
9089   tc->details.monitor.peer = start->peer;
9090   tc->details.monitor.one_shot = ntohl (start->one_shot);
9091   GNUNET_CONTAINER_multipeermap_iterate (neighbours, &notify_client_queues, tc);
9092   GNUNET_SERVICE_client_mark_monitor (tc->client);
9093   GNUNET_SERVICE_client_continue (tc->client);
9094 }
9095
9096
9097 /**
9098  * Find transport client providing communication service
9099  * for the protocol @a prefix.
9100  *
9101  * @param prefix communicator name
9102  * @return NULL if no such transport client is available
9103  */
9104 static struct TransportClient *
9105 lookup_communicator (const char *prefix)
9106 {
9107   for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
9108   {
9109     if (CT_COMMUNICATOR != tc->type)
9110       continue;
9111     if (0 == strcmp (prefix, tc->details.communicator.address_prefix))
9112       return tc;
9113   }
9114   GNUNET_log (
9115     GNUNET_ERROR_TYPE_WARNING,
9116     "Somone suggested use of communicator for `%s', but we do not have such a communicator!\n",
9117     prefix);
9118   return NULL;
9119 }
9120
9121
9122 /**
9123  * Signature of a function called with a communicator @a address of a peer
9124  * @a pid that an application wants us to connect to.
9125  *
9126  * @param pid target peer
9127  * @param address the address to try
9128  */
9129 static void
9130 suggest_to_connect (const struct GNUNET_PeerIdentity *pid, const char *address)
9131 {
9132   static uint32_t idgen;
9133   struct TransportClient *tc;
9134   char *prefix;
9135   struct GNUNET_TRANSPORT_CreateQueue *cqm;
9136   struct GNUNET_MQ_Envelope *env;
9137   size_t alen;
9138
9139   prefix = GNUNET_HELLO_address_to_prefix (address);
9140   if (NULL == prefix)
9141   {
9142     GNUNET_break (0);  /* We got an invalid address!? */
9143     return;
9144   }
9145   tc = lookup_communicator (prefix);
9146   if (NULL == tc)
9147   {
9148     GNUNET_STATISTICS_update (GST_stats,
9149                               "# Suggestions ignored due to missing communicator",
9150                               1,
9151                               GNUNET_NO);
9152     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
9153                 "Cannot connect to %s at `%s', no matching communicator present\n",
9154                 GNUNET_i2s (pid),
9155                 address);
9156     GNUNET_free (prefix);
9157     return;
9158   }
9159   /* forward suggestion for queue creation to communicator */
9160   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9161               "Request #%u for `%s' communicator to create queue to `%s'\n",
9162               (unsigned int) idgen,
9163               prefix,
9164               address);
9165   GNUNET_free (prefix);
9166   alen = strlen (address) + 1;
9167   env =
9168     GNUNET_MQ_msg_extra (cqm, alen, GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE);
9169   cqm->request_id = htonl (idgen++);
9170   cqm->receiver = *pid;
9171   memcpy (&cqm[1], address, alen);
9172   GNUNET_MQ_send (tc->mq, env);
9173 }
9174
9175
9176 /**
9177  * The queue @a q (which matches the peer and address in @a vs) is
9178  * ready for queueing. We should now queue the validation request.
9179  *
9180  * @param q queue to send on
9181  * @param vs state to derive validation challenge from
9182  */
9183 static void
9184 validation_transmit_on_queue (struct Queue *q, struct ValidationState *vs)
9185 {
9186   struct TransportValidationChallengeMessage tvc;
9187
9188   vs->last_challenge_use = GNUNET_TIME_absolute_get_monotonic (GST_cfg);
9189   tvc.header.type =
9190     htons (GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_CHALLENGE);
9191   tvc.header.size = htons (sizeof(tvc));
9192   tvc.reserved = htonl (0);
9193   tvc.challenge = vs->challenge;
9194   tvc.sender_time = GNUNET_TIME_absolute_hton (vs->last_challenge_use);
9195   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
9196               "Sending address validation challenge %s to %s\n",
9197               GNUNET_sh2s (&tvc.challenge.value),
9198               GNUNET_i2s (&q->neighbour->pid));
9199   queue_send_msg (q, NULL, &tvc, sizeof(tvc));
9200 }
9201
9202
9203 /**
9204  * Task run periodically to validate some address based on #validation_heap.
9205  *
9206  * @param cls NULL
9207  */
9208 static void
9209 validation_start_cb (void *cls)
9210 {
9211   struct ValidationState *vs;
9212   struct Queue *q;
9213
9214   (void) cls;
9215   validation_task = NULL;
9216   vs = GNUNET_CONTAINER_heap_peek (validation_heap);
9217   /* drop validations past their expiration */
9218   while (
9219     (NULL != vs) &&
9220     (0 == GNUNET_TIME_absolute_get_remaining (vs->valid_until).rel_value_us))
9221   {
9222     free_validation_state (vs);
9223     vs = GNUNET_CONTAINER_heap_peek (validation_heap);
9224   }
9225   if (NULL == vs)
9226   {
9227     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
9228                 "Address validation task not scheduled anymore, nothing to do\n");
9229     return;   /* woopsie, no more addresses known, should only
9230                  happen if we're really a lonely peer */
9231   }
9232   q = find_queue (&vs->pid, vs->address);
9233   if (NULL == q)
9234   {
9235     vs->awaiting_queue = GNUNET_YES;
9236     suggest_to_connect (&vs->pid, vs->address);
9237   }
9238   else
9239     validation_transmit_on_queue (q, vs);
9240   /* Finally, reschedule next attempt */
9241   vs->challenge_backoff =
9242     GNUNET_TIME_randomized_backoff (vs->challenge_backoff,
9243                                     MAX_VALIDATION_CHALLENGE_FREQ);
9244   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9245               "Address validation task will run again in %s\n",
9246               GNUNET_STRINGS_relative_time_to_string (vs->challenge_backoff,
9247                                                       GNUNET_YES));
9248   update_next_challenge_time (vs,
9249                               GNUNET_TIME_relative_to_absolute (
9250                                 vs->challenge_backoff));
9251 }
9252
9253
9254 /**
9255  * Closure for #check_connection_quality.
9256  */
9257 struct QueueQualityContext
9258 {
9259   /**
9260    * Set to the @e k'th queue encountered.
9261    */
9262   struct Queue *q;
9263
9264   /**
9265    * Set to the number of quality queues encountered.
9266    */
9267   unsigned int quality_count;
9268
9269   /**
9270    * Set to the total number of queues encountered.
9271    */
9272   unsigned int num_queues;
9273
9274   /**
9275    * Decremented for each queue, for selection of the
9276    * k-th queue in @e q.
9277    */
9278   unsigned int k;
9279 };
9280
9281
9282 /**
9283  * Check whether any queue to the given neighbour is
9284  * of a good "quality" and if so, increment the counter.
9285  * Also counts the total number of queues, and returns
9286  * the k-th queue found.
9287  *
9288  * @param cls a `struct QueueQualityContext *` with counters
9289  * @param pid peer this is about
9290  * @param value a `struct Neighbour`
9291  * @return #GNUNET_OK (continue to iterate)
9292  */
9293 static int
9294 check_connection_quality (void *cls,
9295                           const struct GNUNET_PeerIdentity *pid,
9296                           void *value)
9297 {
9298   struct QueueQualityContext *ctx = cls;
9299   struct Neighbour *n = value;
9300   int do_inc;
9301
9302   (void) pid;
9303   do_inc = GNUNET_NO;
9304   for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
9305   {
9306     ctx->num_queues++;
9307     if (0 == ctx->k--)
9308       ctx->q = q;
9309     /* FIXME-CONQ-STATISTICS: in the future, add reliability / goodput
9310        statistics and consider those as well here? */
9311     if (q->pd.aged_rtt.rel_value_us < DV_QUALITY_RTT_THRESHOLD.rel_value_us)
9312       do_inc = GNUNET_YES;
9313   }
9314   if (GNUNET_YES == do_inc)
9315     ctx->quality_count++;
9316   return GNUNET_OK;
9317 }
9318
9319
9320 /**
9321  * Task run when we CONSIDER initiating a DV learn
9322  * process. We first check that sending out a message is
9323  * even possible (queues exist), then that it is desirable
9324  * (if not, reschedule the task for later), and finally
9325  * we may then begin the job.  If there are too many
9326  * entries in the #dvlearn_map, we purge the oldest entry
9327  * using #lle_tail.
9328  *
9329  * @param cls NULL
9330  */
9331 static void
9332 start_dv_learn (void *cls)
9333 {
9334   struct LearnLaunchEntry *lle;
9335   struct QueueQualityContext qqc;
9336   struct TransportDVLearnMessage dvl;
9337
9338   (void) cls;
9339   dvlearn_task = NULL;
9340   if (0 == GNUNET_CONTAINER_multipeermap_size (neighbours))
9341     return; /* lost all connectivity, cannot do learning */
9342   qqc.quality_count = 0;
9343   qqc.num_queues = 0;
9344   GNUNET_CONTAINER_multipeermap_iterate (neighbours,
9345                                          &check_connection_quality,
9346                                          &qqc);
9347   if (qqc.quality_count > DV_LEARN_QUALITY_THRESHOLD)
9348   {
9349     struct GNUNET_TIME_Relative delay;
9350     unsigned int factor;
9351
9352     /* scale our retries by how far we are above the threshold */
9353     factor = qqc.quality_count / DV_LEARN_QUALITY_THRESHOLD;
9354     delay = GNUNET_TIME_relative_multiply (DV_LEARN_BASE_FREQUENCY, factor);
9355     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9356                 "At connection quality %u, will launch DV learn in %s\n",
9357                 qqc.quality_count,
9358                 GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES));
9359     dvlearn_task = GNUNET_SCHEDULER_add_delayed (delay, &start_dv_learn, NULL);
9360     return;
9361   }
9362   /* remove old entries in #dvlearn_map if it has grown too big */
9363   while (MAX_DV_LEARN_PENDING >=
9364          GNUNET_CONTAINER_multishortmap_size (dvlearn_map))
9365   {
9366     lle = lle_tail;
9367     GNUNET_assert (GNUNET_YES ==
9368                    GNUNET_CONTAINER_multishortmap_remove (dvlearn_map,
9369                                                           &lle->challenge.value,
9370                                                           lle));
9371     GNUNET_CONTAINER_DLL_remove (lle_head, lle_tail, lle);
9372     GNUNET_free (lle);
9373   }
9374   /* setup data structure for learning */
9375   lle = GNUNET_new (struct LearnLaunchEntry);
9376   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
9377                               &lle->challenge,
9378                               sizeof(lle->challenge));
9379   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9380               "Starting launch DV learn with challenge %s\n",
9381               GNUNET_sh2s (&lle->challenge.value));
9382   GNUNET_CONTAINER_DLL_insert (lle_head, lle_tail, lle);
9383   GNUNET_break (GNUNET_YES ==
9384                 GNUNET_CONTAINER_multishortmap_put (
9385                   dvlearn_map,
9386                   &lle->challenge.value,
9387                   lle,
9388                   GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
9389   dvl.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN);
9390   dvl.header.size = htons (sizeof(dvl));
9391   dvl.num_hops = htons (0);
9392   dvl.bidirectional = htons (0);
9393   dvl.non_network_delay = GNUNET_TIME_relative_hton (GNUNET_TIME_UNIT_ZERO);
9394   dvl.monotonic_time =
9395     GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_monotonic (GST_cfg));
9396   {
9397     struct DvInitPS dvip = {
9398       .purpose.purpose = htonl (
9399         GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR),
9400       .purpose.size = htonl (sizeof(dvip)),
9401       .monotonic_time = dvl.monotonic_time,
9402       .challenge = lle->challenge
9403     };
9404
9405     GNUNET_CRYPTO_eddsa_sign (GST_my_private_key,
9406                               &dvip,
9407                               &dvl.init_sig);
9408   }
9409   dvl.initiator = GST_my_identity;
9410   dvl.challenge = lle->challenge;
9411
9412   qqc.quality_count = 0;
9413   qqc.k = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, qqc.num_queues);
9414   qqc.num_queues = 0;
9415   qqc.q = NULL;
9416   GNUNET_CONTAINER_multipeermap_iterate (neighbours,
9417                                          &check_connection_quality,
9418                                          &qqc);
9419   GNUNET_assert (NULL != qqc.q);
9420
9421   /* Do this as close to transmission time as possible! */
9422   lle->launch_time = GNUNET_TIME_absolute_get ();
9423
9424   queue_send_msg (qqc.q, NULL, &dvl, sizeof(dvl));
9425   /* reschedule this job, randomizing the time it runs (but no
9426      actual backoff!) */
9427   dvlearn_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_randomize (
9428                                                  DV_LEARN_BASE_FREQUENCY),
9429                                                &start_dv_learn,
9430                                                NULL);
9431 }
9432
9433
9434 /**
9435  * A new queue has been created, check if any address validation
9436  * requests have been waiting for it.
9437  *
9438  * @param cls a `struct Queue`
9439  * @param pid peer concerned (unused)
9440  * @param value a `struct ValidationState`
9441  * @return #GNUNET_NO if a match was found and we can stop looking
9442  */
9443 static int
9444 check_validation_request_pending (void *cls,
9445                                   const struct GNUNET_PeerIdentity *pid,
9446                                   void *value)
9447 {
9448   struct Queue *q = cls;
9449   struct ValidationState *vs = value;
9450
9451   (void) pid;
9452   if ((GNUNET_YES == vs->awaiting_queue) &&
9453       (0 == strcmp (vs->address, q->address)))
9454   {
9455     vs->awaiting_queue = GNUNET_NO;
9456     validation_transmit_on_queue (q, vs);
9457     return GNUNET_NO;
9458   }
9459   return GNUNET_OK;
9460 }
9461
9462
9463 /**
9464  * Function called with the monotonic time of a DV initiator
9465  * by PEERSTORE. Updates the time.
9466  *
9467  * @param cls a `struct Neighbour`
9468  * @param record the information found, NULL for the last call
9469  * @param emsg error message
9470  */
9471 static void
9472 neighbour_dv_monotime_cb (void *cls,
9473                           const struct GNUNET_PEERSTORE_Record *record,
9474                           const char *emsg)
9475 {
9476   struct Neighbour *n = cls;
9477   struct GNUNET_TIME_AbsoluteNBO *mtbe;
9478
9479   (void) emsg;
9480   if (NULL == record)
9481   {
9482     /* we're done with #neighbour_dv_monotime_cb() invocations,
9483        continue normal processing */
9484     n->get = NULL;
9485     n->dv_monotime_available = GNUNET_YES;
9486     return;
9487   }
9488   if (sizeof(*mtbe) != record->value_size)
9489   {
9490     GNUNET_break (0);
9491     return;
9492   }
9493   mtbe = record->value;
9494   n->last_dv_learn_monotime =
9495     GNUNET_TIME_absolute_max (n->last_dv_learn_monotime,
9496                               GNUNET_TIME_absolute_ntoh (*mtbe));
9497 }
9498
9499
9500 /**
9501  * New queue became available.  Process the request.
9502  *
9503  * @param cls the client
9504  * @param aqm the send message that was sent
9505  */
9506 static void
9507 handle_add_queue_message (void *cls,
9508                           const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
9509 {
9510   struct TransportClient *tc = cls;
9511   struct Queue *queue;
9512   struct Neighbour *neighbour;
9513   const char *addr;
9514   uint16_t addr_len;
9515
9516   if (ntohl (aqm->mtu) <= sizeof(struct TransportFragmentBoxMessage))
9517   {
9518     /* MTU so small as to be useless for transmissions,
9519        required for #fragment_message()! */
9520     GNUNET_break_op (0);
9521     GNUNET_SERVICE_client_drop (tc->client);
9522     return;
9523   }
9524   neighbour = lookup_neighbour (&aqm->receiver);
9525   if (NULL == neighbour)
9526   {
9527     neighbour = GNUNET_new (struct Neighbour);
9528     neighbour->pid = aqm->receiver;
9529     GNUNET_assert (GNUNET_OK ==
9530                    GNUNET_CONTAINER_multipeermap_put (
9531                      neighbours,
9532                      &neighbour->pid,
9533                      neighbour,
9534                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
9535     neighbour->get =
9536       GNUNET_PEERSTORE_iterate (peerstore,
9537                                 "transport",
9538                                 &neighbour->pid,
9539                                 GNUNET_PEERSTORE_TRANSPORT_DVLEARN_MONOTIME,
9540                                 &neighbour_dv_monotime_cb,
9541                                 neighbour);
9542   }
9543   addr_len = ntohs (aqm->header.size) - sizeof(*aqm);
9544   addr = (const char *) &aqm[1];
9545   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9546               "New queue %s to %s available with QID %llu\n",
9547               addr,
9548               GNUNET_i2s (&aqm->receiver),
9549               (unsigned long long) aqm->qid);
9550   queue = GNUNET_malloc (sizeof(struct Queue) + addr_len);
9551   queue->tc = tc;
9552   queue->address = (const char *) &queue[1];
9553   queue->pd.aged_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
9554   queue->qid = aqm->qid;
9555   queue->mtu = ntohl (aqm->mtu);
9556   queue->nt = (enum GNUNET_NetworkType) ntohl (aqm->nt);
9557   queue->cs = (enum GNUNET_TRANSPORT_ConnectionStatus) ntohl (aqm->cs);
9558   queue->neighbour = neighbour;
9559   queue->idle = GNUNET_YES;
9560   memcpy (&queue[1], addr, addr_len);
9561   /* notify monitors about new queue */
9562   {
9563     struct MonitorEvent me = { .rtt = queue->pd.aged_rtt, .cs = queue->cs };
9564
9565     notify_monitors (&neighbour->pid, queue->address, queue->nt, &me);
9566   }
9567   GNUNET_CONTAINER_MDLL_insert (neighbour,
9568                                 neighbour->queue_head,
9569                                 neighbour->queue_tail,
9570                                 queue);
9571   GNUNET_CONTAINER_MDLL_insert (client,
9572                                 tc->details.communicator.queue_head,
9573                                 tc->details.communicator.queue_tail,
9574                                 queue);
9575   /* check if valdiations are waiting for the queue */
9576   (void)
9577   GNUNET_CONTAINER_multipeermap_get_multiple (validation_map,
9578                                               &aqm->receiver,
9579                                               &check_validation_request_pending,
9580                                               queue);
9581   /* look for traffic for this queue */
9582   schedule_transmit_on_queue (queue, GNUNET_SCHEDULER_PRIORITY_DEFAULT);
9583   /* might be our first queue, try launching DV learning */
9584   if (NULL == dvlearn_task)
9585     dvlearn_task = GNUNET_SCHEDULER_add_now (&start_dv_learn, NULL);
9586   GNUNET_SERVICE_client_continue (tc->client);
9587 }
9588
9589
9590 /**
9591  * Communicator tells us that our request to create a queue "worked", that
9592  * is setting up the queue is now in process.
9593  *
9594  * @param cls the `struct TransportClient`
9595  * @param cqr confirmation message
9596  */
9597 static void
9598 handle_queue_create_ok (void *cls,
9599                         const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
9600 {
9601   struct TransportClient *tc = cls;
9602
9603   if (CT_COMMUNICATOR != tc->type)
9604   {
9605     GNUNET_break (0);
9606     GNUNET_SERVICE_client_drop (tc->client);
9607     return;
9608   }
9609   GNUNET_STATISTICS_update (GST_stats,
9610                             "# Suggestions succeeded at communicator",
9611                             1,
9612                             GNUNET_NO);
9613   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9614               "Request #%u for communicator to create queue succeeded\n",
9615               (unsigned int) ntohs (cqr->request_id));
9616   GNUNET_SERVICE_client_continue (tc->client);
9617 }
9618
9619
9620 /**
9621  * Communicator tells us that our request to create a queue failed. This
9622  * usually indicates that the provided address is simply invalid or that the
9623  * communicator's resources are exhausted.
9624  *
9625  * @param cls the `struct TransportClient`
9626  * @param cqr failure message
9627  */
9628 static void
9629 handle_queue_create_fail (
9630   void *cls,
9631   const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
9632 {
9633   struct TransportClient *tc = cls;
9634
9635   if (CT_COMMUNICATOR != tc->type)
9636   {
9637     GNUNET_break (0);
9638     GNUNET_SERVICE_client_drop (tc->client);
9639     return;
9640   }
9641   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9642               "Request #%u for communicator to create queue failed\n",
9643               (unsigned int) ntohs (cqr->request_id));
9644   GNUNET_STATISTICS_update (GST_stats,
9645                             "# Suggestions failed in queue creation at communicator",
9646                             1,
9647                             GNUNET_NO);
9648   GNUNET_SERVICE_client_continue (tc->client);
9649 }
9650
9651
9652 /**
9653  * We have received a `struct ExpressPreferenceMessage` from an application
9654  * client.
9655  *
9656  * @param cls handle to the client
9657  * @param msg the start message
9658  */
9659 static void
9660 handle_suggest_cancel (void *cls, const struct ExpressPreferenceMessage *msg)
9661 {
9662   struct TransportClient *tc = cls;
9663   struct PeerRequest *pr;
9664
9665   if (CT_APPLICATION != tc->type)
9666   {
9667     GNUNET_break (0);
9668     GNUNET_SERVICE_client_drop (tc->client);
9669     return;
9670   }
9671   pr = GNUNET_CONTAINER_multipeermap_get (tc->details.application.requests,
9672                                           &msg->peer);
9673   if (NULL == pr)
9674   {
9675     GNUNET_break (0);
9676     GNUNET_SERVICE_client_drop (tc->client);
9677     return;
9678   }
9679   (void) stop_peer_request (tc, &pr->pid, pr);
9680   GNUNET_SERVICE_client_continue (tc->client);
9681 }
9682
9683
9684 /**
9685  * Function called by PEERSTORE for each matching record.
9686  *
9687  * @param cls closure, a `struct PeerRequest`
9688  * @param record peerstore record information
9689  * @param emsg error message, or NULL if no errors
9690  */
9691 static void
9692 handle_hello_for_client (void *cls,
9693                          const struct GNUNET_PEERSTORE_Record *record,
9694                          const char *emsg)
9695 {
9696   struct PeerRequest *pr = cls;
9697   const char *val;
9698
9699   if (NULL != emsg)
9700   {
9701     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
9702                 "Got failure from PEERSTORE: %s\n",
9703                 emsg);
9704     return;
9705   }
9706   val = record->value;
9707   if ((0 == record->value_size) || ('\0' != val[record->value_size - 1]))
9708   {
9709     GNUNET_break (0);
9710     return;
9711   }
9712   start_address_validation (&pr->pid, (const char *) record->value);
9713 }
9714
9715
9716 /**
9717  * We have received a `struct ExpressPreferenceMessage` from an application
9718  * client.
9719  *
9720  * @param cls handle to the client
9721  * @param msg the start message
9722  */
9723 static void
9724 handle_suggest (void *cls, const struct ExpressPreferenceMessage *msg)
9725 {
9726   struct TransportClient *tc = cls;
9727   struct PeerRequest *pr;
9728
9729   if (CT_NONE == tc->type)
9730   {
9731     tc->type = CT_APPLICATION;
9732     tc->details.application.requests =
9733       GNUNET_CONTAINER_multipeermap_create (16, GNUNET_YES);
9734   }
9735   if (CT_APPLICATION != tc->type)
9736   {
9737     GNUNET_break (0);
9738     GNUNET_SERVICE_client_drop (tc->client);
9739     return;
9740   }
9741   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9742               "Client suggested we talk to %s with preference %d at rate %u\n",
9743               GNUNET_i2s (&msg->peer),
9744               (int) ntohl (msg->pk),
9745               (int) ntohl (msg->bw.value__));
9746   pr = GNUNET_new (struct PeerRequest);
9747   pr->tc = tc;
9748   pr->pid = msg->peer;
9749   pr->bw = msg->bw;
9750   pr->pk = (enum GNUNET_MQ_PriorityPreferences) ntohl (msg->pk);
9751   if (GNUNET_YES != GNUNET_CONTAINER_multipeermap_put (
9752         tc->details.application.requests,
9753         &pr->pid,
9754         pr,
9755         GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
9756   {
9757     GNUNET_break (0);
9758     GNUNET_free (pr);
9759     GNUNET_SERVICE_client_drop (tc->client);
9760     return;
9761   }
9762   pr->wc = GNUNET_PEERSTORE_watch (peerstore,
9763                                    "transport",
9764                                    &pr->pid,
9765                                    GNUNET_PEERSTORE_TRANSPORT_URLADDRESS_KEY,
9766                                    &handle_hello_for_client,
9767                                    pr);
9768   GNUNET_SERVICE_client_continue (tc->client);
9769 }
9770
9771
9772 /**
9773  * Check #GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_HELLO_VALIDATION
9774  * messages.
9775  *
9776  * @param cls a `struct TransportClient *`
9777  * @param m message to verify
9778  * @return #GNUNET_OK on success
9779  */
9780 static int
9781 check_request_hello_validation (void *cls,
9782                                 const struct RequestHelloValidationMessage *m)
9783 {
9784   (void) cls;
9785   GNUNET_MQ_check_zero_termination (m);
9786   return GNUNET_OK;
9787 }
9788
9789
9790 /**
9791  * A client encountered an address of another peer. Consider validating it,
9792  * and if validation succeeds, persist it to PEERSTORE.
9793  *
9794  * @param cls a `struct TransportClient *`
9795  * @param m message to verify
9796  */
9797 static void
9798 handle_request_hello_validation (void *cls,
9799                                  const struct RequestHelloValidationMessage *m)
9800 {
9801   struct TransportClient *tc = cls;
9802
9803   start_address_validation (&m->peer, (const char *) &m[1]);
9804   GNUNET_SERVICE_client_continue (tc->client);
9805 }
9806
9807
9808 /**
9809  * Free neighbour entry.
9810  *
9811  * @param cls NULL
9812  * @param pid unused
9813  * @param value a `struct Neighbour`
9814  * @return #GNUNET_OK (always)
9815  */
9816 static int
9817 free_neighbour_cb (void *cls,
9818                    const struct GNUNET_PeerIdentity *pid,
9819                    void *value)
9820 {
9821   struct Neighbour *neighbour = value;
9822
9823   (void) cls;
9824   (void) pid;
9825   GNUNET_break (0);  // should this ever happen?
9826   free_neighbour (neighbour);
9827
9828   return GNUNET_OK;
9829 }
9830
9831
9832 /**
9833  * Free DV route entry.
9834  *
9835  * @param cls NULL
9836  * @param pid unused
9837  * @param value a `struct DistanceVector`
9838  * @return #GNUNET_OK (always)
9839  */
9840 static int
9841 free_dv_routes_cb (void *cls,
9842                    const struct GNUNET_PeerIdentity *pid,
9843                    void *value)
9844 {
9845   struct DistanceVector *dv = value;
9846
9847   (void) cls;
9848   (void) pid;
9849   free_dv_route (dv);
9850
9851   return GNUNET_OK;
9852 }
9853
9854
9855 /**
9856  * Free validation state.
9857  *
9858  * @param cls NULL
9859  * @param pid unused
9860  * @param value a `struct ValidationState`
9861  * @return #GNUNET_OK (always)
9862  */
9863 static int
9864 free_validation_state_cb (void *cls,
9865                           const struct GNUNET_PeerIdentity *pid,
9866                           void *value)
9867 {
9868   struct ValidationState *vs = value;
9869
9870   (void) cls;
9871   (void) pid;
9872   free_validation_state (vs);
9873   return GNUNET_OK;
9874 }
9875
9876
9877 /**
9878  * Free pending acknowledgement.
9879  *
9880  * @param cls NULL
9881  * @param key unused
9882  * @param value a `struct PendingAcknowledgement`
9883  * @return #GNUNET_OK (always)
9884  */
9885 static int
9886 free_pending_ack_cb (void *cls, const struct GNUNET_Uuid *key, void *value)
9887 {
9888   struct PendingAcknowledgement *pa = value;
9889
9890   (void) cls;
9891   (void) key;
9892   free_pending_acknowledgement (pa);
9893   return GNUNET_OK;
9894 }
9895
9896
9897 /**
9898  * Free acknowledgement cummulator.
9899  *
9900  * @param cls NULL
9901  * @param pid unused
9902  * @param value a `struct AcknowledgementCummulator`
9903  * @return #GNUNET_OK (always)
9904  */
9905 static int
9906 free_ack_cummulator_cb (void *cls,
9907                         const struct GNUNET_PeerIdentity *pid,
9908                         void *value)
9909 {
9910   struct AcknowledgementCummulator *ac = value;
9911
9912   (void) cls;
9913   (void) pid;
9914   GNUNET_free (ac);
9915   return GNUNET_OK;
9916 }
9917
9918
9919 /**
9920  * Function called when the service shuts down.  Unloads our plugins
9921  * and cancels pending validations.
9922  *
9923  * @param cls closure, unused
9924  */
9925 static void
9926 do_shutdown (void *cls)
9927 {
9928   struct LearnLaunchEntry *lle;
9929
9930   (void) cls;
9931
9932   GNUNET_CONTAINER_multipeermap_iterate (neighbours, &free_neighbour_cb, NULL);
9933   if (NULL != peerstore)
9934   {
9935     GNUNET_PEERSTORE_disconnect (peerstore, GNUNET_NO);
9936     peerstore = NULL;
9937   }
9938   if (NULL != GST_stats)
9939   {
9940     GNUNET_STATISTICS_destroy (GST_stats, GNUNET_NO);
9941     GST_stats = NULL;
9942   }
9943   if (NULL != GST_my_private_key)
9944   {
9945     GNUNET_free (GST_my_private_key);
9946     GST_my_private_key = NULL;
9947   }
9948   GNUNET_CONTAINER_multipeermap_iterate (ack_cummulators,
9949                                          &free_ack_cummulator_cb,
9950                                          NULL);
9951   GNUNET_CONTAINER_multipeermap_destroy (ack_cummulators);
9952   ack_cummulators = NULL;
9953   GNUNET_CONTAINER_multiuuidmap_iterate (pending_acks,
9954                                          &free_pending_ack_cb,
9955                                          NULL);
9956   GNUNET_CONTAINER_multiuuidmap_destroy (pending_acks);
9957   pending_acks = NULL;
9958   GNUNET_break (0 == GNUNET_CONTAINER_multipeermap_size (neighbours));
9959   GNUNET_CONTAINER_multipeermap_destroy (neighbours);
9960   neighbours = NULL;
9961   GNUNET_break (0 == GNUNET_CONTAINER_multipeermap_size (links));
9962   GNUNET_CONTAINER_multipeermap_destroy (links);
9963   links = NULL;
9964   GNUNET_CONTAINER_multipeermap_iterate (backtalkers,
9965                                          &free_backtalker_cb,
9966                                          NULL);
9967   GNUNET_CONTAINER_multipeermap_destroy (backtalkers);
9968   backtalkers = NULL;
9969   GNUNET_CONTAINER_multipeermap_iterate (validation_map,
9970                                          &free_validation_state_cb,
9971                                          NULL);
9972   GNUNET_CONTAINER_multipeermap_destroy (validation_map);
9973   validation_map = NULL;
9974   while (NULL != ir_head)
9975     free_incoming_request (ir_head);
9976   GNUNET_assert (0 == ir_total);
9977   while (NULL != (lle = lle_head))
9978   {
9979     GNUNET_CONTAINER_DLL_remove (lle_head, lle_tail, lle);
9980     GNUNET_free (lle);
9981   }
9982   GNUNET_CONTAINER_multishortmap_destroy (dvlearn_map);
9983   dvlearn_map = NULL;
9984   GNUNET_CONTAINER_heap_destroy (validation_heap);
9985   validation_heap = NULL;
9986   GNUNET_CONTAINER_multipeermap_iterate (dv_routes, &free_dv_routes_cb, NULL);
9987   GNUNET_CONTAINER_multipeermap_destroy (dv_routes);
9988   dv_routes = NULL;
9989 }
9990
9991
9992 /**
9993  * Initiate transport service.
9994  *
9995  * @param cls closure
9996  * @param c configuration to use
9997  * @param service the initialized service
9998  */
9999 static void
10000 run (void *cls,
10001      const struct GNUNET_CONFIGURATION_Handle *c,
10002      struct GNUNET_SERVICE_Handle *service)
10003 {
10004   (void) cls;
10005   (void) service;
10006   /* setup globals */
10007   hello_mono_time = GNUNET_TIME_absolute_get_monotonic (c);
10008   GST_cfg = c;
10009   backtalkers = GNUNET_CONTAINER_multipeermap_create (16, GNUNET_YES);
10010   pending_acks = GNUNET_CONTAINER_multiuuidmap_create (32768, GNUNET_YES);
10011   ack_cummulators = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_YES);
10012   neighbours = GNUNET_CONTAINER_multipeermap_create (1024, GNUNET_YES);
10013   links = GNUNET_CONTAINER_multipeermap_create (512, GNUNET_YES);
10014   dv_routes = GNUNET_CONTAINER_multipeermap_create (1024, GNUNET_YES);
10015   dvlearn_map = GNUNET_CONTAINER_multishortmap_create (2 * MAX_DV_LEARN_PENDING,
10016                                                        GNUNET_YES);
10017   validation_map = GNUNET_CONTAINER_multipeermap_create (1024, GNUNET_YES);
10018   validation_heap =
10019     GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
10020   GST_my_private_key =
10021     GNUNET_CRYPTO_eddsa_key_create_from_configuration (GST_cfg);
10022   if (NULL == GST_my_private_key)
10023   {
10024     GNUNET_log (
10025       GNUNET_ERROR_TYPE_ERROR,
10026       _ (
10027         "Transport service is lacking key configuration settings. Exiting.\n"));
10028     GNUNET_SCHEDULER_shutdown ();
10029     return;
10030   }
10031   GNUNET_CRYPTO_eddsa_key_get_public (GST_my_private_key,
10032                                       &GST_my_identity.public_key);
10033   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
10034               "My identity is `%s'\n",
10035               GNUNET_i2s_full (&GST_my_identity));
10036   GST_stats = GNUNET_STATISTICS_create ("transport", GST_cfg);
10037   GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
10038   peerstore = GNUNET_PEERSTORE_connect (GST_cfg);
10039   if (NULL == peerstore)
10040   {
10041     GNUNET_break (0);
10042     GNUNET_SCHEDULER_shutdown ();
10043     return;
10044   }
10045 }
10046
10047
10048 /**
10049  * Define "main" method using service macro.
10050  */
10051 GNUNET_SERVICE_MAIN (
10052   "transport",
10053   GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN,
10054   &run,
10055   &client_connect_cb,
10056   &client_disconnect_cb,
10057   NULL,
10058   /* communication with applications */
10059   GNUNET_MQ_hd_fixed_size (suggest,
10060                            GNUNET_MESSAGE_TYPE_TRANSPORT_SUGGEST,
10061                            struct ExpressPreferenceMessage,
10062                            NULL),
10063   GNUNET_MQ_hd_fixed_size (suggest_cancel,
10064                            GNUNET_MESSAGE_TYPE_TRANSPORT_SUGGEST_CANCEL,
10065                            struct ExpressPreferenceMessage,
10066                            NULL),
10067   GNUNET_MQ_hd_var_size (request_hello_validation,
10068                          GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_HELLO_VALIDATION,
10069                          struct RequestHelloValidationMessage,
10070                          NULL),
10071   /* communication with core */
10072   GNUNET_MQ_hd_fixed_size (client_start,
10073                            GNUNET_MESSAGE_TYPE_TRANSPORT_START,
10074                            struct StartMessage,
10075                            NULL),
10076   GNUNET_MQ_hd_var_size (client_send,
10077                          GNUNET_MESSAGE_TYPE_TRANSPORT_SEND,
10078                          struct OutboundMessage,
10079                          NULL),
10080   GNUNET_MQ_hd_fixed_size (client_recv_ok,
10081                            GNUNET_MESSAGE_TYPE_TRANSPORT_RECV_OK,
10082                            struct RecvOkMessage,
10083                            NULL),
10084   /* communication with communicators */
10085   GNUNET_MQ_hd_var_size (communicator_available,
10086                          GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR,
10087                          struct GNUNET_TRANSPORT_CommunicatorAvailableMessage,
10088                          NULL),
10089   GNUNET_MQ_hd_var_size (communicator_backchannel,
10090                          GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL,
10091                          struct GNUNET_TRANSPORT_CommunicatorBackchannel,
10092                          NULL),
10093   GNUNET_MQ_hd_var_size (add_address,
10094                          GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS,
10095                          struct GNUNET_TRANSPORT_AddAddressMessage,
10096                          NULL),
10097   GNUNET_MQ_hd_fixed_size (del_address,
10098                            GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS,
10099                            struct GNUNET_TRANSPORT_DelAddressMessage,
10100                            NULL),
10101   GNUNET_MQ_hd_var_size (incoming_msg,
10102                          GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG,
10103                          struct GNUNET_TRANSPORT_IncomingMessage,
10104                          NULL),
10105   GNUNET_MQ_hd_fixed_size (queue_create_ok,
10106                            GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_OK,
10107                            struct GNUNET_TRANSPORT_CreateQueueResponse,
10108                            NULL),
10109   GNUNET_MQ_hd_fixed_size (queue_create_fail,
10110                            GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_FAIL,
10111                            struct GNUNET_TRANSPORT_CreateQueueResponse,
10112                            NULL),
10113   GNUNET_MQ_hd_var_size (add_queue_message,
10114                          GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP,
10115                          struct GNUNET_TRANSPORT_AddQueueMessage,
10116                          NULL),
10117   GNUNET_MQ_hd_fixed_size (del_queue_message,
10118                            GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN,
10119                            struct GNUNET_TRANSPORT_DelQueueMessage,
10120                            NULL),
10121   GNUNET_MQ_hd_fixed_size (send_message_ack,
10122                            GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK,
10123                            struct GNUNET_TRANSPORT_SendMessageToAck,
10124                            NULL),
10125   /* communication with monitors */
10126   GNUNET_MQ_hd_fixed_size (monitor_start,
10127                            GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_START,
10128                            struct GNUNET_TRANSPORT_MonitorStart,
10129                            NULL),
10130   GNUNET_MQ_handler_end ());
10131
10132
10133 /* end of file gnunet-service-transport.c */