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