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