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