also config files
[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_assert (GNUNET_OK ==
4134                  GNUNET_CRYPTO_ecdhe_key_create2 (&dv->private_key));
4135   GNUNET_CRYPTO_ecdhe_key_get_public (&dv->private_key, &dv->ephemeral_key);
4136   ec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL);
4137   ec.purpose.size = htonl (sizeof(ec));
4138   ec.target = dv->target;
4139   ec.ephemeral_key = dv->ephemeral_key;
4140   GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign (GST_my_private_key,
4141                                                         &ec.purpose,
4142                                                         &dv->sender_sig));
4143 }
4144
4145
4146 /**
4147  * Send the message @a payload on @a queue.
4148  *
4149  * @param queue the queue to use for transmission
4150  * @param pm pending message to update once transmission is done, may be NULL!
4151  * @param payload the payload to send (encapsulated in a
4152  *        #GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG).
4153  * @param payload_size number of bytes in @a payload
4154  */
4155 static void
4156 queue_send_msg (struct Queue *queue,
4157                 struct PendingMessage *pm,
4158                 const void *payload,
4159                 size_t payload_size)
4160 {
4161   struct Neighbour *n = queue->neighbour;
4162   struct GNUNET_TRANSPORT_SendMessageTo *smt;
4163   struct GNUNET_MQ_Envelope *env;
4164
4165   queue->idle = GNUNET_NO;
4166   GNUNET_log (
4167     GNUNET_ERROR_TYPE_DEBUG,
4168     "Queueing %u bytes of payload for transmission <%llu> on queue %llu to %s\n",
4169     (unsigned int) payload_size,
4170     (NULL == pm) ? 0 : pm->logging_uuid,
4171     (unsigned long long) queue->qid,
4172     GNUNET_i2s (&queue->neighbour->pid));
4173   env = GNUNET_MQ_msg_extra (smt,
4174                              payload_size,
4175                              GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG);
4176   smt->qid = queue->qid;
4177   smt->mid = queue->mid_gen;
4178   smt->receiver = n->pid;
4179   memcpy (&smt[1], payload, payload_size);
4180   {
4181     /* Pass the env to the communicator of queue for transmission. */
4182     struct QueueEntry *qe;
4183
4184     qe = GNUNET_new (struct QueueEntry);
4185     qe->mid = queue->mid_gen++;
4186     qe->queue = queue;
4187     if (NULL != pm)
4188     {
4189       qe->pm = pm;
4190       GNUNET_assert (NULL == pm->qe);
4191       pm->qe = qe;
4192     }
4193     GNUNET_CONTAINER_DLL_insert (queue->queue_head, queue->queue_tail, qe);
4194     GNUNET_assert (CT_COMMUNICATOR == queue->tc->type);
4195     queue->queue_length++;
4196     queue->tc->details.communicator.total_queue_length++;
4197     if (COMMUNICATOR_TOTAL_QUEUE_LIMIT ==
4198         queue->tc->details.communicator.total_queue_length)
4199       queue->idle = GNUNET_NO;
4200     if (QUEUE_LENGTH_LIMIT == queue->queue_length)
4201       queue->idle = GNUNET_NO;
4202     GNUNET_MQ_send (queue->tc->mq, env);
4203   }
4204 }
4205
4206
4207 /**
4208  * Pick a queue of @a n under constraints @a options and schedule
4209  * transmission of @a hdr.
4210  *
4211  * @param n neighbour to send to
4212  * @param hdr message to send as payload
4213  * @param options whether queues must be confirmed or not,
4214  *        and whether we may pick multiple (2) queues
4215  * @return expected RTT for transmission, #GNUNET_TIME_UNIT_FOREVER_REL if sending failed
4216  */
4217 static struct GNUNET_TIME_Relative
4218 route_via_neighbour (const struct Neighbour *n,
4219                      const struct GNUNET_MessageHeader *hdr,
4220                      enum RouteMessageOptions options)
4221 {
4222   struct GNUNET_TIME_Absolute now;
4223   unsigned int candidates;
4224   unsigned int sel1;
4225   unsigned int sel2;
4226   struct GNUNET_TIME_Relative rtt;
4227
4228   /* Pick one or two 'random' queues from n (under constraints of options) */
4229   now = GNUNET_TIME_absolute_get ();
4230   /* FIXME-OPTIMIZE: give queues 'weights' and pick proportional to
4231      weight in the future; weight could be assigned by observed
4232      bandwidth (note: not sure if we should do this for this type
4233      of control traffic though). */
4234   candidates = 0;
4235   for (struct Queue *pos = n->queue_head; NULL != pos;
4236        pos = pos->next_neighbour)
4237   {
4238     if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) ||
4239         (pos->validated_until.abs_value_us > now.abs_value_us))
4240       candidates++;
4241   }
4242   if (0 == candidates)
4243   {
4244     /* This can happen rarely if the last confirmed queue timed
4245        out just as we were beginning to process this message. */
4246     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
4247                 "Could not route message of type %u to %s: no valid queue\n",
4248                 ntohs (hdr->type),
4249                 GNUNET_i2s (&n->pid));
4250     GNUNET_STATISTICS_update (GST_stats,
4251                               "# route selection failed (all no valid queue)",
4252                               1,
4253                               GNUNET_NO);
4254     return GNUNET_TIME_UNIT_FOREVER_REL;
4255   }
4256
4257   rtt = GNUNET_TIME_UNIT_FOREVER_REL;
4258   sel1 = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, candidates);
4259   if (0 == (options & RMO_REDUNDANT))
4260     sel2 = candidates; /* picks none! */
4261   else
4262     sel2 = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, candidates);
4263   candidates = 0;
4264   for (struct Queue *pos = n->queue_head; NULL != pos;
4265        pos = pos->next_neighbour)
4266   {
4267     if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) ||
4268         (pos->validated_until.abs_value_us > now.abs_value_us))
4269     {
4270       if ((sel1 == candidates) || (sel2 == candidates))
4271       {
4272         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4273                     "Routing message of type %u to %s using %s (#%u)\n",
4274                     ntohs (hdr->type),
4275                     GNUNET_i2s (&n->pid),
4276                     pos->address,
4277                     (sel1 == candidates) ? 1 : 2);
4278         rtt = GNUNET_TIME_relative_min (rtt, pos->pd.aged_rtt);
4279         queue_send_msg (pos, NULL, hdr, ntohs (hdr->size));
4280       }
4281       candidates++;
4282     }
4283   }
4284   return rtt;
4285 }
4286
4287
4288 /**
4289  * Structure of the key material used to encrypt backchannel messages.
4290  */
4291 struct DVKeyState
4292 {
4293   /**
4294    * State of our block cipher.
4295    */
4296   gcry_cipher_hd_t cipher;
4297
4298   /**
4299    * Actual key material.
4300    */
4301   struct
4302   {
4303     /**
4304      * Key used for HMAC calculations (via #GNUNET_CRYPTO_hmac()).
4305      */
4306     struct GNUNET_CRYPTO_AuthKey hmac_key;
4307
4308     /**
4309      * Symmetric key to use for encryption.
4310      */
4311     char aes_key[256 / 8];
4312
4313     /**
4314      * Counter value to use during setup.
4315      */
4316     char aes_ctr[128 / 8];
4317   } material;
4318 };
4319
4320
4321 /**
4322  * Given the key material in @a km and the initialization vector
4323  * @a iv, setup the key material for the backchannel in @a key.
4324  *
4325  * @param km raw master secret
4326  * @param iv initialization vector
4327  * @param key[out] symmetric cipher and HMAC state to generate
4328  */
4329 static void
4330 dv_setup_key_state_from_km (const struct GNUNET_HashCode *km,
4331                             const struct GNUNET_ShortHashCode *iv,
4332                             struct DVKeyState *key)
4333 {
4334   /* must match #dh_key_derive_eph_pub */
4335   GNUNET_assert (GNUNET_YES ==
4336                  GNUNET_CRYPTO_kdf (&key->material,
4337                                     sizeof(key->material),
4338                                     "transport-backchannel-key",
4339                                     strlen ("transport-backchannel-key"),
4340                                     &km,
4341                                     sizeof(km),
4342                                     iv,
4343                                     sizeof(*iv)));
4344   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4345               "Deriving backchannel key based on KM %s and IV %s\n",
4346               GNUNET_h2s (km),
4347               GNUNET_sh2s (iv));
4348   gcry_cipher_open (&key->cipher,
4349                     GCRY_CIPHER_AES256 /* low level: go for speed */,
4350                     GCRY_CIPHER_MODE_CTR,
4351                     0 /* flags */);
4352   gcry_cipher_setkey (key->cipher,
4353                       &key->material.aes_key,
4354                       sizeof(key->material.aes_key));
4355   gcry_cipher_setctr (key->cipher,
4356                       &key->material.aes_ctr,
4357                       sizeof(key->material.aes_ctr));
4358 }
4359
4360
4361 /**
4362  * Derive backchannel encryption key material from @a priv_ephemeral
4363  * and @a target and @a iv.
4364  *
4365  * @param priv_ephemeral ephemeral private key to use
4366  * @param target the target peer to encrypt to
4367  * @param iv unique IV to use
4368  * @param key[out] set to the key material
4369  */
4370 static void
4371 dh_key_derive_eph_pid (
4372   const struct GNUNET_CRYPTO_EcdhePrivateKey *priv_ephemeral,
4373   const struct GNUNET_PeerIdentity *target,
4374   const struct GNUNET_ShortHashCode *iv,
4375   struct DVKeyState *key)
4376 {
4377   struct GNUNET_HashCode km;
4378
4379   GNUNET_assert (GNUNET_YES == GNUNET_CRYPTO_ecdh_eddsa (priv_ephemeral,
4380                                                          &target->public_key,
4381                                                          &km));
4382   dv_setup_key_state_from_km (&km, iv, key);
4383 }
4384
4385
4386 /**
4387  * Derive backchannel encryption key material from #GST_my_private_key
4388  * and @a pub_ephemeral and @a iv.
4389  *
4390  * @param priv_ephemeral ephemeral private key to use
4391  * @param target the target peer to encrypt to
4392  * @param iv unique IV to use
4393  * @param key[out] set to the key material
4394  */
4395 static void
4396 dh_key_derive_eph_pub (const struct GNUNET_CRYPTO_EcdhePublicKey *pub_ephemeral,
4397                        const struct GNUNET_ShortHashCode *iv,
4398                        struct DVKeyState *key)
4399 {
4400   struct GNUNET_HashCode km;
4401
4402   GNUNET_assert (GNUNET_YES == GNUNET_CRYPTO_eddsa_ecdh (GST_my_private_key,
4403                                                          pub_ephemeral,
4404                                                          &km));
4405   dv_setup_key_state_from_km (&km, iv, key);
4406 }
4407
4408
4409 /**
4410  * Do HMAC calculation for backchannel messages over @a data using key
4411  * material from @a key.
4412  *
4413  * @param key key material (from DH)
4414  * @param hmac[out] set to the HMAC
4415  * @param data data to perform HMAC calculation over
4416  * @param data_size number of bytes in @a data
4417  */
4418 static void
4419 dv_hmac (const struct DVKeyState *key,
4420          struct GNUNET_HashCode *hmac,
4421          const void *data,
4422          size_t data_size)
4423 {
4424   GNUNET_CRYPTO_hmac (&key->material.hmac_key, data, data_size, hmac);
4425 }
4426
4427
4428 /**
4429  * Perform backchannel encryption using symmetric secret in @a key
4430  * to encrypt data from @a in to @a dst.
4431  *
4432  * @param key[in,out] key material to use
4433  * @param dst where to write the result
4434  * @param in input data to encrypt (plaintext)
4435  * @param in_size number of bytes of input in @a in and available at @a dst
4436  */
4437 static void
4438 dv_encrypt (struct DVKeyState *key, const void *in, void *dst, size_t in_size)
4439 {
4440   GNUNET_assert (0 ==
4441                  gcry_cipher_encrypt (key->cipher, dst, in_size, in, in_size));
4442 }
4443
4444
4445 /**
4446  * Perform backchannel encryption using symmetric secret in @a key
4447  * to encrypt data from @a in to @a dst.
4448  *
4449  * @param key[in,out] key material to use
4450  * @param ciph cipher text to decrypt
4451  * @param out[out] output data to generate (plaintext)
4452  * @param out_size number of bytes of input in @a ciph and available in @a out
4453  */
4454 static void
4455 dv_decrypt (struct DVKeyState *key,
4456             void *out,
4457             const void *ciph,
4458             size_t out_size)
4459 {
4460   GNUNET_assert (
4461     0 == gcry_cipher_decrypt (key->cipher, out, out_size, ciph, out_size));
4462 }
4463
4464
4465 /**
4466  * Clean up key material in @a key.
4467  *
4468  * @param key key material to clean up (memory must not be free'd!)
4469  */
4470 static void
4471 dv_key_clean (struct DVKeyState *key)
4472 {
4473   gcry_cipher_close (key->cipher);
4474   GNUNET_CRYPTO_zero_keys (&key->material, sizeof(key->material));
4475 }
4476
4477
4478 /**
4479  * Function to call to further operate on the now DV encapsulated
4480  * message @a hdr, forwarding it via @a next_hop under respect of
4481  * @a options.
4482  *
4483  * @param cls closure
4484  * @param next_hop next hop of the DV path
4485  * @param hdr encapsulated message, technically a `struct TransportDFBoxMessage`
4486  * @param options options of the original message
4487  */
4488 typedef void (*DVMessageHandler) (void *cls,
4489                                   struct Neighbour *next_hop,
4490                                   const struct GNUNET_MessageHeader *hdr,
4491                                   enum RouteMessageOptions options);
4492
4493 /**
4494  * Pick a path of @a dv under constraints @a options and schedule
4495  * transmission of @a hdr.
4496  *
4497  * @param target neighbour to ultimately send to
4498  * @param num_dvhs length of the @a dvhs array
4499  * @param dvhs array of hops to send the message to
4500  * @param hdr message to send as payload
4501  * @param use function to call with the encapsulated message
4502  * @param use_cls closure for @a use
4503  * @param options whether path must be confirmed or not, to be passed to @a use
4504  * @return expected RTT for transmission, #GNUNET_TIME_UNIT_FOREVER_REL if sending failed
4505  */
4506 static struct GNUNET_TIME_Relative
4507 encapsulate_for_dv (struct DistanceVector *dv,
4508                     unsigned int num_dvhs,
4509                     struct DistanceVectorHop **dvhs,
4510                     const struct GNUNET_MessageHeader *hdr,
4511                     DVMessageHandler use,
4512                     void *use_cls,
4513                     enum RouteMessageOptions options)
4514 {
4515   struct TransportDVBoxMessage box_hdr;
4516   struct TransportDVBoxPayloadP payload_hdr;
4517   uint16_t enc_body_size = ntohs (hdr->size);
4518   char enc[sizeof(struct TransportDVBoxPayloadP) + enc_body_size] GNUNET_ALIGN;
4519   struct TransportDVBoxPayloadP *enc_payload_hdr =
4520     (struct TransportDVBoxPayloadP *) enc;
4521   struct DVKeyState key;
4522   struct GNUNET_TIME_Relative rtt;
4523
4524   /* Encrypt payload */
4525   box_hdr.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX);
4526   box_hdr.total_hops = htons (0);
4527   update_ephemeral (dv);
4528   box_hdr.ephemeral_key = dv->ephemeral_key;
4529   payload_hdr.sender_sig = dv->sender_sig;
4530   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
4531                               &box_hdr.iv,
4532                               sizeof(box_hdr.iv));
4533   dh_key_derive_eph_pid (&dv->private_key, &dv->target, &box_hdr.iv, &key);
4534   payload_hdr.sender = GST_my_identity;
4535   payload_hdr.monotonic_time = GNUNET_TIME_absolute_hton (dv->monotime);
4536   dv_encrypt (&key, &payload_hdr, enc_payload_hdr, sizeof(payload_hdr));
4537   dv_encrypt (&key,
4538               hdr,
4539               &enc[sizeof(struct TransportDVBoxPayloadP)],
4540               enc_body_size);
4541   dv_hmac (&key, &box_hdr.hmac, enc, sizeof(enc));
4542   dv_key_clean (&key);
4543   rtt = GNUNET_TIME_UNIT_FOREVER_REL;
4544   /* For each selected path, take the pre-computed header and body
4545      and add the path in the middle of the message; then send it. */
4546   for (unsigned int i = 0; i < num_dvhs; i++)
4547   {
4548     struct DistanceVectorHop *dvh = dvhs[i];
4549     unsigned int num_hops = dvh->distance + 1;
4550     char buf[sizeof(struct TransportDVBoxMessage)
4551              + sizeof(struct GNUNET_PeerIdentity) * num_hops
4552              + sizeof(struct TransportDVBoxPayloadP)
4553              + enc_body_size] GNUNET_ALIGN;
4554     struct GNUNET_PeerIdentity *dhops;
4555
4556     box_hdr.header.size = htons (sizeof(buf));
4557     box_hdr.num_hops = htons (num_hops);
4558     memcpy (buf, &box_hdr, sizeof(box_hdr));
4559     dhops = (struct GNUNET_PeerIdentity *) &buf[sizeof(box_hdr)];
4560     memcpy (dhops,
4561             dvh->path,
4562             dvh->distance * sizeof(struct GNUNET_PeerIdentity));
4563     dhops[dvh->distance] = dv->target;
4564     if (GNUNET_EXTRA_LOGGING > 0)
4565     {
4566       char *path;
4567
4568       path = GNUNET_strdup (GNUNET_i2s (&GST_my_identity));
4569       for (unsigned int j = 0; j <= num_hops; j++)
4570       {
4571         char *tmp;
4572
4573         GNUNET_asprintf (&tmp, "%s-%s", path, GNUNET_i2s (&dhops[j]));
4574         GNUNET_free (path);
4575         path = tmp;
4576       }
4577       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4578                   "Routing message of type %u to %s using DV (#%u/%u) via %s\n",
4579                   ntohs (hdr->type),
4580                   GNUNET_i2s (&dv->target),
4581                   i + 1,
4582                   num_dvhs + 1,
4583                   path);
4584       GNUNET_free (path);
4585     }
4586     rtt = GNUNET_TIME_relative_min (rtt, dvh->pd.aged_rtt);
4587     memcpy (&dhops[num_hops], enc, sizeof(enc));
4588     use (use_cls,
4589          dvh->next_hop,
4590          (const struct GNUNET_MessageHeader *) buf,
4591          options);
4592   }
4593   return rtt;
4594 }
4595
4596
4597 /**
4598  * Wrapper around #route_via_neighbour() that matches the
4599  * #DVMessageHandler structure.
4600  *
4601  * @param cls unused
4602  * @param next_hop where to send next
4603  * @param hdr header of the message to send
4604  * @param options message options for queue selection
4605  */
4606 static void
4607 send_dv_to_neighbour (void *cls,
4608                       struct Neighbour *next_hop,
4609                       const struct GNUNET_MessageHeader *hdr,
4610                       enum RouteMessageOptions options)
4611 {
4612   (void) cls;
4613   (void) route_via_neighbour (next_hop, hdr, options);
4614 }
4615
4616
4617 /**
4618  * We need to transmit @a hdr to @a target.  If necessary, this may
4619  * involve DV routing.  This function routes without applying flow
4620  * control or congestion control and should only be used for control
4621  * traffic.
4622  *
4623  * @param target peer to receive @a hdr
4624  * @param hdr header of the message to route and #GNUNET_free()
4625  * @param options which transmission channels are allowed
4626  * @return expected RTT for transmission, #GNUNET_TIME_UNIT_FOREVER_REL if sending failed
4627  */
4628 static struct GNUNET_TIME_Relative
4629 route_control_message_without_fc (const struct GNUNET_PeerIdentity *target,
4630                                   const struct GNUNET_MessageHeader *hdr,
4631                                   enum RouteMessageOptions options)
4632 {
4633   struct VirtualLink *vl;
4634   struct Neighbour *n;
4635   struct DistanceVector *dv;
4636   struct GNUNET_TIME_Relative rtt1;
4637   struct GNUNET_TIME_Relative rtt2;
4638
4639   vl = lookup_virtual_link (target);
4640   GNUNET_assert (NULL != vl);
4641   n = vl->n;
4642   dv = (0 != (options & RMO_DV_ALLOWED)) ? vl->dv : NULL;
4643   if (0 == (options & RMO_UNCONFIRMED_ALLOWED))
4644   {
4645     /* if confirmed is required, and we do not have anything
4646        confirmed, drop respective options */
4647     if (NULL == n)
4648       n = lookup_neighbour (target);
4649     if ((NULL == dv) && (0 != (options & RMO_DV_ALLOWED)))
4650       dv = GNUNET_CONTAINER_multipeermap_get (dv_routes, target);
4651   }
4652   if ((NULL == n) && (NULL == dv))
4653   {
4654     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
4655                 "Cannot route message of type %u to %s: no route\n",
4656                 ntohs (hdr->type),
4657                 GNUNET_i2s (target));
4658     GNUNET_STATISTICS_update (GST_stats,
4659                               "# Messages dropped in routing: no acceptable method",
4660                               1,
4661                               GNUNET_NO);
4662     return GNUNET_TIME_UNIT_FOREVER_REL;
4663   }
4664   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4665               "Routing message of type %u to %s with options %X\n",
4666               ntohs (hdr->type),
4667               GNUNET_i2s (target),
4668               (unsigned int) options);
4669   /* If both dv and n are possible and we must choose:
4670      flip a coin for the choice between the two; for now 50/50 */
4671   if ((NULL != n) && (NULL != dv) && (0 == (options & RMO_REDUNDANT)))
4672   {
4673     if (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 2))
4674       n = NULL;
4675     else
4676       dv = NULL;
4677   }
4678   if ((NULL != n) && (NULL != dv))
4679     options &= ~RMO_REDUNDANT; /* We will do one DV and one direct, that's
4680                                   enough for redunancy, so clear the flag. */
4681   rtt1 = GNUNET_TIME_UNIT_FOREVER_REL;
4682   rtt2 = GNUNET_TIME_UNIT_FOREVER_REL;
4683   if (NULL != n)
4684   {
4685     rtt1 = route_via_neighbour (n, hdr, options);
4686   }
4687   if (NULL != dv)
4688   {
4689     struct DistanceVectorHop *hops[2];
4690     unsigned int res;
4691
4692     res = pick_random_dv_hops (dv,
4693                                options,
4694                                hops,
4695                                (0 == (options & RMO_REDUNDANT)) ? 1 : 2);
4696     if (0 == res)
4697     {
4698       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
4699                   "Failed to route message, could not determine DV path\n");
4700       return rtt1;
4701     }
4702     rtt2 = encapsulate_for_dv (dv,
4703                                res,
4704                                hops,
4705                                hdr,
4706                                &send_dv_to_neighbour,
4707                                NULL,
4708                                options & (~RMO_REDUNDANT));
4709   }
4710   return GNUNET_TIME_relative_min (rtt1, rtt2);
4711 }
4712
4713
4714 /**
4715  * Something changed on the virtual link with respect to flow
4716  * control. Consider retransmitting the FC window size.
4717  *
4718  * @param cls a `struct VirtualLink` to work with
4719  */
4720 static void
4721 consider_sending_fc (void *cls)
4722 {
4723   struct VirtualLink *vl = cls;
4724   struct GNUNET_TIME_Absolute monotime;
4725   struct TransportFlowControlMessage fc;
4726   struct GNUNET_TIME_Relative duration;
4727   struct GNUNET_TIME_Relative rtt;
4728
4729   duration = GNUNET_TIME_absolute_get_duration (vl->last_fc_transmission);
4730   /* OPTIMIZE-FC-BDP: decide sane criteria on when to do this, instead of doing
4731      it always! */
4732   /* For example, we should probably ONLY do this if a bit more than
4733      an RTT has passed, or if the window changed "significantly" since
4734      then. See vl->last_fc_rtt! NOTE: to do this properly, we also
4735      need an estimate for the bandwidth-delay-product for the entire
4736      VL, as that determines "significantly". We have the delay, but
4737      the bandwidth statistics need to be added for the VL!*/(void) duration;
4738
4739   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4740               "Sending FC seq %u to %s with new window %llu\n",
4741               (unsigned int) vl->fc_seq_gen,
4742               GNUNET_i2s (&vl->target),
4743               (unsigned long long) vl->incoming_fc_window_size);
4744   monotime = GNUNET_TIME_absolute_get_monotonic (GST_cfg);
4745   vl->last_fc_transmission = monotime;
4746   fc.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_FLOW_CONTROL);
4747   fc.header.size = htons (sizeof(fc));
4748   fc.seq = htonl (vl->fc_seq_gen++);
4749   fc.inbound_window_size = GNUNET_htonll (vl->incoming_fc_window_size);
4750   fc.outbound_sent = GNUNET_htonll (vl->outbound_fc_window_size_used);
4751   fc.outbound_window_size = GNUNET_htonll (vl->outbound_fc_window_size);
4752   fc.sender_time = GNUNET_TIME_absolute_hton (monotime);
4753   rtt = route_control_message_without_fc (&vl->target, &fc.header, RMO_NONE);
4754   if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == rtt.rel_value_us)
4755   {
4756     rtt = GNUNET_TIME_UNIT_SECONDS;
4757     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4758                 "FC retransmission to %s failed, will retry in %s\n",
4759                 GNUNET_i2s (&vl->target),
4760                 GNUNET_STRINGS_relative_time_to_string (rtt, GNUNET_YES));
4761     vl->last_fc_rtt = GNUNET_TIME_UNIT_ZERO;
4762   }
4763   else
4764   {
4765     /* OPTIMIZE-FC-BDP: rtt is not ideal, we can do better! */
4766     vl->last_fc_rtt = rtt;
4767   }
4768   if (NULL != vl->fc_retransmit_task)
4769     GNUNET_SCHEDULER_cancel (vl->fc_retransmit_task);
4770   vl->fc_retransmit_task =
4771     GNUNET_SCHEDULER_add_delayed (rtt, &consider_sending_fc, vl);
4772 }
4773
4774
4775 /**
4776  * There is a message at the head of the pending messages for @a vl
4777  * which may be ready for transmission. Check if a queue is ready to
4778  * take it.
4779  *
4780  * This function must (1) check for flow control to ensure that we can
4781  * right now send to @a vl, (2) check that the pending message in the
4782  * queue is actually eligible, (3) determine if any applicable queue
4783  * (direct neighbour or DVH path) is ready to accept messages, and
4784  * (4) prioritize based on the preferences associated with the
4785  * pending message.
4786  *
4787  * So yeah, easy.
4788  *
4789  * @param vl virtual link where we should check for transmission
4790  */
4791 static void
4792 check_vl_transmission (struct VirtualLink *vl)
4793 {
4794   struct Neighbour *n = vl->n;
4795   struct DistanceVector *dv = vl->dv;
4796   struct GNUNET_TIME_Absolute now;
4797   int elig;
4798
4799   /* Check that we have an eligible pending message!
4800      (cheaper than having #transmit_on_queue() find out!) */
4801   elig = GNUNET_NO;
4802   for (struct PendingMessage *pm = vl->pending_msg_head; NULL != pm;
4803        pm = pm->next_vl)
4804   {
4805     if (NULL != pm->qe)
4806       continue;   /* not eligible, is in a queue! */
4807     if (pm->bytes_msg + vl->outbound_fc_window_size_used >
4808         vl->outbound_fc_window_size)
4809     {
4810       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4811                   "Stalled transmision on VL %s due to flow control: %llu < %llu\n",
4812                   GNUNET_i2s (&vl->target),
4813                   (unsigned long long) vl->outbound_fc_window_size,
4814                   (unsigned long long) (pm->bytes_msg
4815                                         + vl->outbound_fc_window_size_used));
4816       consider_sending_fc (vl);
4817       return;     /* We have a message, but flow control says "nope" */
4818     }
4819     elig = GNUNET_YES;
4820     break;
4821   }
4822   if (GNUNET_NO == elig)
4823     return;
4824
4825   /* Notify queues at direct neighbours that we are interested */
4826   now = GNUNET_TIME_absolute_get ();
4827   if (NULL != n)
4828   {
4829     for (struct Queue *queue = n->queue_head; NULL != queue;
4830          queue = queue->next_neighbour)
4831       if ((GNUNET_YES == queue->idle) &&
4832           (queue->validated_until.abs_value_us > now.abs_value_us))
4833         schedule_transmit_on_queue (queue, GNUNET_SCHEDULER_PRIORITY_DEFAULT);
4834   }
4835   /* Notify queues via DV that we are interested */
4836   if (NULL != dv)
4837   {
4838     /* Do DV with lower scheduler priority, which effectively means that
4839        IF a neighbour exists and is available, we prefer it. */
4840     for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
4841          pos = pos->next_dv)
4842     {
4843       struct Neighbour *nh = pos->next_hop;
4844
4845       if (pos->path_valid_until.abs_value_us <= now.abs_value_us)
4846         continue;     /* skip this one: path not validated */
4847       for (struct Queue *queue = nh->queue_head; NULL != queue;
4848            queue = queue->next_neighbour)
4849         if ((GNUNET_YES == queue->idle) &&
4850             (queue->validated_until.abs_value_us > now.abs_value_us))
4851           schedule_transmit_on_queue (queue,
4852                                       GNUNET_SCHEDULER_PRIORITY_BACKGROUND);
4853     }
4854   }
4855 }
4856
4857
4858 /**
4859  * Client asked for transmission to a peer.  Process the request.
4860  *
4861  * @param cls the client
4862  * @param obm the send message that was sent
4863  */
4864 static void
4865 handle_client_send (void *cls, const struct OutboundMessage *obm)
4866 {
4867   struct TransportClient *tc = cls;
4868   struct PendingMessage *pm;
4869   const struct GNUNET_MessageHeader *obmm;
4870   uint32_t bytes_msg;
4871   struct VirtualLink *vl;
4872   enum GNUNET_MQ_PriorityPreferences pp;
4873
4874   GNUNET_assert (CT_CORE == tc->type);
4875   obmm = (const struct GNUNET_MessageHeader *) &obm[1];
4876   bytes_msg = ntohs (obmm->size);
4877   pp = (enum GNUNET_MQ_PriorityPreferences) ntohl (obm->priority);
4878   vl = lookup_virtual_link (&obm->peer);
4879   if (NULL == vl)
4880   {
4881     /* Failure: don't have this peer as a neighbour (anymore).
4882        Might have gone down asynchronously, so this is NOT
4883        a protocol violation by CORE. Still count the event,
4884        as this should be rare. */
4885     GNUNET_SERVICE_client_continue (tc->client);
4886     GNUNET_STATISTICS_update (GST_stats,
4887                               "# messages dropped (neighbour unknown)",
4888                               1,
4889                               GNUNET_NO);
4890     return;
4891   }
4892
4893   pm = GNUNET_malloc (sizeof(struct PendingMessage) + bytes_msg);
4894   pm->logging_uuid = logging_uuid_gen++;
4895   pm->prefs = pp;
4896   pm->client = tc;
4897   pm->vl = vl;
4898   pm->bytes_msg = bytes_msg;
4899   memcpy (&pm[1], obmm, bytes_msg);
4900   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4901               "Sending %u bytes as <%llu> to %s\n",
4902               bytes_msg,
4903               pm->logging_uuid,
4904               GNUNET_i2s (&obm->peer));
4905   GNUNET_CONTAINER_MDLL_insert (client,
4906                                 tc->details.core.pending_msg_head,
4907                                 tc->details.core.pending_msg_tail,
4908                                 pm);
4909   GNUNET_CONTAINER_MDLL_insert (vl,
4910                                 vl->pending_msg_head,
4911                                 vl->pending_msg_tail,
4912                                 pm);
4913   check_vl_transmission (vl);
4914 }
4915
4916
4917 /**
4918  * Communicator requests backchannel transmission.  Process the request.
4919  * Just repacks it into our `struct TransportBackchannelEncapsulationMessage *`
4920  * (which for now has exactly the same format, only a different message type)
4921  * and passes it on for routing.
4922  *
4923  * @param cls the client
4924  * @param cb the send message that was sent
4925  */
4926 static void
4927 handle_communicator_backchannel (
4928   void *cls,
4929   const struct GNUNET_TRANSPORT_CommunicatorBackchannel *cb)
4930 {
4931   struct TransportClient *tc = cls;
4932   const struct GNUNET_MessageHeader *inbox =
4933     (const struct GNUNET_MessageHeader *) &cb[1];
4934   uint16_t isize = ntohs (inbox->size);
4935   const char *is = ((const char *) &cb[1]) + isize;
4936   char
4937     mbuf[isize
4938          + sizeof(struct
4939                   TransportBackchannelEncapsulationMessage)] GNUNET_ALIGN;
4940   struct TransportBackchannelEncapsulationMessage *be =
4941     (struct TransportBackchannelEncapsulationMessage *) mbuf;
4942
4943   /* 0-termination of 'is' was checked already in
4944    #check_communicator_backchannel() */
4945   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4946               "Preparing backchannel transmission to %s:%s of type %u\n",
4947               GNUNET_i2s (&cb->pid),
4948               is,
4949               ntohs (inbox->size));
4950   /* encapsulate and encrypt message */
4951   be->header.type =
4952     htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION);
4953   be->header.size = htons (sizeof(mbuf));
4954   memcpy (&be[1], inbox, isize);
4955   memcpy (&mbuf[sizeof(struct TransportBackchannelEncapsulationMessage)
4956                 + isize],
4957           is,
4958           strlen (is) + 1);
4959   route_control_message_without_fc (&cb->pid, &be->header, RMO_DV_ALLOWED);
4960   GNUNET_SERVICE_client_continue (tc->client);
4961 }
4962
4963
4964 /**
4965  * Address of our peer added.  Test message is well-formed.
4966  *
4967  * @param cls the client
4968  * @param aam the send message that was sent
4969  * @return #GNUNET_OK if message is well-formed
4970  */
4971 static int
4972 check_add_address (void *cls,
4973                    const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
4974 {
4975   struct TransportClient *tc = cls;
4976
4977   if (CT_COMMUNICATOR != tc->type)
4978   {
4979     GNUNET_break (0);
4980     return GNUNET_SYSERR;
4981   }
4982   GNUNET_MQ_check_zero_termination (aam);
4983   return GNUNET_OK;
4984 }
4985
4986
4987 /**
4988  * Ask peerstore to store our address.
4989  *
4990  * @param cls an `struct AddressListEntry *`
4991  */
4992 static void
4993 store_pi (void *cls);
4994
4995
4996 /**
4997  * Function called when peerstore is done storing our address.
4998  *
4999  * @param cls a `struct AddressListEntry`
5000  * @param success #GNUNET_YES if peerstore was successful
5001  */
5002 static void
5003 peerstore_store_own_cb (void *cls, int success)
5004 {
5005   struct AddressListEntry *ale = cls;
5006
5007   ale->sc = NULL;
5008   if (GNUNET_YES != success)
5009     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
5010                 "Failed to store our own address `%s' in peerstore!\n",
5011                 ale->address);
5012   else
5013     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5014                 "Successfully stored our own address `%s' in peerstore!\n",
5015                 ale->address);
5016   /* refresh period is 1/4 of expiration time, that should be plenty
5017      without being excessive. */
5018   ale->st =
5019     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide (ale->expiration,
5020                                                                4ULL),
5021                                   &store_pi,
5022                                   ale);
5023 }
5024
5025
5026 /**
5027  * Ask peerstore to store our address.
5028  *
5029  * @param cls an `struct AddressListEntry *`
5030  */
5031 static void
5032 store_pi (void *cls)
5033 {
5034   struct AddressListEntry *ale = cls;
5035   void *addr;
5036   size_t addr_len;
5037   struct GNUNET_TIME_Absolute expiration;
5038
5039   ale->st = NULL;
5040   expiration = GNUNET_TIME_relative_to_absolute (ale->expiration);
5041   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5042               "Storing our address `%s' in peerstore until %s!\n",
5043               ale->address,
5044               GNUNET_STRINGS_absolute_time_to_string (expiration));
5045   GNUNET_HELLO_sign_address (ale->address,
5046                              ale->nt,
5047                              hello_mono_time,
5048                              GST_my_private_key,
5049                              &addr,
5050                              &addr_len);
5051   ale->sc = GNUNET_PEERSTORE_store (peerstore,
5052                                     "transport",
5053                                     &GST_my_identity,
5054                                     GNUNET_PEERSTORE_TRANSPORT_HELLO_KEY,
5055                                     addr,
5056                                     addr_len,
5057                                     expiration,
5058                                     GNUNET_PEERSTORE_STOREOPTION_MULTIPLE,
5059                                     &peerstore_store_own_cb,
5060                                     ale);
5061   GNUNET_free (addr);
5062   if (NULL == ale->sc)
5063   {
5064     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
5065                 "Failed to store our address `%s' with peerstore\n",
5066                 ale->address);
5067     ale->st =
5068       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &store_pi, ale);
5069   }
5070 }
5071
5072
5073 /**
5074  * Address of our peer added.  Process the request.
5075  *
5076  * @param cls the client
5077  * @param aam the send message that was sent
5078  */
5079 static void
5080 handle_add_address (void *cls,
5081                     const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
5082 {
5083   struct TransportClient *tc = cls;
5084   struct AddressListEntry *ale;
5085   size_t slen;
5086
5087   /* 0-termination of &aam[1] was checked in #check_add_address */
5088   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5089               "Communicator added address `%s'!\n",
5090               (const char *) &aam[1]);
5091   slen = ntohs (aam->header.size) - sizeof(*aam);
5092   ale = GNUNET_malloc (sizeof(struct AddressListEntry) + slen);
5093   ale->tc = tc;
5094   ale->address = (const char *) &ale[1];
5095   ale->expiration = GNUNET_TIME_relative_ntoh (aam->expiration);
5096   ale->aid = aam->aid;
5097   ale->nt = (enum GNUNET_NetworkType) ntohl (aam->nt);
5098   memcpy (&ale[1], &aam[1], slen);
5099   GNUNET_CONTAINER_DLL_insert (tc->details.communicator.addr_head,
5100                                tc->details.communicator.addr_tail,
5101                                ale);
5102   ale->st = GNUNET_SCHEDULER_add_now (&store_pi, ale);
5103   GNUNET_SERVICE_client_continue (tc->client);
5104 }
5105
5106
5107 /**
5108  * Address of our peer deleted.  Process the request.
5109  *
5110  * @param cls the client
5111  * @param dam the send message that was sent
5112  */
5113 static void
5114 handle_del_address (void *cls,
5115                     const struct GNUNET_TRANSPORT_DelAddressMessage *dam)
5116 {
5117   struct TransportClient *tc = cls;
5118   struct AddressListEntry *alen;
5119
5120   if (CT_COMMUNICATOR != tc->type)
5121   {
5122     GNUNET_break (0);
5123     GNUNET_SERVICE_client_drop (tc->client);
5124     return;
5125   }
5126   for (struct AddressListEntry *ale = tc->details.communicator.addr_head;
5127        NULL != ale;
5128        ale = alen)
5129   {
5130     alen = ale->next;
5131     if (dam->aid != ale->aid)
5132       continue;
5133     GNUNET_assert (ale->tc == tc);
5134     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5135                 "Communicator deleted address `%s'!\n",
5136                 ale->address);
5137     free_address_list_entry (ale);
5138     GNUNET_SERVICE_client_continue (tc->client);
5139   }
5140   GNUNET_break (0);
5141   GNUNET_SERVICE_client_drop (tc->client);
5142 }
5143
5144
5145 /**
5146  * Given an inbound message @a msg from a communicator @a cmc,
5147  * demultiplex it based on the type calling the right handler.
5148  *
5149  * @param cmc context for demultiplexing
5150  * @param msg message to demultiplex
5151  */
5152 static void
5153 demultiplex_with_cmc (struct CommunicatorMessageContext *cmc,
5154                       const struct GNUNET_MessageHeader *msg);
5155
5156
5157 /**
5158  * Function called when we are done giving a message of a certain
5159  * size to CORE and should thus decrement the number of bytes of
5160  * RAM reserved for that peer's MQ.
5161  *
5162  * @param cls a `struct CoreSentContext`
5163  */
5164 static void
5165 core_env_sent_cb (void *cls)
5166 {
5167   struct CoreSentContext *ctx = cls;
5168   struct VirtualLink *vl = ctx->vl;
5169
5170   if (NULL == vl)
5171   {
5172     /* lost the link in the meantime, ignore */
5173     GNUNET_free (ctx);
5174     return;
5175   }
5176   GNUNET_CONTAINER_DLL_remove (vl->csc_head, vl->csc_tail, ctx);
5177   GNUNET_assert (vl->incoming_fc_window_size_ram >= ctx->size);
5178   vl->incoming_fc_window_size_ram -= ctx->size;
5179   vl->incoming_fc_window_size_used += ctx->isize;
5180   consider_sending_fc (vl);
5181   GNUNET_free (ctx);
5182 }
5183
5184
5185 /**
5186  * Communicator gave us an unencapsulated message to pass as-is to
5187  * CORE.  Process the request.
5188  *
5189  * @param cls a `struct CommunicatorMessageContext` (must call
5190  * #finish_cmc_handling() when done)
5191  * @param mh the message that was received
5192  */
5193 static void
5194 handle_raw_message (void *cls, const struct GNUNET_MessageHeader *mh)
5195 {
5196   struct CommunicatorMessageContext *cmc = cls;
5197   struct VirtualLink *vl;
5198   uint16_t size = ntohs (mh->size);
5199   int have_core;
5200
5201   if ((size > UINT16_MAX - sizeof(struct InboundMessage)) ||
5202       (size < sizeof(struct GNUNET_MessageHeader)))
5203   {
5204     struct GNUNET_SERVICE_Client *client = cmc->tc->client;
5205
5206     GNUNET_break (0);
5207     finish_cmc_handling (cmc);
5208     GNUNET_SERVICE_client_drop (client);
5209     return;
5210   }
5211   vl = lookup_virtual_link (&cmc->im.sender);
5212   if (NULL == vl)
5213   {
5214     /* FIXME: sender is giving us messages for CORE but we don't have
5215        the link up yet! I *suspect* this can happen right now (i.e.
5216        sender has verified us, but we didn't verify sender), but if
5217        we pass this on, CORE would be confused (link down, messages
5218        arrive).  We should investigate more if this happens often,
5219        or in a persistent manner, and possibly do "something" about
5220        it. Thus logging as error for now. */GNUNET_break_op (0);
5221     GNUNET_STATISTICS_update (GST_stats,
5222                               "# CORE messages droped (virtual link still down)",
5223                               1,
5224                               GNUNET_NO);
5225
5226     finish_cmc_handling (cmc);
5227     return;
5228   }
5229   if (vl->incoming_fc_window_size_ram > UINT_MAX - size)
5230   {
5231     GNUNET_STATISTICS_update (GST_stats,
5232                               "# CORE messages droped (FC arithmetic overflow)",
5233                               1,
5234                               GNUNET_NO);
5235
5236     finish_cmc_handling (cmc);
5237     return;
5238   }
5239   if (vl->incoming_fc_window_size_ram + size > vl->available_fc_window_size)
5240   {
5241     GNUNET_STATISTICS_update (GST_stats,
5242                               "# CORE messages droped (FC window overflow)",
5243                               1,
5244                               GNUNET_NO);
5245     finish_cmc_handling (cmc);
5246     return;
5247   }
5248
5249   /* Forward to all CORE clients */
5250   have_core = GNUNET_NO;
5251   for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
5252   {
5253     struct GNUNET_MQ_Envelope *env;
5254     struct InboundMessage *im;
5255     struct CoreSentContext *ctx;
5256
5257     if (CT_CORE != tc->type)
5258       continue;
5259     vl->incoming_fc_window_size_ram += size;
5260     env = GNUNET_MQ_msg_extra (im, size, GNUNET_MESSAGE_TYPE_TRANSPORT_RECV);
5261     ctx = GNUNET_new (struct CoreSentContext);
5262     ctx->vl = vl;
5263     ctx->size = size;
5264     ctx->isize = (GNUNET_NO == have_core) ? size : 0;
5265     have_core = GNUNET_YES;
5266     GNUNET_CONTAINER_DLL_insert (vl->csc_head, vl->csc_tail, ctx);
5267     GNUNET_MQ_notify_sent (env, &core_env_sent_cb, ctx);
5268     im->peer = cmc->im.sender;
5269     memcpy (&im[1], mh, size);
5270     GNUNET_MQ_send (tc->mq, env);
5271     vl->core_recv_window--;
5272   }
5273   if (GNUNET_NO == have_core)
5274   {
5275     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
5276                 "Dropped message to CORE: no CORE client connected!\n");
5277     /* Nevertheless, count window as used, as it is from the
5278        perspective of the other peer! */
5279     vl->incoming_fc_window_size_used += size;
5280     /* TODO-M1 */
5281     finish_cmc_handling (cmc);
5282     return;
5283   }
5284   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5285               "Delivered message from %s of type %u to CORE\n",
5286               GNUNET_i2s (&cmc->im.sender),
5287               ntohs (mh->type));
5288   if (vl->core_recv_window > 0)
5289   {
5290     finish_cmc_handling (cmc);
5291     return;
5292   }
5293   /* Wait with calling #finish_cmc_handling(cmc) until the message
5294      was processed by CORE MQs (for CORE flow control)! */
5295   GNUNET_CONTAINER_DLL_insert (vl->cmc_head, vl->cmc_tail, cmc);
5296 }
5297
5298
5299 /**
5300  * Communicator gave us a fragment box.  Check the message.
5301  *
5302  * @param cls a `struct CommunicatorMessageContext`
5303  * @param fb the send message that was sent
5304  * @return #GNUNET_YES if message is well-formed
5305  */
5306 static int
5307 check_fragment_box (void *cls, const struct TransportFragmentBoxMessage *fb)
5308 {
5309   uint16_t size = ntohs (fb->header.size);
5310   uint16_t bsize = size - sizeof(*fb);
5311
5312   (void) cls;
5313   if (0 == bsize)
5314   {
5315     GNUNET_break_op (0);
5316     return GNUNET_SYSERR;
5317   }
5318   if (bsize + ntohs (fb->frag_off) > ntohs (fb->msg_size))
5319   {
5320     GNUNET_break_op (0);
5321     return GNUNET_SYSERR;
5322   }
5323   if (ntohs (fb->frag_off) >= ntohs (fb->msg_size))
5324   {
5325     GNUNET_break_op (0);
5326     return GNUNET_SYSERR;
5327   }
5328   return GNUNET_YES;
5329 }
5330
5331
5332 /**
5333  * Clean up an idle cummulative acknowledgement data structure.
5334  *
5335  * @param cls a `struct AcknowledgementCummulator *`
5336  */
5337 static void
5338 destroy_ack_cummulator (void *cls)
5339 {
5340   struct AcknowledgementCummulator *ac = cls;
5341
5342   ac->task = NULL;
5343   GNUNET_assert (0 == ac->num_acks);
5344   GNUNET_assert (
5345     GNUNET_YES ==
5346     GNUNET_CONTAINER_multipeermap_remove (ack_cummulators, &ac->target, ac));
5347   GNUNET_free (ac);
5348 }
5349
5350
5351 /**
5352  * Do the transmission of a cummulative acknowledgement now.
5353  *
5354  * @param cls a `struct AcknowledgementCummulator *`
5355  */
5356 static void
5357 transmit_cummulative_ack_cb (void *cls)
5358 {
5359   struct AcknowledgementCummulator *ac = cls;
5360   char buf[sizeof(struct TransportReliabilityAckMessage)
5361            + ac->ack_counter
5362            * sizeof(struct TransportCummulativeAckPayloadP)] GNUNET_ALIGN;
5363   struct TransportReliabilityAckMessage *ack =
5364     (struct TransportReliabilityAckMessage *) buf;
5365   struct TransportCummulativeAckPayloadP *ap;
5366
5367   ac->task = NULL;
5368   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5369               "Sending ACK with %u components to %s\n",
5370               ac->ack_counter,
5371               GNUNET_i2s (&ac->target));
5372   GNUNET_assert (0 < ac->ack_counter);
5373   ack->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_ACK);
5374   ack->header.size =
5375     htons (sizeof(*ack)
5376            + ac->ack_counter * sizeof(struct TransportCummulativeAckPayloadP));
5377   ack->ack_counter = htonl (ac->ack_counter++);
5378   ap = (struct TransportCummulativeAckPayloadP *) &ack[1];
5379   for (unsigned int i = 0; i < ac->ack_counter; i++)
5380   {
5381     ap[i].ack_uuid = ac->ack_uuids[i].ack_uuid;
5382     ap[i].ack_delay = GNUNET_TIME_relative_hton (
5383       GNUNET_TIME_absolute_get_duration (ac->ack_uuids[i].receive_time));
5384   }
5385   route_control_message_without_fc (&ac->target, &ack->header, RMO_DV_ALLOWED);
5386   ac->num_acks = 0;
5387   ac->task = GNUNET_SCHEDULER_add_delayed (ACK_CUMMULATOR_TIMEOUT,
5388                                            &destroy_ack_cummulator,
5389                                            ac);
5390 }
5391
5392
5393 /**
5394  * Transmit an acknowledgement for @a ack_uuid to @a pid delaying
5395  * transmission by at most @a ack_delay.
5396  *
5397  * @param pid target peer
5398  * @param ack_uuid UUID to ack
5399  * @param max_delay how long can the ACK wait
5400  */
5401 static void
5402 cummulative_ack (const struct GNUNET_PeerIdentity *pid,
5403                  const struct AcknowledgementUUIDP *ack_uuid,
5404                  struct GNUNET_TIME_Absolute max_delay)
5405 {
5406   struct AcknowledgementCummulator *ac;
5407
5408   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5409               "Scheduling ACK %s for transmission to %s\n",
5410               GNUNET_uuid2s (&ack_uuid->value),
5411               GNUNET_i2s (pid));
5412   ac = GNUNET_CONTAINER_multipeermap_get (ack_cummulators, pid);
5413   if (NULL == ac)
5414   {
5415     ac = GNUNET_new (struct AcknowledgementCummulator);
5416     ac->target = *pid;
5417     ac->min_transmission_time = max_delay;
5418     GNUNET_assert (GNUNET_YES ==
5419                    GNUNET_CONTAINER_multipeermap_put (
5420                      ack_cummulators,
5421                      &ac->target,
5422                      ac,
5423                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
5424   }
5425   else
5426   {
5427     if (MAX_CUMMULATIVE_ACKS == ac->num_acks)
5428     {
5429       /* must run immediately, ack buffer full! */
5430       GNUNET_SCHEDULER_cancel (ac->task);
5431       transmit_cummulative_ack_cb (ac);
5432     }
5433     GNUNET_SCHEDULER_cancel (ac->task);
5434     ac->min_transmission_time =
5435       GNUNET_TIME_absolute_min (ac->min_transmission_time, max_delay);
5436   }
5437   GNUNET_assert (ac->num_acks < MAX_CUMMULATIVE_ACKS);
5438   ac->ack_uuids[ac->num_acks].receive_time = GNUNET_TIME_absolute_get ();
5439   ac->ack_uuids[ac->num_acks].ack_uuid = *ack_uuid;
5440   ac->num_acks++;
5441   ac->task = GNUNET_SCHEDULER_add_at (ac->min_transmission_time,
5442                                       &transmit_cummulative_ack_cb,
5443                                       ac);
5444 }
5445
5446
5447 /**
5448  * Closure for #find_by_message_uuid.
5449  */
5450 struct FindByMessageUuidContext
5451 {
5452   /**
5453    * UUID to look for.
5454    */
5455   struct MessageUUIDP message_uuid;
5456
5457   /**
5458    * Set to the reassembly context if found.
5459    */
5460   struct ReassemblyContext *rc;
5461 };
5462
5463
5464 /**
5465  * Iterator called to find a reassembly context by the message UUID in the
5466  * multihashmap32.
5467  *
5468  * @param cls a `struct FindByMessageUuidContext`
5469  * @param key a key (unused)
5470  * @param value a `struct ReassemblyContext`
5471  * @return #GNUNET_YES if not found, #GNUNET_NO if found
5472  */
5473 static int
5474 find_by_message_uuid (void *cls, uint32_t key, void *value)
5475 {
5476   struct FindByMessageUuidContext *fc = cls;
5477   struct ReassemblyContext *rc = value;
5478
5479   (void) key;
5480   if (0 == GNUNET_memcmp (&fc->message_uuid, &rc->msg_uuid))
5481   {
5482     fc->rc = rc;
5483     return GNUNET_NO;
5484   }
5485   return GNUNET_YES;
5486 }
5487
5488
5489 /**
5490  * Communicator gave us a fragment.  Process the request.
5491  *
5492  * @param cls a `struct CommunicatorMessageContext` (must call
5493  * #finish_cmc_handling() when done)
5494  * @param fb the message that was received
5495  */
5496 static void
5497 handle_fragment_box (void *cls, const struct TransportFragmentBoxMessage *fb)
5498 {
5499   struct CommunicatorMessageContext *cmc = cls;
5500   struct Neighbour *n;
5501   struct ReassemblyContext *rc;
5502   const struct GNUNET_MessageHeader *msg;
5503   uint16_t msize;
5504   uint16_t fsize;
5505   uint16_t frag_off;
5506   char *target;
5507   struct GNUNET_TIME_Relative cdelay;
5508   struct FindByMessageUuidContext fc;
5509
5510   n = lookup_neighbour (&cmc->im.sender);
5511   if (NULL == n)
5512   {
5513     struct GNUNET_SERVICE_Client *client = cmc->tc->client;
5514
5515     GNUNET_break (0);
5516     finish_cmc_handling (cmc);
5517     GNUNET_SERVICE_client_drop (client);
5518     return;
5519   }
5520   if (NULL == n->reassembly_map)
5521   {
5522     n->reassembly_map = GNUNET_CONTAINER_multihashmap32_create (8);
5523     n->reassembly_heap =
5524       GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
5525     n->reassembly_timeout_task =
5526       GNUNET_SCHEDULER_add_delayed (REASSEMBLY_EXPIRATION,
5527                                     &reassembly_cleanup_task,
5528                                     n);
5529   }
5530   msize = ntohs (fb->msg_size);
5531   fc.message_uuid = fb->msg_uuid;
5532   fc.rc = NULL;
5533   (void) GNUNET_CONTAINER_multihashmap32_get_multiple (n->reassembly_map,
5534                                                        fb->msg_uuid.uuid,
5535                                                        &find_by_message_uuid,
5536                                                        &fc);
5537   if (NULL == (rc = fc.rc))
5538   {
5539     rc = GNUNET_malloc (sizeof(*rc) + msize    /* reassembly payload buffer */
5540                         + (msize + 7) / 8 * sizeof(uint8_t) /* bitfield */);
5541     rc->msg_uuid = fb->msg_uuid;
5542     rc->neighbour = n;
5543     rc->msg_size = msize;
5544     rc->reassembly_timeout =
5545       GNUNET_TIME_relative_to_absolute (REASSEMBLY_EXPIRATION);
5546     rc->last_frag = GNUNET_TIME_absolute_get ();
5547     rc->hn = GNUNET_CONTAINER_heap_insert (n->reassembly_heap,
5548                                            rc,
5549                                            rc->reassembly_timeout.abs_value_us);
5550     GNUNET_assert (GNUNET_OK ==
5551                    GNUNET_CONTAINER_multihashmap32_put (
5552                      n->reassembly_map,
5553                      rc->msg_uuid.uuid,
5554                      rc,
5555                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
5556     target = (char *) &rc[1];
5557     rc->bitfield = (uint8_t *) (target + rc->msg_size);
5558     rc->msg_missing = rc->msg_size;
5559     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5560                 "Received fragment at offset %u/%u from %s for NEW message %u\n",
5561                 ntohs (fb->frag_off),
5562                 msize,
5563                 GNUNET_i2s (&cmc->im.sender),
5564                 (unsigned int) fb->msg_uuid.uuid);
5565   }
5566   else
5567   {
5568     target = (char *) &rc[1];
5569     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5570                 "Received fragment at offset %u/%u from %s for message %u\n",
5571                 ntohs (fb->frag_off),
5572                 msize,
5573                 GNUNET_i2s (&cmc->im.sender),
5574                 (unsigned int) fb->msg_uuid.uuid);
5575   }
5576   if (msize != rc->msg_size)
5577   {
5578     GNUNET_break (0);
5579     finish_cmc_handling (cmc);
5580     return;
5581   }
5582
5583   /* reassemble */
5584   fsize = ntohs (fb->header.size) - sizeof(*fb);
5585   if (0 == fsize)
5586   {
5587     GNUNET_break (0);
5588     finish_cmc_handling (cmc);
5589     return;
5590   }
5591   frag_off = ntohs (fb->frag_off);
5592   if (frag_off + fsize > msize)
5593   {
5594     /* Fragment (plus fragment size) exceeds message size! */
5595     GNUNET_break_op (0);
5596     finish_cmc_handling (cmc);
5597     return;
5598   }
5599   memcpy (&target[frag_off], &fb[1], fsize);
5600   /* update bitfield and msg_missing */
5601   for (unsigned int i = frag_off; i < frag_off + fsize; i++)
5602   {
5603     if (0 == (rc->bitfield[i / 8] & (1 << (i % 8))))
5604     {
5605       rc->bitfield[i / 8] |= (1 << (i % 8));
5606       rc->msg_missing--;
5607     }
5608   }
5609
5610   /* Compute cummulative ACK */
5611   cdelay = GNUNET_TIME_absolute_get_duration (rc->last_frag);
5612   cdelay = GNUNET_TIME_relative_multiply (cdelay, rc->msg_missing / fsize);
5613   if (0 == rc->msg_missing)
5614     cdelay = GNUNET_TIME_UNIT_ZERO;
5615   cummulative_ack (&cmc->im.sender,
5616                    &fb->ack_uuid,
5617                    GNUNET_TIME_relative_to_absolute (cdelay));
5618   rc->last_frag = GNUNET_TIME_absolute_get ();
5619   /* is reassembly complete? */
5620   if (0 != rc->msg_missing)
5621   {
5622     finish_cmc_handling (cmc);
5623     return;
5624   }
5625   /* reassembly is complete, verify result */
5626   msg = (const struct GNUNET_MessageHeader *) &rc[1];
5627   if (ntohs (msg->size) != rc->msg_size)
5628   {
5629     GNUNET_break (0);
5630     free_reassembly_context (rc);
5631     finish_cmc_handling (cmc);
5632     return;
5633   }
5634   /* successful reassembly */
5635   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5636               "Fragment reassembly complete for message %u\n",
5637               (unsigned int) fb->msg_uuid.uuid);
5638   /* FIXME: check that the resulting msg is NOT a
5639      DV Box or Reliability Box, as that is NOT allowed! */
5640   demultiplex_with_cmc (cmc, msg);
5641   /* FIXME-OPTIMIZE: really free here? Might be bad if fragments are still
5642      en-route and we forget that we finished this reassembly immediately!
5643      -> keep around until timeout?
5644      -> shorten timeout based on ACK? */
5645   free_reassembly_context (rc);
5646 }
5647
5648
5649 /**
5650  * Communicator gave us a reliability box.  Check the message.
5651  *
5652  * @param cls a `struct CommunicatorMessageContext`
5653  * @param rb the send message that was sent
5654  * @return #GNUNET_YES if message is well-formed
5655  */
5656 static int
5657 check_reliability_box (void *cls,
5658                        const struct TransportReliabilityBoxMessage *rb)
5659 {
5660   (void) cls;
5661   GNUNET_MQ_check_boxed_message (rb);
5662   return GNUNET_YES;
5663 }
5664
5665
5666 /**
5667  * Communicator gave us a reliability box.  Process the request.
5668  *
5669  * @param cls a `struct CommunicatorMessageContext` (must call
5670  * #finish_cmc_handling() when done)
5671  * @param rb the message that was received
5672  */
5673 static void
5674 handle_reliability_box (void *cls,
5675                         const struct TransportReliabilityBoxMessage *rb)
5676 {
5677   struct CommunicatorMessageContext *cmc = cls;
5678   const struct GNUNET_MessageHeader *inbox =
5679     (const struct GNUNET_MessageHeader *) &rb[1];
5680   struct GNUNET_TIME_Relative rtt;
5681
5682   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5683               "Received reliability box from %s with UUID %s of type %u\n",
5684               GNUNET_i2s (&cmc->im.sender),
5685               GNUNET_uuid2s (&rb->ack_uuid.value),
5686               (unsigned int) ntohs (inbox->type));
5687   rtt = GNUNET_TIME_UNIT_SECONDS; /* FIXME: should base this on "RTT", but we
5688                                      do not really have an RTT for the
5689                                    * incoming* queue (should we have
5690                                      the sender add it to the rb message?) */
5691   cummulative_ack (
5692     &cmc->im.sender,
5693     &rb->ack_uuid,
5694     (0 == ntohl (rb->ack_countdown))
5695     ? GNUNET_TIME_UNIT_ZERO_ABS
5696     : GNUNET_TIME_relative_to_absolute (
5697       GNUNET_TIME_relative_divide (rtt, 8 /* FIXME: magic constant */)));
5698   /* continue with inner message */
5699   /* FIXME: check that inbox is NOT a DV Box, fragment or another
5700      reliability box (not allowed!) */
5701   demultiplex_with_cmc (cmc, inbox);
5702 }
5703
5704
5705 /**
5706  * Check if we have advanced to another age since the last time.  If
5707  * so, purge ancient statistics (more than GOODPUT_AGING_SLOTS before
5708  * the current age)
5709  *
5710  * @param pd[in,out] data to update
5711  * @param age current age
5712  */
5713 static void
5714 update_pd_age (struct PerformanceData *pd, unsigned int age)
5715 {
5716   unsigned int sage;
5717
5718   if (age == pd->last_age)
5719     return; /* nothing to do */
5720   sage = GNUNET_MAX (pd->last_age, age - 2 * GOODPUT_AGING_SLOTS);
5721   for (unsigned int i = sage; i <= age - GOODPUT_AGING_SLOTS; i++)
5722   {
5723     struct TransmissionHistoryEntry *the = &pd->the[i % GOODPUT_AGING_SLOTS];
5724
5725     the->bytes_sent = 0;
5726     the->bytes_received = 0;
5727   }
5728   pd->last_age = age;
5729 }
5730
5731
5732 /**
5733  * Update @a pd based on the latest @a rtt and the number of bytes
5734  * that were confirmed to be successfully transmitted.
5735  *
5736  * @param pd[in,out] data to update
5737  * @param rtt latest round-trip time
5738  * @param bytes_transmitted_ok number of bytes receiver confirmed as received
5739  */
5740 static void
5741 update_performance_data (struct PerformanceData *pd,
5742                          struct GNUNET_TIME_Relative rtt,
5743                          uint16_t bytes_transmitted_ok)
5744 {
5745   uint64_t nval = rtt.rel_value_us;
5746   uint64_t oval = pd->aged_rtt.rel_value_us;
5747   unsigned int age = get_age ();
5748   struct TransmissionHistoryEntry *the = &pd->the[age % GOODPUT_AGING_SLOTS];
5749
5750   if (oval == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
5751     pd->aged_rtt = rtt;
5752   else
5753     pd->aged_rtt.rel_value_us = (nval + 7 * oval) / 8;
5754   update_pd_age (pd, age);
5755   the->bytes_received += bytes_transmitted_ok;
5756 }
5757
5758
5759 /**
5760  * We have successfully transmitted data via @a q, update metrics.
5761  *
5762  * @param q queue to update
5763  * @param rtt round trip time observed
5764  * @param bytes_transmitted_ok number of bytes successfully transmitted
5765  */
5766 static void
5767 update_queue_performance (struct Queue *q,
5768                           struct GNUNET_TIME_Relative rtt,
5769                           uint16_t bytes_transmitted_ok)
5770 {
5771   update_performance_data (&q->pd, rtt, bytes_transmitted_ok);
5772 }
5773
5774
5775 /**
5776  * We have successfully transmitted data via @a dvh, update metrics.
5777  *
5778  * @param dvh distance vector path data to update
5779  * @param rtt round trip time observed
5780  * @param bytes_transmitted_ok number of bytes successfully transmitted
5781  */
5782 static void
5783 update_dvh_performance (struct DistanceVectorHop *dvh,
5784                         struct GNUNET_TIME_Relative rtt,
5785                         uint16_t bytes_transmitted_ok)
5786 {
5787   update_performance_data (&dvh->pd, rtt, bytes_transmitted_ok);
5788 }
5789
5790
5791 /**
5792  * We have completed transmission of @a pm, remove it from
5793  * the transmission queues (and if it is a fragment, continue
5794  * up the tree as necessary).
5795  *
5796  * @param pm pending message that was transmitted
5797  */
5798 static void
5799 completed_pending_message (struct PendingMessage *pm)
5800 {
5801   struct PendingMessage *pos;
5802
5803   switch (pm->pmt)
5804   {
5805   case PMT_CORE:
5806   case PMT_RELIABILITY_BOX:
5807     /* Full message sent, we are done */
5808     client_send_response (pm);
5809     return;
5810
5811   case PMT_FRAGMENT_BOX:
5812     /* Fragment sent over reliabile channel */
5813     free_fragment_tree (pm);
5814     pos = pm->frag_parent;
5815     GNUNET_CONTAINER_MDLL_remove (frag, pos->head_frag, pos->tail_frag, pm);
5816     GNUNET_free (pm);
5817     /* check if subtree is done */
5818     while ((NULL == pos->head_frag) && (pos->frag_off == pos->bytes_msg) &&
5819            (pos != pm))
5820     {
5821       pm = pos;
5822       pos = pm->frag_parent;
5823       GNUNET_CONTAINER_MDLL_remove (frag, pos->head_frag, pos->tail_frag, pm);
5824       GNUNET_free (pm);
5825     }
5826
5827     /* Was this the last applicable fragmment? */
5828     if ((NULL == pos->head_frag) && (NULL == pos->frag_parent) &&
5829         (pos->frag_off == pos->bytes_msg))
5830       client_send_response (pos);
5831     return;
5832
5833   case PMT_DV_BOX:
5834     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5835                 "Completed transmission of message %llu (DV Box)\n",
5836                 pm->logging_uuid);
5837     free_pending_message (pm);
5838     return;
5839   }
5840 }
5841
5842
5843 /**
5844  * The @a pa was acknowledged, process the acknowledgement.
5845  *
5846  * @param pa the pending acknowledgement that was satisfied
5847  * @param ack_delay artificial delay from cummulative acks created by the
5848  * other peer
5849  */
5850 static void
5851 handle_acknowledged (struct PendingAcknowledgement *pa,
5852                      struct GNUNET_TIME_Relative ack_delay)
5853 {
5854   struct GNUNET_TIME_Relative delay;
5855
5856   delay = GNUNET_TIME_absolute_get_duration (pa->transmission_time);
5857   if (delay.rel_value_us > ack_delay.rel_value_us)
5858     delay = GNUNET_TIME_UNIT_ZERO;
5859   else
5860     delay = GNUNET_TIME_relative_subtract (delay, ack_delay);
5861   if (NULL != pa->queue)
5862     update_queue_performance (pa->queue, delay, pa->message_size);
5863   if (NULL != pa->dvh)
5864     update_dvh_performance (pa->dvh, delay, pa->message_size);
5865   if (NULL != pa->pm)
5866     completed_pending_message (pa->pm);
5867   free_pending_acknowledgement (pa);
5868 }
5869
5870
5871 /**
5872  * Communicator gave us a reliability ack.  Check it is well-formed.
5873  *
5874  * @param cls a `struct CommunicatorMessageContext` (unused)
5875  * @param ra the message that was received
5876  * @return #GNUNET_Ok if @a ra is well-formed
5877  */
5878 static int
5879 check_reliability_ack (void *cls,
5880                        const struct TransportReliabilityAckMessage *ra)
5881 {
5882   unsigned int n_acks;
5883
5884   (void) cls;
5885   n_acks = (ntohs (ra->header.size) - sizeof(*ra))
5886            / sizeof(struct TransportCummulativeAckPayloadP);
5887   if (0 == n_acks)
5888   {
5889     GNUNET_break_op (0);
5890     return GNUNET_SYSERR;
5891   }
5892   if ((ntohs (ra->header.size) - sizeof(*ra)) !=
5893       n_acks * sizeof(struct TransportCummulativeAckPayloadP))
5894   {
5895     GNUNET_break_op (0);
5896     return GNUNET_SYSERR;
5897   }
5898   return GNUNET_OK;
5899 }
5900
5901
5902 /**
5903  * Communicator gave us a reliability ack.  Process the request.
5904  *
5905  * @param cls a `struct CommunicatorMessageContext` (must call
5906  * #finish_cmc_handling() when done)
5907  * @param ra the message that was received
5908  */
5909 static void
5910 handle_reliability_ack (void *cls,
5911                         const struct TransportReliabilityAckMessage *ra)
5912 {
5913   struct CommunicatorMessageContext *cmc = cls;
5914   const struct TransportCummulativeAckPayloadP *ack;
5915   unsigned int n_acks;
5916   uint32_t ack_counter;
5917
5918   n_acks = (ntohs (ra->header.size) - sizeof(*ra))
5919            / sizeof(struct TransportCummulativeAckPayloadP);
5920   ack = (const struct TransportCummulativeAckPayloadP *) &ra[1];
5921   for (unsigned int i = 0; i < n_acks; i++)
5922   {
5923     struct PendingAcknowledgement *pa =
5924       GNUNET_CONTAINER_multiuuidmap_get (pending_acks, &ack[i].ack_uuid.value);
5925     if (NULL == pa)
5926     {
5927       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
5928                   "Received ACK from %s with UUID %s which is unknown to us!\n",
5929                   GNUNET_i2s (&cmc->im.sender),
5930                   GNUNET_uuid2s (&ack[i].ack_uuid.value));
5931       GNUNET_STATISTICS_update (
5932         GST_stats,
5933         "# FRAGMENT_ACKS dropped, no matching pending message",
5934         1,
5935         GNUNET_NO);
5936       continue;
5937     }
5938     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5939                 "Received ACK from %s with UUID %s\n",
5940                 GNUNET_i2s (&cmc->im.sender),
5941                 GNUNET_uuid2s (&ack[i].ack_uuid.value));
5942     handle_acknowledged (pa, GNUNET_TIME_relative_ntoh (ack[i].ack_delay));
5943   }
5944
5945   ack_counter = htonl (ra->ack_counter);
5946   (void) ack_counter;  /* silence compiler warning for now */
5947   // FIXME-OPTIMIZE: track ACK losses based on ack_counter somewhere!
5948   // (DV and/or Neighbour?)
5949   finish_cmc_handling (cmc);
5950 }
5951
5952
5953 /**
5954  * Communicator gave us a backchannel encapsulation.  Check the message.
5955  *
5956  * @param cls a `struct CommunicatorMessageContext`
5957  * @param be the send message that was sent
5958  * @return #GNUNET_YES if message is well-formed
5959  */
5960 static int
5961 check_backchannel_encapsulation (
5962   void *cls,
5963   const struct TransportBackchannelEncapsulationMessage *be)
5964 {
5965   uint16_t size = ntohs (be->header.size) - sizeof(*be);
5966   const struct GNUNET_MessageHeader *inbox =
5967     (const struct GNUNET_MessageHeader *) &be[1];
5968   const char *is;
5969   uint16_t isize;
5970
5971   (void) cls;
5972   if (ntohs (inbox->size) >= size)
5973   {
5974     GNUNET_break_op (0);
5975     return GNUNET_SYSERR;
5976   }
5977   isize = ntohs (inbox->size);
5978   is = ((const char *) inbox) + isize;
5979   size -= isize;
5980   if ('\0' != is[size - 1])
5981   {
5982     GNUNET_break_op (0);
5983     return GNUNET_SYSERR;
5984   }
5985   return GNUNET_YES;
5986 }
5987
5988
5989 /**
5990  * Communicator gave us a backchannel encapsulation.  Process the request.
5991  * (We are the destination of the backchannel here.)
5992  *
5993  * @param cls a `struct CommunicatorMessageContext` (must call
5994  * #finish_cmc_handling() when done)
5995  * @param be the message that was received
5996  */
5997 static void
5998 handle_backchannel_encapsulation (
5999   void *cls,
6000   const struct TransportBackchannelEncapsulationMessage *be)
6001 {
6002   struct CommunicatorMessageContext *cmc = cls;
6003   struct GNUNET_TRANSPORT_CommunicatorBackchannelIncoming *cbi;
6004   struct GNUNET_MQ_Envelope *env;
6005   struct TransportClient *tc;
6006   const struct GNUNET_MessageHeader *inbox =
6007     (const struct GNUNET_MessageHeader *) &be[1];
6008   uint16_t isize = ntohs (inbox->size);
6009   const char *target_communicator = ((const char *) inbox) + isize;
6010
6011   /* Find client providing this communicator */
6012   for (tc = clients_head; NULL != tc; tc = tc->next)
6013     if ((CT_COMMUNICATOR == tc->type) &&
6014         (0 ==
6015          strcmp (tc->details.communicator.address_prefix, target_communicator)))
6016       break;
6017   if (NULL == tc)
6018   {
6019     char *stastr;
6020
6021     GNUNET_asprintf (
6022       &stastr,
6023       "# Backchannel message dropped: target communicator `%s' unknown",
6024       target_communicator);
6025     GNUNET_STATISTICS_update (GST_stats, stastr, 1, GNUNET_NO);
6026     GNUNET_free (stastr);
6027     return;
6028   }
6029   /* Finally, deliver backchannel message to communicator */
6030   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6031               "Delivering backchannel message from %s of type %u to %s\n",
6032               GNUNET_i2s (&cmc->im.sender),
6033               ntohs (inbox->type),
6034               target_communicator);
6035   env = GNUNET_MQ_msg_extra (
6036     cbi,
6037     isize,
6038     GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL_INCOMING);
6039   cbi->pid = cmc->im.sender;
6040   memcpy (&cbi[1], inbox, isize);
6041   GNUNET_MQ_send (tc->mq, env);
6042 }
6043
6044
6045 /**
6046  * Task called when we should check if any of the DV paths
6047  * we have learned to a target are due for garbage collection.
6048  *
6049  * Collects stale paths, and possibly frees the entire DV
6050  * entry if no paths are left. Otherwise re-schedules itself.
6051  *
6052  * @param cls a `struct DistanceVector`
6053  */
6054 static void
6055 path_cleanup_cb (void *cls)
6056 {
6057   struct DistanceVector *dv = cls;
6058   struct DistanceVectorHop *pos;
6059
6060   dv->timeout_task = NULL;
6061   while (NULL != (pos = dv->dv_head))
6062   {
6063     GNUNET_assert (dv == pos->dv);
6064     if (GNUNET_TIME_absolute_get_remaining (pos->timeout).rel_value_us > 0)
6065       break;
6066     free_distance_vector_hop (pos);
6067   }
6068   if (NULL == pos)
6069   {
6070     free_dv_route (dv);
6071     return;
6072   }
6073   dv->timeout_task =
6074     GNUNET_SCHEDULER_add_at (pos->timeout, &path_cleanup_cb, dv);
6075 }
6076
6077
6078 /**
6079  * The @a hop is a validated path to the respective target
6080  * peer and we should tell core about it -- and schedule
6081  * a job to revoke the state.
6082  *
6083  * @param hop a path to some peer that is the reason for activation
6084  */
6085 static void
6086 activate_core_visible_dv_path (struct DistanceVectorHop *hop)
6087 {
6088   struct DistanceVector *dv = hop->dv;
6089   struct VirtualLink *vl;
6090
6091   vl = lookup_virtual_link (&dv->target);
6092   if (NULL != vl)
6093   {
6094     /* Link was already up, remember dv is also now available and we are done */
6095     vl->dv = dv;
6096     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6097                 "Virtual link to %s could now also use DV!\n",
6098                 GNUNET_i2s (&dv->target));
6099     return;
6100   }
6101   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6102               "Creating new virtual link to %s using DV!\n",
6103               GNUNET_i2s (&dv->target));
6104   vl = GNUNET_new (struct VirtualLink);
6105   vl->message_uuid_ctr =
6106     GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX);
6107   vl->target = dv->target;
6108   vl->dv = dv;
6109   dv->vl = vl;
6110   vl->core_recv_window = RECV_WINDOW_SIZE;
6111   vl->available_fc_window_size = DEFAULT_WINDOW_SIZE;
6112   vl->visibility_task =
6113     GNUNET_SCHEDULER_add_at (hop->path_valid_until, &check_link_down, vl);
6114   GNUNET_break (GNUNET_YES ==
6115                 GNUNET_CONTAINER_multipeermap_put (
6116                   links,
6117                   &vl->target,
6118                   vl,
6119                   GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
6120   consider_sending_fc (vl);
6121   /* We lacked a confirmed connection to the target
6122      before, so tell CORE about it (finally!) */
6123   cores_send_connect_info (&dv->target);
6124 }
6125
6126
6127 /**
6128  * We have learned a @a path through the network to some other peer, add it to
6129  * our DV data structure (returning #GNUNET_YES on success).
6130  *
6131  * We do not add paths if we have a sufficient number of shorter
6132  * paths to this target already (returning #GNUNET_NO).
6133  *
6134  * We also do not add problematic paths, like those where we lack the first
6135  * hop in our neighbour list (i.e. due to a topology change) or where some
6136  * non-first hop is in our neighbour list (returning #GNUNET_SYSERR).
6137  *
6138  * @param path the path we learned, path[0] should be us,
6139  *             and then path contains a valid path from us to
6140  * `path[path_len-1]` path[1] should be a direct neighbour (we should check!)
6141  * @param path_len number of entries on the @a path, at least three!
6142  * @param network_latency how long does the message take from us to
6143  * `path[path_len-1]`? set to "forever" if unknown
6144  * @param path_valid_until how long is this path considered validated? Maybe
6145  * be zero.
6146  * @return #GNUNET_YES on success,
6147  *         #GNUNET_NO if we have better path(s) to the target
6148  *         #GNUNET_SYSERR if the path is useless and/or invalid
6149  *                         (i.e. path[1] not a direct neighbour
6150  *                        or path[i+1] is a direct neighbour for i>0)
6151  */
6152 static int
6153 learn_dv_path (const struct GNUNET_PeerIdentity *path,
6154                unsigned int path_len,
6155                struct GNUNET_TIME_Relative network_latency,
6156                struct GNUNET_TIME_Absolute path_valid_until)
6157 {
6158   struct DistanceVectorHop *hop;
6159   struct DistanceVector *dv;
6160   struct Neighbour *next_hop;
6161   unsigned int shorter_distance;
6162
6163   if (path_len < 3)
6164   {
6165     /* what a boring path! not allowed! */
6166     GNUNET_break (0);
6167     return GNUNET_SYSERR;
6168   }
6169   GNUNET_assert (0 == GNUNET_memcmp (&GST_my_identity, &path[0]));
6170   next_hop = lookup_neighbour (&path[1]);
6171   if (NULL == next_hop)
6172   {
6173     /* next hop must be a neighbour, otherwise this whole thing is useless! */
6174     GNUNET_break (0);
6175     return GNUNET_SYSERR;
6176   }
6177   for (unsigned int i = 2; i < path_len; i++)
6178     if (NULL != lookup_neighbour (&path[i]))
6179     {
6180       /* Useless path: we have a direct connection to some hop
6181          in the middle of the path, so this one is not even
6182          terribly useful for redundancy */
6183       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
6184                   "Path of %u hops useless: directly link to hop %u (%s)\n",
6185                   path_len,
6186                   i,
6187                   GNUNET_i2s (&path[i]));
6188       GNUNET_STATISTICS_update (GST_stats,
6189                                 "# Useless DV path ignored: hop is neighbour",
6190                                 1,
6191                                 GNUNET_NO);
6192       return GNUNET_SYSERR;
6193     }
6194   dv = GNUNET_CONTAINER_multipeermap_get (dv_routes, &path[path_len - 1]);
6195   if (NULL == dv)
6196   {
6197     dv = GNUNET_new (struct DistanceVector);
6198     dv->target = path[path_len - 1];
6199     dv->timeout_task = GNUNET_SCHEDULER_add_delayed (DV_PATH_VALIDITY_TIMEOUT,
6200                                                      &path_cleanup_cb,
6201                                                      dv);
6202     GNUNET_assert (GNUNET_OK ==
6203                    GNUNET_CONTAINER_multipeermap_put (
6204                      dv_routes,
6205                      &dv->target,
6206                      dv,
6207                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
6208   }
6209   /* Check if we have this path already! */
6210   shorter_distance = 0;
6211   for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
6212        pos = pos->next_dv)
6213   {
6214     if (pos->distance < path_len - 2)
6215       shorter_distance++;
6216     /* Note that the distances in 'pos' excludes us (path[0]) and
6217        the next_hop (path[1]), so we need to subtract two
6218        and check next_hop explicitly */
6219     if ((pos->distance == path_len - 2) && (pos->next_hop == next_hop))
6220     {
6221       int match = GNUNET_YES;
6222
6223       for (unsigned int i = 0; i < pos->distance; i++)
6224       {
6225         if (0 != GNUNET_memcmp (&pos->path[i], &path[i + 2]))
6226         {
6227           match = GNUNET_NO;
6228           break;
6229         }
6230       }
6231       if (GNUNET_YES == match)
6232       {
6233         struct GNUNET_TIME_Relative last_timeout;
6234
6235         /* Re-discovered known path, update timeout */
6236         GNUNET_STATISTICS_update (GST_stats,
6237                                   "# Known DV path refreshed",
6238                                   1,
6239                                   GNUNET_NO);
6240         last_timeout = GNUNET_TIME_absolute_get_remaining (pos->timeout);
6241         pos->timeout =
6242           GNUNET_TIME_relative_to_absolute (DV_PATH_VALIDITY_TIMEOUT);
6243         pos->path_valid_until =
6244           GNUNET_TIME_absolute_max (pos->path_valid_until, path_valid_until);
6245         GNUNET_CONTAINER_MDLL_remove (dv, dv->dv_head, dv->dv_tail, pos);
6246         GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, pos);
6247         if (0 <
6248             GNUNET_TIME_absolute_get_remaining (path_valid_until).rel_value_us)
6249           activate_core_visible_dv_path (pos);
6250         if (last_timeout.rel_value_us <
6251             GNUNET_TIME_relative_subtract (DV_PATH_VALIDITY_TIMEOUT,
6252                                            DV_PATH_DISCOVERY_FREQUENCY)
6253             .rel_value_us)
6254         {
6255           /* Some peer send DV learn messages too often, we are learning
6256              the same path faster than it would be useful; do not forward! */
6257           GNUNET_log (GNUNET_ERROR_TYPE_INFO,
6258                       "Rediscovered path too quickly, not forwarding further\n");
6259           return GNUNET_NO;
6260         }
6261         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6262                     "Refreshed known path to %s, forwarding further\n",
6263                     GNUNET_i2s (&dv->target));
6264         return GNUNET_YES;
6265       }
6266     }
6267   }
6268   /* Count how many shorter paths we have (incl. direct
6269      neighbours) before simply giving up on this one! */
6270   if (shorter_distance >= MAX_DV_PATHS_TO_TARGET)
6271   {
6272     /* We have a shorter path already! */
6273     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6274                 "Have many shorter DV paths %s, not forwarding further\n",
6275                 GNUNET_i2s (&dv->target));
6276     return GNUNET_NO;
6277   }
6278   /* create new DV path entry */
6279   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6280               "Discovered new DV path to %s\n",
6281               GNUNET_i2s (&dv->target));
6282   hop = GNUNET_malloc (sizeof(struct DistanceVectorHop)
6283                        + sizeof(struct GNUNET_PeerIdentity) * (path_len - 2));
6284   hop->next_hop = next_hop;
6285   hop->dv = dv;
6286   hop->path = (const struct GNUNET_PeerIdentity *) &hop[1];
6287   memcpy (&hop[1],
6288           &path[2],
6289           sizeof(struct GNUNET_PeerIdentity) * (path_len - 2));
6290   hop->timeout = GNUNET_TIME_relative_to_absolute (DV_PATH_VALIDITY_TIMEOUT);
6291   hop->path_valid_until = path_valid_until;
6292   hop->distance = path_len - 2;
6293   hop->pd.aged_rtt = network_latency;
6294   GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, hop);
6295   GNUNET_CONTAINER_MDLL_insert (neighbour,
6296                                 next_hop->dv_head,
6297                                 next_hop->dv_tail,
6298                                 hop);
6299   if (0 < GNUNET_TIME_absolute_get_remaining (path_valid_until).rel_value_us)
6300     activate_core_visible_dv_path (hop);
6301   return GNUNET_YES;
6302 }
6303
6304
6305 /**
6306  * Communicator gave us a DV learn message.  Check the message.
6307  *
6308  * @param cls a `struct CommunicatorMessageContext`
6309  * @param dvl the send message that was sent
6310  * @return #GNUNET_YES if message is well-formed
6311  */
6312 static int
6313 check_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
6314 {
6315   uint16_t size = ntohs (dvl->header.size);
6316   uint16_t num_hops = ntohs (dvl->num_hops);
6317   const struct DVPathEntryP *hops = (const struct DVPathEntryP *) &dvl[1];
6318
6319   (void) cls;
6320   if (size != sizeof(*dvl) + num_hops * sizeof(struct DVPathEntryP))
6321   {
6322     GNUNET_break_op (0);
6323     return GNUNET_SYSERR;
6324   }
6325   if (num_hops > MAX_DV_HOPS_ALLOWED)
6326   {
6327     GNUNET_break_op (0);
6328     return GNUNET_SYSERR;
6329   }
6330   for (unsigned int i = 0; i < num_hops; i++)
6331   {
6332     if (0 == GNUNET_memcmp (&dvl->initiator, &hops[i].hop))
6333     {
6334       GNUNET_break_op (0);
6335       return GNUNET_SYSERR;
6336     }
6337     if (0 == GNUNET_memcmp (&GST_my_identity, &hops[i].hop))
6338     {
6339       GNUNET_break_op (0);
6340       return GNUNET_SYSERR;
6341     }
6342   }
6343   return GNUNET_YES;
6344 }
6345
6346
6347 /**
6348  * Build and forward a DV learn message to @a next_hop.
6349  *
6350  * @param next_hop peer to send the message to
6351  * @param msg message received
6352  * @param bi_history bitmask specifying hops on path that were bidirectional
6353  * @param nhops length of the @a hops array
6354  * @param hops path the message traversed so far
6355  * @param in_time when did we receive the message, used to calculate network
6356  * delay
6357  */
6358 static void
6359 forward_dv_learn (const struct GNUNET_PeerIdentity *next_hop,
6360                   const struct TransportDVLearnMessage *msg,
6361                   uint16_t bi_history,
6362                   uint16_t nhops,
6363                   const struct DVPathEntryP *hops,
6364                   struct GNUNET_TIME_Absolute in_time)
6365 {
6366   struct DVPathEntryP *dhops;
6367   char buf[sizeof(struct TransportDVLearnMessage)
6368            + (nhops + 1) * sizeof(struct DVPathEntryP)] GNUNET_ALIGN;
6369   struct TransportDVLearnMessage *fwd = (struct TransportDVLearnMessage *) buf;
6370   struct GNUNET_TIME_Relative nnd;
6371
6372   /* compute message for forwarding */
6373   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6374               "Forwarding DV learn message originating from %s to %s\n",
6375               GNUNET_i2s (&msg->initiator),
6376               GNUNET_i2s2 (next_hop));
6377   GNUNET_assert (nhops < MAX_DV_HOPS_ALLOWED);
6378   fwd->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN);
6379   fwd->header.size = htons (sizeof(struct TransportDVLearnMessage)
6380                             + (nhops + 1) * sizeof(struct DVPathEntryP));
6381   fwd->num_hops = htons (nhops + 1);
6382   fwd->bidirectional = htons (bi_history);
6383   nnd = GNUNET_TIME_relative_add (GNUNET_TIME_absolute_get_duration (in_time),
6384                                   GNUNET_TIME_relative_ntoh (
6385                                     msg->non_network_delay));
6386   fwd->non_network_delay = GNUNET_TIME_relative_hton (nnd);
6387   fwd->init_sig = msg->init_sig;
6388   fwd->initiator = msg->initiator;
6389   fwd->challenge = msg->challenge;
6390   dhops = (struct DVPathEntryP *) &fwd[1];
6391   GNUNET_memcpy (dhops, hops, sizeof(struct DVPathEntryP) * nhops);
6392   dhops[nhops].hop = GST_my_identity;
6393   {
6394     struct DvHopPS dhp = { .purpose.purpose =
6395                              htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_HOP),
6396                            .purpose.size = htonl (sizeof(dhp)),
6397                            .pred = dhops[nhops - 1].hop,
6398                            .succ = *next_hop,
6399                            .challenge = msg->challenge };
6400
6401     GNUNET_assert (GNUNET_OK ==
6402                    GNUNET_CRYPTO_eddsa_sign (GST_my_private_key,
6403                                              &dhp.purpose,
6404                                              &dhops[nhops].hop_sig));
6405   }
6406   route_control_message_without_fc (next_hop,
6407                                     &fwd->header,
6408                                     RMO_UNCONFIRMED_ALLOWED);
6409 }
6410
6411
6412 /**
6413  * Check signature of type #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR
6414  *
6415  * @param sender_monotonic_time monotonic time of the initiator
6416  * @param init the signer
6417  * @param challenge the challenge that was signed
6418  * @param init_sig signature presumably by @a init
6419  * @return #GNUNET_OK if the signature is valid
6420  */
6421 static int
6422 validate_dv_initiator_signature (
6423   struct GNUNET_TIME_AbsoluteNBO sender_monotonic_time,
6424   const struct GNUNET_PeerIdentity *init,
6425   const struct ChallengeNonceP *challenge,
6426   const struct GNUNET_CRYPTO_EddsaSignature *init_sig)
6427 {
6428   struct DvInitPS ip = { .purpose.purpose = htonl (
6429                            GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR),
6430                          .purpose.size = htonl (sizeof(ip)),
6431                          .monotonic_time = sender_monotonic_time,
6432                          .challenge = *challenge };
6433
6434   if (
6435     GNUNET_OK !=
6436     GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR,
6437                                 &ip.purpose,
6438                                 init_sig,
6439                                 &init->public_key))
6440   {
6441     GNUNET_break_op (0);
6442     return GNUNET_SYSERR;
6443   }
6444   return GNUNET_OK;
6445 }
6446
6447
6448 /**
6449  * Closure for #dv_neighbour_selection and #dv_neighbour_transmission.
6450  */
6451 struct NeighbourSelectionContext
6452 {
6453   /**
6454    * Original message we received.
6455    */
6456   const struct TransportDVLearnMessage *dvl;
6457
6458   /**
6459    * The hops taken.
6460    */
6461   const struct DVPathEntryP *hops;
6462
6463   /**
6464    * Time we received the message.
6465    */
6466   struct GNUNET_TIME_Absolute in_time;
6467
6468   /**
6469    * Offsets of the selected peers.
6470    */
6471   uint32_t selections[MAX_DV_DISCOVERY_SELECTION];
6472
6473   /**
6474    * Number of peers eligible for selection.
6475    */
6476   unsigned int num_eligible;
6477
6478   /**
6479    * Number of peers that were selected for forwarding.
6480    */
6481   unsigned int num_selections;
6482
6483   /**
6484    * Number of hops in @e hops
6485    */
6486   uint16_t nhops;
6487
6488   /**
6489    * Bitmap of bidirectional connections encountered.
6490    */
6491   uint16_t bi_history;
6492 };
6493
6494
6495 /**
6496  * Function called for each neighbour during #handle_dv_learn.
6497  *
6498  * @param cls a `struct NeighbourSelectionContext *`
6499  * @param pid identity of the peer
6500  * @param value a `struct Neighbour`
6501  * @return #GNUNET_YES (always)
6502  */
6503 static int
6504 dv_neighbour_selection (void *cls,
6505                         const struct GNUNET_PeerIdentity *pid,
6506                         void *value)
6507 {
6508   struct NeighbourSelectionContext *nsc = cls;
6509
6510   (void) value;
6511   if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator))
6512     return GNUNET_YES; /* skip initiator */
6513   for (unsigned int i = 0; i < nsc->nhops; i++)
6514     if (0 == GNUNET_memcmp (pid, &nsc->hops[i].hop))
6515       return GNUNET_YES;
6516   /* skip peers on path */
6517   nsc->num_eligible++;
6518   return GNUNET_YES;
6519 }
6520
6521
6522 /**
6523  * Function called for each neighbour during #handle_dv_learn.
6524  * We call #forward_dv_learn() on the neighbour(s) selected
6525  * during #dv_neighbour_selection().
6526  *
6527  * @param cls a `struct NeighbourSelectionContext *`
6528  * @param pid identity of the peer
6529  * @param value a `struct Neighbour`
6530  * @return #GNUNET_YES (always)
6531  */
6532 static int
6533 dv_neighbour_transmission (void *cls,
6534                            const struct GNUNET_PeerIdentity *pid,
6535                            void *value)
6536 {
6537   struct NeighbourSelectionContext *nsc = cls;
6538
6539   (void) value;
6540   if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator))
6541     return GNUNET_YES; /* skip initiator */
6542   for (unsigned int i = 0; i < nsc->nhops; i++)
6543     if (0 == GNUNET_memcmp (pid, &nsc->hops[i].hop))
6544       return GNUNET_YES;
6545   /* skip peers on path */
6546   for (unsigned int i = 0; i < nsc->num_selections; i++)
6547   {
6548     if (nsc->selections[i] == nsc->num_eligible)
6549     {
6550       forward_dv_learn (pid,
6551                         nsc->dvl,
6552                         nsc->bi_history,
6553                         nsc->nhops,
6554                         nsc->hops,
6555                         nsc->in_time);
6556       break;
6557     }
6558   }
6559   nsc->num_eligible++;
6560   return GNUNET_YES;
6561 }
6562
6563
6564 /**
6565  * Computes the number of neighbours we should forward a DVInit
6566  * message to given that it has so far taken @a hops_taken hops
6567  * though the network and that the number of neighbours we have
6568  * in total is @a neighbour_count, out of which @a eligible_count
6569  * are not yet on the path.
6570  *
6571  * NOTE: technically we might want to include NSE in the formula to
6572  * get a better grip on the overall network size. However, for now
6573  * using NSE here would create a dependency issue in the build system.
6574  * => Left for later, hardcoded to 50 for now.
6575  *
6576  * The goal of the fomula is that we want to reach a total of LOG(NSE)
6577  * peers via DV (`target_total`).  We want the reach to be spread out
6578  * over various distances to the origin, with a bias towards shorter
6579  * distances.
6580  *
6581  * We make the strong assumption that the network topology looks
6582  * "similar" at other hops, in particular the @a neighbour_count
6583  * should be comparable at other hops.
6584  *
6585  * If the local neighbourhood is densely connected, we expect that @a
6586  * eligible_count is close to @a neighbour_count minus @a hops_taken
6587  * as a lot of the path is already known. In that case, we should
6588  * forward to few(er) peers to try to find a path out of the
6589  * neighbourhood. OTOH, if @a eligible_count is close to @a
6590  * neighbour_count, we should forward to many peers as we are either
6591  * still close to the origin (i.e.  @a hops_taken is small) or because
6592  * we managed to get beyond a local cluster.  We express this as
6593  * the `boost_factor` using the square of the fraction of eligible
6594  * neighbours (so if only 50% are eligible, we boost by 1/4, but if
6595  * 99% are eligible, the 'boost' will be almost 1).
6596  *
6597  * Second, the more hops we have taken, the larger the problem of an
6598  * exponential traffic explosion gets.  So we take the `target_total`,
6599  * and compute our degree such that at each distance d 2^{-d} peers
6600  * are selected (corrected by the `boost_factor`).
6601  *
6602  * @param hops_taken number of hops DVInit has travelled so far
6603  * @param neighbour_count number of neighbours we have in total
6604  * @param eligible_count number of neighbours we could in
6605  *        theory forward to
6606  */
6607 static unsigned int
6608 calculate_fork_degree (unsigned int hops_taken,
6609                        unsigned int neighbour_count,
6610                        unsigned int eligible_count)
6611 {
6612   double target_total = 50.0; /* FIXME: use LOG(NSE)? */
6613   double eligible_ratio =
6614     ((double) eligible_count) / ((double) neighbour_count);
6615   double boost_factor = eligible_ratio * eligible_ratio;
6616   unsigned int rnd;
6617   double left;
6618
6619   if (hops_taken >= 64)
6620   {
6621     GNUNET_break (0);
6622     return 0;   /* precaution given bitshift below */
6623   }
6624   for (unsigned int i = 1; i < hops_taken; i++)
6625   {
6626     /* For each hop, subtract the expected number of targets
6627        reached at distance d (so what remains divided by 2^d) */
6628     target_total -= (target_total * boost_factor / (1LLU << i));
6629   }
6630   rnd =
6631     (unsigned int) floor (target_total * boost_factor / (1LLU << hops_taken));
6632   /* round up or down probabilistically depending on how close we were
6633      when floor()ing to rnd */
6634   left = target_total - (double) rnd;
6635   if (UINT32_MAX * left >
6636       GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX))
6637     rnd++; /* round up */
6638   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6639               "Forwarding DV learn message of %u hops %u(/%u/%u) times\n",
6640               hops_taken,
6641               rnd,
6642               eligible_count,
6643               neighbour_count);
6644   return rnd;
6645 }
6646
6647
6648 /**
6649  * Function called when peerstore is done storing a DV monotonic time.
6650  *
6651  * @param cls a `struct Neighbour`
6652  * @param success #GNUNET_YES if peerstore was successful
6653  */
6654 static void
6655 neighbour_store_dvmono_cb (void *cls, int success)
6656 {
6657   struct Neighbour *n = cls;
6658
6659   n->sc = NULL;
6660   if (GNUNET_YES != success)
6661     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
6662                 "Failed to store other peer's monotonic time in peerstore!\n");
6663 }
6664
6665
6666 /**
6667  * Communicator gave us a DV learn message.  Process the request.
6668  *
6669  * @param cls a `struct CommunicatorMessageContext` (must call
6670  * #finish_cmc_handling() when done)
6671  * @param dvl the message that was received
6672  */
6673 static void
6674 handle_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
6675 {
6676   struct CommunicatorMessageContext *cmc = cls;
6677   enum GNUNET_TRANSPORT_CommunicatorCharacteristics cc;
6678   int bi_hop;
6679   uint16_t nhops;
6680   uint16_t bi_history;
6681   const struct DVPathEntryP *hops;
6682   int do_fwd;
6683   int did_initiator;
6684   struct GNUNET_TIME_Absolute in_time;
6685   struct Neighbour *n;
6686
6687   nhops = ntohs (dvl->bidirectional);  /* 0 = sender is initiator */
6688   bi_history = ntohs (dvl->bidirectional);
6689   hops = (const struct DVPathEntryP *) &dvl[1];
6690   if (0 == nhops)
6691   {
6692     /* sanity check */
6693     if (0 != GNUNET_memcmp (&dvl->initiator, &cmc->im.sender))
6694     {
6695       GNUNET_break (0);
6696       finish_cmc_handling (cmc);
6697       return;
6698     }
6699   }
6700   else
6701   {
6702     /* sanity check */
6703     if (0 != GNUNET_memcmp (&hops[nhops - 1].hop, &cmc->im.sender))
6704     {
6705       GNUNET_break (0);
6706       finish_cmc_handling (cmc);
6707       return;
6708     }
6709   }
6710
6711   GNUNET_assert (CT_COMMUNICATOR == cmc->tc->type);
6712   cc = cmc->tc->details.communicator.cc;
6713   bi_hop = (GNUNET_TRANSPORT_CC_RELIABLE ==
6714             cc); // FIXME: add bi-directional flag to cc?
6715   in_time = GNUNET_TIME_absolute_get ();
6716
6717   /* continue communicator here, everything else can happen asynchronous! */
6718   finish_cmc_handling (cmc);
6719
6720   n = lookup_neighbour (&dvl->initiator);
6721   if (NULL != n)
6722   {
6723     if ((n->dv_monotime_available == GNUNET_YES) &&
6724         (GNUNET_TIME_absolute_ntoh (dvl->monotonic_time).abs_value_us <
6725          n->last_dv_learn_monotime.abs_value_us))
6726     {
6727       GNUNET_STATISTICS_update (GST_stats,
6728                                 "# DV learn discarded due to time travel",
6729                                 1,
6730                                 GNUNET_NO);
6731       return;
6732     }
6733     if (GNUNET_OK != validate_dv_initiator_signature (dvl->monotonic_time,
6734                                                       &dvl->initiator,
6735                                                       &dvl->challenge,
6736                                                       &dvl->init_sig))
6737     {
6738       GNUNET_break_op (0);
6739       return;
6740     }
6741     n->last_dv_learn_monotime = GNUNET_TIME_absolute_ntoh (dvl->monotonic_time);
6742     if (GNUNET_YES == n->dv_monotime_available)
6743     {
6744       if (NULL != n->sc)
6745         GNUNET_PEERSTORE_store_cancel (n->sc);
6746       n->sc =
6747         GNUNET_PEERSTORE_store (peerstore,
6748                                 "transport",
6749                                 &dvl->initiator,
6750                                 GNUNET_PEERSTORE_TRANSPORT_DVLEARN_MONOTIME,
6751                                 &dvl->monotonic_time,
6752                                 sizeof(dvl->monotonic_time),
6753                                 GNUNET_TIME_UNIT_FOREVER_ABS,
6754                                 GNUNET_PEERSTORE_STOREOPTION_REPLACE,
6755                                 &neighbour_store_dvmono_cb,
6756                                 n);
6757     }
6758   }
6759   /* OPTIMIZE-FIXME: asynchronously (!) verify signatures!,
6760      If signature verification load too high, implement random drop strategy */
6761   for (unsigned int i = 0; i < nhops; i++)
6762   {
6763     struct DvHopPS dhp = { .purpose.purpose =
6764                              htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_HOP),
6765                            .purpose.size = htonl (sizeof(dhp)),
6766                            .pred = (0 == i) ? dvl->initiator : hops[i - 1].hop,
6767                            .succ = (nhops == i + 1) ? GST_my_identity
6768                                    : hops[i + 1].hop,
6769                            .challenge = dvl->challenge };
6770
6771     if (GNUNET_OK !=
6772         GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_HOP,
6773                                     &dhp.purpose,
6774                                     &hops[i].hop_sig,
6775                                     &hops[i].hop.public_key))
6776     {
6777       GNUNET_break_op (0);
6778       return;
6779     }
6780   }
6781
6782   if (GNUNET_EXTRA_LOGGING > 0)
6783   {
6784     char *path;
6785
6786     path = GNUNET_strdup (GNUNET_i2s (&dvl->initiator));
6787     for (unsigned int i = 0; i < nhops; i++)
6788     {
6789       char *tmp;
6790
6791       GNUNET_asprintf (&tmp,
6792                        "%s%s%s",
6793                        path,
6794                        (bi_history & (1 << (nhops - i))) ? "<->" : "-->",
6795                        GNUNET_i2s (&hops[i].hop));
6796       GNUNET_free (path);
6797       path = tmp;
6798     }
6799     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6800                 "Received DVInit via %s%s%s\n",
6801                 path,
6802                 bi_hop ? "<->" : "-->",
6803                 GNUNET_i2s (&GST_my_identity));
6804     GNUNET_free (path);
6805   }
6806
6807   do_fwd = GNUNET_YES;
6808   if (0 == GNUNET_memcmp (&GST_my_identity, &dvl->initiator))
6809   {
6810     struct GNUNET_PeerIdentity path[nhops + 1];
6811     struct GNUNET_TIME_Relative host_latency_sum;
6812     struct GNUNET_TIME_Relative latency;
6813     struct GNUNET_TIME_Relative network_latency;
6814
6815     /* We initiated this, learn the forward path! */
6816     path[0] = GST_my_identity;
6817     path[1] = hops[0].hop;
6818     host_latency_sum = GNUNET_TIME_relative_ntoh (dvl->non_network_delay);
6819
6820     // Need also something to lookup initiation time
6821     // to compute RTT! -> add RTT argument here?
6822     latency = GNUNET_TIME_UNIT_FOREVER_REL;   // FIXME: initialize properly
6823     // (based on dvl->challenge, we can identify time of origin!)
6824
6825     network_latency = GNUNET_TIME_relative_subtract (latency, host_latency_sum);
6826     /* assumption: latency on all links is the same */
6827     network_latency = GNUNET_TIME_relative_divide (network_latency, nhops);
6828
6829     for (unsigned int i = 2; i <= nhops; i++)
6830     {
6831       struct GNUNET_TIME_Relative ilat;
6832
6833       /* assumption: linear latency increase per hop */
6834       ilat = GNUNET_TIME_relative_multiply (network_latency, i);
6835       path[i] = hops[i - 1].hop;
6836       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6837                   "Learned path with %u hops to %s with latency %s\n",
6838                   i,
6839                   GNUNET_i2s (&path[i]),
6840                   GNUNET_STRINGS_relative_time_to_string (ilat, GNUNET_YES));
6841       learn_dv_path (path,
6842                      i,
6843                      ilat,
6844                      GNUNET_TIME_relative_to_absolute (
6845                        ADDRESS_VALIDATION_LIFETIME));
6846     }
6847     /* as we initiated, do not forward again (would be circular!) */
6848     do_fwd = GNUNET_NO;
6849     return;
6850   }
6851   if (bi_hop)
6852   {
6853     /* last hop was bi-directional, we could learn something here! */
6854     struct GNUNET_PeerIdentity path[nhops + 2];
6855
6856     path[0] = GST_my_identity;
6857     path[1] = hops[nhops - 1].hop;   /* direct neighbour == predecessor! */
6858     for (unsigned int i = 0; i < nhops; i++)
6859     {
6860       int iret;
6861
6862       if (0 == (bi_history & (1 << i)))
6863         break;     /* i-th hop not bi-directional, stop learning! */
6864       if (i == nhops - 1)
6865       {
6866         path[i + 2] = dvl->initiator;
6867       }
6868       else
6869       {
6870         path[i + 2] = hops[nhops - i - 2].hop;
6871       }
6872
6873       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6874                   "Learned inverse path with %u hops to %s\n",
6875                   i + 1,
6876                   GNUNET_i2s (&path[i + 2]));
6877       iret = learn_dv_path (path,
6878                             i + 2,
6879                             GNUNET_TIME_UNIT_FOREVER_REL,
6880                             GNUNET_TIME_UNIT_ZERO_ABS);
6881       if (GNUNET_SYSERR == iret)
6882       {
6883         /* path invalid or too long to be interesting for US, thus should also
6884            not be interesting to our neighbours, cut path when forwarding to
6885            'i' hops, except of course for the one that goes back to the
6886            initiator */
6887         GNUNET_STATISTICS_update (GST_stats,
6888                                   "# DV learn not forwarded due invalidity of path",
6889                                   1,
6890                                   GNUNET_NO);
6891         do_fwd = GNUNET_NO;
6892         break;
6893       }
6894       if ((GNUNET_NO == iret) && (nhops == i + 1))
6895       {
6896         /* we have better paths, and this is the longest target,
6897            so there cannot be anything interesting later */
6898         GNUNET_STATISTICS_update (GST_stats,
6899                                   "# DV learn not forwarded, got better paths",
6900                                   1,
6901                                   GNUNET_NO);
6902         do_fwd = GNUNET_NO;
6903         break;
6904       }
6905     }
6906   }
6907
6908   if (MAX_DV_HOPS_ALLOWED == nhops)
6909   {
6910     /* At limit, we're out of here! */
6911     finish_cmc_handling (cmc);
6912     return;
6913   }
6914
6915   /* Forward to initiator, if path non-trivial and possible */
6916   bi_history = (bi_history << 1) | (bi_hop ? 1 : 0);
6917   did_initiator = GNUNET_NO;
6918   if ((1 < nhops) &&
6919       (GNUNET_YES ==
6920        GNUNET_CONTAINER_multipeermap_contains (neighbours, &dvl->initiator)))
6921   {
6922     /* send back to origin! */
6923     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6924                 "Sending DVL back to initiator %s\n",
6925                 GNUNET_i2s (&dvl->initiator));
6926     forward_dv_learn (&dvl->initiator, dvl, bi_history, nhops, hops, in_time);
6927     did_initiator = GNUNET_YES;
6928   }
6929   /* We forward under two conditions: either we still learned something
6930      ourselves (do_fwd), or the path was darn short and thus the initiator is
6931      likely to still be very interested in this (and we did NOT already
6932      send it back to the initiator) */
6933   if ((do_fwd) || ((nhops < MIN_DV_PATH_LENGTH_FOR_INITIATOR) &&
6934                    (GNUNET_NO == did_initiator)))
6935   {
6936     /* Pick random neighbours that are not yet on the path */
6937     struct NeighbourSelectionContext nsc;
6938     unsigned int n_cnt;
6939
6940     n_cnt = GNUNET_CONTAINER_multipeermap_size (neighbours);
6941     nsc.nhops = nhops;
6942     nsc.dvl = dvl;
6943     nsc.bi_history = bi_history;
6944     nsc.hops = hops;
6945     nsc.in_time = in_time;
6946     nsc.num_eligible = 0;
6947     GNUNET_CONTAINER_multipeermap_iterate (neighbours,
6948                                            &dv_neighbour_selection,
6949                                            &nsc);
6950     if (0 == nsc.num_eligible)
6951       return;   /* done here, cannot forward to anyone else */
6952     nsc.num_selections = calculate_fork_degree (nhops, n_cnt, nsc.num_eligible);
6953     nsc.num_selections =
6954       GNUNET_MIN (MAX_DV_DISCOVERY_SELECTION, nsc.num_selections);
6955     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
6956                 "Forwarding DVL to %u other peers\n",
6957                 nsc.num_selections);
6958     for (unsigned int i = 0; i < nsc.num_selections; i++)
6959       nsc.selections[i] =
6960         (nsc.num_selections == n_cnt)
6961         ? i   /* all were selected, avoid collisions by chance */
6962         : GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, n_cnt);
6963     nsc.num_eligible = 0;
6964     GNUNET_CONTAINER_multipeermap_iterate (neighbours,
6965                                            &dv_neighbour_transmission,
6966                                            &nsc);
6967   }
6968 }
6969
6970
6971 /**
6972  * Communicator gave us a DV box.  Check the message.
6973  *
6974  * @param cls a `struct CommunicatorMessageContext`
6975  * @param dvb the send message that was sent
6976  * @return #GNUNET_YES if message is well-formed
6977  */
6978 static int
6979 check_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
6980 {
6981   uint16_t size = ntohs (dvb->header.size);
6982   uint16_t num_hops = ntohs (dvb->num_hops);
6983   const struct GNUNET_PeerIdentity *hops =
6984     (const struct GNUNET_PeerIdentity *) &dvb[1];
6985
6986   (void) cls;
6987   if (size < sizeof(*dvb) + num_hops * sizeof(struct GNUNET_PeerIdentity)
6988       + sizeof(struct GNUNET_MessageHeader))
6989   {
6990     GNUNET_break_op (0);
6991     return GNUNET_SYSERR;
6992   }
6993   /* This peer must not be on the path */
6994   for (unsigned int i = 0; i < num_hops; i++)
6995     if (0 == GNUNET_memcmp (&hops[i], &GST_my_identity))
6996     {
6997       GNUNET_break_op (0);
6998       return GNUNET_SYSERR;
6999     }
7000   return GNUNET_YES;
7001 }
7002
7003
7004 /**
7005  * Create a DV Box message and queue it for transmission to
7006  * @ea next_hop.
7007  *
7008  * @param next_hop peer to receive the message next
7009  * @param total_hops how many hops did the message take so far
7010  * @param num_hops length of the @a hops array
7011  * @param origin origin of the message
7012  * @param hops next peer(s) to the destination, including destination
7013  * @param payload payload of the box
7014  * @param payload_size number of bytes in @a payload
7015  */
7016 static void
7017 forward_dv_box (struct Neighbour *next_hop,
7018                 const struct TransportDVBoxMessage *hdr,
7019                 uint16_t total_hops,
7020                 uint16_t num_hops,
7021                 const struct GNUNET_PeerIdentity *hops,
7022                 const void *enc_payload,
7023                 uint16_t enc_payload_size)
7024 {
7025   struct VirtualLink *vl = next_hop->vl;
7026   struct PendingMessage *pm;
7027   size_t msg_size;
7028   char *buf;
7029   struct GNUNET_PeerIdentity *dhops;
7030
7031   GNUNET_assert (NULL != vl);
7032   msg_size = sizeof(struct TransportDVBoxMessage)
7033              + num_hops * sizeof(struct GNUNET_PeerIdentity) + enc_payload_size;
7034   pm = GNUNET_malloc (sizeof(struct PendingMessage) + msg_size);
7035   pm->pmt = PMT_DV_BOX;
7036   pm->vl = vl;
7037   pm->timeout = GNUNET_TIME_relative_to_absolute (DV_FORWARD_TIMEOUT);
7038   pm->logging_uuid = logging_uuid_gen++;
7039   pm->prefs = GNUNET_MQ_PRIO_BACKGROUND;
7040   pm->bytes_msg = msg_size;
7041   buf = (char *) &pm[1];
7042   memcpy (buf, hdr, sizeof(*hdr));
7043   dhops =
7044     (struct GNUNET_PeerIdentity *) &buf[sizeof(struct TransportDVBoxMessage)];
7045   memcpy (dhops, hops, num_hops * sizeof(struct GNUNET_PeerIdentity));
7046   memcpy (&dhops[num_hops], enc_payload, enc_payload_size);
7047   GNUNET_CONTAINER_MDLL_insert (vl,
7048                                 vl->pending_msg_head,
7049                                 vl->pending_msg_tail,
7050                                 pm);
7051   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7052               "Created pending message %llu for DV Box with next hop %s (%u/%u)\n",
7053               pm->logging_uuid,
7054               GNUNET_i2s (&next_hop->pid),
7055               (unsigned int) num_hops,
7056               (unsigned int) total_hops);
7057   check_vl_transmission (vl);
7058 }
7059
7060
7061 /**
7062  * Free data structures associated with @a b.
7063  *
7064  * @param b data structure to release
7065  */
7066 static void
7067 free_backtalker (struct Backtalker *b)
7068 {
7069   if (NULL != b->get)
7070   {
7071     GNUNET_PEERSTORE_iterate_cancel (b->get);
7072     b->get = NULL;
7073     GNUNET_assert (NULL != b->cmc);
7074     finish_cmc_handling (b->cmc);
7075     b->cmc = NULL;
7076   }
7077   if (NULL != b->task)
7078   {
7079     GNUNET_SCHEDULER_cancel (b->task);
7080     b->task = NULL;
7081   }
7082   if (NULL != b->sc)
7083   {
7084     GNUNET_PEERSTORE_store_cancel (b->sc);
7085     b->sc = NULL;
7086   }
7087   GNUNET_assert (
7088     GNUNET_YES ==
7089     GNUNET_CONTAINER_multipeermap_remove (backtalkers, &b->pid, b));
7090   GNUNET_free (b);
7091 }
7092
7093
7094 /**
7095  * Callback to free backtalker records.
7096  *
7097  * @param cls NULL
7098  * @param pid unused
7099  * @param value a `struct Backtalker`
7100  * @return #GNUNET_OK (always)
7101  */
7102 static int
7103 free_backtalker_cb (void *cls,
7104                     const struct GNUNET_PeerIdentity *pid,
7105                     void *value)
7106 {
7107   struct Backtalker *b = value;
7108
7109   (void) cls;
7110   (void) pid;
7111   free_backtalker (b);
7112   return GNUNET_OK;
7113 }
7114
7115
7116 /**
7117  * Function called when it is time to clean up a backtalker.
7118  *
7119  * @param cls a `struct Backtalker`
7120  */
7121 static void
7122 backtalker_timeout_cb (void *cls)
7123 {
7124   struct Backtalker *b = cls;
7125
7126   b->task = NULL;
7127   if (0 != GNUNET_TIME_absolute_get_remaining (b->timeout).rel_value_us)
7128   {
7129     b->task = GNUNET_SCHEDULER_add_at (b->timeout, &backtalker_timeout_cb, b);
7130     return;
7131   }
7132   GNUNET_assert (NULL == b->sc);
7133   free_backtalker (b);
7134 }
7135
7136
7137 /**
7138  * Function called with the monotonic time of a backtalker
7139  * by PEERSTORE. Updates the time and continues processing.
7140  *
7141  * @param cls a `struct Backtalker`
7142  * @param record the information found, NULL for the last call
7143  * @param emsg error message
7144  */
7145 static void
7146 backtalker_monotime_cb (void *cls,
7147                         const struct GNUNET_PEERSTORE_Record *record,
7148                         const char *emsg)
7149 {
7150   struct Backtalker *b = cls;
7151   struct GNUNET_TIME_AbsoluteNBO *mtbe;
7152   struct GNUNET_TIME_Absolute mt;
7153
7154   (void) emsg;
7155   if (NULL == record)
7156   {
7157     /* we're done with #backtalker_monotime_cb() invocations,
7158        continue normal processing */
7159     b->get = NULL;
7160     GNUNET_assert (NULL != b->cmc);
7161     if (0 != b->body_size)
7162       demultiplex_with_cmc (b->cmc,
7163                             (const struct GNUNET_MessageHeader *) &b[1]);
7164     else
7165       finish_cmc_handling (b->cmc);
7166     b->cmc = NULL;
7167     return;
7168   }
7169   if (sizeof(*mtbe) != record->value_size)
7170   {
7171     GNUNET_break (0);
7172     return;
7173   }
7174   mtbe = record->value;
7175   mt = GNUNET_TIME_absolute_ntoh (*mtbe);
7176   if (mt.abs_value_us > b->monotonic_time.abs_value_us)
7177   {
7178     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7179                 "Backtalker message from %s dropped, monotime in the past\n",
7180                 GNUNET_i2s (&b->pid));
7181     GNUNET_STATISTICS_update (
7182       GST_stats,
7183       "# Backchannel messages dropped: monotonic time not increasing",
7184       1,
7185       GNUNET_NO);
7186     b->monotonic_time = mt;
7187     /* Setting body_size to 0 prevents call to #forward_backchannel_payload()
7188      */
7189     b->body_size = 0;
7190     return;
7191   }
7192 }
7193
7194
7195 /**
7196  * Function called by PEERSTORE when the store operation of
7197  * a backtalker's monotonic time is complete.
7198  *
7199  * @param cls the `struct Backtalker`
7200  * @param success #GNUNET_OK on success
7201  */
7202 static void
7203 backtalker_monotime_store_cb (void *cls, int success)
7204 {
7205   struct Backtalker *b = cls;
7206
7207   if (GNUNET_OK != success)
7208   {
7209     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
7210                 "Failed to store backtalker's monotonic time in PEERSTORE!\n");
7211   }
7212   b->sc = NULL;
7213   b->task = GNUNET_SCHEDULER_add_at (b->timeout, &backtalker_timeout_cb, b);
7214 }
7215
7216
7217 /**
7218  * The backtalker @a b monotonic time changed. Update PEERSTORE.
7219  *
7220  * @param b a backtalker with updated monotonic time
7221  */
7222 static void
7223 update_backtalker_monotime (struct Backtalker *b)
7224 {
7225   struct GNUNET_TIME_AbsoluteNBO mtbe;
7226
7227   if (NULL != b->sc)
7228   {
7229     GNUNET_PEERSTORE_store_cancel (b->sc);
7230     b->sc = NULL;
7231   }
7232   else
7233   {
7234     GNUNET_SCHEDULER_cancel (b->task);
7235     b->task = NULL;
7236   }
7237   mtbe = GNUNET_TIME_absolute_hton (b->monotonic_time);
7238   b->sc =
7239     GNUNET_PEERSTORE_store (peerstore,
7240                             "transport",
7241                             &b->pid,
7242                             GNUNET_PEERSTORE_TRANSPORT_BACKCHANNEL_MONOTIME,
7243                             &mtbe,
7244                             sizeof(mtbe),
7245                             GNUNET_TIME_UNIT_FOREVER_ABS,
7246                             GNUNET_PEERSTORE_STOREOPTION_REPLACE,
7247                             &backtalker_monotime_store_cb,
7248                             b);
7249 }
7250
7251
7252 /**
7253  * Communicator gave us a DV box.  Process the request.
7254  *
7255  * @param cls a `struct CommunicatorMessageContext` (must call
7256  * #finish_cmc_handling() when done)
7257  * @param dvb the message that was received
7258  */
7259 static void
7260 handle_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
7261 {
7262   struct CommunicatorMessageContext *cmc = cls;
7263   uint16_t size = ntohs (dvb->header.size) - sizeof(*dvb);
7264   uint16_t num_hops = ntohs (dvb->num_hops);
7265   const struct GNUNET_PeerIdentity *hops =
7266     (const struct GNUNET_PeerIdentity *) &dvb[1];
7267   const char *enc_payload = (const char *) &hops[num_hops];
7268   uint16_t enc_payload_size =
7269     size - (num_hops * sizeof(struct GNUNET_PeerIdentity));
7270   struct DVKeyState key;
7271   struct GNUNET_HashCode hmac;
7272   const char *hdr;
7273   size_t hdr_len;
7274
7275   if (GNUNET_EXTRA_LOGGING > 0)
7276   {
7277     char *path;
7278
7279     path = GNUNET_strdup (GNUNET_i2s (&GST_my_identity));
7280     for (unsigned int i = 0; i < num_hops; i++)
7281     {
7282       char *tmp;
7283
7284       GNUNET_asprintf (&tmp, "%s->%s", path, GNUNET_i2s (&hops[i]));
7285       GNUNET_free (path);
7286       path = tmp;
7287     }
7288     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7289                 "Received DVBox with remainig path %s\n",
7290                 path);
7291     GNUNET_free (path);
7292   }
7293
7294   if (num_hops > 0)
7295   {
7296     /* We're trying from the end of the hops array, as we may be
7297        able to find a shortcut unknown to the origin that way */
7298     for (int i = num_hops - 1; i >= 0; i--)
7299     {
7300       struct Neighbour *n;
7301
7302       if (0 == GNUNET_memcmp (&hops[i], &GST_my_identity))
7303       {
7304         GNUNET_break_op (0);
7305         finish_cmc_handling (cmc);
7306         return;
7307       }
7308       n = lookup_neighbour (&hops[i]);
7309       if (NULL == n)
7310         continue;
7311       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7312                   "Skipping %u/%u hops ahead while routing DV Box\n",
7313                   i,
7314                   num_hops);
7315       forward_dv_box (n,
7316                       dvb,
7317                       ntohs (dvb->total_hops) + 1,
7318                       num_hops - i - 1,    /* number of hops left */
7319                       &hops[i + 1],    /* remaining hops */
7320                       enc_payload,
7321                       enc_payload_size);
7322       GNUNET_STATISTICS_update (GST_stats,
7323                                 "# DV hops skipped routing boxes",
7324                                 i,
7325                                 GNUNET_NO);
7326       GNUNET_STATISTICS_update (GST_stats,
7327                                 "# DV boxes routed (total)",
7328                                 1,
7329                                 GNUNET_NO);
7330       finish_cmc_handling (cmc);
7331       return;
7332     }
7333     /* Woopsie, next hop not in neighbours, drop! */
7334     GNUNET_STATISTICS_update (GST_stats,
7335                               "# DV Boxes dropped: next hop unknown",
7336                               1,
7337                               GNUNET_NO);
7338     finish_cmc_handling (cmc);
7339     return;
7340   }
7341   /* We are the target. Unbox and handle message. */
7342   GNUNET_STATISTICS_update (GST_stats,
7343                             "# DV boxes opened (ultimate target)",
7344                             1,
7345                             GNUNET_NO);
7346   cmc->total_hops = ntohs (dvb->total_hops);
7347
7348   dh_key_derive_eph_pub (&dvb->ephemeral_key, &dvb->iv, &key);
7349   hdr = (const char *) &dvb[1];
7350   hdr_len = ntohs (dvb->header.size) - sizeof(*dvb);
7351   dv_hmac (&key, &hmac, hdr, hdr_len);
7352   if (0 != GNUNET_memcmp (&hmac, &dvb->hmac))
7353   {
7354     /* HMAC missmatch, disard! */
7355     GNUNET_break_op (0);
7356     finish_cmc_handling (cmc);
7357     return;
7358   }
7359   /* begin actual decryption */
7360   {
7361     struct Backtalker *b;
7362     struct GNUNET_TIME_Absolute monotime;
7363     struct TransportDVBoxPayloadP ppay;
7364     char body[hdr_len - sizeof(ppay)] GNUNET_ALIGN;
7365     const struct GNUNET_MessageHeader *mh =
7366       (const struct GNUNET_MessageHeader *) body;
7367
7368     GNUNET_assert (hdr_len >=
7369                    sizeof(ppay) + sizeof(struct GNUNET_MessageHeader));
7370     dv_decrypt (&key, &ppay, hdr, sizeof(ppay));
7371     dv_decrypt (&key, &body, &hdr[sizeof(ppay)], hdr_len - sizeof(ppay));
7372     dv_key_clean (&key);
7373     if (ntohs (mh->size) != sizeof(body))
7374     {
7375       GNUNET_break_op (0);
7376       finish_cmc_handling (cmc);
7377       return;
7378     }
7379     /* need to prevent box-in-a-box (and DV_LEARN) so check inbox type! */
7380     switch (ntohs (mh->type))
7381     {
7382     case GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX:
7383       GNUNET_break_op (0);
7384       finish_cmc_handling (cmc);
7385       return;
7386
7387     case GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN:
7388       GNUNET_break_op (0);
7389       finish_cmc_handling (cmc);
7390       return;
7391
7392     default:
7393       /* permitted, continue */
7394       break;
7395     }
7396     monotime = GNUNET_TIME_absolute_ntoh (ppay.monotonic_time);
7397     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7398                 "Decrypted backtalk from %s\n",
7399                 GNUNET_i2s (&ppay.sender));
7400     b = GNUNET_CONTAINER_multipeermap_get (backtalkers, &ppay.sender);
7401     if ((NULL != b) && (monotime.abs_value_us < b->monotonic_time.abs_value_us))
7402     {
7403       GNUNET_STATISTICS_update (
7404         GST_stats,
7405         "# Backchannel messages dropped: monotonic time not increasing",
7406         1,
7407         GNUNET_NO);
7408       finish_cmc_handling (cmc);
7409       return;
7410     }
7411     if ((NULL == b) ||
7412         (0 != GNUNET_memcmp (&b->last_ephemeral, &dvb->ephemeral_key)))
7413     {
7414       /* Check signature */
7415       struct EphemeralConfirmationPS ec;
7416
7417       ec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL);
7418       ec.purpose.size = htonl (sizeof(ec));
7419       ec.target = GST_my_identity;
7420       ec.ephemeral_key = dvb->ephemeral_key;
7421       if (
7422         GNUNET_OK !=
7423         GNUNET_CRYPTO_eddsa_verify (
7424           GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL,
7425           &ec.purpose,
7426           &ppay.sender_sig,
7427           &ppay.sender.public_key))
7428       {
7429         /* Signature invalid, disard! */
7430         GNUNET_break_op (0);
7431         finish_cmc_handling (cmc);
7432         return;
7433       }
7434     }
7435     /* Update sender, we now know the real origin! */
7436     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7437                 "DVBox received for me from %s via %s\n",
7438                 GNUNET_i2s2 (&ppay.sender),
7439                 GNUNET_i2s (&cmc->im.sender));
7440     cmc->im.sender = ppay.sender;
7441
7442     if (NULL != b)
7443     {
7444       /* update key cache and mono time */
7445       b->last_ephemeral = dvb->ephemeral_key;
7446       b->monotonic_time = monotime;
7447       update_backtalker_monotime (b);
7448       b->timeout =
7449         GNUNET_TIME_relative_to_absolute (BACKCHANNEL_INACTIVITY_TIMEOUT);
7450
7451       demultiplex_with_cmc (cmc, mh);
7452       return;
7453     }
7454     /* setup data structure to cache signature AND check
7455        monotonic time with PEERSTORE before forwarding backchannel payload */
7456     b = GNUNET_malloc (sizeof(struct Backtalker) + sizeof(body));
7457     b->pid = ppay.sender;
7458     b->body_size = sizeof(body);
7459     memcpy (&b[1], body, sizeof(body));
7460     GNUNET_assert (GNUNET_YES ==
7461                    GNUNET_CONTAINER_multipeermap_put (
7462                      backtalkers,
7463                      &b->pid,
7464                      b,
7465                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
7466     b->monotonic_time = monotime; /* NOTE: to be checked still! */
7467     b->cmc = cmc;
7468     b->timeout =
7469       GNUNET_TIME_relative_to_absolute (BACKCHANNEL_INACTIVITY_TIMEOUT);
7470     b->task = GNUNET_SCHEDULER_add_at (b->timeout, &backtalker_timeout_cb, b);
7471     b->get =
7472       GNUNET_PEERSTORE_iterate (peerstore,
7473                                 "transport",
7474                                 &b->pid,
7475                                 GNUNET_PEERSTORE_TRANSPORT_BACKCHANNEL_MONOTIME,
7476                                 &backtalker_monotime_cb,
7477                                 b);
7478   } /* end actual decryption */
7479 }
7480
7481
7482 /**
7483  * Client notified us about transmission from a peer.  Process the request.
7484  *
7485  * @param cls a `struct TransportClient` which sent us the message
7486  * @param obm the send message that was sent
7487  * @return #GNUNET_YES if message is well-formed
7488  */
7489 static int
7490 check_incoming_msg (void *cls,
7491                     const struct GNUNET_TRANSPORT_IncomingMessage *im)
7492 {
7493   struct TransportClient *tc = cls;
7494
7495   if (CT_COMMUNICATOR != tc->type)
7496   {
7497     GNUNET_break (0);
7498     return GNUNET_SYSERR;
7499   }
7500   GNUNET_MQ_check_boxed_message (im);
7501   return GNUNET_OK;
7502 }
7503
7504
7505 /**
7506  * Closure for #check_known_address.
7507  */
7508 struct CheckKnownAddressContext
7509 {
7510   /**
7511    * Set to the address we are looking for.
7512    */
7513   const char *address;
7514
7515   /**
7516    * Set to a matching validation state, if one was found.
7517    */
7518   struct ValidationState *vs;
7519 };
7520
7521
7522 /**
7523  * Test if the validation state in @a value matches the
7524  * address from @a cls.
7525  *
7526  * @param cls a `struct CheckKnownAddressContext`
7527  * @param pid unused (must match though)
7528  * @param value a `struct ValidationState`
7529  * @return #GNUNET_OK if not matching, #GNUNET_NO if match found
7530  */
7531 static int
7532 check_known_address (void *cls,
7533                      const struct GNUNET_PeerIdentity *pid,
7534                      void *value)
7535 {
7536   struct CheckKnownAddressContext *ckac = cls;
7537   struct ValidationState *vs = value;
7538
7539   (void) pid;
7540   if (0 != strcmp (vs->address, ckac->address))
7541     return GNUNET_OK;
7542   ckac->vs = vs;
7543   return GNUNET_NO;
7544 }
7545
7546
7547 /**
7548  * Task run periodically to validate some address based on #validation_heap.
7549  *
7550  * @param cls NULL
7551  */
7552 static void
7553 validation_start_cb (void *cls);
7554
7555
7556 /**
7557  * Set the time for next_challenge of @a vs to @a new_time.
7558  * Updates the heap and if necessary reschedules the job.
7559  *
7560  * @param vs validation state to update
7561  * @param new_time new time for revalidation
7562  */
7563 static void
7564 update_next_challenge_time (struct ValidationState *vs,
7565                             struct GNUNET_TIME_Absolute new_time)
7566 {
7567   struct GNUNET_TIME_Relative delta;
7568
7569   if (new_time.abs_value_us == vs->next_challenge.abs_value_us)
7570     return; /* be lazy */
7571   vs->next_challenge = new_time;
7572   if (NULL == vs->hn)
7573     vs->hn =
7574       GNUNET_CONTAINER_heap_insert (validation_heap, vs, new_time.abs_value_us);
7575   else
7576     GNUNET_CONTAINER_heap_update_cost (vs->hn, new_time.abs_value_us);
7577   if ((vs != GNUNET_CONTAINER_heap_peek (validation_heap)) &&
7578       (NULL != validation_task))
7579     return;
7580   if (NULL != validation_task)
7581     GNUNET_SCHEDULER_cancel (validation_task);
7582   /* randomize a bit */
7583   delta.rel_value_us =
7584     GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
7585                               MIN_DELAY_ADDRESS_VALIDATION.rel_value_us);
7586   new_time = GNUNET_TIME_absolute_add (new_time, delta);
7587   validation_task =
7588     GNUNET_SCHEDULER_add_at (new_time, &validation_start_cb, NULL);
7589 }
7590
7591
7592 /**
7593  * Start address validation.
7594  *
7595  * @param pid peer the @a address is for
7596  * @param address an address to reach @a pid (presumably)
7597  */
7598 static void
7599 start_address_validation (const struct GNUNET_PeerIdentity *pid,
7600                           const char *address)
7601 {
7602   struct GNUNET_TIME_Absolute now;
7603   struct ValidationState *vs;
7604   struct CheckKnownAddressContext ckac = { .address = address, .vs = NULL };
7605
7606   (void) GNUNET_CONTAINER_multipeermap_get_multiple (validation_map,
7607                                                      pid,
7608                                                      &check_known_address,
7609                                                      &ckac);
7610   if (NULL != (vs = ckac.vs))
7611   {
7612     /* if 'vs' is not currently valid, we need to speed up retrying the
7613      * validation */
7614     if (vs->validated_until.abs_value_us < vs->next_challenge.abs_value_us)
7615     {
7616       /* reduce backoff as we got a fresh advertisement */
7617       vs->challenge_backoff =
7618         GNUNET_TIME_relative_min (FAST_VALIDATION_CHALLENGE_FREQ,
7619                                   GNUNET_TIME_relative_divide (
7620                                     vs->challenge_backoff,
7621                                     2));
7622       update_next_challenge_time (vs,
7623                                   GNUNET_TIME_relative_to_absolute (
7624                                     vs->challenge_backoff));
7625     }
7626     return;
7627   }
7628   now = GNUNET_TIME_absolute_get ();
7629   vs = GNUNET_new (struct ValidationState);
7630   vs->pid = *pid;
7631   vs->valid_until =
7632     GNUNET_TIME_relative_to_absolute (ADDRESS_VALIDATION_LIFETIME);
7633   vs->first_challenge_use = now;
7634   vs->validation_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
7635   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
7636                               &vs->challenge,
7637                               sizeof(vs->challenge));
7638   vs->address = GNUNET_strdup (address);
7639   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7640               "Starting address validation `%s' of peer %s using challenge %s\n",
7641               address,
7642               GNUNET_i2s (pid),
7643               GNUNET_sh2s (&vs->challenge.value));
7644   GNUNET_assert (GNUNET_YES ==
7645                  GNUNET_CONTAINER_multipeermap_put (
7646                    validation_map,
7647                    &vs->pid,
7648                    vs,
7649                    GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
7650   update_next_challenge_time (vs, now);
7651 }
7652
7653
7654 /**
7655  * Function called by PEERSTORE for each matching record.
7656  *
7657  * @param cls closure, a `struct IncomingRequest`
7658  * @param record peerstore record information
7659  * @param emsg error message, or NULL if no errors
7660  */
7661 static void
7662 handle_hello_for_incoming (void *cls,
7663                            const struct GNUNET_PEERSTORE_Record *record,
7664                            const char *emsg)
7665 {
7666   struct IncomingRequest *ir = cls;
7667   const char *val;
7668
7669   if (NULL != emsg)
7670   {
7671     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
7672                 "Got failure from PEERSTORE: %s\n",
7673                 emsg);
7674     return;
7675   }
7676   val = record->value;
7677   if ((0 == record->value_size) || ('\0' != val[record->value_size - 1]))
7678   {
7679     GNUNET_break (0);
7680     return;
7681   }
7682   start_address_validation (&ir->pid, (const char *) record->value);
7683 }
7684
7685
7686 /**
7687  * Communicator gave us a transport address validation challenge.  Process the
7688  * request.
7689  *
7690  * @param cls a `struct CommunicatorMessageContext` (must call
7691  * #finish_cmc_handling() when done)
7692  * @param tvc the message that was received
7693  */
7694 static void
7695 handle_validation_challenge (
7696   void *cls,
7697   const struct TransportValidationChallengeMessage *tvc)
7698 {
7699   struct CommunicatorMessageContext *cmc = cls;
7700   struct TransportValidationResponseMessage tvr;
7701   struct VirtualLink *vl;
7702   struct GNUNET_TIME_RelativeNBO validity_duration;
7703   struct IncomingRequest *ir;
7704   struct Neighbour *n;
7705   struct GNUNET_PeerIdentity sender;
7706
7707   /* DV-routed messages are not allowed for validation challenges */
7708   if (cmc->total_hops > 0)
7709   {
7710     GNUNET_break_op (0);
7711     finish_cmc_handling (cmc);
7712     return;
7713   }
7714   validity_duration = cmc->im.expected_address_validity;
7715   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7716               "Received address validation challenge %s\n",
7717               GNUNET_sh2s (&tvc->challenge.value));
7718   /* If we have a virtual link, we use this mechanism to signal the
7719      size of the flow control window, and to allow the sender
7720      to ask for increases. If for us the virtual link is still down,
7721      we will always give a window size of zero. */
7722   tvr.header.type =
7723     htons (GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_RESPONSE);
7724   tvr.header.size = htons (sizeof(tvr));
7725   tvr.reserved = htonl (0);
7726   tvr.challenge = tvc->challenge;
7727   tvr.origin_time = tvc->sender_time;
7728   tvr.validity_duration = validity_duration;
7729   {
7730     /* create signature */
7731     struct TransportValidationPS tvp =
7732     { .purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_CHALLENGE),
7733       .purpose.size = htonl (sizeof(tvp)),
7734       .validity_duration = validity_duration,
7735       .challenge = tvc->challenge };
7736
7737     GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign (GST_my_private_key,
7738                                                           &tvp.purpose,
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     if (
7931       GNUNET_OK !=
7932       GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_CHALLENGE,
7933                                   &tvp.purpose,
7934                                   &tvr->signature,
7935                                   &cmc->im.sender.public_key))
7936     {
7937       GNUNET_break_op (0);
7938       finish_cmc_handling (cmc);
7939       return;
7940     }
7941   }
7942
7943   /* validity is capped by our willingness to keep track of the
7944      validation entry and the maximum the other peer allows */
7945   vs->valid_until = GNUNET_TIME_relative_to_absolute (
7946     GNUNET_TIME_relative_min (GNUNET_TIME_relative_ntoh (
7947                                 tvr->validity_duration),
7948                               MAX_ADDRESS_VALID_UNTIL));
7949   vs->validated_until =
7950     GNUNET_TIME_absolute_min (vs->valid_until,
7951                               GNUNET_TIME_relative_to_absolute (
7952                                 ADDRESS_VALIDATION_LIFETIME));
7953   vs->validation_rtt = GNUNET_TIME_absolute_get_duration (origin_time);
7954   vs->challenge_backoff = GNUNET_TIME_UNIT_ZERO;
7955   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
7956                               &vs->challenge,
7957                               sizeof(vs->challenge));
7958   vs->first_challenge_use = GNUNET_TIME_absolute_subtract (
7959     vs->validated_until,
7960     GNUNET_TIME_relative_multiply (vs->validation_rtt,
7961                                    VALIDATION_RTT_BUFFER_FACTOR));
7962   vs->last_challenge_use =
7963     GNUNET_TIME_UNIT_ZERO_ABS; /* challenge was not yet used */
7964   update_next_challenge_time (vs, vs->first_challenge_use);
7965   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
7966               "Validation response %s accepted, address valid until %s\n",
7967               GNUNET_sh2s (&tvr->challenge.value),
7968               GNUNET_STRINGS_absolute_time_to_string (vs->valid_until));
7969   vs->sc = GNUNET_PEERSTORE_store (peerstore,
7970                                    "transport",
7971                                    &cmc->im.sender,
7972                                    GNUNET_PEERSTORE_TRANSPORT_URLADDRESS_KEY,
7973                                    vs->address,
7974                                    strlen (vs->address) + 1,
7975                                    vs->valid_until,
7976                                    GNUNET_PEERSTORE_STOREOPTION_MULTIPLE,
7977                                    &peerstore_store_validation_cb,
7978                                    vs);
7979   finish_cmc_handling (cmc);
7980
7981   /* Finally, we now possibly have a confirmed (!) working queue,
7982      update queue status (if queue still is around) */
7983   q = find_queue (&vs->pid, vs->address);
7984   if (NULL == q)
7985   {
7986     GNUNET_STATISTICS_update (GST_stats,
7987                               "# Queues lost at time of successful validation",
7988                               1,
7989                               GNUNET_NO);
7990     return;
7991   }
7992   q->validated_until = vs->validated_until;
7993   q->pd.aged_rtt = vs->validation_rtt;
7994   n = q->neighbour;
7995   vl = lookup_virtual_link (&vs->pid);
7996   if (NULL != vl)
7997   {
7998     /* Link was already up, remember n is also now available and we are done */
7999     if (NULL == vl->n)
8000     {
8001       vl->n = n;
8002       n->vl = vl;
8003       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8004                   "Virtual link to %s could now also direct neighbour!\n",
8005                   GNUNET_i2s (&vs->pid));
8006     }
8007     else
8008     {
8009       GNUNET_assert (n == vl->n);
8010     }
8011     return;
8012   }
8013   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8014               "Creating new virtual link to %s using direct neighbour!\n",
8015               GNUNET_i2s (&vs->pid));
8016   vl = GNUNET_new (struct VirtualLink);
8017   vl->target = n->pid;
8018   vl->n = n;
8019   n->vl = vl;
8020   vl->core_recv_window = RECV_WINDOW_SIZE;
8021   vl->available_fc_window_size = DEFAULT_WINDOW_SIZE;
8022   vl->visibility_task =
8023     GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl);
8024   GNUNET_break (GNUNET_YES ==
8025                 GNUNET_CONTAINER_multipeermap_put (
8026                   links,
8027                   &vl->target,
8028                   vl,
8029                   GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
8030   consider_sending_fc (vl);
8031   /* We lacked a confirmed connection to the target
8032      before, so tell CORE about it (finally!) */
8033   cores_send_connect_info (&n->pid);
8034 }
8035
8036
8037 /**
8038  * Incoming meessage.  Process the request.
8039  *
8040  * @param im the send message that was received
8041  */
8042 static void
8043 handle_incoming_msg (void *cls,
8044                      const struct GNUNET_TRANSPORT_IncomingMessage *im)
8045 {
8046   struct TransportClient *tc = cls;
8047   struct CommunicatorMessageContext *cmc =
8048     GNUNET_new (struct CommunicatorMessageContext);
8049
8050   cmc->tc = tc;
8051   cmc->im = *im;
8052   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8053               "Received message via communicator from peer %s\n",
8054               GNUNET_i2s (&im->sender));
8055   demultiplex_with_cmc (cmc, (const struct GNUNET_MessageHeader *) &im[1]);
8056 }
8057
8058
8059 /**
8060  * Communicator gave us a transport address validation response.  Process the
8061  * request.
8062  *
8063  * @param cls a `struct CommunicatorMessageContext` (must call
8064  * #finish_cmc_handling() when done)
8065  * @param fc the message that was received
8066  */
8067 static void
8068 handle_flow_control (void *cls, const struct TransportFlowControlMessage *fc)
8069 {
8070   struct CommunicatorMessageContext *cmc = cls;
8071   struct VirtualLink *vl;
8072   uint32_t seq;
8073   struct GNUNET_TIME_Absolute st;
8074   uint64_t os;
8075   uint64_t wnd;
8076
8077   vl = lookup_virtual_link (&cmc->im.sender);
8078   if (NULL == vl)
8079   {
8080     GNUNET_STATISTICS_update (GST_stats,
8081                               "# FC dropped: virtual link unknown",
8082                               1,
8083                               GNUNET_NO);
8084     finish_cmc_handling (cmc);
8085     return;
8086   }
8087   st = GNUNET_TIME_absolute_ntoh (fc->sender_time);
8088   if (st.abs_value_us < vl->last_fc_timestamp.abs_value_us)
8089   {
8090     /* out of order, drop */
8091     GNUNET_STATISTICS_update (GST_stats,
8092                               "# FC dropped: message out of order",
8093                               1,
8094                               GNUNET_NO);
8095     finish_cmc_handling (cmc);
8096     return;
8097   }
8098   seq = ntohl (fc->seq);
8099   if (seq < vl->last_fc_seq)
8100   {
8101     /* Wrap-around/reset of other peer; start all counters from zero */
8102     vl->outbound_fc_window_size_used = 0;
8103   }
8104   vl->last_fc_seq = seq;
8105   vl->last_fc_timestamp = st;
8106   vl->outbound_fc_window_size = GNUNET_ntohll (fc->inbound_window_size);
8107   os = GNUNET_ntohll (fc->outbound_sent);
8108   vl->incoming_fc_window_size_loss =
8109     (int64_t) (os - vl->incoming_fc_window_size_used);
8110   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8111               "Received FC from %s, seq %u, new window %llu (loss at %lld)\n",
8112               GNUNET_i2s (&vl->target),
8113               (unsigned int) seq,
8114               (unsigned long long) vl->outbound_fc_window_size,
8115               (long long) vl->incoming_fc_window_size_loss);
8116   wnd = GNUNET_ntohll (fc->outbound_window_size);
8117   if ((wnd < vl->incoming_fc_window_size) ||
8118       (vl->last_outbound_window_size_received != wnd) ||
8119       (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX)
8120        % FC_NO_CHANGE_REPLY_PROBABILITY))
8121   {
8122     /* Consider re-sending our FC message, as clearly the
8123        other peer's idea of the window is not up-to-date */
8124     consider_sending_fc (vl);
8125   }
8126   if ((wnd == vl->incoming_fc_window_size) &&
8127       (vl->last_outbound_window_size_received == wnd) &&
8128       (NULL != vl->fc_retransmit_task))
8129   {
8130     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8131                 "Stopping FC retransmission to %s: peer is current at window %llu\n",
8132                 GNUNET_i2s (&vl->target),
8133                 (unsigned long long) wnd);
8134     GNUNET_SCHEDULER_cancel (vl->fc_retransmit_task);
8135     vl->fc_retransmit_task = NULL;
8136   }
8137   vl->last_outbound_window_size_received = wnd;
8138   /* FC window likely increased, check transmission possibilities! */
8139   check_vl_transmission (vl);
8140   finish_cmc_handling (cmc);
8141 }
8142
8143
8144 /**
8145  * Given an inbound message @a msg from a communicator @a cmc,
8146  * demultiplex it based on the type calling the right handler.
8147  *
8148  * @param cmc context for demultiplexing
8149  * @param msg message to demultiplex
8150  */
8151 static void
8152 demultiplex_with_cmc (struct CommunicatorMessageContext *cmc,
8153                       const struct GNUNET_MessageHeader *msg)
8154 {
8155   struct GNUNET_MQ_MessageHandler handlers[] =
8156   { GNUNET_MQ_hd_var_size (fragment_box,
8157                            GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT,
8158                            struct TransportFragmentBoxMessage,
8159                            &cmc),
8160     GNUNET_MQ_hd_var_size (reliability_box,
8161                            GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX,
8162                            struct TransportReliabilityBoxMessage,
8163                            &cmc),
8164     GNUNET_MQ_hd_var_size (reliability_ack,
8165                            GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_ACK,
8166                            struct TransportReliabilityAckMessage,
8167                            &cmc),
8168     GNUNET_MQ_hd_var_size (backchannel_encapsulation,
8169                            GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION,
8170                            struct TransportBackchannelEncapsulationMessage,
8171                            &cmc),
8172     GNUNET_MQ_hd_var_size (dv_learn,
8173                            GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN,
8174                            struct TransportDVLearnMessage,
8175                            &cmc),
8176     GNUNET_MQ_hd_var_size (dv_box,
8177                            GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX,
8178                            struct TransportDVBoxMessage,
8179                            &cmc),
8180     GNUNET_MQ_hd_fixed_size (
8181       validation_challenge,
8182       GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_CHALLENGE,
8183       struct TransportValidationChallengeMessage,
8184       &cmc),
8185     GNUNET_MQ_hd_fixed_size (flow_control,
8186                              GNUNET_MESSAGE_TYPE_TRANSPORT_FLOW_CONTROL,
8187                              struct TransportFlowControlMessage,
8188                              &cmc),
8189     GNUNET_MQ_hd_fixed_size (
8190       validation_response,
8191       GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_RESPONSE,
8192       struct TransportValidationResponseMessage,
8193       &cmc),
8194     GNUNET_MQ_handler_end () };
8195   int ret;
8196
8197   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8198               "Handling message of type %u with %u bytes\n",
8199               (unsigned int) ntohs (msg->type),
8200               (unsigned int) ntohs (msg->size));
8201   ret = GNUNET_MQ_handle_message (handlers, msg);
8202   if (GNUNET_SYSERR == ret)
8203   {
8204     GNUNET_break (0);
8205     GNUNET_SERVICE_client_drop (cmc->tc->client);
8206     GNUNET_free (cmc);
8207     return;
8208   }
8209   if (GNUNET_NO == ret)
8210   {
8211     /* unencapsulated 'raw' message */
8212     handle_raw_message (&cmc, msg);
8213   }
8214 }
8215
8216
8217 /**
8218  * New queue became available.  Check message.
8219  *
8220  * @param cls the client
8221  * @param aqm the send message that was sent
8222  */
8223 static int
8224 check_add_queue_message (void *cls,
8225                          const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
8226 {
8227   struct TransportClient *tc = cls;
8228
8229   if (CT_COMMUNICATOR != tc->type)
8230   {
8231     GNUNET_break (0);
8232     return GNUNET_SYSERR;
8233   }
8234   GNUNET_MQ_check_zero_termination (aqm);
8235   return GNUNET_OK;
8236 }
8237
8238
8239 /**
8240  * If necessary, generates the UUID for a @a pm
8241  *
8242  * @param pm pending message to generate UUID for.
8243  */
8244 static void
8245 set_pending_message_uuid (struct PendingMessage *pm)
8246 {
8247   if (pm->msg_uuid_set)
8248     return;
8249   pm->msg_uuid.uuid = pm->vl->message_uuid_ctr++;
8250   pm->msg_uuid_set = GNUNET_YES;
8251 }
8252
8253
8254 /**
8255  * Setup data structure waiting for acknowledgements.
8256  *
8257  * @param queue queue the @a pm will be sent over
8258  * @param dvh path the message will take, may be NULL
8259  * @param pm the pending message for transmission
8260  * @return corresponding fresh pending acknowledgement
8261  */
8262 static struct PendingAcknowledgement *
8263 prepare_pending_acknowledgement (struct Queue *queue,
8264                                  struct DistanceVectorHop *dvh,
8265                                  struct PendingMessage *pm)
8266 {
8267   struct PendingAcknowledgement *pa;
8268
8269   pa = GNUNET_new (struct PendingAcknowledgement);
8270   pa->queue = queue;
8271   pa->dvh = dvh;
8272   pa->pm = pm;
8273   do
8274   {
8275     GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
8276                                 &pa->ack_uuid,
8277                                 sizeof(pa->ack_uuid));
8278   }
8279   while (GNUNET_YES != GNUNET_CONTAINER_multiuuidmap_put (
8280            pending_acks,
8281            &pa->ack_uuid.value,
8282            pa,
8283            GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
8284   GNUNET_CONTAINER_MDLL_insert (queue, queue->pa_head, queue->pa_tail, pa);
8285   GNUNET_CONTAINER_MDLL_insert (pm, pm->pa_head, pm->pa_tail, pa);
8286   if (NULL != dvh)
8287     GNUNET_CONTAINER_MDLL_insert (dvh, dvh->pa_head, dvh->pa_tail, pa);
8288   pa->transmission_time = GNUNET_TIME_absolute_get ();
8289   pa->message_size = pm->bytes_msg;
8290   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8291               "Waiting for ACKnowledgment `%s' for <%llu>\n",
8292               GNUNET_uuid2s (&pa->ack_uuid.value),
8293               pm->logging_uuid);
8294   return pa;
8295 }
8296
8297
8298 /**
8299  * Fragment the given @a pm to the given @a mtu.  Adds
8300  * additional fragments to the neighbour as well. If the
8301  * @a mtu is too small, generates and error for the @a pm
8302  * and returns NULL.
8303  *
8304  * @param queue which queue to fragment for
8305  * @param dvh path the message will take, or NULL
8306  * @param pm pending message to fragment for transmission
8307  * @return new message to transmit
8308  */
8309 static struct PendingMessage *
8310 fragment_message (struct Queue *queue,
8311                   struct DistanceVectorHop *dvh,
8312                   struct PendingMessage *pm)
8313 {
8314   struct PendingAcknowledgement *pa;
8315   struct PendingMessage *ff;
8316   uint16_t mtu;
8317
8318   mtu = (0 == queue->mtu)
8319         ? UINT16_MAX - sizeof(struct GNUNET_TRANSPORT_SendMessageTo)
8320         : queue->mtu;
8321   set_pending_message_uuid (pm);
8322   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8323               "Fragmenting message %llu <%llu> to %s for MTU %u\n",
8324               (unsigned long long) pm->msg_uuid.uuid,
8325               pm->logging_uuid,
8326               GNUNET_i2s (&pm->vl->target),
8327               (unsigned int) mtu);
8328   pa = prepare_pending_acknowledgement (queue, dvh, pm);
8329
8330   /* This invariant is established in #handle_add_queue_message() */
8331   GNUNET_assert (mtu > sizeof(struct TransportFragmentBoxMessage));
8332
8333   /* select fragment for transmission, descending the tree if it has
8334      been expanded until we are at a leaf or at a fragment that is small
8335      enough
8336    */
8337   ff = pm;
8338   while (((ff->bytes_msg > mtu) || (pm == ff)) &&
8339          (ff->frag_off == ff->bytes_msg) && (NULL != ff->head_frag))
8340   {
8341     ff = ff->head_frag;   /* descent into fragmented fragments */
8342   }
8343
8344   if (((ff->bytes_msg > mtu) || (pm == ff)) && (pm->frag_off < pm->bytes_msg))
8345   {
8346     /* Did not yet calculate all fragments, calculate next fragment */
8347     struct PendingMessage *frag;
8348     struct TransportFragmentBoxMessage tfb;
8349     const char *orig;
8350     char *msg;
8351     uint16_t fragmax;
8352     uint16_t fragsize;
8353     uint16_t msize;
8354     uint16_t xoff = 0;
8355
8356     orig = (const char *) &ff[1];
8357     msize = ff->bytes_msg;
8358     if (pm != ff)
8359     {
8360       const struct TransportFragmentBoxMessage *tfbo;
8361
8362       tfbo = (const struct TransportFragmentBoxMessage *) orig;
8363       orig += sizeof(struct TransportFragmentBoxMessage);
8364       msize -= sizeof(struct TransportFragmentBoxMessage);
8365       xoff = ntohs (tfbo->frag_off);
8366     }
8367     fragmax = mtu - sizeof(struct TransportFragmentBoxMessage);
8368     fragsize = GNUNET_MIN (msize - ff->frag_off, fragmax);
8369     frag =
8370       GNUNET_malloc (sizeof(struct PendingMessage)
8371                      + sizeof(struct TransportFragmentBoxMessage) + fragsize);
8372     frag->logging_uuid = logging_uuid_gen++;
8373     frag->vl = pm->vl;
8374     frag->frag_parent = ff;
8375     frag->timeout = pm->timeout;
8376     frag->bytes_msg = sizeof(struct TransportFragmentBoxMessage) + fragsize;
8377     frag->pmt = PMT_FRAGMENT_BOX;
8378     msg = (char *) &frag[1];
8379     tfb.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT);
8380     tfb.header.size =
8381       htons (sizeof(struct TransportFragmentBoxMessage) + fragsize);
8382     tfb.ack_uuid = pa->ack_uuid;
8383     tfb.msg_uuid = pm->msg_uuid;
8384     tfb.frag_off = htons (ff->frag_off + xoff);
8385     tfb.msg_size = htons (pm->bytes_msg);
8386     memcpy (msg, &tfb, sizeof(tfb));
8387     memcpy (&msg[sizeof(tfb)], &orig[ff->frag_off], fragsize);
8388     GNUNET_CONTAINER_MDLL_insert (frag, ff->head_frag, ff->tail_frag, frag);
8389     ff->frag_off += fragsize;
8390     ff = frag;
8391   }
8392
8393   /* Move head to the tail and return it */
8394   GNUNET_CONTAINER_MDLL_remove (frag,
8395                                 ff->frag_parent->head_frag,
8396                                 ff->frag_parent->tail_frag,
8397                                 ff);
8398   GNUNET_CONTAINER_MDLL_insert_tail (frag,
8399                                      ff->frag_parent->head_frag,
8400                                      ff->frag_parent->tail_frag,
8401                                      ff);
8402   return ff;
8403 }
8404
8405
8406 /**
8407  * Reliability-box the given @a pm. On error (can there be any), NULL
8408  * may be returned, otherwise the "replacement" for @a pm (which
8409  * should then be added to the respective neighbour's queue instead of
8410  * @a pm).  If the @a pm is already fragmented or reliability boxed,
8411  * or itself an ACK, this function simply returns @a pm.
8412  *
8413  * @param queue which queue to prepare transmission for
8414  * @param dvh path the message will take, or NULL
8415  * @param pm pending message to box for transmission over unreliabile queue
8416  * @return new message to transmit
8417  */
8418 static struct PendingMessage *
8419 reliability_box_message (struct Queue *queue,
8420                          struct DistanceVectorHop *dvh,
8421                          struct PendingMessage *pm)
8422 {
8423   struct TransportReliabilityBoxMessage rbox;
8424   struct PendingAcknowledgement *pa;
8425   struct PendingMessage *bpm;
8426   char *msg;
8427
8428   if (PMT_CORE != pm->pmt)
8429     return pm; /* already fragmented or reliability boxed, or control message:
8430                   do nothing */
8431   if (NULL != pm->bpm)
8432     return pm->bpm; /* already computed earlier: do nothing */
8433   GNUNET_assert (NULL == pm->head_frag);
8434   if (pm->bytes_msg + sizeof(rbox) > UINT16_MAX)
8435   {
8436     /* failed hard */
8437     GNUNET_break (0);
8438     client_send_response (pm);
8439     return NULL;
8440   }
8441   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8442               "Preparing reliability box for message <%llu> to %s on queue %s\n",
8443               pm->logging_uuid,
8444               GNUNET_i2s (&pm->vl->target),
8445               queue->address);
8446   pa = prepare_pending_acknowledgement (queue, dvh, pm);
8447
8448   bpm = GNUNET_malloc (sizeof(struct PendingMessage) + sizeof(rbox)
8449                        + pm->bytes_msg);
8450   bpm->logging_uuid = logging_uuid_gen++;
8451   bpm->vl = pm->vl;
8452   bpm->frag_parent = pm;
8453   GNUNET_CONTAINER_MDLL_insert (frag, pm->head_frag, pm->tail_frag, bpm);
8454   bpm->timeout = pm->timeout;
8455   bpm->pmt = PMT_RELIABILITY_BOX;
8456   bpm->bytes_msg = pm->bytes_msg + sizeof(rbox);
8457   set_pending_message_uuid (bpm);
8458   rbox.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX);
8459   rbox.header.size = htons (sizeof(rbox) + pm->bytes_msg);
8460   rbox.ack_countdown = htonl (0);  // FIXME: implement ACK countdown support
8461
8462   rbox.ack_uuid = pa->ack_uuid;
8463   msg = (char *) &bpm[1];
8464   memcpy (msg, &rbox, sizeof(rbox));
8465   memcpy (&msg[sizeof(rbox)], &pm[1], pm->bytes_msg);
8466   pm->bpm = bpm;
8467   return bpm;
8468 }
8469
8470
8471 /**
8472  * Change the value of the `next_attempt` field of @a pm
8473  * to @a next_attempt and re-order @a pm in the transmission
8474  * list as required by the new timestmap.
8475  *
8476  * @param pm a pending message to update
8477  * @param next_attempt timestamp to use
8478  */
8479 static void
8480 update_pm_next_attempt (struct PendingMessage *pm,
8481                         struct GNUNET_TIME_Absolute next_attempt)
8482 {
8483   struct VirtualLink *vl = pm->vl;
8484
8485   pm->next_attempt = next_attempt;
8486   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8487               "Next attempt for message <%llu> set to %s\n",
8488               pm->logging_uuid,
8489               GNUNET_STRINGS_absolute_time_to_string (next_attempt));
8490
8491   if (NULL == pm->frag_parent)
8492   {
8493     struct PendingMessage *pos;
8494
8495     /* re-insert sort in neighbour list */
8496     GNUNET_CONTAINER_MDLL_remove (vl,
8497                                   vl->pending_msg_head,
8498                                   vl->pending_msg_tail,
8499                                   pm);
8500     pos = vl->pending_msg_tail;
8501     while ((NULL != pos) &&
8502            (next_attempt.abs_value_us > pos->next_attempt.abs_value_us))
8503       pos = pos->prev_vl;
8504     GNUNET_CONTAINER_MDLL_insert_after (vl,
8505                                         vl->pending_msg_head,
8506                                         vl->pending_msg_tail,
8507                                         pos,
8508                                         pm);
8509   }
8510   else
8511   {
8512     /* re-insert sort in fragment list */
8513     struct PendingMessage *fp = pm->frag_parent;
8514     struct PendingMessage *pos;
8515
8516     GNUNET_CONTAINER_MDLL_remove (frag, fp->head_frag, fp->tail_frag, pm);
8517     pos = fp->tail_frag;
8518     while ((NULL != pos) &&
8519            (next_attempt.abs_value_us > pos->next_attempt.abs_value_us))
8520       pos = pos->prev_frag;
8521     GNUNET_CONTAINER_MDLL_insert_after (frag,
8522                                         fp->head_frag,
8523                                         fp->tail_frag,
8524                                         pos,
8525                                         pm);
8526   }
8527 }
8528
8529
8530 /**
8531  * Context for #select_best_pending_from_link().
8532  */
8533 struct PendingMessageScoreContext
8534 {
8535   /**
8536    * Set to the best message that was found, NULL for none.
8537    */
8538   struct PendingMessage *best;
8539
8540   /**
8541    * DVH that @e best should take, or NULL for direct transmission.
8542    */
8543   struct DistanceVectorHop *dvh;
8544
8545   /**
8546    * What is the estimated total overhead for this message?
8547    */
8548   size_t real_overhead;
8549
8550   /**
8551    * Number of pending messages we seriously considered this time.
8552    */
8553   unsigned int consideration_counter;
8554
8555   /**
8556    * Did we have to fragment?
8557    */
8558   int frag;
8559
8560   /**
8561    * Did we have to reliability box?
8562    */
8563   int relb;
8564 };
8565
8566
8567 /**
8568  * Select the best pending message from @a vl for transmission
8569  * via @a queue.
8570  *
8571  * @param sc[in,out] best message so far (NULL for none), plus scoring data
8572  * @param queue the queue that will be used for transmission
8573  * @param vl the virtual link providing the messages
8574  * @param dvh path we are currently considering, or NULL for none
8575  * @param overhead number of bytes of overhead to be expected
8576  *        from DV encapsulation (0 for without DV)
8577  */
8578 static void
8579 select_best_pending_from_link (struct PendingMessageScoreContext *sc,
8580                                struct Queue *queue,
8581                                struct VirtualLink *vl,
8582                                struct DistanceVectorHop *dvh,
8583                                size_t overhead)
8584 {
8585   struct GNUNET_TIME_Absolute now;
8586
8587   now = GNUNET_TIME_absolute_get ();
8588   for (struct PendingMessage *pos = vl->pending_msg_head; NULL != pos;
8589        pos = pos->next_vl)
8590   {
8591     size_t real_overhead = overhead;
8592     int frag;
8593     int relb;
8594
8595     if ((NULL != dvh) && (PMT_DV_BOX == pos->pmt))
8596       continue;   /* DV messages must not be DV-routed to next hop! */
8597     if (pos->next_attempt.abs_value_us > now.abs_value_us)
8598       break;   /* too early for all messages, they are sorted by next_attempt */
8599     if (NULL != pos->qe)
8600       continue;   /* not eligible */
8601     sc->consideration_counter++;
8602     /* determine if we have to fragment, if so add fragmentation
8603        overhead! */
8604     frag = GNUNET_NO;
8605     if (((0 != queue->mtu) &&
8606          (pos->bytes_msg + real_overhead > queue->mtu)) ||
8607         (pos->bytes_msg > UINT16_MAX - sizeof(struct
8608                                               GNUNET_TRANSPORT_SendMessageTo))
8609         ||
8610         (NULL != pos->head_frag /* fragments already exist, should
8611                                      respect that even if MTU is 0 for
8612                                      this queue */))
8613     {
8614       frag = GNUNET_YES;
8615       if (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc)
8616       {
8617         /* FIXME-FRAG-REL-UUID: we could use an optimized, shorter fragmentation
8618            header without the ACK UUID when using a *reliable* channel! */
8619       }
8620       real_overhead = overhead + sizeof(struct TransportFragmentBoxMessage);
8621     }
8622     /* determine if we have to reliability-box, if so add reliability box
8623        overhead */
8624     relb = GNUNET_NO;
8625     if ((GNUNET_NO == frag) &&
8626         (0 == (pos->prefs & GNUNET_MQ_PREF_UNRELIABLE)) &&
8627         (GNUNET_TRANSPORT_CC_RELIABLE != queue->tc->details.communicator.cc))
8628     {
8629       relb = GNUNET_YES;
8630       real_overhead += sizeof(struct TransportReliabilityBoxMessage);
8631     }
8632
8633     /* Finally, compare to existing 'best' in sc to see if this 'pos' pending
8634        message would beat it! */
8635     if (NULL != sc->best)
8636     {
8637       /* CHECK if pos fits queue BETTER (=smaller) than pm, if not: continue;
8638          OPTIMIZE-ME: This is a heuristic, which so far has NOT been
8639          experimentally validated. There may be some huge potential for
8640          improvement here. Also, we right now only compare how well the
8641          given message fits _this_ queue, and do not consider how well other
8642          queues might suit the message. Taking other queues into consideration
8643          may further improve the result, but could also be expensive
8644          in terms of CPU time.  */long long sc_score = sc->frag * 40 + sc->relb * 20 + sc->real_overhead;
8645       long long pm_score = frag * 40 + relb * 20 + real_overhead;
8646       long long time_delta =
8647         (sc->best->next_attempt.abs_value_us - pos->next_attempt.abs_value_us)
8648         / 1000LL;
8649
8650       /* "time_delta" considers which message has been 'ready' for transmission
8651          for longer, if a message has a preference for low latency, increase
8652          the weight of the time_delta by 10x if it is favorable for that message */
8653       if ((0 != (pos->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
8654           (0 != (sc->best->prefs & GNUNET_MQ_PREF_LOW_LATENCY)))
8655         time_delta *= 10;     /* increase weight (always, both are low latency) */
8656       else if ((0 != (pos->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
8657                (time_delta > 0))
8658         time_delta *=
8659           10;     /* increase weight, favors 'pos', which is low latency */
8660       else if ((0 != (sc->best->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) &&
8661                (time_delta < 0))
8662         time_delta *=
8663           10;     /* increase weight, favors 'sc->best', which is low latency */
8664       if (0 != queue->mtu)
8665       {
8666         /* Grant bonus if we are bellow MTU, larger bonus the closer we will
8667            be to the MTU */
8668         if (queue->mtu > sc->real_overhead + sc->best->bytes_msg)
8669           sc_score -= queue->mtu - (sc->real_overhead + sc->best->bytes_msg);
8670         if (queue->mtu > real_overhead + pos->bytes_msg)
8671           pm_score -= queue->mtu - (real_overhead + pos->bytes_msg);
8672       }
8673       if (sc_score + time_delta > pm_score)
8674         continue;     /* sc_score larger, keep sc->best */
8675     }
8676     sc->best = pos;
8677     sc->dvh = dvh;
8678     sc->frag = frag;
8679     sc->relb = relb;
8680   }
8681 }
8682
8683
8684 /**
8685  * Function to call to further operate on the now DV encapsulated
8686  * message @a hdr, forwarding it via @a next_hop under respect of
8687  * @a options.
8688  *
8689  * @param cls a `struct PendingMessageScoreContext`
8690  * @param next_hop next hop of the DV path
8691  * @param hdr encapsulated message, technically a `struct TransportDFBoxMessage`
8692  * @param options options of the original message
8693  */
8694 static void
8695 extract_box_cb (void *cls,
8696                 struct Neighbour *next_hop,
8697                 const struct GNUNET_MessageHeader *hdr,
8698                 enum RouteMessageOptions options)
8699 {
8700   struct PendingMessageScoreContext *sc = cls;
8701   struct PendingMessage *pm = sc->best;
8702   struct PendingMessage *bpm;
8703   uint16_t bsize = ntohs (hdr->size);
8704
8705   GNUNET_assert (NULL == pm->bpm);
8706   bpm = GNUNET_malloc (sizeof(struct PendingMessage) + bsize);
8707   bpm->logging_uuid = logging_uuid_gen++;
8708   bpm->pmt = PMT_DV_BOX;
8709   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8710               "Creating DV Box %llu for original message %llu (next hop is %s)\n",
8711               bpm->logging_uuid,
8712               pm->logging_uuid,
8713               GNUNET_i2s (&next_hop->pid));
8714   memcpy (&bpm[1], hdr, bsize);
8715   pm->bpm = bpm;
8716 }
8717
8718
8719 /**
8720  * We believe we are ready to transmit a `struct PendingMessage` on a
8721  * queue, the big question is which one!  We need to see if there is
8722  * one pending that is allowed by flow control and congestion control
8723  * and (ideally) matches our queue's performance profile.
8724  *
8725  * If such a message is found, we give the message to the communicator
8726  * for transmission (updating the tracker, and re-scheduling ourselves
8727  * if applicable).
8728  *
8729  * If no such message is found, the queue's `idle` field must be set
8730  * to #GNUNET_YES.
8731  *
8732  * @param cls the `struct Queue` to process transmissions for
8733  */
8734 static void
8735 transmit_on_queue (void *cls)
8736 {
8737   struct Queue *queue = cls;
8738   struct Neighbour *n = queue->neighbour;
8739   struct PendingMessageScoreContext sc;
8740   struct PendingMessage *pm;
8741
8742   queue->transmit_task = NULL;
8743   if (NULL == n->vl)
8744   {
8745     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8746                 "Virtual link `%s' is down, cannot have PM for queue `%s'\n",
8747                 GNUNET_i2s (&n->pid),
8748                 queue->address);
8749     queue->idle = GNUNET_YES;
8750     return;
8751   }
8752   memset (&sc, 0, sizeof(sc));
8753   select_best_pending_from_link (&sc, queue, n->vl, NULL, 0);
8754   if (NULL == sc.best)
8755   {
8756     /* Also look at DVH that have the n as first hop! */
8757     for (struct DistanceVectorHop *dvh = n->dv_head; NULL != dvh;
8758          dvh = dvh->next_neighbour)
8759     {
8760       select_best_pending_from_link (&sc,
8761                                      queue,
8762                                      dvh->dv->vl,
8763                                      dvh,
8764                                      sizeof(struct GNUNET_PeerIdentity)
8765                                      * (1 + dvh->distance)
8766                                      + sizeof(struct TransportDVBoxMessage)
8767                                      + sizeof(struct TransportDVBoxPayloadP));
8768     }
8769   }
8770   if (NULL == sc.best)
8771   {
8772     /* no message pending, nothing to do here! */
8773     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8774                 "No pending messages, queue `%s' to %s now idle\n",
8775                 queue->address,
8776                 GNUNET_i2s (&n->pid));
8777     queue->idle = GNUNET_YES;
8778     return;
8779   }
8780
8781   /* Given selection in `sc`, do transmission */
8782   pm = sc.best;
8783   if (NULL != sc.dvh)
8784   {
8785     GNUNET_assert (PMT_DV_BOX != pm->pmt);
8786     if (NULL != sc.best->bpm)
8787     {
8788       /* We did this boxing before, but possibly for a different path!
8789          Discard old DV box!  OPTIMIZE-ME: we might want to check if
8790          it is the same and then not re-build the message... */
8791       free_pending_message (sc.best->bpm);
8792       sc.best->bpm = NULL;
8793     }
8794     encapsulate_for_dv (sc.dvh->dv,
8795                         1,
8796                         &sc.dvh,
8797                         (const struct GNUNET_MessageHeader *) &sc.best[1],
8798                         &extract_box_cb,
8799                         &sc,
8800                         RMO_NONE);
8801     GNUNET_assert (NULL != sc.best->bpm);
8802     pm = sc.best->bpm;
8803   }
8804   if (GNUNET_YES == sc.frag)
8805   {
8806     pm = fragment_message (queue, sc.dvh, pm);
8807     if (NULL == pm)
8808     {
8809       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8810                   "Fragmentation failed queue %s to %s for <%llu>, trying again\n",
8811                   queue->address,
8812                   GNUNET_i2s (&n->pid),
8813                   sc.best->logging_uuid);
8814       schedule_transmit_on_queue (queue, GNUNET_SCHEDULER_PRIORITY_DEFAULT);
8815       return;
8816     }
8817   }
8818   else if (GNUNET_YES == sc.relb)
8819   {
8820     pm = reliability_box_message (queue, sc.dvh, pm);
8821     if (NULL == pm)
8822     {
8823       /* Reliability boxing failed, try next message... */
8824       GNUNET_log (
8825         GNUNET_ERROR_TYPE_DEBUG,
8826         "Reliability boxing failed queue %s to %s for <%llu>, trying again\n",
8827         queue->address,
8828         GNUNET_i2s (&n->pid),
8829         sc.best->logging_uuid);
8830       schedule_transmit_on_queue (queue, GNUNET_SCHEDULER_PRIORITY_DEFAULT);
8831       return;
8832     }
8833   }
8834
8835   /* Pass 'pm' for transission to the communicator */
8836   GNUNET_log (
8837     GNUNET_ERROR_TYPE_DEBUG,
8838     "Passing message <%llu> to queue %s for peer %s (considered %u others)\n",
8839     pm->logging_uuid,
8840     queue->address,
8841     GNUNET_i2s (&n->pid),
8842     sc.consideration_counter);
8843
8844   /* Flow control: increment amount of traffic sent; if we are routing
8845      via DV (and thus the ultimate target of the pending message is for
8846      a different virtual link than the one of the queue), then we need
8847      to use up not only the window of the direct link but also the
8848      flow control window for the DV link! */pm->vl->outbound_fc_window_size_used += pm->bytes_msg;
8849
8850   if (pm->vl != queue->neighbour->vl)
8851   {
8852     /* If the virtual link of the queue differs, this better be distance
8853        vector routing! */
8854     GNUNET_assert (NULL != sc.dvh);
8855     /* If we do distance vector routing, we better not do this for a
8856        message that was itself DV-routed */
8857     GNUNET_assert (PMT_DV_BOX != sc.best->pmt);
8858     /* We use the size of the unboxed message here, to avoid counting
8859        the DV-Box header which is eaten up on the way by intermediaries */
8860     queue->neighbour->vl->outbound_fc_window_size_used += sc.best->bytes_msg;
8861   }
8862   else
8863   {
8864     GNUNET_assert (NULL == sc.dvh);
8865   }
8866
8867   queue_send_msg (queue, pm, &pm[1], pm->bytes_msg);
8868
8869   /* Check if this transmission somehow conclusively finished handing 'pm'
8870      even without any explicit ACKs */
8871   if ((PMT_CORE == pm->pmt) ||
8872       (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc))
8873   {
8874     completed_pending_message (pm);
8875   }
8876   else
8877   {
8878     /* Message not finished, waiting for acknowledgement.
8879        Update time by which we might retransmit 's' based on queue
8880        characteristics (i.e. RTT); it takes one RTT for the message to
8881        arrive and the ACK to come back in the best case; but the other
8882        side is allowed to delay ACKs by 2 RTTs, so we use 4 RTT before
8883        retransmitting.
8884
8885        OPTIMIZE: Note that in the future this heuristic should likely
8886        be improved further (measure RTT stability, consider message
8887        urgency and size when delaying ACKs, etc.) */update_pm_next_attempt (pm,
8888                             GNUNET_TIME_relative_to_absolute (
8889                               GNUNET_TIME_relative_multiply (queue->pd.aged_rtt,
8890                                                              4)));
8891   }
8892   /* finally, re-schedule queue transmission task itself */
8893   schedule_transmit_on_queue (queue, GNUNET_SCHEDULER_PRIORITY_DEFAULT);
8894 }
8895
8896
8897 /**
8898  * Queue to a peer went down.  Process the request.
8899  *
8900  * @param cls the client
8901  * @param dqm the send message that was sent
8902  */
8903 static void
8904 handle_del_queue_message (void *cls,
8905                           const struct GNUNET_TRANSPORT_DelQueueMessage *dqm)
8906 {
8907   struct TransportClient *tc = cls;
8908
8909   if (CT_COMMUNICATOR != tc->type)
8910   {
8911     GNUNET_break (0);
8912     GNUNET_SERVICE_client_drop (tc->client);
8913     return;
8914   }
8915   for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
8916        queue = queue->next_client)
8917   {
8918     struct Neighbour *neighbour = queue->neighbour;
8919
8920     if ((dqm->qid != queue->qid) ||
8921         (0 != GNUNET_memcmp (&dqm->receiver, &neighbour->pid)))
8922       continue;
8923     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8924                 "Dropped queue %s to peer %s\n",
8925                 queue->address,
8926                 GNUNET_i2s (&neighbour->pid));
8927     free_queue (queue);
8928     GNUNET_SERVICE_client_continue (tc->client);
8929     return;
8930   }
8931   GNUNET_break (0);
8932   GNUNET_SERVICE_client_drop (tc->client);
8933 }
8934
8935
8936 /**
8937  * Message was transmitted.  Process the request.
8938  *
8939  * @param cls the client
8940  * @param sma the send message that was sent
8941  */
8942 static void
8943 handle_send_message_ack (void *cls,
8944                          const struct GNUNET_TRANSPORT_SendMessageToAck *sma)
8945 {
8946   struct TransportClient *tc = cls;
8947   struct QueueEntry *qe;
8948   struct PendingMessage *pm;
8949
8950   if (CT_COMMUNICATOR != tc->type)
8951   {
8952     GNUNET_break (0);
8953     GNUNET_SERVICE_client_drop (tc->client);
8954     return;
8955   }
8956
8957   /* find our queue entry matching the ACK */
8958   qe = NULL;
8959   for (struct Queue *queue = tc->details.communicator.queue_head; NULL != queue;
8960        queue = queue->next_client)
8961   {
8962     if (0 != GNUNET_memcmp (&queue->neighbour->pid, &sma->receiver))
8963       continue;
8964     for (struct QueueEntry *qep = queue->queue_head; NULL != qep;
8965          qep = qep->next)
8966     {
8967       if (qep->mid != sma->mid)
8968         continue;
8969       qe = qep;
8970       break;
8971     }
8972     break;
8973   }
8974   if (NULL == qe)
8975   {
8976     /* this should never happen */
8977     GNUNET_break (0);
8978     GNUNET_SERVICE_client_drop (tc->client);
8979     return;
8980   }
8981   GNUNET_CONTAINER_DLL_remove (qe->queue->queue_head,
8982                                qe->queue->queue_tail,
8983                                qe);
8984   qe->queue->queue_length--;
8985   tc->details.communicator.total_queue_length--;
8986   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
8987               "Received ACK on queue %s to peer %s (new length: %u/%u)\n",
8988               qe->queue->address,
8989               GNUNET_i2s (&qe->queue->neighbour->pid),
8990               qe->queue->queue_length,
8991               tc->details.communicator.total_queue_length);
8992   GNUNET_SERVICE_client_continue (tc->client);
8993
8994   /* if applicable, resume transmissions that waited on ACK */
8995   if (COMMUNICATOR_TOTAL_QUEUE_LIMIT - 1 ==
8996       tc->details.communicator.total_queue_length)
8997   {
8998     /* Communicator dropped below threshold, resume all queues
8999        incident with this client! */
9000     GNUNET_STATISTICS_update (
9001       GST_stats,
9002       "# Transmission throttled due to communicator queue limit",
9003       -1,
9004       GNUNET_NO);
9005     for (struct Queue *queue = tc->details.communicator.queue_head;
9006          NULL != queue;
9007          queue = queue->next_client)
9008       schedule_transmit_on_queue (queue, GNUNET_SCHEDULER_PRIORITY_DEFAULT);
9009   }
9010   else if (QUEUE_LENGTH_LIMIT - 1 == qe->queue->queue_length)
9011   {
9012     /* queue dropped below threshold; only resume this one queue */
9013     GNUNET_STATISTICS_update (GST_stats,
9014                               "# Transmission throttled due to queue queue limit",
9015                               -1,
9016                               GNUNET_NO);
9017     schedule_transmit_on_queue (qe->queue, GNUNET_SCHEDULER_PRIORITY_DEFAULT);
9018   }
9019
9020   if (NULL != (pm = qe->pm))
9021   {
9022     struct VirtualLink *vl;
9023
9024     GNUNET_assert (qe == pm->qe);
9025     pm->qe = NULL;
9026     /* If waiting for this communicator may have blocked transmission
9027        of pm on other queues for this neighbour, force schedule
9028        transmit on queue for queues of the neighbour */
9029     vl = pm->vl;
9030     if (vl->pending_msg_head == pm)
9031       check_vl_transmission (vl);
9032   }
9033   GNUNET_free (qe);
9034 }
9035
9036
9037 /**
9038  * Iterator telling new MONITOR client about all existing
9039  * queues to peers.
9040  *
9041  * @param cls the new `struct TransportClient`
9042  * @param pid a connected peer
9043  * @param value the `struct Neighbour` with more information
9044  * @return #GNUNET_OK (continue to iterate)
9045  */
9046 static int
9047 notify_client_queues (void *cls,
9048                       const struct GNUNET_PeerIdentity *pid,
9049                       void *value)
9050 {
9051   struct TransportClient *tc = cls;
9052   struct Neighbour *neighbour = value;
9053
9054   GNUNET_assert (CT_MONITOR == tc->type);
9055   for (struct Queue *q = neighbour->queue_head; NULL != q;
9056        q = q->next_neighbour)
9057   {
9058     struct MonitorEvent me = { .rtt = q->pd.aged_rtt,
9059                                .cs = q->cs,
9060                                .num_msg_pending = q->num_msg_pending,
9061                                .num_bytes_pending = q->num_bytes_pending };
9062
9063     notify_monitor (tc, pid, q->address, q->nt, &me);
9064   }
9065   return GNUNET_OK;
9066 }
9067
9068
9069 /**
9070  * Initialize a monitor client.
9071  *
9072  * @param cls the client
9073  * @param start the start message that was sent
9074  */
9075 static void
9076 handle_monitor_start (void *cls,
9077                       const struct GNUNET_TRANSPORT_MonitorStart *start)
9078 {
9079   struct TransportClient *tc = cls;
9080
9081   if (CT_NONE != tc->type)
9082   {
9083     GNUNET_break (0);
9084     GNUNET_SERVICE_client_drop (tc->client);
9085     return;
9086   }
9087   tc->type = CT_MONITOR;
9088   tc->details.monitor.peer = start->peer;
9089   tc->details.monitor.one_shot = ntohl (start->one_shot);
9090   GNUNET_CONTAINER_multipeermap_iterate (neighbours, &notify_client_queues, tc);
9091   GNUNET_SERVICE_client_mark_monitor (tc->client);
9092   GNUNET_SERVICE_client_continue (tc->client);
9093 }
9094
9095
9096 /**
9097  * Find transport client providing communication service
9098  * for the protocol @a prefix.
9099  *
9100  * @param prefix communicator name
9101  * @return NULL if no such transport client is available
9102  */
9103 static struct TransportClient *
9104 lookup_communicator (const char *prefix)
9105 {
9106   for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
9107   {
9108     if (CT_COMMUNICATOR != tc->type)
9109       continue;
9110     if (0 == strcmp (prefix, tc->details.communicator.address_prefix))
9111       return tc;
9112   }
9113   GNUNET_log (
9114     GNUNET_ERROR_TYPE_WARNING,
9115     "Somone suggested use of communicator for `%s', but we do not have such a communicator!\n",
9116     prefix);
9117   return NULL;
9118 }
9119
9120
9121 /**
9122  * Signature of a function called with a communicator @a address of a peer
9123  * @a pid that an application wants us to connect to.
9124  *
9125  * @param pid target peer
9126  * @param address the address to try
9127  */
9128 static void
9129 suggest_to_connect (const struct GNUNET_PeerIdentity *pid, const char *address)
9130 {
9131   static uint32_t idgen;
9132   struct TransportClient *tc;
9133   char *prefix;
9134   struct GNUNET_TRANSPORT_CreateQueue *cqm;
9135   struct GNUNET_MQ_Envelope *env;
9136   size_t alen;
9137
9138   prefix = GNUNET_HELLO_address_to_prefix (address);
9139   if (NULL == prefix)
9140   {
9141     GNUNET_break (0);  /* We got an invalid address!? */
9142     return;
9143   }
9144   tc = lookup_communicator (prefix);
9145   if (NULL == tc)
9146   {
9147     GNUNET_STATISTICS_update (GST_stats,
9148                               "# Suggestions ignored due to missing communicator",
9149                               1,
9150                               GNUNET_NO);
9151     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
9152                 "Cannot connect to %s at `%s', no matching communicator present\n",
9153                 GNUNET_i2s (pid),
9154                 address);
9155     GNUNET_free (prefix);
9156     return;
9157   }
9158   /* forward suggestion for queue creation to communicator */
9159   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9160               "Request #%u for `%s' communicator to create queue to `%s'\n",
9161               (unsigned int) idgen,
9162               prefix,
9163               address);
9164   GNUNET_free (prefix);
9165   alen = strlen (address) + 1;
9166   env =
9167     GNUNET_MQ_msg_extra (cqm, alen, GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE);
9168   cqm->request_id = htonl (idgen++);
9169   cqm->receiver = *pid;
9170   memcpy (&cqm[1], address, alen);
9171   GNUNET_MQ_send (tc->mq, env);
9172 }
9173
9174
9175 /**
9176  * The queue @a q (which matches the peer and address in @a vs) is
9177  * ready for queueing. We should now queue the validation request.
9178  *
9179  * @param q queue to send on
9180  * @param vs state to derive validation challenge from
9181  */
9182 static void
9183 validation_transmit_on_queue (struct Queue *q, struct ValidationState *vs)
9184 {
9185   struct TransportValidationChallengeMessage tvc;
9186
9187   vs->last_challenge_use = GNUNET_TIME_absolute_get_monotonic (GST_cfg);
9188   tvc.header.type =
9189     htons (GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_CHALLENGE);
9190   tvc.header.size = htons (sizeof(tvc));
9191   tvc.reserved = htonl (0);
9192   tvc.challenge = vs->challenge;
9193   tvc.sender_time = GNUNET_TIME_absolute_hton (vs->last_challenge_use);
9194   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
9195               "Sending address validation challenge %s to %s\n",
9196               GNUNET_sh2s (&tvc.challenge.value),
9197               GNUNET_i2s (&q->neighbour->pid));
9198   queue_send_msg (q, NULL, &tvc, sizeof(tvc));
9199 }
9200
9201
9202 /**
9203  * Task run periodically to validate some address based on #validation_heap.
9204  *
9205  * @param cls NULL
9206  */
9207 static void
9208 validation_start_cb (void *cls)
9209 {
9210   struct ValidationState *vs;
9211   struct Queue *q;
9212
9213   (void) cls;
9214   validation_task = NULL;
9215   vs = GNUNET_CONTAINER_heap_peek (validation_heap);
9216   /* drop validations past their expiration */
9217   while (
9218     (NULL != vs) &&
9219     (0 == GNUNET_TIME_absolute_get_remaining (vs->valid_until).rel_value_us))
9220   {
9221     free_validation_state (vs);
9222     vs = GNUNET_CONTAINER_heap_peek (validation_heap);
9223   }
9224   if (NULL == vs)
9225   {
9226     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
9227                 "Address validation task not scheduled anymore, nothing to do\n");
9228     return;   /* woopsie, no more addresses known, should only
9229                  happen if we're really a lonely peer */
9230   }
9231   q = find_queue (&vs->pid, vs->address);
9232   if (NULL == q)
9233   {
9234     vs->awaiting_queue = GNUNET_YES;
9235     suggest_to_connect (&vs->pid, vs->address);
9236   }
9237   else
9238     validation_transmit_on_queue (q, vs);
9239   /* Finally, reschedule next attempt */
9240   vs->challenge_backoff =
9241     GNUNET_TIME_randomized_backoff (vs->challenge_backoff,
9242                                     MAX_VALIDATION_CHALLENGE_FREQ);
9243   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9244               "Address validation task will run again in %s\n",
9245               GNUNET_STRINGS_relative_time_to_string (vs->challenge_backoff,
9246                                                       GNUNET_YES));
9247   update_next_challenge_time (vs,
9248                               GNUNET_TIME_relative_to_absolute (
9249                                 vs->challenge_backoff));
9250 }
9251
9252
9253 /**
9254  * Closure for #check_connection_quality.
9255  */
9256 struct QueueQualityContext
9257 {
9258   /**
9259    * Set to the @e k'th queue encountered.
9260    */
9261   struct Queue *q;
9262
9263   /**
9264    * Set to the number of quality queues encountered.
9265    */
9266   unsigned int quality_count;
9267
9268   /**
9269    * Set to the total number of queues encountered.
9270    */
9271   unsigned int num_queues;
9272
9273   /**
9274    * Decremented for each queue, for selection of the
9275    * k-th queue in @e q.
9276    */
9277   unsigned int k;
9278 };
9279
9280
9281 /**
9282  * Check whether any queue to the given neighbour is
9283  * of a good "quality" and if so, increment the counter.
9284  * Also counts the total number of queues, and returns
9285  * the k-th queue found.
9286  *
9287  * @param cls a `struct QueueQualityContext *` with counters
9288  * @param pid peer this is about
9289  * @param value a `struct Neighbour`
9290  * @return #GNUNET_OK (continue to iterate)
9291  */
9292 static int
9293 check_connection_quality (void *cls,
9294                           const struct GNUNET_PeerIdentity *pid,
9295                           void *value)
9296 {
9297   struct QueueQualityContext *ctx = cls;
9298   struct Neighbour *n = value;
9299   int do_inc;
9300
9301   (void) pid;
9302   do_inc = GNUNET_NO;
9303   for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
9304   {
9305     ctx->num_queues++;
9306     if (0 == ctx->k--)
9307       ctx->q = q;
9308     /* FIXME-CONQ-STATISTICS: in the future, add reliability / goodput
9309        statistics and consider those as well here? */
9310     if (q->pd.aged_rtt.rel_value_us < DV_QUALITY_RTT_THRESHOLD.rel_value_us)
9311       do_inc = GNUNET_YES;
9312   }
9313   if (GNUNET_YES == do_inc)
9314     ctx->quality_count++;
9315   return GNUNET_OK;
9316 }
9317
9318
9319 /**
9320  * Task run when we CONSIDER initiating a DV learn
9321  * process. We first check that sending out a message is
9322  * even possible (queues exist), then that it is desirable
9323  * (if not, reschedule the task for later), and finally
9324  * we may then begin the job.  If there are too many
9325  * entries in the #dvlearn_map, we purge the oldest entry
9326  * using #lle_tail.
9327  *
9328  * @param cls NULL
9329  */
9330 static void
9331 start_dv_learn (void *cls)
9332 {
9333   struct LearnLaunchEntry *lle;
9334   struct QueueQualityContext qqc;
9335   struct TransportDVLearnMessage dvl;
9336
9337   (void) cls;
9338   dvlearn_task = NULL;
9339   if (0 == GNUNET_CONTAINER_multipeermap_size (neighbours))
9340     return; /* lost all connectivity, cannot do learning */
9341   qqc.quality_count = 0;
9342   qqc.num_queues = 0;
9343   GNUNET_CONTAINER_multipeermap_iterate (neighbours,
9344                                          &check_connection_quality,
9345                                          &qqc);
9346   if (qqc.quality_count > DV_LEARN_QUALITY_THRESHOLD)
9347   {
9348     struct GNUNET_TIME_Relative delay;
9349     unsigned int factor;
9350
9351     /* scale our retries by how far we are above the threshold */
9352     factor = qqc.quality_count / DV_LEARN_QUALITY_THRESHOLD;
9353     delay = GNUNET_TIME_relative_multiply (DV_LEARN_BASE_FREQUENCY, factor);
9354     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9355                 "At connection quality %u, will launch DV learn in %s\n",
9356                 qqc.quality_count,
9357                 GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES));
9358     dvlearn_task = GNUNET_SCHEDULER_add_delayed (delay, &start_dv_learn, NULL);
9359     return;
9360   }
9361   /* remove old entries in #dvlearn_map if it has grown too big */
9362   while (MAX_DV_LEARN_PENDING >=
9363          GNUNET_CONTAINER_multishortmap_size (dvlearn_map))
9364   {
9365     lle = lle_tail;
9366     GNUNET_assert (GNUNET_YES ==
9367                    GNUNET_CONTAINER_multishortmap_remove (dvlearn_map,
9368                                                           &lle->challenge.value,
9369                                                           lle));
9370     GNUNET_CONTAINER_DLL_remove (lle_head, lle_tail, lle);
9371     GNUNET_free (lle);
9372   }
9373   /* setup data structure for learning */
9374   lle = GNUNET_new (struct LearnLaunchEntry);
9375   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
9376                               &lle->challenge,
9377                               sizeof(lle->challenge));
9378   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9379               "Starting launch DV learn with challenge %s\n",
9380               GNUNET_sh2s (&lle->challenge.value));
9381   GNUNET_CONTAINER_DLL_insert (lle_head, lle_tail, lle);
9382   GNUNET_break (GNUNET_YES ==
9383                 GNUNET_CONTAINER_multishortmap_put (
9384                   dvlearn_map,
9385                   &lle->challenge.value,
9386                   lle,
9387                   GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
9388   dvl.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN);
9389   dvl.header.size = htons (sizeof(dvl));
9390   dvl.num_hops = htons (0);
9391   dvl.bidirectional = htons (0);
9392   dvl.non_network_delay = GNUNET_TIME_relative_hton (GNUNET_TIME_UNIT_ZERO);
9393   dvl.monotonic_time =
9394     GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_monotonic (GST_cfg));
9395   {
9396     struct DvInitPS dvip = { .purpose.purpose = htonl (
9397                                GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR),
9398                              .purpose.size = htonl (sizeof(dvip)),
9399                              .monotonic_time = dvl.monotonic_time,
9400                              .challenge = lle->challenge };
9401
9402     GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign (GST_my_private_key,
9403                                                           &dvip.purpose,
9404                                                           &dvl.init_sig));
9405   }
9406   dvl.initiator = GST_my_identity;
9407   dvl.challenge = lle->challenge;
9408
9409   qqc.quality_count = 0;
9410   qqc.k = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, qqc.num_queues);
9411   qqc.num_queues = 0;
9412   qqc.q = NULL;
9413   GNUNET_CONTAINER_multipeermap_iterate (neighbours,
9414                                          &check_connection_quality,
9415                                          &qqc);
9416   GNUNET_assert (NULL != qqc.q);
9417
9418   /* Do this as close to transmission time as possible! */
9419   lle->launch_time = GNUNET_TIME_absolute_get ();
9420
9421   queue_send_msg (qqc.q, NULL, &dvl, sizeof(dvl));
9422   /* reschedule this job, randomizing the time it runs (but no
9423      actual backoff!) */
9424   dvlearn_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_randomize (
9425                                                  DV_LEARN_BASE_FREQUENCY),
9426                                                &start_dv_learn,
9427                                                NULL);
9428 }
9429
9430
9431 /**
9432  * A new queue has been created, check if any address validation
9433  * requests have been waiting for it.
9434  *
9435  * @param cls a `struct Queue`
9436  * @param pid peer concerned (unused)
9437  * @param value a `struct ValidationState`
9438  * @return #GNUNET_NO if a match was found and we can stop looking
9439  */
9440 static int
9441 check_validation_request_pending (void *cls,
9442                                   const struct GNUNET_PeerIdentity *pid,
9443                                   void *value)
9444 {
9445   struct Queue *q = cls;
9446   struct ValidationState *vs = value;
9447
9448   (void) pid;
9449   if ((GNUNET_YES == vs->awaiting_queue) &&
9450       (0 == strcmp (vs->address, q->address)))
9451   {
9452     vs->awaiting_queue = GNUNET_NO;
9453     validation_transmit_on_queue (q, vs);
9454     return GNUNET_NO;
9455   }
9456   return GNUNET_OK;
9457 }
9458
9459
9460 /**
9461  * Function called with the monotonic time of a DV initiator
9462  * by PEERSTORE. Updates the time.
9463  *
9464  * @param cls a `struct Neighbour`
9465  * @param record the information found, NULL for the last call
9466  * @param emsg error message
9467  */
9468 static void
9469 neighbour_dv_monotime_cb (void *cls,
9470                           const struct GNUNET_PEERSTORE_Record *record,
9471                           const char *emsg)
9472 {
9473   struct Neighbour *n = cls;
9474   struct GNUNET_TIME_AbsoluteNBO *mtbe;
9475
9476   (void) emsg;
9477   if (NULL == record)
9478   {
9479     /* we're done with #neighbour_dv_monotime_cb() invocations,
9480        continue normal processing */
9481     n->get = NULL;
9482     n->dv_monotime_available = GNUNET_YES;
9483     return;
9484   }
9485   if (sizeof(*mtbe) != record->value_size)
9486   {
9487     GNUNET_break (0);
9488     return;
9489   }
9490   mtbe = record->value;
9491   n->last_dv_learn_monotime =
9492     GNUNET_TIME_absolute_max (n->last_dv_learn_monotime,
9493                               GNUNET_TIME_absolute_ntoh (*mtbe));
9494 }
9495
9496
9497 /**
9498  * New queue became available.  Process the request.
9499  *
9500  * @param cls the client
9501  * @param aqm the send message that was sent
9502  */
9503 static void
9504 handle_add_queue_message (void *cls,
9505                           const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
9506 {
9507   struct TransportClient *tc = cls;
9508   struct Queue *queue;
9509   struct Neighbour *neighbour;
9510   const char *addr;
9511   uint16_t addr_len;
9512
9513   if (ntohl (aqm->mtu) <= sizeof(struct TransportFragmentBoxMessage))
9514   {
9515     /* MTU so small as to be useless for transmissions,
9516        required for #fragment_message()! */
9517     GNUNET_break_op (0);
9518     GNUNET_SERVICE_client_drop (tc->client);
9519     return;
9520   }
9521   neighbour = lookup_neighbour (&aqm->receiver);
9522   if (NULL == neighbour)
9523   {
9524     neighbour = GNUNET_new (struct Neighbour);
9525     neighbour->pid = aqm->receiver;
9526     GNUNET_assert (GNUNET_OK ==
9527                    GNUNET_CONTAINER_multipeermap_put (
9528                      neighbours,
9529                      &neighbour->pid,
9530                      neighbour,
9531                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
9532     neighbour->get =
9533       GNUNET_PEERSTORE_iterate (peerstore,
9534                                 "transport",
9535                                 &neighbour->pid,
9536                                 GNUNET_PEERSTORE_TRANSPORT_DVLEARN_MONOTIME,
9537                                 &neighbour_dv_monotime_cb,
9538                                 neighbour);
9539   }
9540   addr_len = ntohs (aqm->header.size) - sizeof(*aqm);
9541   addr = (const char *) &aqm[1];
9542   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9543               "New queue %s to %s available with QID %llu\n",
9544               addr,
9545               GNUNET_i2s (&aqm->receiver),
9546               (unsigned long long) aqm->qid);
9547   queue = GNUNET_malloc (sizeof(struct Queue) + addr_len);
9548   queue->tc = tc;
9549   queue->address = (const char *) &queue[1];
9550   queue->pd.aged_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
9551   queue->qid = aqm->qid;
9552   queue->mtu = ntohl (aqm->mtu);
9553   queue->nt = (enum GNUNET_NetworkType) ntohl (aqm->nt);
9554   queue->cs = (enum GNUNET_TRANSPORT_ConnectionStatus) ntohl (aqm->cs);
9555   queue->neighbour = neighbour;
9556   queue->idle = GNUNET_YES;
9557   memcpy (&queue[1], addr, addr_len);
9558   /* notify monitors about new queue */
9559   {
9560     struct MonitorEvent me = { .rtt = queue->pd.aged_rtt, .cs = queue->cs };
9561
9562     notify_monitors (&neighbour->pid, queue->address, queue->nt, &me);
9563   }
9564   GNUNET_CONTAINER_MDLL_insert (neighbour,
9565                                 neighbour->queue_head,
9566                                 neighbour->queue_tail,
9567                                 queue);
9568   GNUNET_CONTAINER_MDLL_insert (client,
9569                                 tc->details.communicator.queue_head,
9570                                 tc->details.communicator.queue_tail,
9571                                 queue);
9572   /* check if valdiations are waiting for the queue */
9573   (void)
9574   GNUNET_CONTAINER_multipeermap_get_multiple (validation_map,
9575                                               &aqm->receiver,
9576                                               &check_validation_request_pending,
9577                                               queue);
9578   /* look for traffic for this queue */
9579   schedule_transmit_on_queue (queue, GNUNET_SCHEDULER_PRIORITY_DEFAULT);
9580   /* might be our first queue, try launching DV learning */
9581   if (NULL == dvlearn_task)
9582     dvlearn_task = GNUNET_SCHEDULER_add_now (&start_dv_learn, NULL);
9583   GNUNET_SERVICE_client_continue (tc->client);
9584 }
9585
9586
9587 /**
9588  * Communicator tells us that our request to create a queue "worked", that
9589  * is setting up the queue is now in process.
9590  *
9591  * @param cls the `struct TransportClient`
9592  * @param cqr confirmation message
9593  */
9594 static void
9595 handle_queue_create_ok (void *cls,
9596                         const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
9597 {
9598   struct TransportClient *tc = cls;
9599
9600   if (CT_COMMUNICATOR != tc->type)
9601   {
9602     GNUNET_break (0);
9603     GNUNET_SERVICE_client_drop (tc->client);
9604     return;
9605   }
9606   GNUNET_STATISTICS_update (GST_stats,
9607                             "# Suggestions succeeded at communicator",
9608                             1,
9609                             GNUNET_NO);
9610   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9611               "Request #%u for communicator to create queue succeeded\n",
9612               (unsigned int) ntohs (cqr->request_id));
9613   GNUNET_SERVICE_client_continue (tc->client);
9614 }
9615
9616
9617 /**
9618  * Communicator tells us that our request to create a queue failed. This
9619  * usually indicates that the provided address is simply invalid or that the
9620  * communicator's resources are exhausted.
9621  *
9622  * @param cls the `struct TransportClient`
9623  * @param cqr failure message
9624  */
9625 static void
9626 handle_queue_create_fail (
9627   void *cls,
9628   const struct GNUNET_TRANSPORT_CreateQueueResponse *cqr)
9629 {
9630   struct TransportClient *tc = cls;
9631
9632   if (CT_COMMUNICATOR != tc->type)
9633   {
9634     GNUNET_break (0);
9635     GNUNET_SERVICE_client_drop (tc->client);
9636     return;
9637   }
9638   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9639               "Request #%u for communicator to create queue failed\n",
9640               (unsigned int) ntohs (cqr->request_id));
9641   GNUNET_STATISTICS_update (GST_stats,
9642                             "# Suggestions failed in queue creation at communicator",
9643                             1,
9644                             GNUNET_NO);
9645   GNUNET_SERVICE_client_continue (tc->client);
9646 }
9647
9648
9649 /**
9650  * We have received a `struct ExpressPreferenceMessage` from an application
9651  * client.
9652  *
9653  * @param cls handle to the client
9654  * @param msg the start message
9655  */
9656 static void
9657 handle_suggest_cancel (void *cls, const struct ExpressPreferenceMessage *msg)
9658 {
9659   struct TransportClient *tc = cls;
9660   struct PeerRequest *pr;
9661
9662   if (CT_APPLICATION != tc->type)
9663   {
9664     GNUNET_break (0);
9665     GNUNET_SERVICE_client_drop (tc->client);
9666     return;
9667   }
9668   pr = GNUNET_CONTAINER_multipeermap_get (tc->details.application.requests,
9669                                           &msg->peer);
9670   if (NULL == pr)
9671   {
9672     GNUNET_break (0);
9673     GNUNET_SERVICE_client_drop (tc->client);
9674     return;
9675   }
9676   (void) stop_peer_request (tc, &pr->pid, pr);
9677   GNUNET_SERVICE_client_continue (tc->client);
9678 }
9679
9680
9681 /**
9682  * Function called by PEERSTORE for each matching record.
9683  *
9684  * @param cls closure, a `struct PeerRequest`
9685  * @param record peerstore record information
9686  * @param emsg error message, or NULL if no errors
9687  */
9688 static void
9689 handle_hello_for_client (void *cls,
9690                          const struct GNUNET_PEERSTORE_Record *record,
9691                          const char *emsg)
9692 {
9693   struct PeerRequest *pr = cls;
9694   const char *val;
9695
9696   if (NULL != emsg)
9697   {
9698     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
9699                 "Got failure from PEERSTORE: %s\n",
9700                 emsg);
9701     return;
9702   }
9703   val = record->value;
9704   if ((0 == record->value_size) || ('\0' != val[record->value_size - 1]))
9705   {
9706     GNUNET_break (0);
9707     return;
9708   }
9709   start_address_validation (&pr->pid, (const char *) record->value);
9710 }
9711
9712
9713 /**
9714  * We have received a `struct ExpressPreferenceMessage` from an application
9715  * client.
9716  *
9717  * @param cls handle to the client
9718  * @param msg the start message
9719  */
9720 static void
9721 handle_suggest (void *cls, const struct ExpressPreferenceMessage *msg)
9722 {
9723   struct TransportClient *tc = cls;
9724   struct PeerRequest *pr;
9725
9726   if (CT_NONE == tc->type)
9727   {
9728     tc->type = CT_APPLICATION;
9729     tc->details.application.requests =
9730       GNUNET_CONTAINER_multipeermap_create (16, GNUNET_YES);
9731   }
9732   if (CT_APPLICATION != tc->type)
9733   {
9734     GNUNET_break (0);
9735     GNUNET_SERVICE_client_drop (tc->client);
9736     return;
9737   }
9738   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
9739               "Client suggested we talk to %s with preference %d at rate %u\n",
9740               GNUNET_i2s (&msg->peer),
9741               (int) ntohl (msg->pk),
9742               (int) ntohl (msg->bw.value__));
9743   pr = GNUNET_new (struct PeerRequest);
9744   pr->tc = tc;
9745   pr->pid = msg->peer;
9746   pr->bw = msg->bw;
9747   pr->pk = (enum GNUNET_MQ_PriorityPreferences) ntohl (msg->pk);
9748   if (GNUNET_YES != GNUNET_CONTAINER_multipeermap_put (
9749         tc->details.application.requests,
9750         &pr->pid,
9751         pr,
9752         GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
9753   {
9754     GNUNET_break (0);
9755     GNUNET_free (pr);
9756     GNUNET_SERVICE_client_drop (tc->client);
9757     return;
9758   }
9759   pr->wc = GNUNET_PEERSTORE_watch (peerstore,
9760                                    "transport",
9761                                    &pr->pid,
9762                                    GNUNET_PEERSTORE_TRANSPORT_URLADDRESS_KEY,
9763                                    &handle_hello_for_client,
9764                                    pr);
9765   GNUNET_SERVICE_client_continue (tc->client);
9766 }
9767
9768
9769 /**
9770  * Check #GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_HELLO_VALIDATION
9771  * messages.
9772  *
9773  * @param cls a `struct TransportClient *`
9774  * @param m message to verify
9775  * @return #GNUNET_OK on success
9776  */
9777 static int
9778 check_request_hello_validation (void *cls,
9779                                 const struct RequestHelloValidationMessage *m)
9780 {
9781   (void) cls;
9782   GNUNET_MQ_check_zero_termination (m);
9783   return GNUNET_OK;
9784 }
9785
9786
9787 /**
9788  * A client encountered an address of another peer. Consider validating it,
9789  * and if validation succeeds, persist it to PEERSTORE.
9790  *
9791  * @param cls a `struct TransportClient *`
9792  * @param m message to verify
9793  */
9794 static void
9795 handle_request_hello_validation (void *cls,
9796                                  const struct RequestHelloValidationMessage *m)
9797 {
9798   struct TransportClient *tc = cls;
9799
9800   start_address_validation (&m->peer, (const char *) &m[1]);
9801   GNUNET_SERVICE_client_continue (tc->client);
9802 }
9803
9804
9805 /**
9806  * Free neighbour entry.
9807  *
9808  * @param cls NULL
9809  * @param pid unused
9810  * @param value a `struct Neighbour`
9811  * @return #GNUNET_OK (always)
9812  */
9813 static int
9814 free_neighbour_cb (void *cls,
9815                    const struct GNUNET_PeerIdentity *pid,
9816                    void *value)
9817 {
9818   struct Neighbour *neighbour = value;
9819
9820   (void) cls;
9821   (void) pid;
9822   GNUNET_break (0);  // should this ever happen?
9823   free_neighbour (neighbour);
9824
9825   return GNUNET_OK;
9826 }
9827
9828
9829 /**
9830  * Free DV route entry.
9831  *
9832  * @param cls NULL
9833  * @param pid unused
9834  * @param value a `struct DistanceVector`
9835  * @return #GNUNET_OK (always)
9836  */
9837 static int
9838 free_dv_routes_cb (void *cls,
9839                    const struct GNUNET_PeerIdentity *pid,
9840                    void *value)
9841 {
9842   struct DistanceVector *dv = value;
9843
9844   (void) cls;
9845   (void) pid;
9846   free_dv_route (dv);
9847
9848   return GNUNET_OK;
9849 }
9850
9851
9852 /**
9853  * Free validation state.
9854  *
9855  * @param cls NULL
9856  * @param pid unused
9857  * @param value a `struct ValidationState`
9858  * @return #GNUNET_OK (always)
9859  */
9860 static int
9861 free_validation_state_cb (void *cls,
9862                           const struct GNUNET_PeerIdentity *pid,
9863                           void *value)
9864 {
9865   struct ValidationState *vs = value;
9866
9867   (void) cls;
9868   (void) pid;
9869   free_validation_state (vs);
9870   return GNUNET_OK;
9871 }
9872
9873
9874 /**
9875  * Free pending acknowledgement.
9876  *
9877  * @param cls NULL
9878  * @param key unused
9879  * @param value a `struct PendingAcknowledgement`
9880  * @return #GNUNET_OK (always)
9881  */
9882 static int
9883 free_pending_ack_cb (void *cls, const struct GNUNET_Uuid *key, void *value)
9884 {
9885   struct PendingAcknowledgement *pa = value;
9886
9887   (void) cls;
9888   (void) key;
9889   free_pending_acknowledgement (pa);
9890   return GNUNET_OK;
9891 }
9892
9893
9894 /**
9895  * Free acknowledgement cummulator.
9896  *
9897  * @param cls NULL
9898  * @param pid unused
9899  * @param value a `struct AcknowledgementCummulator`
9900  * @return #GNUNET_OK (always)
9901  */
9902 static int
9903 free_ack_cummulator_cb (void *cls,
9904                         const struct GNUNET_PeerIdentity *pid,
9905                         void *value)
9906 {
9907   struct AcknowledgementCummulator *ac = value;
9908
9909   (void) cls;
9910   (void) pid;
9911   GNUNET_free (ac);
9912   return GNUNET_OK;
9913 }
9914
9915
9916 /**
9917  * Function called when the service shuts down.  Unloads our plugins
9918  * and cancels pending validations.
9919  *
9920  * @param cls closure, unused
9921  */
9922 static void
9923 do_shutdown (void *cls)
9924 {
9925   struct LearnLaunchEntry *lle;
9926
9927   (void) cls;
9928
9929   GNUNET_CONTAINER_multipeermap_iterate (neighbours, &free_neighbour_cb, NULL);
9930   if (NULL != peerstore)
9931   {
9932     GNUNET_PEERSTORE_disconnect (peerstore, GNUNET_NO);
9933     peerstore = NULL;
9934   }
9935   if (NULL != GST_stats)
9936   {
9937     GNUNET_STATISTICS_destroy (GST_stats, GNUNET_NO);
9938     GST_stats = NULL;
9939   }
9940   if (NULL != GST_my_private_key)
9941   {
9942     GNUNET_free (GST_my_private_key);
9943     GST_my_private_key = NULL;
9944   }
9945   GNUNET_CONTAINER_multipeermap_iterate (ack_cummulators,
9946                                          &free_ack_cummulator_cb,
9947                                          NULL);
9948   GNUNET_CONTAINER_multipeermap_destroy (ack_cummulators);
9949   ack_cummulators = NULL;
9950   GNUNET_CONTAINER_multiuuidmap_iterate (pending_acks,
9951                                          &free_pending_ack_cb,
9952                                          NULL);
9953   GNUNET_CONTAINER_multiuuidmap_destroy (pending_acks);
9954   pending_acks = NULL;
9955   GNUNET_break (0 == GNUNET_CONTAINER_multipeermap_size (neighbours));
9956   GNUNET_CONTAINER_multipeermap_destroy (neighbours);
9957   neighbours = NULL;
9958   GNUNET_break (0 == GNUNET_CONTAINER_multipeermap_size (links));
9959   GNUNET_CONTAINER_multipeermap_destroy (links);
9960   links = NULL;
9961   GNUNET_CONTAINER_multipeermap_iterate (backtalkers,
9962                                          &free_backtalker_cb,
9963                                          NULL);
9964   GNUNET_CONTAINER_multipeermap_destroy (backtalkers);
9965   backtalkers = NULL;
9966   GNUNET_CONTAINER_multipeermap_iterate (validation_map,
9967                                          &free_validation_state_cb,
9968                                          NULL);
9969   GNUNET_CONTAINER_multipeermap_destroy (validation_map);
9970   validation_map = NULL;
9971   while (NULL != ir_head)
9972     free_incoming_request (ir_head);
9973   GNUNET_assert (0 == ir_total);
9974   while (NULL != (lle = lle_head))
9975   {
9976     GNUNET_CONTAINER_DLL_remove (lle_head, lle_tail, lle);
9977     GNUNET_free (lle);
9978   }
9979   GNUNET_CONTAINER_multishortmap_destroy (dvlearn_map);
9980   dvlearn_map = NULL;
9981   GNUNET_CONTAINER_heap_destroy (validation_heap);
9982   validation_heap = NULL;
9983   GNUNET_CONTAINER_multipeermap_iterate (dv_routes, &free_dv_routes_cb, NULL);
9984   GNUNET_CONTAINER_multipeermap_destroy (dv_routes);
9985   dv_routes = NULL;
9986 }
9987
9988
9989 /**
9990  * Initiate transport service.
9991  *
9992  * @param cls closure
9993  * @param c configuration to use
9994  * @param service the initialized service
9995  */
9996 static void
9997 run (void *cls,
9998      const struct GNUNET_CONFIGURATION_Handle *c,
9999      struct GNUNET_SERVICE_Handle *service)
10000 {
10001   (void) cls;
10002   (void) service;
10003   /* setup globals */
10004   hello_mono_time = GNUNET_TIME_absolute_get_monotonic (c);
10005   GST_cfg = c;
10006   backtalkers = GNUNET_CONTAINER_multipeermap_create (16, GNUNET_YES);
10007   pending_acks = GNUNET_CONTAINER_multiuuidmap_create (32768, GNUNET_YES);
10008   ack_cummulators = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_YES);
10009   neighbours = GNUNET_CONTAINER_multipeermap_create (1024, GNUNET_YES);
10010   links = GNUNET_CONTAINER_multipeermap_create (512, GNUNET_YES);
10011   dv_routes = GNUNET_CONTAINER_multipeermap_create (1024, GNUNET_YES);
10012   dvlearn_map = GNUNET_CONTAINER_multishortmap_create (2 * MAX_DV_LEARN_PENDING,
10013                                                        GNUNET_YES);
10014   validation_map = GNUNET_CONTAINER_multipeermap_create (1024, GNUNET_YES);
10015   validation_heap =
10016     GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
10017   GST_my_private_key =
10018     GNUNET_CRYPTO_eddsa_key_create_from_configuration (GST_cfg);
10019   if (NULL == GST_my_private_key)
10020   {
10021     GNUNET_log (
10022       GNUNET_ERROR_TYPE_ERROR,
10023       _ (
10024         "Transport service is lacking key configuration settings. Exiting.\n"));
10025     GNUNET_SCHEDULER_shutdown ();
10026     return;
10027   }
10028   GNUNET_CRYPTO_eddsa_key_get_public (GST_my_private_key,
10029                                       &GST_my_identity.public_key);
10030   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
10031               "My identity is `%s'\n",
10032               GNUNET_i2s_full (&GST_my_identity));
10033   GST_stats = GNUNET_STATISTICS_create ("transport", GST_cfg);
10034   GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
10035   peerstore = GNUNET_PEERSTORE_connect (GST_cfg);
10036   if (NULL == peerstore)
10037   {
10038     GNUNET_break (0);
10039     GNUNET_SCHEDULER_shutdown ();
10040     return;
10041   }
10042 }
10043
10044
10045 /**
10046  * Define "main" method using service macro.
10047  */
10048 GNUNET_SERVICE_MAIN (
10049   "transport",
10050   GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN,
10051   &run,
10052   &client_connect_cb,
10053   &client_disconnect_cb,
10054   NULL,
10055   /* communication with applications */
10056   GNUNET_MQ_hd_fixed_size (suggest,
10057                            GNUNET_MESSAGE_TYPE_TRANSPORT_SUGGEST,
10058                            struct ExpressPreferenceMessage,
10059                            NULL),
10060   GNUNET_MQ_hd_fixed_size (suggest_cancel,
10061                            GNUNET_MESSAGE_TYPE_TRANSPORT_SUGGEST_CANCEL,
10062                            struct ExpressPreferenceMessage,
10063                            NULL),
10064   GNUNET_MQ_hd_var_size (request_hello_validation,
10065                          GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_HELLO_VALIDATION,
10066                          struct RequestHelloValidationMessage,
10067                          NULL),
10068   /* communication with core */
10069   GNUNET_MQ_hd_fixed_size (client_start,
10070                            GNUNET_MESSAGE_TYPE_TRANSPORT_START,
10071                            struct StartMessage,
10072                            NULL),
10073   GNUNET_MQ_hd_var_size (client_send,
10074                          GNUNET_MESSAGE_TYPE_TRANSPORT_SEND,
10075                          struct OutboundMessage,
10076                          NULL),
10077   GNUNET_MQ_hd_fixed_size (client_recv_ok,
10078                            GNUNET_MESSAGE_TYPE_TRANSPORT_RECV_OK,
10079                            struct RecvOkMessage,
10080                            NULL),
10081   /* communication with communicators */
10082   GNUNET_MQ_hd_var_size (communicator_available,
10083                          GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR,
10084                          struct GNUNET_TRANSPORT_CommunicatorAvailableMessage,
10085                          NULL),
10086   GNUNET_MQ_hd_var_size (communicator_backchannel,
10087                          GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL,
10088                          struct GNUNET_TRANSPORT_CommunicatorBackchannel,
10089                          NULL),
10090   GNUNET_MQ_hd_var_size (add_address,
10091                          GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS,
10092                          struct GNUNET_TRANSPORT_AddAddressMessage,
10093                          NULL),
10094   GNUNET_MQ_hd_fixed_size (del_address,
10095                            GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS,
10096                            struct GNUNET_TRANSPORT_DelAddressMessage,
10097                            NULL),
10098   GNUNET_MQ_hd_var_size (incoming_msg,
10099                          GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG,
10100                          struct GNUNET_TRANSPORT_IncomingMessage,
10101                          NULL),
10102   GNUNET_MQ_hd_fixed_size (queue_create_ok,
10103                            GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_OK,
10104                            struct GNUNET_TRANSPORT_CreateQueueResponse,
10105                            NULL),
10106   GNUNET_MQ_hd_fixed_size (queue_create_fail,
10107                            GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_FAIL,
10108                            struct GNUNET_TRANSPORT_CreateQueueResponse,
10109                            NULL),
10110   GNUNET_MQ_hd_var_size (add_queue_message,
10111                          GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP,
10112                          struct GNUNET_TRANSPORT_AddQueueMessage,
10113                          NULL),
10114   GNUNET_MQ_hd_fixed_size (del_queue_message,
10115                            GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN,
10116                            struct GNUNET_TRANSPORT_DelQueueMessage,
10117                            NULL),
10118   GNUNET_MQ_hd_fixed_size (send_message_ack,
10119                            GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK,
10120                            struct GNUNET_TRANSPORT_SendMessageToAck,
10121                            NULL),
10122   /* communication with monitors */
10123   GNUNET_MQ_hd_fixed_size (monitor_start,
10124                            GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_START,
10125                            struct GNUNET_TRANSPORT_MonitorStart,
10126                            NULL),
10127   GNUNET_MQ_handler_end ());
10128
10129
10130 /* end of file gnunet-service-transport.c */