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