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