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