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