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