GNUnet  0.11.x
gnunet-service-tng.c
Go to the documentation of this file.
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  */
75 #include "platform.h"
76 #include "gnunet_util_lib.h"
80 #include "gnunet_hello_lib.h"
81 #include "gnunet_signatures.h"
82 #include "transport.h"
83 
88 #define MAX_CUMMULATIVE_ACKS 64
89 
102 #define FC_NO_CHANGE_REPLY_PROBABILITY 8
103 
108 #define IN_PACKET_SIZE_WITHOUT_MTU 128
109 
114 #define GOODPUT_AGING_SLOTS 4
115 
120 #define DEFAULT_WINDOW_SIZE (128 * 1024)
121 
130 #define MAX_INCOMING_REQUEST 16
131 
136 #define MAX_DV_DISCOVERY_SELECTION 16
137 
146 #define RECV_WINDOW_SIZE 4
147 
155 #define MIN_DV_PATH_LENGTH_FOR_INITIATOR 3
156 
160 #define MAX_DV_HOPS_ALLOWED 16
161 
166 #define MAX_DV_LEARN_PENDING 64
167 
171 #define MAX_DV_PATHS_TO_TARGET 3
172 
178 #define DELAY_WARN_THRESHOLD \
179  GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
180 
185 #define DV_FORWARD_TIMEOUT \
186  GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
187 
193 #define DV_QUALITY_RTT_THRESHOLD \
194  GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
195 
200 #define DV_PATH_VALIDITY_TIMEOUT \
201  GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
202 
207 #define BACKCHANNEL_INACTIVITY_TIMEOUT \
208  GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
209 
214 #define DV_PATH_DISCOVERY_FREQUENCY \
215  GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 4)
216 
220 #define EPHEMERAL_VALIDITY \
221  GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
222 
226 #define REASSEMBLY_EXPIRATION \
227  GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 4)
228 
233 #define FAST_VALIDATION_CHALLENGE_FREQ \
234  GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 1)
235 
239 #define MAX_VALIDATION_CHALLENGE_FREQ \
240  GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_DAYS, 1)
241 
247 #define ACK_CUMMULATOR_TIMEOUT \
248  GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
249 
254 #define DV_LEARN_BASE_FREQUENCY GNUNET_TIME_UNIT_MINUTES
255 
260 #define DV_LEARN_QUALITY_THRESHOLD 100
261 
265 #define MAX_ADDRESS_VALID_UNTIL \
266  GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MONTHS, 1)
267 
271 #define ADDRESS_VALIDATION_LIFETIME \
272  GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
273 
280 #define MIN_DELAY_ADDRESS_VALIDATION GNUNET_TIME_UNIT_MILLISECONDS
281 
288 #define VALIDATION_RTT_BUFFER_FACTOR 3
289 
296 #define COMMUNICATOR_TOTAL_QUEUE_LIMIT 512
297 
303 #define QUEUE_LENGTH_LIMIT 32
304 
305 
307 
312 {
317  uint64_t uuid GNUNET_PACKED;
318 };
319 
320 
325 {
330 };
331 
332 
337 {
341  struct GNUNET_ShortHashCode value;
342 };
343 
344 
349 {
353  struct GNUNET_MessageHeader header;
354 
355  /* Followed by *another* message header which is the message to
356  the communicator */
357 
358  /* Followed by a 0-terminated name of the communicator */
359 };
360 
361 
366 {
371 
386  struct GNUNET_TIME_AbsoluteNBO sender_monotonic_time;
387 
391  struct GNUNET_PeerIdentity target;
392 
397  struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
398 };
399 
400 
406 {
410  struct GNUNET_PeerIdentity sender;
411 
416  struct GNUNET_CRYPTO_EddsaSignature sender_sig;
417 
428  struct GNUNET_TIME_AbsoluteNBO monotonic_time;
429 
430  /* Followed by a `struct GNUNET_MessageHeader` with a message
431  for the target peer */
432 };
433 
434 
440 {
444  struct GNUNET_MessageHeader header;
445 
452  uint32_t ack_countdown GNUNET_PACKED;
453 
459  struct AcknowledgementUUIDP ack_uuid;
460 };
461 
462 
467 {
474  struct GNUNET_TIME_RelativeNBO ack_delay;
475 
479  struct AcknowledgementUUIDP ack_uuid;
480 };
481 
482 
491 {
495  struct GNUNET_MessageHeader header;
496 
501  uint32_t ack_counter GNUNET_PACKED;
502 
503  /* followed by any number of `struct TransportCummulativeAckPayloadP`
504  messages providing ACKs */
505 };
506 
507 
512 {
516  struct GNUNET_MessageHeader header;
517 
521  uint16_t frag_off GNUNET_PACKED;
522 
526  uint16_t msg_size GNUNET_PACKED;
527 
535  struct AcknowledgementUUIDP ack_uuid;
536 
541  struct MessageUUIDP msg_uuid;
542 };
543 
544 
562 struct DvInitPS
563 {
568 
581  struct GNUNET_TIME_AbsoluteNBO monotonic_time;
582 
586  struct ChallengeNonceP challenge;
587 };
588 
589 
606 struct DvHopPS
607 {
612 
616  struct GNUNET_PeerIdentity pred;
617 
621  struct GNUNET_PeerIdentity succ;
622 
626  struct ChallengeNonceP challenge;
627 };
628 
629 
635 {
640 
646 };
647 
648 
663 {
667  struct GNUNET_MessageHeader header;
668 
673  uint16_t num_hops GNUNET_PACKED;
674 
683  uint16_t bidirectional GNUNET_PACKED;
684 
690  struct GNUNET_TIME_RelativeNBO non_network_delay;
691 
704  struct GNUNET_TIME_AbsoluteNBO monotonic_time;
705 
711 
715  struct GNUNET_PeerIdentity initiator;
716 
720  struct ChallengeNonceP challenge;
721 
722  /* Followed by @e num_hops `struct DVPathEntryP` values,
723  excluding the initiator of the DV trace; the last entry is the
724  current sender; the current peer must not be included. */
725 };
726 
727 
751 {
755  struct GNUNET_MessageHeader header;
756 
763  uint16_t total_hops GNUNET_PACKED;
764 
770  uint16_t num_hops GNUNET_PACKED;
771 
776  struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
777 
784 
790  struct GNUNET_HashCode hmac;
791 
792  /* Followed by @e num_hops `struct GNUNET_PeerIdentity` values;
793  excluding the @e origin and the current peer, the last must be
794  the ultimate target; if @e num_hops is zero, the receiver of this
795  message is the ultimate target. */
796 
797  /* Followed by encrypted, variable-size payload, which
798  must begin with a `struct TransportDVBoxPayloadP` */
799 
800  /* Followed by the actual message, which itself must not be a
801  a DV_LEARN or DV_BOX message! */
802 };
803 
804 
810 {
814  struct GNUNET_MessageHeader header;
815 
820 
824  struct ChallengeNonceP challenge;
825 
830  struct GNUNET_TIME_AbsoluteNBO sender_time;
831 };
832 
833 
839 {
844 
849  struct GNUNET_TIME_RelativeNBO validity_duration;
850 
854  struct ChallengeNonceP challenge;
855 };
856 
857 
863 {
867  struct GNUNET_MessageHeader header;
868 
873 
879 
883  struct ChallengeNonceP challenge;
884 
889  struct GNUNET_TIME_AbsoluteNBO origin_time;
890 
895  struct GNUNET_TIME_RelativeNBO validity_duration;
896 };
897 
898 
908 {
912  struct GNUNET_MessageHeader header;
913 
921  uint32_t seq GNUNET_PACKED;
922 
927  uint64_t inbound_window_size GNUNET_PACKED;
928 
934  uint64_t outbound_sent GNUNET_PACKED;
935 
944  uint64_t outbound_window_size GNUNET_PACKED;
945 
954  struct GNUNET_TIME_AbsoluteNBO sender_time;
955 };
956 
957 
959 
960 
965 {
969  CT_NONE = 0,
970 
974  CT_CORE = 1,
975 
980 
985 
990 };
991 
992 
998 {
1003 
1008 
1013 
1018 
1025 };
1026 
1027 
1032 {
1037 
1042 
1046  struct ChallengeNonceP challenge;
1047 
1052  struct GNUNET_TIME_Absolute launch_time;
1053 };
1054 
1055 
1061 {
1065  uint64_t bytes_sent;
1066 
1071  uint64_t bytes_received;
1072 };
1073 
1074 
1079 {
1083  struct GNUNET_TIME_Relative aged_rtt;
1084 
1090 
1095  unsigned int last_age;
1096 };
1097 
1098 
1102 struct TransportClient;
1103 
1107 struct Neighbour;
1108 
1113 struct DistanceVector;
1114 
1119 struct Queue;
1120 
1124 struct PendingMessage;
1125 
1129 struct DistanceVectorHop;
1130 
1139 struct VirtualLink;
1140 
1141 
1147 {
1153 
1159 
1164 
1168  struct GNUNET_TRANSPORT_IncomingMessage im;
1169 
1174  uint16_t total_hops;
1175 };
1176 
1177 
1182 {
1187 
1192 
1196  struct VirtualLink *vl;
1197 
1201  uint16_t size;
1202 
1209  uint16_t isize;
1210 };
1211 
1212 
1222 {
1226  struct GNUNET_PeerIdentity target;
1227 
1233 
1239 
1244 
1249 
1254 
1259 
1267 
1273 
1277  struct Neighbour *n;
1278 
1283 
1289  struct GNUNET_TIME_Absolute n_challenge_time;
1290 
1296  struct GNUNET_TIME_Absolute last_fc_transmission;
1297 
1305  struct GNUNET_TIME_Absolute last_fc_timestamp;
1306 
1311  struct GNUNET_TIME_Relative last_fc_rtt;
1312 
1318 
1327 
1335 
1342 
1351 
1364 
1370 
1377 
1388 
1393  uint32_t fc_seq_gen;
1394 
1400  uint32_t last_fc_seq;
1401 
1414 };
1415 
1416 
1421 {
1427 
1433 
1440 
1447 
1454 
1461 
1468 
1475 
1479  struct AcknowledgementUUIDP ack_uuid;
1480 
1486 
1492 
1497  struct Queue *queue;
1498 
1502  struct GNUNET_TIME_Absolute transmission_time;
1503 
1507  uint16_t message_size;
1508 };
1509 
1510 
1515 {
1520 
1525 
1530 
1535 
1540 
1545 
1550 
1555 
1561  const struct GNUNET_PeerIdentity *path;
1562 
1568 
1576  struct GNUNET_TIME_Absolute path_valid_until;
1577 
1581  struct PerformanceData pd;
1582 
1588  unsigned int distance;
1589 };
1590 
1591 
1597 {
1601  struct GNUNET_PeerIdentity target;
1602 
1607 
1612 
1617 
1622  struct VirtualLink *vl;
1623 
1628  struct GNUNET_CRYPTO_EddsaSignature sender_sig;
1629 
1633  struct GNUNET_TIME_Absolute ephemeral_validity;
1634 
1638  struct GNUNET_TIME_Absolute monotime;
1639 
1643  struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
1644 
1648  struct GNUNET_CRYPTO_EcdhePrivateKey private_key;
1649 };
1650 
1651 
1661 struct QueueEntry
1662 {
1666  struct QueueEntry *next;
1667 
1671  struct QueueEntry *prev;
1672 
1676  struct Queue *queue;
1677 
1682 
1686  uint64_t mid;
1687 };
1688 
1689 
1694 struct Queue
1695 {
1700 
1705 
1710 
1715 
1720 
1725 
1730 
1735 
1740 
1745 
1749  const char *address;
1750 
1756 
1764  struct GNUNET_TIME_Absolute validated_until;
1765 
1769  struct PerformanceData pd;
1770 
1775  uint64_t mid_gen;
1776 
1780  uint32_t qid;
1781 
1785  uint32_t mtu;
1786 
1791 
1796 
1800  unsigned int queue_length;
1801 
1805  enum GNUNET_NetworkType nt;
1806 
1811 
1816  int idle;
1817 };
1818 
1819 
1824 {
1829  struct MessageUUIDP msg_uuid;
1830 
1835 
1840 
1848  uint8_t *bitfield;
1849 
1853  struct GNUNET_TIME_Absolute reassembly_timeout;
1854 
1859  struct GNUNET_TIME_Absolute last_frag;
1860 
1864  uint16_t msg_size;
1865 
1870  uint16_t msg_missing;
1871 
1872  /* Followed by @e msg_size bytes of the (partially) defragmented original
1873  * message */
1874 
1875  /* Followed by @e bitfield data */
1876 };
1877 
1878 
1882 struct Neighbour
1883 {
1888 
1895 
1902 
1907 
1913 
1919 
1924 
1929 
1935 
1941 
1946  struct VirtualLink *vl;
1947 
1952  struct GNUNET_TIME_Absolute last_dv_learn_monotime;
1953 
1959 };
1960 
1961 
1967 {
1972 
1977 
1982 
1987 };
1988 
1989 
1993 struct PeerRequest
1994 {
1999 
2004 
2009 
2016 
2021 };
2022 
2023 
2028 {
2033 
2038 
2043 
2048 };
2049 
2050 
2077 struct PendingMessage
2078 {
2083 
2088 
2093 
2098 
2104 
2110 
2115 
2120 
2126 
2130  struct VirtualLink *vl;
2131 
2140  struct QueueEntry *qe;
2141 
2146 
2151 
2156 
2161 
2166 
2170  struct GNUNET_TIME_Absolute next_attempt;
2171 
2176  struct MessageUUIDP msg_uuid;
2177 
2182  unsigned long long logging_uuid;
2183 
2188 
2194 
2198  uint16_t bytes_msg;
2199 
2203  uint16_t frag_off;
2204 
2208  int16_t msg_uuid_set;
2209 
2210  /* Followed by @e bytes_msg to transmit */
2211 };
2212 
2213 
2218 {
2223  struct GNUNET_TIME_Absolute receive_time;
2224 
2228  struct AcknowledgementUUIDP ack_uuid;
2229 };
2230 
2231 
2237 {
2241  struct GNUNET_PeerIdentity target;
2242 
2247 
2254 
2258  struct GNUNET_TIME_Absolute min_transmission_time;
2259 
2265  uint32_t ack_counter;
2266 
2270  unsigned int num_acks;
2271 };
2272 
2273 
2278 {
2283 
2288 
2293 
2297  const char *address;
2298 
2303 
2308 
2314 
2318  uint32_t aid;
2319 
2324 };
2325 
2326 
2331 {
2336 
2341 
2346 
2351 
2356 
2357  union
2358  {
2362  struct
2363  {
2369 
2374  } core;
2375 
2379  struct
2380  {
2387 
2392  } monitor;
2393 
2394 
2398  struct
2399  {
2405 
2410 
2415 
2421 
2427 
2433  unsigned int total_queue_length;
2434 
2439  } communicator;
2440 
2444  struct
2445  {
2451  } application;
2452  } details;
2453 };
2454 
2455 
2461 {
2467 
2474  struct GNUNET_TIME_Absolute valid_until;
2475 
2480  struct GNUNET_TIME_Absolute validated_until;
2481 
2488  struct GNUNET_TIME_Absolute first_challenge_use;
2489 
2496  struct GNUNET_TIME_Absolute last_challenge_use;
2497 
2505  struct GNUNET_TIME_Absolute next_challenge;
2506 
2515  struct GNUNET_TIME_Relative challenge_backoff;
2516 
2521  struct GNUNET_TIME_Relative validation_rtt;
2522 
2530  struct ChallengeNonceP challenge;
2531 
2535  char *address;
2536 
2542  struct GNUNET_CONTAINER_HeapNode *hn;
2543 
2549 
2555  uint32_t last_window_consum_limit;
2556 
2561  int awaiting_queue;
2562 };
2563 
2564 
2572 {
2577 
2581  struct GNUNET_TIME_Absolute monotonic_time;
2582 
2587 
2591  struct GNUNET_CRYPTO_EcdhePublicKey last_ephemeral;
2592 
2598 
2603 
2609 
2615 
2620  size_t body_size;
2621 };
2622 
2623 
2628 
2633 
2638 
2643 
2648 
2653 
2659 
2665 
2671 
2677 
2683 
2689 
2695 
2700 
2705 
2710 
2717 
2722 
2727 
2732 
2738 
2744 
2750 static struct IncomingRequest *ir_head;
2751 
2755 static struct IncomingRequest *ir_tail;
2756 
2760 static unsigned int ir_total;
2761 
2765 static unsigned long long logging_uuid_gen;
2766 
2771 static unsigned int pa_count;
2772 
2782 
2783 
2794 static unsigned int
2796 {
2797  struct GNUNET_TIME_Absolute now;
2798 
2799  now = GNUNET_TIME_absolute_get ();
2800  return now.abs_value_us / GNUNET_TIME_UNIT_MINUTES.rel_value_us / 15;
2801 }
2802 
2803 
2809 static void
2811 {
2812  GNUNET_CONTAINER_DLL_remove (ir_head, ir_tail, ir);
2813  GNUNET_assert (ir_total > 0);
2814  ir_total--;
2816  GNUNET_free (ir);
2817 }
2818 
2819 
2825 static void
2827 {
2828  struct Queue *q = pa->queue;
2829  struct PendingMessage *pm = pa->pm;
2830  struct DistanceVectorHop *dvh = pa->dvh;
2831 
2832  GNUNET_CONTAINER_MDLL_remove (pa, pa_head, pa_tail, pa);
2833  pa_count--;
2834  if (NULL != q)
2835  {
2837  pa->queue = NULL;
2838  }
2839  if (NULL != pm)
2840  {
2841  GNUNET_CONTAINER_MDLL_remove (pm, pm->pa_head, pm->pa_tail, pa);
2842  pa->pm = NULL;
2843  }
2844  if (NULL != dvh)
2845  {
2846  GNUNET_CONTAINER_MDLL_remove (dvh, dvh->pa_head, dvh->pa_tail, pa);
2847  pa->queue = NULL;
2848  }
2851  &pa->ack_uuid.value,
2852  pa));
2853  GNUNET_free (pa);
2854 }
2855 
2856 
2865 static void
2867 {
2868  struct PendingMessage *frag;
2869 
2870  while (NULL != (frag = root->head_frag))
2871  {
2872  struct PendingAcknowledgement *pa;
2873 
2874  free_fragment_tree (frag);
2875  while (NULL != (pa = frag->pa_head))
2876  {
2877  GNUNET_CONTAINER_MDLL_remove (pm, frag->pa_head, frag->pa_tail, pa);
2878  pa->pm = NULL;
2879  }
2880  GNUNET_CONTAINER_MDLL_remove (frag, root->head_frag, root->tail_frag, frag);
2881  GNUNET_free (frag);
2882  }
2883 }
2884 
2885 
2893 static void
2895 {
2896  struct TransportClient *tc = pm->client;
2897  struct VirtualLink *vl = pm->vl;
2898  struct PendingAcknowledgement *pa;
2899 
2900  if (NULL != tc)
2901  {
2903  tc->details.core.pending_msg_head,
2904  tc->details.core.pending_msg_tail,
2905  pm);
2906  }
2907  if (NULL != vl)
2908  {
2910  vl->pending_msg_head,
2911  vl->pending_msg_tail,
2912  pm);
2913  }
2914  while (NULL != (pa = pm->pa_head))
2915  {
2916  GNUNET_CONTAINER_MDLL_remove (pm, pm->pa_head, pm->pa_tail, pa);
2917  pa->pm = NULL;
2918  }
2919 
2920  free_fragment_tree (pm);
2921  if (NULL != pm->qe)
2922  {
2923  GNUNET_assert (pm == pm->qe->pm);
2924  pm->qe->pm = NULL;
2925  }
2926  if (NULL != pm->bpm)
2927  {
2928  free_fragment_tree (pm->bpm);
2929  GNUNET_free (pm->bpm);
2930  }
2931  GNUNET_free (pm);
2932 }
2933 
2934 
2940 static void
2942 {
2943  struct PendingMessage *pm;
2944  struct CoreSentContext *csc;
2945 
2946  while (NULL != (pm = vl->pending_msg_head))
2947  free_pending_message (pm);
2949  GNUNET_CONTAINER_multipeermap_remove (links, &vl->target, vl));
2950  if (NULL != vl->visibility_task)
2951  {
2953  vl->visibility_task = NULL;
2954  }
2955  if (NULL != vl->fc_retransmit_task)
2956  {
2958  vl->fc_retransmit_task = NULL;
2959  }
2960  while (NULL != (csc = vl->csc_head))
2961  {
2963  GNUNET_assert (vl == csc->vl);
2964  csc->vl = NULL;
2965  }
2966  GNUNET_break (NULL == vl->n);
2967  GNUNET_break (NULL == vl->dv);
2968  GNUNET_free (vl);
2969 }
2970 
2971 
2977 static void
2979 {
2980  GNUNET_assert (
2981  GNUNET_YES ==
2982  GNUNET_CONTAINER_multipeermap_remove (validation_map, &vs->pid, vs));
2984  vs->hn = NULL;
2985  if (NULL != vs->sc)
2986  {
2988  vs->sc = NULL;
2989  }
2990  GNUNET_free (vs->address);
2991  GNUNET_free (vs);
2992 }
2993 
2994 
3001 static struct Neighbour *
3003 {
3004  return GNUNET_CONTAINER_multipeermap_get (neighbours, pid);
3005 }
3006 
3007 
3014 static struct VirtualLink *
3016 {
3017  return GNUNET_CONTAINER_multipeermap_get (links, pid);
3018 }
3019 
3020 
3025 {
3029  struct GNUNET_TIME_Absolute last_validation;
3030  struct GNUNET_TIME_Absolute valid_until;
3031  struct GNUNET_TIME_Absolute next_validation;
3032 
3037 
3042 
3047 
3052 };
3053 
3054 
3063 static void
3065 {
3066  struct Neighbour *n = dvh->next_hop;
3067  struct DistanceVector *dv = dvh->dv;
3068  struct PendingAcknowledgement *pa;
3069 
3070  while (NULL != (pa = dvh->pa_head))
3071  {
3072  GNUNET_CONTAINER_MDLL_remove (dvh, dvh->pa_head, dvh->pa_tail, pa);
3073  pa->dvh = NULL;
3074  }
3075  GNUNET_CONTAINER_MDLL_remove (neighbour, n->dv_head, n->dv_tail, dvh);
3076  GNUNET_CONTAINER_MDLL_remove (dv, dv->dv_head, dv->dv_tail, dvh);
3077  GNUNET_free (dvh);
3078 }
3079 
3080 
3087 static void
3088 check_link_down (void *cls);
3089 
3090 
3096 static void
3098 {
3100  "Informing CORE clients about disconnect from %s\n",
3101  GNUNET_i2s (pid));
3102  for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
3103  {
3104  struct GNUNET_MQ_Envelope *env;
3105  struct DisconnectInfoMessage *dim;
3106 
3107  if (CT_CORE != tc->type)
3108  continue;
3110  dim->peer = *pid;
3111  GNUNET_MQ_send (tc->mq, env);
3112  }
3113 }
3114 
3115 
3122 static void
3124 {
3125  struct DistanceVectorHop *dvh;
3126 
3127  while (NULL != (dvh = dv->dv_head))
3129  if (NULL == dv->dv_head)
3130  {
3131  struct VirtualLink *vl;
3132 
3133  GNUNET_assert (
3134  GNUNET_YES ==
3135  GNUNET_CONTAINER_multipeermap_remove (dv_routes, &dv->target, dv));
3136  if (NULL != (vl = dv->vl))
3137  {
3138  GNUNET_assert (dv == vl->dv);
3139  vl->dv = NULL;
3140  if (NULL == vl->n)
3141  {
3143  free_virtual_link (vl);
3144  }
3145  else
3146  {
3149  }
3150  dv->vl = NULL;
3151  }
3152 
3153  if (NULL != dv->timeout_task)
3154  {
3156  dv->timeout_task = NULL;
3157  }
3158  GNUNET_free (dv);
3159  }
3160 }
3161 
3162 
3176 static void
3178  const struct GNUNET_PeerIdentity *peer,
3179  const char *address,
3180  enum GNUNET_NetworkType nt,
3181  const struct MonitorEvent *me)
3182 {
3183  struct GNUNET_MQ_Envelope *env;
3184  struct GNUNET_TRANSPORT_MonitorData *md;
3185  size_t addr_len = strlen (address) + 1;
3186 
3187  env = GNUNET_MQ_msg_extra (md,
3188  addr_len,
3190  md->nt = htonl ((uint32_t) nt);
3191  md->peer = *peer;
3192  md->last_validation = GNUNET_TIME_absolute_hton (me->last_validation);
3193  md->valid_until = GNUNET_TIME_absolute_hton (me->valid_until);
3194  md->next_validation = GNUNET_TIME_absolute_hton (me->next_validation);
3195  md->rtt = GNUNET_TIME_relative_hton (me->rtt);
3196  md->cs = htonl ((uint32_t) me->cs);
3197  md->num_msg_pending = htonl (me->num_msg_pending);
3198  md->num_bytes_pending = htonl (me->num_bytes_pending);
3199  memcpy (&md[1], address, addr_len);
3200  GNUNET_MQ_send (tc->mq, env);
3201 }
3202 
3203 
3213 static void
3215  const char *address,
3216  enum GNUNET_NetworkType nt,
3217  const struct MonitorEvent *me)
3218 {
3219  for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
3220  {
3221  if (CT_MONITOR != tc->type)
3222  continue;
3223  if (tc->details.monitor.one_shot)
3224  continue;
3225  if ((0 != GNUNET_is_zero (&tc->details.monitor.peer)) &&
3226  (0 != GNUNET_memcmp (&tc->details.monitor.peer, peer)))
3227  continue;
3228  notify_monitor (tc, peer, address, nt, me);
3229  }
3230 }
3231 
3232 
3242 static void *
3244  struct GNUNET_SERVICE_Client *client,
3245  struct GNUNET_MQ_Handle *mq)
3246 {
3247  struct TransportClient *tc;
3248 
3249  (void) cls;
3250  tc = GNUNET_new (struct TransportClient);
3251  tc->client = client;
3252  tc->mq = mq;
3253  GNUNET_CONTAINER_DLL_insert (clients_head, clients_tail, tc);
3254  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", tc);
3255  return tc;
3256 }
3257 
3258 
3264 static void
3266 {
3267  struct Neighbour *n = rc->neighbour;
3268 
3272  rc->msg_uuid.uuid,
3273  rc));
3274  GNUNET_free (rc);
3275 }
3276 
3277 
3283 static void
3285 {
3286  struct Neighbour *n = cls;
3287  struct ReassemblyContext *rc;
3288 
3289  n->reassembly_timeout_task = NULL;
3290  while (NULL != (rc = GNUNET_CONTAINER_heap_peek (n->reassembly_heap)))
3291  {
3293  .rel_value_us)
3294  {
3296  continue;
3297  }
3302  n);
3303  return;
3304  }
3305 }
3306 
3307 
3316 static int
3317 free_reassembly_cb (void *cls, uint32_t key, void *value)
3318 {
3319  struct ReassemblyContext *rc = value;
3320 
3321  (void) cls;
3322  (void) key;
3324  return GNUNET_OK;
3325 }
3326 
3327 
3333 static void
3335 {
3336  struct DistanceVectorHop *dvh;
3337  struct VirtualLink *vl;
3338 
3339  GNUNET_assert (NULL == neighbour->queue_head);
3342  &neighbour->pid,
3343  neighbour));
3344  if (NULL != neighbour->reassembly_map)
3345  {
3348  NULL);
3350  neighbour->reassembly_map = NULL;
3352  neighbour->reassembly_heap = NULL;
3353  }
3354  while (NULL != (dvh = neighbour->dv_head))
3355  {
3356  struct DistanceVector *dv = dvh->dv;
3357 
3359  if (NULL == dv->dv_head)
3360  free_dv_route (dv);
3361  }
3362  if (NULL != neighbour->reassembly_timeout_task)
3363  {
3365  neighbour->reassembly_timeout_task = NULL;
3366  }
3367  if (NULL != neighbour->get)
3368  {
3369  GNUNET_PEERSTORE_iterate_cancel (neighbour->get);
3370  neighbour->get = NULL;
3371  }
3372  if (NULL != neighbour->sc)
3373  {
3374  GNUNET_PEERSTORE_store_cancel (neighbour->sc);
3375  neighbour->sc = NULL;
3376  }
3377  if (NULL != (vl = neighbour->vl))
3378  {
3379  GNUNET_assert (neighbour == vl->n);
3380  vl->n = NULL;
3381  if (NULL == vl->dv)
3382  {
3384  free_virtual_link (vl);
3385  }
3386  else
3387  {
3390  }
3391  neighbour->vl = NULL;
3392  }
3393  GNUNET_free (neighbour);
3394 }
3395 
3396 
3403 static void
3405  const struct GNUNET_PeerIdentity *pid)
3406 {
3407  struct GNUNET_MQ_Envelope *env;
3408  struct ConnectInfoMessage *cim;
3409 
3410  GNUNET_assert (CT_CORE == tc->type);
3412  cim->id = *pid;
3413  GNUNET_MQ_send (tc->mq, env);
3414 }
3415 
3416 
3422 static void
3424 {
3426  "Informing CORE clients about connection to %s\n",
3427  GNUNET_i2s (pid));
3428  for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
3429  {
3430  if (CT_CORE != tc->type)
3431  continue;
3432  core_send_connect_info (tc, pid);
3433  }
3434 }
3435 
3436 
3444 static void
3445 transmit_on_queue (void *cls);
3446 
3447 
3455 static void
3458 {
3459  if (queue->tc->details.communicator.total_queue_length >=
3461  {
3463  GST_stats,
3464  "# Transmission throttled due to communicator queue limit",
3465  1,
3466  GNUNET_NO);
3467  queue->idle = GNUNET_NO;
3468  return;
3469  }
3470  if (queue->queue_length >= QUEUE_LENGTH_LIMIT)
3471  {
3472  GNUNET_STATISTICS_update (GST_stats,
3473  "# Transmission throttled due to queue queue limit",
3474  1,
3475  GNUNET_NO);
3476  queue->idle = GNUNET_NO;
3477  return;
3478  }
3479  /* queue might indeed be ready, schedule it */
3480  if (NULL != queue->transmit_task)
3482  queue->transmit_task =
3485  "Considering transmission on queue `%s' to %s\n",
3486  queue->address,
3487  GNUNET_i2s (&queue->neighbour->pid));
3488 }
3489 
3490 
3497 static void
3498 check_link_down (void *cls)
3499 {
3500  struct VirtualLink *vl = cls;
3501  struct DistanceVector *dv = vl->dv;
3502  struct Neighbour *n = vl->n;
3503  struct GNUNET_TIME_Absolute dvh_timeout;
3504  struct GNUNET_TIME_Absolute q_timeout;
3505 
3506  vl->visibility_task = NULL;
3507  dvh_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
3508  for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
3509  pos = pos->next_dv)
3510  dvh_timeout = GNUNET_TIME_absolute_max (dvh_timeout, pos->path_valid_until);
3511  if (0 == GNUNET_TIME_absolute_get_remaining (dvh_timeout).rel_value_us)
3512  {
3513  vl->dv->vl = NULL;
3514  vl->dv = NULL;
3515  }
3516  q_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
3517  for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
3518  q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
3519  if (0 == GNUNET_TIME_absolute_get_remaining (q_timeout).rel_value_us)
3520  {
3521  vl->n->vl = NULL;
3522  vl->n = NULL;
3523  }
3524  if ((NULL == vl->n) && (NULL == vl->dv))
3525  {
3527  free_virtual_link (vl);
3528  return;
3529  }
3530  vl->visibility_task =
3531  GNUNET_SCHEDULER_add_at (GNUNET_TIME_absolute_max (q_timeout, dvh_timeout),
3532  &check_link_down,
3533  vl);
3534 }
3535 
3536 
3542 static void
3544 {
3545  struct Neighbour *neighbour = queue->neighbour;
3546  struct TransportClient *tc = queue->tc;
3547  struct MonitorEvent me = { .cs = GNUNET_TRANSPORT_CS_DOWN,
3549  struct QueueEntry *qe;
3550  int maxxed;
3551  struct PendingAcknowledgement *pa;
3552  struct VirtualLink *vl;
3553 
3554  if (NULL != queue->transmit_task)
3555  {
3557  queue->transmit_task = NULL;
3558  }
3559  while (NULL != (pa = queue->pa_head))
3560  {
3561  GNUNET_CONTAINER_MDLL_remove (queue, queue->pa_head, queue->pa_tail, pa);
3562  pa->queue = NULL;
3563  }
3564 
3565  GNUNET_CONTAINER_MDLL_remove (neighbour,
3566  neighbour->queue_head,
3567  neighbour->queue_tail,
3568  queue);
3570  tc->details.communicator.queue_head,
3571  tc->details.communicator.queue_tail,
3572  queue);
3573  maxxed = (COMMUNICATOR_TOTAL_QUEUE_LIMIT >=
3574  tc->details.communicator.total_queue_length);
3575  while (NULL != (qe = queue->queue_head))
3576  {
3577  GNUNET_CONTAINER_DLL_remove (queue->queue_head, queue->queue_tail, qe);
3578  queue->queue_length--;
3579  tc->details.communicator.total_queue_length--;
3580  if (NULL != qe->pm)
3581  {
3582  GNUNET_assert (qe == qe->pm->qe);
3583  qe->pm->qe = NULL;
3584  }
3585  GNUNET_free (qe);
3586  }
3587  GNUNET_assert (0 == queue->queue_length);
3588  if ((maxxed) && (COMMUNICATOR_TOTAL_QUEUE_LIMIT <
3589  tc->details.communicator.total_queue_length))
3590  {
3591  /* Communicator dropped below threshold, resume all _other_ queues */
3593  GST_stats,
3594  "# Transmission throttled due to communicator queue limit",
3595  -1,
3596  GNUNET_NO);
3597  for (struct Queue *s = tc->details.communicator.queue_head; NULL != s;
3598  s = s->next_client)
3600  }
3601  notify_monitors (&neighbour->pid, queue->address, queue->nt, &me);
3602  GNUNET_free (queue);
3603 
3604  vl = lookup_virtual_link (&neighbour->pid);
3605  if ((NULL != vl) && (neighbour == vl->n))
3606  {
3608  check_link_down (vl);
3609  }
3610  if (NULL == neighbour->queue_head)
3611  {
3612  free_neighbour (neighbour);
3613  }
3614 }
3615 
3616 
3622 static void
3624 {
3625  struct TransportClient *tc = ale->tc;
3626 
3628  tc->details.communicator.addr_tail,
3629  ale);
3630  if (NULL != ale->sc)
3631  {
3633  ale->sc = NULL;
3634  }
3635  if (NULL != ale->st)
3636  {
3637  GNUNET_SCHEDULER_cancel (ale->st);
3638  ale->st = NULL;
3639  }
3640  GNUNET_free (ale);
3641 }
3642 
3643 
3652 static int
3654  const struct GNUNET_PeerIdentity *pid,
3655  void *value)
3656 {
3657  struct TransportClient *tc = cls;
3658  struct PeerRequest *pr = value;
3659 
3661  GNUNET_assert (
3662  GNUNET_YES ==
3664  pid,
3665  pr));
3666  GNUNET_free (pr);
3667 
3668  return GNUNET_OK;
3669 }
3670 
3671 
3680 static void
3682  struct GNUNET_SERVICE_Client *client,
3683  void *app_ctx)
3684 {
3685  struct TransportClient *tc = app_ctx;
3686 
3687  (void) cls;
3688  (void) client;
3690  "Client %p disconnected, cleaning up.\n",
3691  tc);
3692  GNUNET_CONTAINER_DLL_remove (clients_head, clients_tail, tc);
3693  switch (tc->type)
3694  {
3695  case CT_NONE:
3696  break;
3697 
3698  case CT_CORE: {
3699  struct PendingMessage *pm;
3700 
3701  while (NULL != (pm = tc->details.core.pending_msg_head))
3702  {
3704  tc->details.core.pending_msg_head,
3705  tc->details.core.pending_msg_tail,
3706  pm);
3707  pm->client = NULL;
3708  }
3709  }
3710  break;
3711 
3712  case CT_MONITOR:
3713  break;
3714 
3715  case CT_COMMUNICATOR: {
3716  struct Queue *q;
3717  struct AddressListEntry *ale;
3718 
3719  while (NULL != (q = tc->details.communicator.queue_head))
3720  free_queue (q);
3721  while (NULL != (ale = tc->details.communicator.addr_head))
3723  GNUNET_free (tc->details.communicator.address_prefix);
3724  }
3725  break;
3726 
3727  case CT_APPLICATION:
3730  tc);
3732  break;
3733  }
3734  GNUNET_free (tc);
3735 }
3736 
3737 
3747 static int
3749  const struct GNUNET_PeerIdentity *pid,
3750  void *value)
3751 {
3752  struct TransportClient *tc = cls;
3753 
3754  (void) value;
3756  "Telling new CORE client about existing connection to %s\n",
3757  GNUNET_i2s (pid));
3758  core_send_connect_info (tc, pid);
3759  return GNUNET_OK;
3760 }
3761 
3762 
3771 static void
3772 handle_client_start (void *cls, const struct StartMessage *start)
3773 {
3774  struct TransportClient *tc = cls;
3775  uint32_t options;
3776 
3777  options = ntohl (start->options);
3778  if ((0 != (1 & options)) &&
3779  (0 != GNUNET_memcmp (&start->self, &GST_my_identity)))
3780  {
3781  /* client thinks this is a different peer, reject */
3782  GNUNET_break (0);
3784  return;
3785  }
3786  if (CT_NONE != tc->type)
3787  {
3788  GNUNET_break (0);
3790  return;
3791  }
3792  tc->type = CT_CORE;
3794  "New CORE client with PID %s registered\n",
3795  GNUNET_i2s (&start->self));
3798  tc);
3800 }
3801 
3802 
3809 static int
3810 check_client_send (void *cls, const struct OutboundMessage *obm)
3811 {
3812  struct TransportClient *tc = cls;
3813  uint16_t size;
3814  const struct GNUNET_MessageHeader *obmm;
3815 
3816  if (CT_CORE != tc->type)
3817  {
3818  GNUNET_break (0);
3819  return GNUNET_SYSERR;
3820  }
3821  size = ntohs (obm->header.size) - sizeof(struct OutboundMessage);
3822  if (size < sizeof(struct GNUNET_MessageHeader))
3823  {
3824  GNUNET_break (0);
3825  return GNUNET_SYSERR;
3826  }
3827  obmm = (const struct GNUNET_MessageHeader *) &obm[1];
3828  if (size != ntohs (obmm->size))
3829  {
3830  GNUNET_break (0);
3831  return GNUNET_SYSERR;
3832  }
3833  return GNUNET_OK;
3834 }
3835 
3836 
3844 static void
3846 {
3847  struct TransportClient *tc = pm->client;
3848  struct VirtualLink *vl = pm->vl;
3849 
3850  if (NULL != tc)
3851  {
3852  struct GNUNET_MQ_Envelope *env;
3853  struct SendOkMessage *som;
3854 
3856  som->peer = vl->target;
3858  "Confirming transmission of <%llu> to %s\n",
3859  pm->logging_uuid,
3860  GNUNET_i2s (&vl->target));
3861  GNUNET_MQ_send (tc->mq, env);
3862  }
3863  free_pending_message (pm);
3864 }
3865 
3866 
3876 static unsigned int
3879  struct DistanceVectorHop **hops_array,
3880  unsigned int hops_array_length)
3881 {
3882  uint64_t choices[hops_array_length];
3883  uint64_t num_dv;
3884  unsigned int dv_count;
3885 
3886  /* Pick random vectors, but weighted by distance, giving more weight
3887  to shorter vectors */
3888  num_dv = 0;
3889  dv_count = 0;
3890  for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
3891  pos = pos->next_dv)
3892  {
3893  if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) &&
3894  (GNUNET_TIME_absolute_get_remaining (pos->path_valid_until)
3895  .rel_value_us == 0))
3896  continue; /* pos unconfirmed and confirmed required */
3897  num_dv += MAX_DV_HOPS_ALLOWED - pos->distance;
3898  dv_count++;
3899  }
3900  if (0 == dv_count)
3901  return 0;
3902  if (dv_count <= hops_array_length)
3903  {
3904  dv_count = 0;
3905  for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
3906  pos = pos->next_dv)
3907  hops_array[dv_count++] = pos;
3908  return dv_count;
3909  }
3910  for (unsigned int i = 0; i < hops_array_length; i++)
3911  {
3912  int ok = GNUNET_NO;
3913  while (GNUNET_NO == ok)
3914  {
3915  choices[i] =
3917  ok = GNUNET_YES;
3918  for (unsigned int j = 0; j < i; j++)
3919  if (choices[i] == choices[j])
3920  {
3921  ok = GNUNET_NO;
3922  break;
3923  }
3924  }
3925  }
3926  dv_count = 0;
3927  num_dv = 0;
3928  for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
3929  pos = pos->next_dv)
3930  {
3931  uint32_t delta = MAX_DV_HOPS_ALLOWED - pos->distance;
3932 
3933  if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) &&
3934  (GNUNET_TIME_absolute_get_remaining (pos->path_valid_until)
3935  .rel_value_us == 0))
3936  continue; /* pos unconfirmed and confirmed required */
3937  for (unsigned int i = 0; i < hops_array_length; i++)
3938  if ((num_dv <= choices[i]) && (num_dv + delta > choices[i]))
3939  hops_array[dv_count++] = pos;
3940  num_dv += delta;
3941  }
3942  return dv_count;
3943 }
3944 
3945 
3952 static int
3954  void *cls,
3955  const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
3956 {
3957  struct TransportClient *tc = cls;
3958  uint16_t size;
3959 
3960  if (CT_NONE != tc->type)
3961  {
3962  GNUNET_break (0);
3963  return GNUNET_SYSERR;
3964  }
3965  tc->type = CT_COMMUNICATOR;
3966  size = ntohs (cam->header.size) - sizeof(*cam);
3967  if (0 == size)
3968  return GNUNET_OK; /* receive-only communicator */
3970  return GNUNET_OK;
3971 }
3972 
3973 
3979 static void
3981 {
3982  if (0 != ntohl (cmc->im.fc_on))
3983  {
3984  /* send ACK when done to communicator for flow control! */
3985  struct GNUNET_MQ_Envelope *env;
3986  struct GNUNET_TRANSPORT_IncomingMessageAck *ack;
3987 
3989  ack->reserved = htonl (0);
3990  ack->fc_id = cmc->im.fc_id;
3991  ack->sender = cmc->im.sender;
3992  GNUNET_MQ_send (cmc->tc->mq, env);
3993  }
3995  GNUNET_free (cmc);
3996 }
3997 
3998 
4008 static void
4009 handle_client_recv_ok (void *cls, const struct RecvOkMessage *rom)
4010 {
4011  struct TransportClient *tc = cls;
4012  struct VirtualLink *vl;
4013  uint32_t delta;
4014  struct CommunicatorMessageContext *cmc;
4015 
4016  if (CT_CORE != tc->type)
4017  {
4018  GNUNET_break (0);
4020  return;
4021  }
4022  vl = lookup_virtual_link (&rom->peer);
4023  if (NULL == vl)
4024  {
4025  GNUNET_STATISTICS_update (GST_stats,
4026  "# RECV_OK dropped: virtual link unknown",
4027  1,
4028  GNUNET_NO);
4030  return;
4031  }
4032  delta = ntohl (rom->increase_window_delta);
4033  vl->core_recv_window += delta;
4034  if (vl->core_recv_window <= 0)
4035  return;
4036  /* resume communicators */
4037  while (NULL != (cmc = vl->cmc_tail))
4038  {
4040  finish_cmc_handling (cmc);
4041  }
4042 }
4043 
4044 
4051 static void
4053  void *cls,
4054  const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
4055 {
4056  struct TransportClient *tc = cls;
4057  uint16_t size;
4058 
4059  size = ntohs (cam->header.size) - sizeof(*cam);
4060  if (0 == size)
4061  {
4063  "Receive-only communicator connected\n");
4064  return; /* receive-only communicator */
4065  }
4066  tc->details.communicator.address_prefix =
4067  GNUNET_strdup ((const char *) &cam[1]);
4068  tc->details.communicator.cc =
4069  (enum GNUNET_TRANSPORT_CommunicatorCharacteristics) ntohl (cam->cc);
4071  "Communicator with prefix `%s' connected\n",
4072  tc->details.communicator.address_prefix);
4074 }
4075 
4076 
4084 static int
4086  void *cls,
4087  const struct GNUNET_TRANSPORT_CommunicatorBackchannel *cb)
4088 {
4089  const struct GNUNET_MessageHeader *inbox;
4090  const char *is;
4091  uint16_t msize;
4092  uint16_t isize;
4093 
4094  (void) cls;
4095  msize = ntohs (cb->header.size) - sizeof(*cb);
4096  inbox = (const struct GNUNET_MessageHeader *) &cb[1];
4097  isize = ntohs (inbox->size);
4098  if (isize >= msize)
4099  {
4100  GNUNET_break (0);
4101  return GNUNET_SYSERR;
4102  }
4103  is = (const char *) inbox;
4104  is += isize;
4105  msize -= isize;
4106  GNUNET_assert (0 < msize);
4107  if ('\0' != is[msize - 1])
4108  {
4109  GNUNET_break (0);
4110  return GNUNET_SYSERR;
4111  }
4112  return GNUNET_OK;
4113 }
4114 
4115 
4122 static void
4124 {
4125  struct EphemeralConfirmationPS ec;
4126 
4127  if (0 !=
4129  return;
4131  dv->ephemeral_validity =
4137  ec.purpose.size = htonl (sizeof(ec));
4138  ec.target = dv->target;
4139  ec.ephemeral_key = dv->ephemeral_key;
4140  GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign (GST_my_private_key,
4141  &ec.purpose,
4142  &dv->sender_sig));
4143 }
4144 
4145 
4155 static void
4157  struct PendingMessage *pm,
4158  const void *payload,
4159  size_t payload_size)
4160 {
4161  struct Neighbour *n = queue->neighbour;
4162  struct GNUNET_TRANSPORT_SendMessageTo *smt;
4163  struct GNUNET_MQ_Envelope *env;
4164 
4165  queue->idle = GNUNET_NO;
4166  GNUNET_log (
4168  "Queueing %u bytes of payload for transmission <%llu> on queue %llu to %s\n",
4169  (unsigned int) payload_size,
4170  (NULL == pm) ? 0 : pm->logging_uuid,
4171  (unsigned long long) queue->qid,
4172  GNUNET_i2s (&queue->neighbour->pid));
4173  env = GNUNET_MQ_msg_extra (smt,
4174  payload_size,
4176  smt->qid = queue->qid;
4177  smt->mid = queue->mid_gen;
4178  smt->receiver = n->pid;
4179  memcpy (&smt[1], payload, payload_size);
4180  {
4181  /* Pass the env to the communicator of queue for transmission. */
4182  struct QueueEntry *qe;
4183 
4184  qe = GNUNET_new (struct QueueEntry);
4185  qe->mid = queue->mid_gen++;
4186  qe->queue = queue;
4187  if (NULL != pm)
4188  {
4189  qe->pm = pm;
4190  GNUNET_assert (NULL == pm->qe);
4191  pm->qe = qe;
4192  }
4193  GNUNET_CONTAINER_DLL_insert (queue->queue_head, queue->queue_tail, qe);
4194  GNUNET_assert (CT_COMMUNICATOR == queue->tc->type);
4195  queue->queue_length++;
4196  queue->tc->details.communicator.total_queue_length++;
4198  queue->tc->details.communicator.total_queue_length)
4199  queue->idle = GNUNET_NO;
4200  if (QUEUE_LENGTH_LIMIT == queue->queue_length)
4201  queue->idle = GNUNET_NO;
4202  GNUNET_MQ_send (queue->tc->mq, env);
4203  }
4204 }
4205 
4206 
4217 static struct GNUNET_TIME_Relative
4219  const struct GNUNET_MessageHeader *hdr,
4221 {
4222  struct GNUNET_TIME_Absolute now;
4223  unsigned int candidates;
4224  unsigned int sel1;
4225  unsigned int sel2;
4226  struct GNUNET_TIME_Relative rtt;
4227 
4228  /* Pick one or two 'random' queues from n (under constraints of options) */
4229  now = GNUNET_TIME_absolute_get ();
4230  /* FIXME-OPTIMIZE: give queues 'weights' and pick proportional to
4231  weight in the future; weight could be assigned by observed
4232  bandwidth (note: not sure if we should do this for this type
4233  of control traffic though). */
4234  candidates = 0;
4235  for (struct Queue *pos = n->queue_head; NULL != pos;
4236  pos = pos->next_neighbour)
4237  {
4238  if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) ||
4239  (pos->validated_until.abs_value_us > now.abs_value_us))
4240  candidates++;
4241  }
4242  if (0 == candidates)
4243  {
4244  /* This can happen rarely if the last confirmed queue timed
4245  out just as we were beginning to process this message. */
4247  "Could not route message of type %u to %s: no valid queue\n",
4248  ntohs (hdr->type),
4249  GNUNET_i2s (&n->pid));
4250  GNUNET_STATISTICS_update (GST_stats,
4251  "# route selection failed (all no valid queue)",
4252  1,
4253  GNUNET_NO);
4255  }
4256 
4259  if (0 == (options & RMO_REDUNDANT))
4260  sel2 = candidates; /* picks none! */
4261  else
4263  candidates = 0;
4264  for (struct Queue *pos = n->queue_head; NULL != pos;
4265  pos = pos->next_neighbour)
4266  {
4267  if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) ||
4268  (pos->validated_until.abs_value_us > now.abs_value_us))
4269  {
4270  if ((sel1 == candidates) || (sel2 == candidates))
4271  {
4273  "Routing message of type %u to %s using %s (#%u)\n",
4274  ntohs (hdr->type),
4275  GNUNET_i2s (&n->pid),
4276  pos->address,
4277  (sel1 == candidates) ? 1 : 2);
4278  rtt = GNUNET_TIME_relative_min (rtt, pos->pd.aged_rtt);
4279  queue_send_msg (pos, NULL, hdr, ntohs (hdr->size));
4280  }
4281  candidates++;
4282  }
4283  }
4284  return rtt;
4285 }
4286 
4287 
4292 {
4296  gcry_cipher_hd_t cipher;
4297 
4301  struct
4302  {
4306  struct GNUNET_CRYPTO_AuthKey hmac_key;
4307 
4311  char aes_key[256 / 8];
4312 
4316  char aes_ctr[128 / 8];
4317  } material;
4318 };
4319 
4320 
4329 static void
4331  const struct GNUNET_ShortHashCode *iv,
4332  struct DVKeyState *key)
4333 {
4334  /* must match #dh_key_derive_eph_pub */
4336  GNUNET_CRYPTO_kdf (&key->material,
4337  sizeof(key->material),
4338  "transport-backchannel-key",
4339  strlen ("transport-backchannel-key"),
4340  &km,
4341  sizeof(km),
4342  iv,
4343  sizeof(*iv)));
4345  "Deriving backchannel key based on KM %s and IV %s\n",
4346  GNUNET_h2s (km),
4347  GNUNET_sh2s (iv));
4348  gcry_cipher_open (&key->cipher,
4349  GCRY_CIPHER_AES256 /* low level: go for speed */,
4350  GCRY_CIPHER_MODE_CTR,
4351  0 /* flags */);
4352  gcry_cipher_setkey (key->cipher,
4353  &key->material.aes_key,
4354  sizeof(key->material.aes_key));
4355  gcry_cipher_setctr (key->cipher,
4356  &key->material.aes_ctr,
4357  sizeof(key->material.aes_ctr));
4358 }
4359 
4360 
4370 static void
4372  const struct GNUNET_CRYPTO_EcdhePrivateKey *priv_ephemeral,
4373  const struct GNUNET_PeerIdentity *target,
4374  const struct GNUNET_ShortHashCode *iv,
4375  struct DVKeyState *key)
4376 {
4377  struct GNUNET_HashCode km;
4378 
4380  &target->public_key,
4381  &km));
4382  dv_setup_key_state_from_km (&km, iv, key);
4383 }
4384 
4385 
4395 static void
4397  const struct GNUNET_ShortHashCode *iv,
4398  struct DVKeyState *key)
4399 {
4400  struct GNUNET_HashCode km;
4401 
4402  GNUNET_assert (GNUNET_YES == GNUNET_CRYPTO_eddsa_ecdh (GST_my_private_key,
4403  pub_ephemeral,
4404  &km));
4405  dv_setup_key_state_from_km (&km, iv, key);
4406 }
4407 
4408 
4418 static void
4419 dv_hmac (const struct DVKeyState *key,
4420  struct GNUNET_HashCode *hmac,
4421  const void *data,
4422  size_t data_size)
4423 {
4424  GNUNET_CRYPTO_hmac (&key->material.hmac_key, data, data_size, hmac);
4425 }
4426 
4427 
4437 static void
4438 dv_encrypt (struct DVKeyState *key, const void *in, void *dst, size_t in_size)
4439 {
4440  GNUNET_assert (0 ==
4441  gcry_cipher_encrypt (key->cipher, dst, in_size, in, in_size));
4442 }
4443 
4444 
4454 static void
4456  void *out,
4457  const void *ciph,
4458  size_t out_size)
4459 {
4460  GNUNET_assert (
4461  0 == gcry_cipher_decrypt (key->cipher, out, out_size, ciph, out_size));
4462 }
4463 
4464 
4470 static void
4472 {
4473  gcry_cipher_close (key->cipher);
4474  GNUNET_CRYPTO_zero_keys (&key->material, sizeof(key->material));
4475 }
4476 
4477 
4488 typedef void (*DVMessageHandler) (void *cls,
4489  struct Neighbour *next_hop,
4490  const struct GNUNET_MessageHeader *hdr,
4492 
4506 static struct GNUNET_TIME_Relative
4508  unsigned int num_dvhs,
4509  struct DistanceVectorHop **dvhs,
4510  const struct GNUNET_MessageHeader *hdr,
4511  DVMessageHandler use,
4512  void *use_cls,
4514 {
4515  struct TransportDVBoxMessage box_hdr;
4516  struct TransportDVBoxPayloadP payload_hdr;
4517  uint16_t enc_body_size = ntohs (hdr->size);
4518  char enc[sizeof(struct TransportDVBoxPayloadP) + enc_body_size] GNUNET_ALIGN;
4519  struct TransportDVBoxPayloadP *enc_payload_hdr =
4520  (struct TransportDVBoxPayloadP *) enc;
4521  struct DVKeyState key;
4522  struct GNUNET_TIME_Relative rtt;
4523 
4524  /* Encrypt payload */
4526  box_hdr.total_hops = htons (0);
4527  update_ephemeral (dv);
4528  box_hdr.ephemeral_key = dv->ephemeral_key;
4529  payload_hdr.sender_sig = dv->sender_sig;
4531  &box_hdr.iv,
4532  sizeof(box_hdr.iv));
4533  dh_key_derive_eph_pid (&dv->private_key, &dv->target, &box_hdr.iv, &key);
4534  payload_hdr.sender = GST_my_identity;
4535  payload_hdr.monotonic_time = GNUNET_TIME_absolute_hton (dv->monotime);
4536  dv_encrypt (&key, &payload_hdr, enc_payload_hdr, sizeof(payload_hdr));
4537  dv_encrypt (&key,
4538  hdr,
4539  &enc[sizeof(struct TransportDVBoxPayloadP)],
4540  enc_body_size);
4541  dv_hmac (&key, &box_hdr.hmac, enc, sizeof(enc));
4542  dv_key_clean (&key);
4544  /* For each selected path, take the pre-computed header and body
4545  and add the path in the middle of the message; then send it. */
4546  for (unsigned int i = 0; i < num_dvhs; i++)
4547  {
4548  struct DistanceVectorHop *dvh = dvhs[i];
4549  unsigned int num_hops = dvh->distance + 1;
4550  char buf[sizeof(struct TransportDVBoxMessage)
4551  + sizeof(struct GNUNET_PeerIdentity) * num_hops
4552  + sizeof(struct TransportDVBoxPayloadP)
4553  + enc_body_size] GNUNET_ALIGN;
4554  struct GNUNET_PeerIdentity *dhops;
4555 
4556  box_hdr.header.size = htons (sizeof(buf));
4557  box_hdr.num_hops = htons (num_hops);
4558  memcpy (buf, &box_hdr, sizeof(box_hdr));
4559  dhops = (struct GNUNET_PeerIdentity *) &buf[sizeof(box_hdr)];
4560  memcpy (dhops,
4561  dvh->path,
4562  dvh->distance * sizeof(struct GNUNET_PeerIdentity));
4563  dhops[dvh->distance] = dv->target;
4564  if (GNUNET_EXTRA_LOGGING > 0)
4565  {
4566  char *path;
4567 
4569  for (unsigned int j = 0; j <= num_hops; j++)
4570  {
4571  char *tmp;
4572 
4573  GNUNET_asprintf (&tmp, "%s-%s", path, GNUNET_i2s (&dhops[j]));
4574  GNUNET_free (path);
4575  path = tmp;
4576  }
4578  "Routing message of type %u to %s using DV (#%u/%u) via %s\n",
4579  ntohs (hdr->type),
4580  GNUNET_i2s (&dv->target),
4581  i + 1,
4582  num_dvhs + 1,
4583  path);
4584  GNUNET_free (path);
4585  }
4586  rtt = GNUNET_TIME_relative_min (rtt, dvh->pd.aged_rtt);
4587  memcpy (&dhops[num_hops], enc, sizeof(enc));
4588  use (use_cls,
4589  dvh->next_hop,
4590  (const struct GNUNET_MessageHeader *) buf,
4591  options);
4592  }
4593  return rtt;
4594 }
4595 
4596 
4606 static void
4608  struct Neighbour *next_hop,
4609  const struct GNUNET_MessageHeader *hdr,
4611 {
4612  (void) cls;
4613  (void) route_via_neighbour (next_hop, hdr, options);
4614 }
4615 
4616 
4628 static struct GNUNET_TIME_Relative
4630  const struct GNUNET_MessageHeader *hdr,
4632 {
4633  struct VirtualLink *vl;
4634  struct Neighbour *n;
4635  struct DistanceVector *dv;
4636  struct GNUNET_TIME_Relative rtt1;
4637  struct GNUNET_TIME_Relative rtt2;
4638 
4639  vl = lookup_virtual_link (target);
4640  GNUNET_assert (NULL != vl);
4641  n = vl->n;
4642  dv = (0 != (options & RMO_DV_ALLOWED)) ? vl->dv : NULL;
4643  if (0 == (options & RMO_UNCONFIRMED_ALLOWED))
4644  {
4645  /* if confirmed is required, and we do not have anything
4646  confirmed, drop respective options */
4647  if (NULL == n)
4648  n = lookup_neighbour (target);
4649  if ((NULL == dv) && (0 != (options & RMO_DV_ALLOWED)))
4650  dv = GNUNET_CONTAINER_multipeermap_get (dv_routes, target);
4651  }
4652  if ((NULL == n) && (NULL == dv))
4653  {
4655  "Cannot route message of type %u to %s: no route\n",
4656  ntohs (hdr->type),
4657  GNUNET_i2s (target));
4658  GNUNET_STATISTICS_update (GST_stats,
4659  "# Messages dropped in routing: no acceptable method",
4660  1,
4661  GNUNET_NO);
4663  }
4665  "Routing message of type %u to %s with options %X\n",
4666  ntohs (hdr->type),
4667  GNUNET_i2s (target),
4668  (unsigned int) options);
4669  /* If both dv and n are possible and we must choose:
4670  flip a coin for the choice between the two; for now 50/50 */
4671  if ((NULL != n) && (NULL != dv) && (0 == (options & RMO_REDUNDANT)))
4672  {
4674  n = NULL;
4675  else
4676  dv = NULL;
4677  }
4678  if ((NULL != n) && (NULL != dv))
4679  options &= ~RMO_REDUNDANT; /* We will do one DV and one direct, that's
4680  enough for redunancy, so clear the flag. */
4683  if (NULL != n)
4684  {
4685  rtt1 = route_via_neighbour (n, hdr, options);
4686  }
4687  if (NULL != dv)
4688  {
4689  struct DistanceVectorHop *hops[2];
4690  unsigned int res;
4691 
4692  res = pick_random_dv_hops (dv,
4693  options,
4694  hops,
4695  (0 == (options & RMO_REDUNDANT)) ? 1 : 2);
4696  if (0 == res)
4697  {
4699  "Failed to route message, could not determine DV path\n");
4700  return rtt1;
4701  }
4702  rtt2 = encapsulate_for_dv (dv,
4703  res,
4704  hops,
4705  hdr,
4707  NULL,
4708  options & (~RMO_REDUNDANT));
4709  }
4710  return GNUNET_TIME_relative_min (rtt1, rtt2);
4711 }
4712 
4713 
4720 static void
4722 {
4723  struct VirtualLink *vl = cls;
4724  struct GNUNET_TIME_Absolute monotime;
4725  struct TransportFlowControlMessage fc;
4726  struct GNUNET_TIME_Relative duration;
4727  struct GNUNET_TIME_Relative rtt;
4728 
4730  /* OPTIMIZE-FC-BDP: decide sane criteria on when to do this, instead of doing
4731  it always! */
4732  /* For example, we should probably ONLY do this if a bit more than
4733  an RTT has passed, or if the window changed "significantly" since
4734  then. See vl->last_fc_rtt! NOTE: to do this properly, we also
4735  need an estimate for the bandwidth-delay-product for the entire
4736  VL, as that determines "significantly". We have the delay, but
4737  the bandwidth statistics need to be added for the VL!*/(void) duration;
4738 
4740  "Sending FC seq %u to %s with new window %llu\n",
4741  (unsigned int) vl->fc_seq_gen,
4742  GNUNET_i2s (&vl->target),
4743  (unsigned long long) vl->incoming_fc_window_size);
4744  monotime = GNUNET_TIME_absolute_get_monotonic (GST_cfg);
4745  vl->last_fc_transmission = monotime;
4747  fc.header.size = htons (sizeof(fc));
4748  fc.seq = htonl (vl->fc_seq_gen++);
4752  fc.sender_time = GNUNET_TIME_absolute_hton (monotime);
4754  if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == rtt.rel_value_us)
4755  {
4758  "FC retransmission to %s failed, will retry in %s\n",
4759  GNUNET_i2s (&vl->target),
4762  }
4763  else
4764  {
4765  /* OPTIMIZE-FC-BDP: rtt is not ideal, we can do better! */
4766  vl->last_fc_rtt = rtt;
4767  }
4768  if (NULL != vl->fc_retransmit_task)
4770  vl->fc_retransmit_task =
4772 }
4773 
4774 
4791 static void
4793 {
4794  struct Neighbour *n = vl->n;
4795  struct DistanceVector *dv = vl->dv;
4796  struct GNUNET_TIME_Absolute now;
4797  int elig;
4798 
4799  /* Check that we have an eligible pending message!
4800  (cheaper than having #transmit_on_queue() find out!) */
4801  elig = GNUNET_NO;
4802  for (struct PendingMessage *pm = vl->pending_msg_head; NULL != pm;
4803  pm = pm->next_vl)
4804  {
4805  if (NULL != pm->qe)
4806  continue; /* not eligible, is in a queue! */
4807  if (pm->bytes_msg + vl->outbound_fc_window_size_used >
4809  {
4811  "Stalled transmision on VL %s due to flow control: %llu < %llu\n",
4812  GNUNET_i2s (&vl->target),
4813  (unsigned long long) vl->outbound_fc_window_size,
4814  (unsigned long long) (pm->bytes_msg
4816  consider_sending_fc (vl);
4817  return; /* We have a message, but flow control says "nope" */
4818  }
4819  elig = GNUNET_YES;
4820  break;
4821  }
4822  if (GNUNET_NO == elig)
4823  return;
4824 
4825  /* Notify queues at direct neighbours that we are interested */
4826  now = GNUNET_TIME_absolute_get ();
4827  if (NULL != n)
4828  {
4829  for (struct Queue *queue = n->queue_head; NULL != queue;
4830  queue = queue->next_neighbour)
4831  if ((GNUNET_YES == queue->idle) &&
4832  (queue->validated_until.abs_value_us > now.abs_value_us))
4834  }
4835  /* Notify queues via DV that we are interested */
4836  if (NULL != dv)
4837  {
4838  /* Do DV with lower scheduler priority, which effectively means that
4839  IF a neighbour exists and is available, we prefer it. */
4840  for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
4841  pos = pos->next_dv)
4842  {
4843  struct Neighbour *nh = pos->next_hop;
4844 
4845  if (pos->path_valid_until.abs_value_us <= now.abs_value_us)
4846  continue; /* skip this one: path not validated */
4847  for (struct Queue *queue = nh->queue_head; NULL != queue;
4848  queue = queue->next_neighbour)
4849  if ((GNUNET_YES == queue->idle) &&
4850  (queue->validated_until.abs_value_us > now.abs_value_us))
4853  }
4854  }
4855 }
4856 
4857 
4864 static void
4865 handle_client_send (void *cls, const struct OutboundMessage *obm)
4866 {
4867  struct TransportClient *tc = cls;
4868  struct PendingMessage *pm;
4869  const struct GNUNET_MessageHeader *obmm;
4870  uint32_t bytes_msg;
4871  struct VirtualLink *vl;
4873 
4874  GNUNET_assert (CT_CORE == tc->type);
4875  obmm = (const struct GNUNET_MessageHeader *) &obm[1];
4876  bytes_msg = ntohs (obmm->size);
4877  pp = (enum GNUNET_MQ_PriorityPreferences) ntohl (obm->priority);
4878  vl = lookup_virtual_link (&obm->peer);
4879  if (NULL == vl)
4880  {
4881  /* Failure: don't have this peer as a neighbour (anymore).
4882  Might have gone down asynchronously, so this is NOT
4883  a protocol violation by CORE. Still count the event,
4884  as this should be rare. */
4886  GNUNET_STATISTICS_update (GST_stats,
4887  "# messages dropped (neighbour unknown)",
4888  1,
4889  GNUNET_NO);
4890  return;
4891  }
4892 
4893  pm = GNUNET_malloc (sizeof(struct PendingMessage) + bytes_msg);
4895  pm->prefs = pp;
4896  pm->client = tc;
4897  pm->vl = vl;
4898  pm->bytes_msg = bytes_msg;
4899  memcpy (&pm[1], obmm, bytes_msg);
4901  "Sending %u bytes as <%llu> to %s\n",
4902  bytes_msg,
4903  pm->logging_uuid,
4904  GNUNET_i2s (&obm->peer));
4906  tc->details.core.pending_msg_head,
4907  tc->details.core.pending_msg_tail,
4908  pm);
4910  vl->pending_msg_head,
4911  vl->pending_msg_tail,
4912  pm);
4913  check_vl_transmission (vl);
4914 }
4915 
4916 
4926 static void
4928  void *cls,
4929  const struct GNUNET_TRANSPORT_CommunicatorBackchannel *cb)
4930 {
4931  struct TransportClient *tc = cls;
4932  const struct GNUNET_MessageHeader *inbox =
4933  (const struct GNUNET_MessageHeader *) &cb[1];
4934  uint16_t isize = ntohs (inbox->size);
4935  const char *is = ((const char *) &cb[1]) + isize;
4936  char
4937  mbuf[isize
4938  + sizeof(struct
4942 
4943  /* 0-termination of 'is' was checked already in
4944  #check_communicator_backchannel() */
4946  "Preparing backchannel transmission to %s:%s of type %u\n",
4947  GNUNET_i2s (&cb->pid),
4948  is,
4949  ntohs (inbox->size));
4950  /* encapsulate and encrypt message */
4951  be->header.type =
4953  be->header.size = htons (sizeof(mbuf));
4954  memcpy (&be[1], inbox, isize);
4955  memcpy (&mbuf[sizeof(struct TransportBackchannelEncapsulationMessage)
4956  + isize],
4957  is,
4958  strlen (is) + 1);
4961 }
4962 
4963 
4971 static int
4973  const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
4974 {
4975  struct TransportClient *tc = cls;
4976 
4977  if (CT_COMMUNICATOR != tc->type)
4978  {
4979  GNUNET_break (0);
4980  return GNUNET_SYSERR;
4981  }
4983  return GNUNET_OK;
4984 }
4985 
4986 
4992 static void
4993 store_pi (void *cls);
4994 
4995 
5002 static void
5003 peerstore_store_own_cb (void *cls, int success)
5004 {
5005  struct AddressListEntry *ale = cls;
5006 
5007  ale->sc = NULL;
5008  if (GNUNET_YES != success)
5010  "Failed to store our own address `%s' in peerstore!\n",
5011  ale->address);
5012  else
5014  "Successfully stored our own address `%s' in peerstore!\n",
5015  ale->address);
5016  /* refresh period is 1/4 of expiration time, that should be plenty
5017  without being excessive. */
5018  ale->st =
5020  4ULL),
5021  &store_pi,
5022  ale);
5023 }
5024 
5025 
5031 static void
5032 store_pi (void *cls)
5033 {
5034  struct AddressListEntry *ale = cls;
5035  void *addr;
5036  size_t addr_len;
5037  struct GNUNET_TIME_Absolute expiration;
5038 
5039  ale->st = NULL;
5040  expiration = GNUNET_TIME_relative_to_absolute (ale->expiration);
5042  "Storing our address `%s' in peerstore until %s!\n",
5043  ale->address,
5046  ale->nt,
5048  GST_my_private_key,
5049  &addr,
5050  &addr_len);
5051  ale->sc = GNUNET_PEERSTORE_store (peerstore,
5052  "transport",
5053  &GST_my_identity,
5055  addr,
5056  addr_len,
5057  expiration,
5060  ale);
5061  GNUNET_free (addr);
5062  if (NULL == ale->sc)
5063  {
5065  "Failed to store our address `%s' with peerstore\n",
5066  ale->address);
5067  ale->st =
5069  }
5070 }
5071 
5072 
5079 static void
5081  const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
5082 {
5083  struct TransportClient *tc = cls;
5084  struct AddressListEntry *ale;
5085  size_t slen;
5086 
5087  /* 0-termination of &aam[1] was checked in #check_add_address */
5089  "Communicator added address `%s'!\n",
5090  (const char *) &aam[1]);
5091  slen = ntohs (aam->header.size) - sizeof(*aam);
5092  ale = GNUNET_malloc (sizeof(struct AddressListEntry) + slen);
5093  ale->tc = tc;
5094  ale->address = (const char *) &ale[1];
5095  ale->expiration = GNUNET_TIME_relative_ntoh (aam->expiration);
5096  ale->aid = aam->aid;
5097  ale->nt = (enum GNUNET_NetworkType) ntohl (aam->nt);
5098  memcpy (&ale[1], &aam[1], slen);
5100  tc->details.communicator.addr_tail,
5101  ale);
5102  ale->st = GNUNET_SCHEDULER_add_now (&store_pi, ale);
5104 }
5105 
5106 
5113 static void
5115  const struct GNUNET_TRANSPORT_DelAddressMessage *dam)
5116 {
5117  struct TransportClient *tc = cls;
5118  struct AddressListEntry *alen;
5119 
5120  if (CT_COMMUNICATOR != tc->type)
5121  {
5122  GNUNET_break (0);
5124  return;
5125  }
5126  for (struct AddressListEntry *ale = tc->details.communicator.addr_head;
5127  NULL != ale;
5128  ale = alen)
5129  {
5130  alen = ale->next;
5131  if (dam->aid != ale->aid)
5132  continue;
5133  GNUNET_assert (ale->tc == tc);
5135  "Communicator deleted address `%s'!\n",
5136  ale->address);
5139  }
5140  GNUNET_break (0);
5142 }
5143 
5144 
5152 static void
5154  const struct GNUNET_MessageHeader *msg);
5155 
5156 
5164 static void
5165 core_env_sent_cb (void *cls)
5166 {
5167  struct CoreSentContext *ctx = cls;
5168  struct VirtualLink *vl = ctx->vl;
5169 
5170  if (NULL == vl)
5171  {
5172  /* lost the link in the meantime, ignore */
5173  GNUNET_free (ctx);
5174  return;
5175  }
5178  vl->incoming_fc_window_size_ram -= ctx->size;
5179  vl->incoming_fc_window_size_used += ctx->isize;
5180  consider_sending_fc (vl);
5181  GNUNET_free (ctx);
5182 }
5183 
5184 
5193 static void
5194 handle_raw_message (void *cls, const struct GNUNET_MessageHeader *mh)
5195 {
5196  struct CommunicatorMessageContext *cmc = cls;
5197  struct VirtualLink *vl;
5198  uint16_t size = ntohs (mh->size);
5199  int have_core;
5200 
5201  if ((size > UINT16_MAX - sizeof(struct InboundMessage)) ||
5202  (size < sizeof(struct GNUNET_MessageHeader)))
5203  {
5204  struct GNUNET_SERVICE_Client *client = cmc->tc->client;
5205 
5206  GNUNET_break (0);
5207  finish_cmc_handling (cmc);
5208  GNUNET_SERVICE_client_drop (client);
5209  return;
5210  }
5211  vl = lookup_virtual_link (&cmc->im.sender);
5212  if (NULL == vl)
5213  {
5214  /* FIXME: sender is giving us messages for CORE but we don't have
5215  the link up yet! I *suspect* this can happen right now (i.e.
5216  sender has verified us, but we didn't verify sender), but if
5217  we pass this on, CORE would be confused (link down, messages
5218  arrive). We should investigate more if this happens often,
5219  or in a persistent manner, and possibly do "something" about
5220  it. Thus logging as error for now. */GNUNET_break_op (0);
5221  GNUNET_STATISTICS_update (GST_stats,
5222  "# CORE messages droped (virtual link still down)",
5223  1,
5224  GNUNET_NO);
5225 
5226  finish_cmc_handling (cmc);
5227  return;
5228  }
5229  if (vl->incoming_fc_window_size_ram > UINT_MAX - size)
5230  {
5231  GNUNET_STATISTICS_update (GST_stats,
5232  "# CORE messages droped (FC arithmetic overflow)",
5233  1,
5234  GNUNET_NO);
5235 
5236  finish_cmc_handling (cmc);
5237  return;
5238  }
5240  {
5241  GNUNET_STATISTICS_update (GST_stats,
5242  "# CORE messages droped (FC window overflow)",
5243  1,
5244  GNUNET_NO);
5245  finish_cmc_handling (cmc);
5246  return;
5247  }
5248 
5249  /* Forward to all CORE clients */
5250  have_core = GNUNET_NO;
5251  for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
5252  {
5253  struct GNUNET_MQ_Envelope *env;
5254  struct InboundMessage *im;
5255  struct CoreSentContext *ctx;
5256 
5257  if (CT_CORE != tc->type)
5258  continue;
5261  ctx = GNUNET_new (struct CoreSentContext);
5262  ctx->vl = vl;
5263  ctx->size = size;
5264  ctx->isize = (GNUNET_NO == have_core) ? size : 0;
5265  have_core = GNUNET_YES;
5268  im->peer = cmc->im.sender;
5269  memcpy (&im[1], mh, size);
5270  GNUNET_MQ_send (tc->mq, env);
5271  vl->core_recv_window--;
5272  }
5273  if (GNUNET_NO == have_core)
5274  {
5276  "Dropped message to CORE: no CORE client connected!\n");
5277  /* Nevertheless, count window as used, as it is from the
5278  perspective of the other peer! */
5280  /* TODO-M1 */
5281  finish_cmc_handling (cmc);
5282  return;
5283  }
5285  "Delivered message from %s of type %u to CORE\n",
5286  GNUNET_i2s (&cmc->im.sender),
5287  ntohs (mh->type));
5288  if (vl->core_recv_window > 0)
5289  {
5290  finish_cmc_handling (cmc);
5291  return;
5292  }
5293  /* Wait with calling #finish_cmc_handling(cmc) until the message
5294  was processed by CORE MQs (for CORE flow control)! */
5296 }
5297 
5298 
5306 static int
5308 {
5309  uint16_t size = ntohs (fb->header.size);
5310  uint16_t bsize = size - sizeof(*fb);
5311 
5312  (void) cls;
5313  if (0 == bsize)
5314  {
5315  GNUNET_break_op (0);
5316  return GNUNET_SYSERR;
5317  }
5318  if (bsize + ntohs (fb->frag_off) > ntohs (fb->msg_size))
5319  {
5320  GNUNET_break_op (0);
5321  return GNUNET_SYSERR;
5322  }
5323  if (ntohs (fb->frag_off) >= ntohs (fb->msg_size))
5324  {
5325  GNUNET_break_op (0);
5326  return GNUNET_SYSERR;
5327  }
5328  return GNUNET_YES;
5329 }
5330 
5331 
5337 static void
5339 {
5340  struct AcknowledgementCummulator *ac = cls;
5341 
5342  ac->task = NULL;
5343  GNUNET_assert (0 == ac->num_acks);
5344  GNUNET_assert (
5345  GNUNET_YES ==
5346  GNUNET_CONTAINER_multipeermap_remove (ack_cummulators, &ac->target, ac));
5347  GNUNET_free (ac);
5348 }
5349 
5350 
5356 static void
5358 {
5359  struct AcknowledgementCummulator *ac = cls;
5360  char buf[sizeof(struct TransportReliabilityAckMessage)
5361  + ac->ack_counter
5362  * sizeof(struct TransportCummulativeAckPayloadP)] GNUNET_ALIGN;
5363  struct TransportReliabilityAckMessage *ack =
5366 
5367  ac->task = NULL;
5369  "Sending ACK with %u components to %s\n",
5370  ac->ack_counter,
5371  GNUNET_i2s (&ac->target));
5372  GNUNET_assert (0 < ac->ack_counter);
5374  ack->header.size =
5375  htons (sizeof(*ack)
5376  + ac->ack_counter * sizeof(struct TransportCummulativeAckPayloadP));
5377  ack->ack_counter = htonl (ac->ack_counter++);
5378  ap = (struct TransportCummulativeAckPayloadP *) &ack[1];
5379  for (unsigned int i = 0; i < ac->ack_counter; i++)
5380  {
5381  ap[i].ack_uuid = ac->ack_uuids[i].ack_uuid;
5383  GNUNET_TIME_absolute_get_duration (ac->ack_uuids[i].receive_time));
5384  }
5386  ac->num_acks = 0;
5389  ac);
5390 }
5391 
5392 
5401 static void
5403  const struct AcknowledgementUUIDP *ack_uuid,
5404  struct GNUNET_TIME_Absolute max_delay)
5405 {
5406  struct AcknowledgementCummulator *ac;
5407 
5409  "Scheduling ACK %s for transmission to %s\n",
5410  GNUNET_uuid2s (&ack_uuid->value),
5411  GNUNET_i2s (pid));
5412  ac = GNUNET_CONTAINER_multipeermap_get (ack_cummulators, pid);
5413  if (NULL == ac)
5414  {
5415  ac = GNUNET_new (struct AcknowledgementCummulator);
5416  ac->target = *pid;
5417  ac->min_transmission_time = max_delay;
5420  ack_cummulators,
5421  &ac->target,
5422  ac,
5424  }
5425  else
5426  {
5427  if (MAX_CUMMULATIVE_ACKS == ac->num_acks)
5428  {
5429  /* must run immediately, ack buffer full! */
5432  }
5434  ac->min_transmission_time =
5436  }
5439  ac->ack_uuids[ac->num_acks].ack_uuid = *ack_uuid;
5440  ac->num_acks++;
5443  ac);
5444 }
5445 
5446 
5451 {
5455  struct MessageUUIDP message_uuid;
5456 
5461 };
5462 
5463 
5473 static int
5474 find_by_message_uuid (void *cls, uint32_t key, void *value)
5475 {
5476  struct FindByMessageUuidContext *fc = cls;
5477  struct ReassemblyContext *rc = value;
5478 
5479  (void) key;
5480  if (0 == GNUNET_memcmp (&fc->message_uuid, &rc->msg_uuid))
5481  {
5482  fc->rc = rc;
5483  return GNUNET_NO;
5484  }
5485  return GNUNET_YES;
5486 }
5487 
5488 
5496 static void
5498 {
5499  struct CommunicatorMessageContext *cmc = cls;
5500  struct Neighbour *n;
5501  struct ReassemblyContext *rc;
5502  const struct GNUNET_MessageHeader *msg;
5503  uint16_t msize;
5504  uint16_t fsize;
5505  uint16_t frag_off;
5506  char *target;
5507  struct GNUNET_TIME_Relative cdelay;
5508  struct FindByMessageUuidContext fc;
5509 
5510  n = lookup_neighbour (&cmc->im.sender);
5511  if (NULL == n)
5512  {
5513  struct GNUNET_SERVICE_Client *client = cmc->tc->client;
5514 
5515  GNUNET_break (0);
5516  finish_cmc_handling (cmc);
5517  GNUNET_SERVICE_client_drop (client);
5518  return;
5519  }
5520  if (NULL == n->reassembly_map)
5521  {
5522  n->reassembly_map = GNUNET_CONTAINER_multihashmap32_create (8);
5523  n->reassembly_heap =
5525  n->reassembly_timeout_task =
5528  n);
5529  }
5530  msize = ntohs (fb->msg_size);
5531  fc.message_uuid = fb->msg_uuid;
5532  fc.rc = NULL;
5533  (void) GNUNET_CONTAINER_multihashmap32_get_multiple (n->reassembly_map,
5534  fb->msg_uuid.uuid,
5536  &fc);
5537  if (NULL == (rc = fc.rc))
5538  {
5539  rc = GNUNET_malloc (sizeof(*rc) + msize /* reassembly payload buffer */
5540  + (msize + 7) / 8 * sizeof(uint8_t) /* bitfield */);
5541  rc->msg_uuid = fb->msg_uuid;
5542  rc->neighbour = n;
5543  rc->msg_size = msize;
5544  rc->reassembly_timeout =
5547  rc->hn = GNUNET_CONTAINER_heap_insert (n->reassembly_heap,
5548  rc,
5552  n->reassembly_map,
5553  rc->msg_uuid.uuid,
5554  rc,
5556  target = (char *) &rc[1];
5557  rc->bitfield = (uint8_t *) (target + rc->msg_size);
5558  rc->msg_missing = rc->msg_size;
5560  "Received fragment at offset %u/%u from %s for NEW message %u\n",
5561  ntohs (fb->frag_off),
5562  msize,
5563  GNUNET_i2s (&cmc->im.sender),
5564  (unsigned int) fb->msg_uuid.uuid);
5565  }
5566  else
5567  {
5568  target = (char *) &rc[1];
5570  "Received fragment at offset %u/%u from %s for message %u\n",
5571  ntohs (fb->frag_off),
5572  msize,
5573  GNUNET_i2s (&cmc->im.sender),
5574  (unsigned int) fb->msg_uuid.uuid);
5575  }
5576  if (msize != rc->msg_size)
5577  {
5578  GNUNET_break (0);
5579  finish_cmc_handling (cmc);
5580  return;
5581  }
5582 
5583  /* reassemble */
5584  fsize = ntohs (fb->header.size) - sizeof(*fb);
5585  if (0 == fsize)
5586  {
5587  GNUNET_break (0);
5588  finish_cmc_handling (cmc);
5589  return;
5590  }
5591  frag_off = ntohs (fb->frag_off);
5592  if (frag_off + fsize > msize)
5593  {
5594  /* Fragment (plus fragment size) exceeds message size! */
5595  GNUNET_break_op (0);
5596  finish_cmc_handling (cmc);
5597  return;
5598  }
5599  memcpy (&target[frag_off], &fb[1], fsize);
5600  /* update bitfield and msg_missing */
5601  for (unsigned int i = frag_off; i < frag_off + fsize; i++)
5602  {
5603  if (0 == (rc->bitfield[i / 8] & (1 << (i % 8))))
5604  {
5605  rc->bitfield[i / 8] |= (1 << (i % 8));
5606  rc->msg_missing--;
5607  }
5608  }
5609 
5610  /* Compute cummulative ACK */
5612  cdelay = GNUNET_TIME_relative_multiply (cdelay, rc->msg_missing / fsize);
5613  if (0 == rc->msg_missing)
5614  cdelay = GNUNET_TIME_UNIT_ZERO;
5615  cummulative_ack (&cmc->im.sender,
5616  &fb->ack_uuid,
5619  /* is reassembly complete? */
5620  if (0 != rc->msg_missing)
5621  {
5622  finish_cmc_handling (cmc);
5623  return;
5624  }
5625  /* reassembly is complete, verify result */
5626  msg = (const struct GNUNET_MessageHeader *) &rc[1];
5627  if (ntohs (msg->size) != rc->msg_size)
5628  {
5629  GNUNET_break (0);
5631  finish_cmc_handling (cmc);
5632  return;
5633  }
5634  /* successful reassembly */
5636  "Fragment reassembly complete for message %u\n",
5637  (unsigned int) fb->msg_uuid.uuid);
5638  /* FIXME: check that the resulting msg is NOT a
5639  DV Box or Reliability Box, as that is NOT allowed! */
5640  demultiplex_with_cmc (cmc, msg);
5641  /* FIXME-OPTIMIZE: really free here? Might be bad if fragments are still
5642  en-route and we forget that we finished this reassembly immediately!
5643  -> keep around until timeout?
5644  -> shorten timeout based on ACK? */
5646 }
5647 
5648 
5656 static int
5658  const struct TransportReliabilityBoxMessage *rb)
5659 {
5660  (void) cls;
5662  return GNUNET_YES;
5663 }
5664 
5665 
5673 static void
5675  const struct TransportReliabilityBoxMessage *rb)
5676 {
5677  struct CommunicatorMessageContext *cmc = cls;
5678  const struct GNUNET_MessageHeader *inbox =
5679  (const struct GNUNET_MessageHeader *) &rb[1];
5680  struct GNUNET_TIME_Relative rtt;
5681 
5683  "Received reliability box from %s with UUID %s of type %u\n",
5684  GNUNET_i2s (&cmc->im.sender),
5685  GNUNET_uuid2s (&rb->ack_uuid.value),
5686  (unsigned int) ntohs (inbox->type));
5687  rtt = GNUNET_TIME_UNIT_SECONDS; /* FIXME: should base this on "RTT", but we
5688  do not really have an RTT for the
5689  * incoming* queue (should we have
5690  the sender add it to the rb message?) */
5691  cummulative_ack (
5692  &cmc->im.sender,
5693  &rb->ack_uuid,
5694  (0 == ntohl (rb->ack_countdown))
5697  GNUNET_TIME_relative_divide (rtt, 8 /* FIXME: magic constant */)));
5698  /* continue with inner message */
5699  /* FIXME: check that inbox is NOT a DV Box, fragment or another
5700  reliability box (not allowed!) */
5701  demultiplex_with_cmc (cmc, inbox);
5702 }
5703 
5704 
5713 static void
5714 update_pd_age (struct PerformanceData *pd, unsigned int age)
5715 {
5716  unsigned int sage;
5717 
5718  if (age == pd->last_age)
5719  return; /* nothing to do */
5720  sage = GNUNET_MAX (pd->last_age, age - 2 * GOODPUT_AGING_SLOTS);
5721  for (unsigned int i = sage; i <= age - GOODPUT_AGING_SLOTS; i++)
5722  {
5723  struct TransmissionHistoryEntry *the = &pd->the[i % GOODPUT_AGING_SLOTS];
5724 
5725  the->bytes_sent = 0;
5726  the->bytes_received = 0;
5727  }
5728  pd->last_age = age;
5729 }
5730 
5731 
5740 static void
5742  struct GNUNET_TIME_Relative rtt,
5743  uint16_t bytes_transmitted_ok)
5744 {
5745  uint64_t nval = rtt.rel_value_us;
5746  uint64_t oval = pd->aged_rtt.rel_value_us;
5747  unsigned int age = get_age ();
5748  struct TransmissionHistoryEntry *the = &pd->the[age % GOODPUT_AGING_SLOTS];
5749 
5750  if (oval == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
5751  pd->aged_rtt = rtt;
5752  else
5753  pd->aged_rtt.rel_value_us = (nval + 7 * oval) / 8;
5754  update_pd_age (pd, age);
5755  the->bytes_received += bytes_transmitted_ok;
5756 }
5757 
5758 
5766 static void
5768  struct GNUNET_TIME_Relative rtt,
5769  uint16_t bytes_transmitted_ok)
5770 {
5771  update_performance_data (&q->pd, rtt, bytes_transmitted_ok);
5772 }
5773 
5774 
5782 static void
5784  struct GNUNET_TIME_Relative rtt,
5785  uint16_t bytes_transmitted_ok)
5786 {
5787  update_performance_data (&dvh->pd, rtt, bytes_transmitted_ok);
5788 }
5789 
5790 
5798 static void
5800 {
5801  struct PendingMessage *pos;
5802 
5803  switch (pm->pmt)
5804  {
5805  case PMT_CORE:
5806  case PMT_RELIABILITY_BOX:
5807  /* Full message sent, we are done */
5808  client_send_response (pm);
5809  return;
5810 
5811  case PMT_FRAGMENT_BOX:
5812  /* Fragment sent over reliabile channel */
5813  free_fragment_tree (pm);
5814  pos = pm->frag_parent;
5815  GNUNET_CONTAINER_MDLL_remove (frag, pos->head_frag, pos->tail_frag, pm);
5816  GNUNET_free (pm);
5817  /* check if subtree is done */
5818  while ((NULL == pos->head_frag) && (pos->frag_off == pos->bytes_msg) &&
5819  (pos != pm))
5820  {
5821  pm = pos;
5822  pos = pm->frag_parent;
5823  GNUNET_CONTAINER_MDLL_remove (frag, pos->head_frag, pos->tail_frag, pm);
5824  GNUNET_free (pm);
5825  }
5826 
5827  /* Was this the last applicable fragmment? */
5828  if ((NULL == pos->head_frag) && (NULL == pos->frag_parent) &&
5829  (pos->frag_off == pos->bytes_msg))
5830  client_send_response (pos);
5831  return;
5832 
5833  case PMT_DV_BOX:
5835  "Completed transmission of message %llu (DV Box)\n",
5836  pm->logging_uuid);
5837  free_pending_message (pm);
5838  return;
5839  }
5840 }
5841 
5842 
5850 static void
5852  struct GNUNET_TIME_Relative ack_delay)
5853 {
5854  struct GNUNET_TIME_Relative delay;
5855 
5857  if (delay.rel_value_us > ack_delay.rel_value_us)
5858  delay = GNUNET_TIME_UNIT_ZERO;
5859  else
5860  delay = GNUNET_TIME_relative_subtract (delay, ack_delay);
5861  if (NULL != pa->queue)
5862  update_queue_performance (pa->queue, delay, pa->message_size);
5863  if (NULL != pa->dvh)
5864  update_dvh_performance (pa->dvh, delay, pa->message_size);
5865  if (NULL != pa->pm)
5868 }
5869 
5870 
5878 static int
5880  const struct TransportReliabilityAckMessage *ra)
5881 {
5882  unsigned int n_acks;
5883 
5884  (void) cls;
5885  n_acks = (ntohs (ra->header.size) - sizeof(*ra))
5886  / sizeof(struct TransportCummulativeAckPayloadP);
5887  if (0 == n_acks)
5888  {
5889  GNUNET_break_op (0);
5890  return GNUNET_SYSERR;
5891  }
5892  if ((ntohs (ra->header.size) - sizeof(*ra)) !=
5893  n_acks * sizeof(struct TransportCummulativeAckPayloadP))
5894  {
5895  GNUNET_break_op (0);
5896  return GNUNET_SYSERR;
5897  }
5898  return GNUNET_OK;
5899 }
5900 
5901 
5909 static void
5911  const struct TransportReliabilityAckMessage *ra)
5912 {
5913  struct CommunicatorMessageContext *cmc = cls;
5914  const struct TransportCummulativeAckPayloadP *ack;
5915  unsigned int n_acks;
5916  uint32_t ack_counter;
5917 
5918  n_acks = (ntohs (ra->header.size) - sizeof(*ra))
5919  / sizeof(struct TransportCummulativeAckPayloadP);
5920  ack = (const struct TransportCummulativeAckPayloadP *) &ra[1];
5921  for (unsigned int i = 0; i < n_acks; i++)
5922  {
5923  struct PendingAcknowledgement *pa =
5924  GNUNET_CONTAINER_multiuuidmap_get (pending_acks, &ack[i].ack_uuid.value);
5925  if (NULL == pa)
5926  {
5928  "Received ACK from %s with UUID %s which is unknown to us!\n",
5929  GNUNET_i2s (&cmc->im.sender),
5930  GNUNET_uuid2s (&ack[i].ack_uuid.value));
5932  GST_stats,
5933  "# FRAGMENT_ACKS dropped, no matching pending message",
5934  1,
5935  GNUNET_NO);
5936  continue;
5937  }
5939  "Received ACK from %s with UUID %s\n",
5940  GNUNET_i2s (&cmc->im.sender),
5941  GNUNET_uuid2s (&ack[i].ack_uuid.value));
5942  handle_acknowledged (pa, GNUNET_TIME_relative_ntoh (ack[i].ack_delay));
5943  }
5944 
5945  ack_counter = htonl (ra->ack_counter);
5946  (void) ack_counter; /* silence compiler warning for now */
5947  // FIXME-OPTIMIZE: track ACK losses based on ack_counter somewhere!
5948  // (DV and/or Neighbour?)
5949  finish_cmc_handling (cmc);
5950 }
5951 
5952 
5960 static int
5962  void *cls,
5964 {
5965  uint16_t size = ntohs (be->header.size) - sizeof(*be);
5966  const struct GNUNET_MessageHeader *inbox =
5967  (const struct GNUNET_MessageHeader *) &be[1];
5968  const char *is;
5969  uint16_t isize;
5970 
5971  (void) cls;
5972  if (ntohs (inbox->size) >= size)
5973  {
5974  GNUNET_break_op (0);
5975  return GNUNET_SYSERR;
5976  }
5977  isize = ntohs (inbox->size);
5978  is = ((const char *) inbox) + isize;
5979  size -= isize;
5980  if ('\0' != is[size - 1])
5981  {
5982  GNUNET_break_op (0);
5983  return GNUNET_SYSERR;
5984  }
5985  return GNUNET_YES;
5986 }
5987 
5988 
5997 static void
5999  void *cls,
6001 {
6002  struct CommunicatorMessageContext *cmc = cls;
6003  struct GNUNET_TRANSPORT_CommunicatorBackchannelIncoming *cbi;
6004  struct GNUNET_MQ_Envelope *env;
6005  struct TransportClient *tc;
6006  const struct GNUNET_MessageHeader *inbox =
6007  (const struct GNUNET_MessageHeader *) &be[1];
6008  uint16_t isize = ntohs (inbox->size);
6009  const char *target_communicator = ((const char *) inbox) + isize;
6010 
6011  /* Find client providing this communicator */
6012  for (tc = clients_head; NULL != tc; tc = tc->next)
6013  if ((CT_COMMUNICATOR == tc->type) &&
6014  (0 ==
6015  strcmp (tc->details.communicator.address_prefix, target_communicator)))
6016  break;
6017  if (NULL == tc)
6018  {
6019  char *stastr;
6020 
6021  GNUNET_asprintf (
6022  &stastr,
6023  "# Backchannel message dropped: target communicator `%s' unknown",
6024  target_communicator);
6025  GNUNET_STATISTICS_update (GST_stats, stastr, 1, GNUNET_NO);
6026  GNUNET_free (stastr);
6027  return;
6028  }
6029  /* Finally, deliver backchannel message to communicator */
6031  "Delivering backchannel message from %s of type %u to %s\n",
6032  GNUNET_i2s (&cmc->im.sender),
6033  ntohs (inbox->type),
6034  target_communicator);
6035  env = GNUNET_MQ_msg_extra (
6036  cbi,
6037  isize,
6039  cbi->pid = cmc->im.sender;
6040  memcpy (&cbi[1], inbox, isize);
6041  GNUNET_MQ_send (tc->mq, env);
6042 }
6043 
6044 
6054 static void
6055 path_cleanup_cb (void *cls)
6056 {
6057  struct DistanceVector *dv = cls;
6058  struct DistanceVectorHop *pos;
6059 
6060  dv->timeout_task = NULL;
6061  while (NULL != (pos = dv->dv_head))
6062  {
6063  GNUNET_assert (dv == pos->dv);
6065  break;
6067  }
6068  if (NULL == pos)
6069  {
6070  free_dv_route (dv);
6071  return;
6072  }
6073  dv->timeout_task =
6075 }
6076 
6077 
6085 static void
6087 {
6088  struct DistanceVector *dv = hop->dv;
6089  struct VirtualLink *vl;
6090 
6091  vl = lookup_virtual_link (&dv->target);
6092  if (NULL != vl)
6093  {
6094  /* Link was already up, remember dv is also now available and we are done */
6095  vl->dv = dv;
6097  "Virtual link to %s could now also use DV!\n",
6098  GNUNET_i2s (&dv->target));
6099  return;
6100  }
6102  "Creating new virtual link to %s using DV!\n",
6103  GNUNET_i2s (&dv->target));
6104  vl = GNUNET_new (struct VirtualLink);
6105  vl->message_uuid_ctr =
6107  vl->target = dv->target;
6108  vl->dv = dv;
6109  dv->vl = vl;
6112  vl->visibility_task =
6116  links,
6117  &vl->target,
6118  vl,
6120  consider_sending_fc (vl);
6121  /* We lacked a confirmed connection to the target
6122  before, so tell CORE about it (finally!) */
6124 }
6125 
6126 
6152 static int
6154  unsigned int path_len,
6155  struct GNUNET_TIME_Relative network_latency,
6156  struct GNUNET_TIME_Absolute path_valid_until)
6157 {
6158  struct DistanceVectorHop *hop;
6159  struct DistanceVector *dv;
6160  struct Neighbour *next_hop;
6161  unsigned int shorter_distance;
6162 
6163  if (path_len < 3)
6164  {
6165  /* what a boring path! not allowed! */
6166  GNUNET_break (0);
6167  return GNUNET_SYSERR;
6168  }
6169  GNUNET_assert (0 == GNUNET_memcmp (&GST_my_identity, &path[0]));
6170  next_hop = lookup_neighbour (&path[1]);
6171  if (NULL == next_hop)
6172  {
6173  /* next hop must be a neighbour, otherwise this whole thing is useless! */
6174  GNUNET_break (0);
6175  return GNUNET_SYSERR;
6176  }
6177  for (unsigned int i = 2; i < path_len; i++)
6178  if (NULL != lookup_neighbour (&path[i]))
6179  {
6180  /* Useless path: we have a direct connection to some hop
6181  in the middle of the path, so this one is not even
6182  terribly useful for redundancy */
6184  "Path of %u hops useless: directly link to hop %u (%s)\n",
6185  path_len,
6186  i,
6187  GNUNET_i2s (&path[i]));
6188  GNUNET_STATISTICS_update (GST_stats,
6189  "# Useless DV path ignored: hop is neighbour",
6190  1,
6191  GNUNET_NO);
6192  return GNUNET_SYSERR;
6193  }
6194  dv = GNUNET_CONTAINER_multipeermap_get (dv_routes, &path[path_len - 1]);
6195  if (NULL == dv)
6196  {
6197  dv = GNUNET_new (struct DistanceVector);
6198  dv->target = path[path_len - 1];
6200  &path_cleanup_cb,
6201  dv);
6204  dv_routes,
6205  &dv->target,
6206  dv,
6208  }
6209  /* Check if we have this path already! */
6210  shorter_distance = 0;
6211  for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
6212  pos = pos->next_dv)
6213  {
6214  if (pos->distance < path_len - 2)
6215  shorter_distance++;
6216  /* Note that the distances in 'pos' excludes us (path[0]) and
6217  the next_hop (path[1]), so we need to subtract two
6218  and check next_hop explicitly */
6219  if ((pos->distance == path_len - 2) && (pos->next_hop == next_hop))
6220  {
6221  int match = GNUNET_YES;
6222 
6223  for (unsigned int i = 0; i < pos->distance; i++)
6224  {
6225  if (0 != GNUNET_memcmp (&pos->path[i], &path[i + 2]))
6226  {
6227  match = GNUNET_NO;
6228  break;
6229  }
6230  }
6231  if (GNUNET_YES == match)
6232  {
6233  struct GNUNET_TIME_Relative last_timeout;
6234 
6235  /* Re-discovered known path, update timeout */
6236  GNUNET_STATISTICS_update (GST_stats,
6237  "# Known DV path refreshed",
6238  1,
6239  GNUNET_NO);
6240  last_timeout = GNUNET_TIME_absolute_get_remaining (pos->timeout);
6241  pos->timeout =
6243  pos->path_valid_until =
6244  GNUNET_TIME_absolute_max (pos->path_valid_until, path_valid_until);
6245  GNUNET_CONTAINER_MDLL_remove (dv, dv->dv_head, dv->dv_tail, pos);
6246  GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, pos);
6247  if (0 <
6250  if (last_timeout.rel_value_us <
6253  .rel_value_us)
6254  {
6255  /* Some peer send DV learn messages too often, we are learning
6256  the same path faster than it would be useful; do not forward! */
6258  "Rediscovered path too quickly, not forwarding further\n");
6259  return GNUNET_NO;
6260  }
6262  "Refreshed known path to %s, forwarding further\n",
6263  GNUNET_i2s (&dv->target));
6264  return GNUNET_YES;
6265  }
6266  }
6267  }
6268  /* Count how many shorter paths we have (incl. direct
6269  neighbours) before simply giving up on this one! */
6270  if (shorter_distance >= MAX_DV_PATHS_TO_TARGET)
6271  {
6272  /* We have a shorter path already! */
6274  "Have many shorter DV paths %s, not forwarding further\n",
6275  GNUNET_i2s (&dv->target));
6276  return GNUNET_NO;
6277  }
6278  /* create new DV path entry */
6280  "Discovered new DV path to %s\n",
6281  GNUNET_i2s (&dv->target));
6282  hop = GNUNET_malloc (sizeof(struct DistanceVectorHop)
6283  + sizeof(struct GNUNET_PeerIdentity) * (path_len - 2));
6284  hop->next_hop = next_hop;
6285  hop->dv = dv;
6286  hop->path = (const struct GNUNET_PeerIdentity *) &hop[1];
6287  memcpy (&hop[1],
6288  &path[2],
6289  sizeof(struct GNUNET_PeerIdentity) * (path_len - 2));
6291  hop->path_valid_until = path_valid_until;
6292  hop->distance = path_len - 2;
6293  hop->pd.aged_rtt = network_latency;
6294  GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, hop);
6295  GNUNET_CONTAINER_MDLL_insert (neighbour,
6296  next_hop->dv_head,
6297  next_hop->dv_tail,
6298  hop);
6299  if (0 < GNUNET_TIME_absolute_get_remaining (path_valid_until).rel_value_us)
6301  return GNUNET_YES;
6302 }
6303 
6304 
6312 static int
6313 check_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
6314 {
6315  uint16_t size = ntohs (dvl->header.size);
6316  uint16_t num_hops = ntohs (dvl->num_hops);
6317  const struct DVPathEntryP *hops = (const struct DVPathEntryP *) &dvl[1];
6318 
6319  (void) cls;
6320  if (size != sizeof(*dvl) + num_hops * sizeof(struct DVPathEntryP))
6321  {
6322  GNUNET_break_op (0);
6323  return GNUNET_SYSERR;
6324  }
6325  if (num_hops > MAX_DV_HOPS_ALLOWED)
6326  {
6327  GNUNET_break_op (0);
6328  return GNUNET_SYSERR;
6329  }
6330  for (unsigned int i = 0; i < num_hops; i++)
6331  {
6332  if (0 == GNUNET_memcmp (&dvl->initiator, &hops[i].hop))
6333  {
6334  GNUNET_break_op (0);
6335  return GNUNET_SYSERR;
6336  }
6337  if (0 == GNUNET_memcmp (&GST_my_identity, &hops[i].hop))
6338  {
6339  GNUNET_break_op (0);
6340  return GNUNET_SYSERR;
6341  }
6342  }
6343  return GNUNET_YES;
6344 }
6345 
6346 
6358 static void
6359 forward_dv_learn (const struct GNUNET_PeerIdentity *next_hop,
6360  const struct TransportDVLearnMessage *msg,
6361  uint16_t bi_history,
6362  uint16_t nhops,
6363  const struct DVPathEntryP *hops,
6364  struct GNUNET_TIME_Absolute in_time)
6365 {
6366  struct DVPathEntryP *dhops;
6367  char buf[sizeof(struct TransportDVLearnMessage)
6368  + (nhops + 1) * sizeof(struct DVPathEntryP)] GNUNET_ALIGN;
6369  struct TransportDVLearnMessage *fwd = (struct TransportDVLearnMessage *) buf;
6370  struct GNUNET_TIME_Relative nnd;
6371 
6372  /* compute message for forwarding */
6374  "Forwarding DV learn message originating from %s to %s\n",
6375  GNUNET_i2s (&msg->initiator),
6376  GNUNET_i2s2 (next_hop));
6379  fwd->header.size = htons (sizeof(struct TransportDVLearnMessage)
6380  + (nhops + 1) * sizeof(struct DVPathEntryP));
6381  fwd->num_hops = htons (nhops + 1);
6382  fwd->bidirectional = htons (bi_history);
6385  msg->non_network_delay));
6387  fwd->init_sig = msg->init_sig;
6388  fwd->initiator = msg->initiator;
6389  fwd->challenge = msg->challenge;
6390  dhops = (struct DVPathEntryP *) &fwd[1];
6391  GNUNET_memcpy (dhops, hops, sizeof(struct DVPathEntryP) * nhops);
6392  dhops[nhops].hop = GST_my_identity;
6393  {
6394  struct DvHopPS dhp = { .purpose.purpose =
6396  .purpose.size = htonl (sizeof(dhp)),
6397  .pred = dhops[nhops - 1].hop,
6398  .succ = *next_hop,
6399  .challenge = msg->challenge };
6400 
6402  GNUNET_CRYPTO_eddsa_sign (GST_my_private_key,
6403  &dhp.purpose,
6404  &dhops[nhops].hop_sig));
6405  }
6407  &fwd->header,
6409 }
6410 
6411 
6421 static int
6423  struct GNUNET_TIME_AbsoluteNBO sender_monotonic_time,
6424  const struct GNUNET_PeerIdentity *init,
6425  const struct ChallengeNonceP *challenge,
6426  const struct GNUNET_CRYPTO_EddsaSignature *init_sig)
6427 {
6428  struct DvInitPS ip = { .purpose.purpose = htonl (
6430  .purpose.size = htonl (sizeof(ip)),
6431  .monotonic_time = sender_monotonic_time,
6432  .challenge = *challenge };
6433 
6434  if (
6435  GNUNET_OK !=
6437  &ip.purpose,
6438  init_sig,
6439  &init->public_key))
6440  {
6441  GNUNET_break_op (0);
6442  return GNUNET_SYSERR;
6443  }
6444  return GNUNET_OK;
6445 }
6446 
6447 
6452 {
6457 
6461  const struct DVPathEntryP *hops;
6462 
6466  struct GNUNET_TIME_Absolute in_time;
6467 
6471  uint32_t selections[MAX_DV_DISCOVERY_SELECTION];
6472 
6476  unsigned int num_eligible;
6477 
6481  unsigned int num_selections;
6482 
6486  uint16_t nhops;
6487 
6491  uint16_t bi_history;
6492 };
6493 
6494 
6503 static int
6505  const struct GNUNET_PeerIdentity *pid,
6506  void *value)
6507 {
6508  struct NeighbourSelectionContext *nsc = cls;
6509 
6510  (void) value;
6511  if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator))
6512  return GNUNET_YES; /* skip initiator */
6513  for (unsigned int i = 0; i < nsc->nhops; i++)
6514  if (0 == GNUNET_memcmp (pid, &nsc->hops[i].hop))
6515  return GNUNET_YES;
6516  /* skip peers on path */
6517  nsc->num_eligible++;
6518  return GNUNET_YES;
6519 }
6520 
6521 
6532 static int
6534  const struct GNUNET_PeerIdentity *pid,
6535  void *value)
6536 {
6537  struct NeighbourSelectionContext *nsc = cls;
6538 
6539  (void) value;
6540  if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator))
6541  return GNUNET_YES; /* skip initiator */
6542  for (unsigned int i = 0; i < nsc->nhops; i++)
6543  if (0 == GNUNET_memcmp (pid, &nsc->hops[i].hop))
6544  return GNUNET_YES;
6545  /* skip peers on path */
6546  for (unsigned int i = 0; i < nsc->num_selections; i++)
6547  {
6548  if (nsc->selections[i] == nsc->num_eligible)
6549  {
6550  forward_dv_learn (pid,
6551  nsc->dvl,
6552  nsc->bi_history,
6553  nsc->nhops,
6554  nsc->hops,
6555  nsc->in_time);
6556  break;
6557  }
6558  }
6559  nsc->num_eligible++;
6560  return GNUNET_YES;
6561 }
6562 
6563 
6607 static unsigned int
6608 calculate_fork_degree (unsigned int hops_taken,
6609  unsigned int neighbour_count,
6610  unsigned int eligible_count)
6611 {
6612  double target_total = 50.0; /* FIXME: use LOG(NSE)? */
6613  double eligible_ratio =
6614  ((double) eligible_count) / ((double) neighbour_count);
6615  double boost_factor = eligible_ratio * eligible_ratio;
6616  unsigned int rnd;
6617  double left;
6618 
6619  if (hops_taken >= 64)
6620  {
6621  GNUNET_break (0);
6622  return 0; /* precaution given bitshift below */
6623  }
6624  for (unsigned int i = 1; i < hops_taken; i++)
6625  {
6626  /* For each hop, subtract the expected number of targets
6627  reached at distance d (so what remains divided by 2^d) */
6628  target_total -= (target_total * boost_factor / (1LLU << i));
6629  }
6630  rnd =
6631  (unsigned int) floor (target_total * boost_factor / (1LLU << hops_taken));
6632  /* round up or down probabilistically depending on how close we were
6633  when floor()ing to rnd */
6634  left = target_total - (double) rnd;
6635  if (UINT32_MAX * left >
6637  rnd++; /* round up */
6639  "Forwarding DV learn message of %u hops %u(/%u/%u) times\n",
6640  hops_taken,
6641  rnd,
6642  eligible_count,
6643  neighbour_count);
6644  return rnd;
6645 }
6646 
6647 
6654 static void
6655 neighbour_store_dvmono_cb (void *cls, int success)
6656 {
6657  struct Neighbour *n = cls;
6658 
6659  n->sc = NULL;
6660  if (GNUNET_YES != success)
6662  "Failed to store other peer's monotonic time in peerstore!\n");
6663 }
6664 
6665 
6673 static void
6674 handle_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
6675 {
6676  struct CommunicatorMessageContext *cmc = cls;
6678  int bi_hop;
6679  uint16_t nhops;
6680  uint16_t bi_history;
6681  const struct DVPathEntryP *hops;
6682  int do_fwd;
6683  int did_initiator;
6684  struct GNUNET_TIME_Absolute in_time;
6685  struct Neighbour *n;
6686 
6687  nhops = ntohs (dvl->bidirectional); /* 0 = sender is initiator */
6688  bi_history = ntohs (dvl->bidirectional);
6689  hops = (const struct DVPathEntryP *) &dvl[1];
6690  if (0 == nhops)
6691  {
6692  /* sanity check */
6693  if (0 != GNUNET_memcmp (&dvl->initiator, &cmc->im.sender))
6694  {
6695  GNUNET_break (0);
6696  finish_cmc_handling (cmc);
6697  return;
6698  }
6699  }
6700  else
6701  {
6702  /* sanity check */
6703  if (0 != GNUNET_memcmp (&hops[nhops - 1].hop, &cmc->im.sender))
6704  {
6705  GNUNET_break (0);
6706  finish_cmc_handling (cmc);
6707  return;
6708  }
6709  }
6710 
6711  GNUNET_assert (CT_COMMUNICATOR == cmc->tc->type);
6712  cc = cmc->tc->details.communicator.cc;
6713  bi_hop = (GNUNET_TRANSPORT_CC_RELIABLE ==
6714  cc); // FIXME: add bi-directional flag to cc?
6715  in_time = GNUNET_TIME_absolute_get ();
6716 
6717  /* continue communicator here, everything else can happen asynchronous! */
6718  finish_cmc_handling (cmc);
6719 
6720  n = lookup_neighbour (&dvl->initiator);
6721  if (NULL != n)
6722  {
6723  if ((n->dv_monotime_available == GNUNET_YES) &&
6726  {
6727  GNUNET_STATISTICS_update (GST_stats,
6728  "# DV learn discarded due to time travel",
6729  1,
6730  GNUNET_NO);
6731  return;
6732  }
6734  &dvl->initiator,
6735  &dvl->challenge,
6736  &dvl->init_sig))
6737  {
6738  GNUNET_break_op (0);
6739  return;
6740  }
6743  {
6744  if (NULL != n->sc)
6746  n->sc =
6747  GNUNET_PEERSTORE_store (peerstore,
6748  "transport",
6749  &dvl->initiator,
6751  &dvl->monotonic_time,
6752  sizeof(dvl->monotonic_time),
6756  n);
6757  }
6758  }
6759  /* OPTIMIZE-FIXME: asynchronously (!) verify signatures!,
6760  If signature verification load too high, implement random drop strategy */
6761  for (unsigned int i = 0; i < nhops; i++)
6762  {
6763  struct DvHopPS dhp = { .purpose.purpose =
6765  .purpose.size = htonl (sizeof(dhp)),
6766  .pred = (0 == i) ? dvl->initiator : hops[i - 1].hop,
6767  .succ = (nhops == i + 1) ? GST_my_identity
6768  : hops[i + 1].hop,
6769  .challenge = dvl->challenge };
6770 
6771  if (GNUNET_OK !=
6773  &dhp.purpose,
6774  &hops[i].hop_sig,
6775  &hops[i].hop.public_key))
6776  {
6777  GNUNET_break_op (0);
6778  return;
6779  }
6780  }
6781 
6782  if (GNUNET_EXTRA_LOGGING > 0)
6783  {
6784  char *path;
6785 
6786  path = GNUNET_strdup (GNUNET_i2s (&dvl->initiator));
6787  for (unsigned int i = 0; i < nhops; i++)
6788  {
6789  char *tmp;
6790 
6791  GNUNET_asprintf (&tmp,
6792  "%s%s%s",
6793  path,
6794  (bi_history & (1 << (nhops - i))) ? "<->" : "-->",
6795  GNUNET_i2s (&hops[i].hop));
6796  GNUNET_free (path);
6797  path = tmp;
6798  }
6800  "Received DVInit via %s%s%s\n",
6801  path,
6802  bi_hop ? "<->" : "-->",
6804  GNUNET_free (path);
6805  }
6806 
6807  do_fwd = GNUNET_YES;
6808  if (0 == GNUNET_memcmp (&GST_my_identity, &dvl->initiator))
6809  {
6810  struct GNUNET_PeerIdentity path[nhops + 1];
6811  struct GNUNET_TIME_Relative host_latency_sum;
6812  struct GNUNET_TIME_Relative latency;
6813  struct GNUNET_TIME_Relative network_latency;
6814 
6815  /* We initiated this, learn the forward path! */
6816  path[0] = GST_my_identity;
6817  path[1] = hops[0].hop;
6818  host_latency_sum = GNUNET_TIME_relative_ntoh (dvl->non_network_delay);
6819 
6820  // Need also something to lookup initiation time
6821  // to compute RTT! -> add RTT argument here?
6822  latency = GNUNET_TIME_UNIT_FOREVER_REL; // FIXME: initialize properly
6823  // (based on dvl->challenge, we can identify time of origin!)
6824 
6825  network_latency = GNUNET_TIME_relative_subtract (latency, host_latency_sum);
6826  /* assumption: latency on all links is the same */
6827  network_latency = GNUNET_TIME_relative_divide (network_latency, nhops);
6828 
6829  for (unsigned int i = 2; i <= nhops; i++)
6830  {
6831  struct GNUNET_TIME_Relative ilat;
6832 
6833  /* assumption: linear latency increase per hop */
6834  ilat = GNUNET_TIME_relative_multiply (network_latency, i);
6835  path[i] = hops[i - 1].hop;
6837  "Learned path with %u hops to %s with latency %s\n",
6838  i,
6839  GNUNET_i2s (&path[i]),
6841  learn_dv_path (path,
6842  i,
6843  ilat,
6846  }
6847  /* as we initiated, do not forward again (would be circular!) */
6848  do_fwd = GNUNET_NO;
6849  return;
6850  }
6851  if (bi_hop)
6852  {
6853  /* last hop was bi-directional, we could learn something here! */
6854  struct GNUNET_PeerIdentity path[nhops + 2];
6855 
6856  path[0] = GST_my_identity;
6857  path[1] = hops[nhops - 1].hop; /* direct neighbour == predecessor! */
6858  for (unsigned int i = 0; i < nhops; i++)
6859  {
6860  int iret;
6861 
6862  if (0 == (bi_history & (1 << i)))
6863  break; /* i-th hop not bi-directional, stop learning! */
6864  if (i == nhops - 1)
6865  {
6866  path[i + 2] = dvl->initiator;
6867  }
6868  else
6869  {
6870  path[i + 2] = hops[nhops - i - 2].hop;
6871  }
6872 
6874  "Learned inverse path with %u hops to %s\n",
6875  i + 1,
6876  GNUNET_i2s (&path[i + 2]));
6877  iret = learn_dv_path (path,
6878  i + 2,
6881  if (GNUNET_SYSERR == iret)
6882  {
6883  /* path invalid or too long to be interesting for US, thus should also
6884  not be interesting to our neighbours, cut path when forwarding to
6885  'i' hops, except of course for the one that goes back to the
6886  initiator */
6887  GNUNET_STATISTICS_update (GST_stats,
6888  "# DV learn not forwarded due invalidity of path",
6889  1,
6890  GNUNET_NO);
6891  do_fwd = GNUNET_NO;
6892  break;
6893  }
6894  if ((GNUNET_NO == iret) && (nhops == i + 1))
6895  {
6896  /* we have better paths, and this is the longest target,
6897  so there cannot be anything interesting later */
6898  GNUNET_STATISTICS_update (GST_stats,
6899  "# DV learn not forwarded, got better paths",
6900  1,
6901  GNUNET_NO);
6902  do_fwd = GNUNET_NO;
6903  break;
6904  }
6905  }
6906  }
6907 
6908  if (MAX_DV_HOPS_ALLOWED == nhops)
6909  {
6910  /* At limit, we're out of here! */
6911  finish_cmc_handling (cmc);
6912  return;
6913  }
6914 
6915  /* Forward to initiator, if path non-trivial and possible */
6916  bi_history = (bi_history << 1) | (bi_hop ? 1 : 0);
6917  did_initiator = GNUNET_NO;
6918  if ((1 < nhops) &&
6919  (GNUNET_YES ==
6921  {
6922  /* send back to origin! */
6924  "Sending DVL back to initiator %s\n",
6925  GNUNET_i2s (&dvl->initiator));
6926  forward_dv_learn (&dvl->initiator, dvl, bi_history, nhops, hops, in_time);
6927  did_initiator = GNUNET_YES;
6928  }
6929  /* We forward under two conditions: either we still learned something
6930  ourselves (do_fwd), or the path was darn short and thus the initiator is
6931  likely to still be very interested in this (and we did NOT already
6932  send it back to the initiator) */
6933  if ((do_fwd) || ((nhops < MIN_DV_PATH_LENGTH_FOR_INITIATOR) &&
6934  (GNUNET_NO == did_initiator)))
6935  {
6936  /* Pick random neighbours that are not yet on the path */
6937  struct NeighbourSelectionContext nsc;
6938  unsigned int n_cnt;
6939 
6940  n_cnt = GNUNET_CONTAINER_multipeermap_size (neighbours);
6941  nsc.nhops = nhops;
6942  nsc.dvl = dvl;
6943  nsc.bi_history = bi_history;
6944  nsc.hops = hops;
6945  nsc.in_time = in_time;
6946  nsc.num_eligible = 0;
6949  &nsc);
6950  if (0 == nsc.num_eligible)
6951  return; /* done here, cannot forward to anyone else */
6952  nsc.num_selections = calculate_fork_degree (nhops, n_cnt, nsc.num_eligible);
6953  nsc.num_selections =
6956  "Forwarding DVL to %u other peers\n",
6957  nsc.num_selections);
6958  for (unsigned int i = 0; i < nsc.num_selections; i++)
6959  nsc.selections[i] =
6960  (nsc.num_selections == n_cnt)
6961  ? i /* all were selected, avoid collisions by chance */
6963  nsc.num_eligible = 0;
6966  &nsc);
6967  }
6968 }
6969 
6970 
6978 static int
6979 check_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
6980 {
6981  uint16_t size = ntohs (dvb->header.size);
6982  uint16_t num_hops = ntohs (dvb->num_hops);
6983  const struct GNUNET_PeerIdentity *hops =
6984  (const struct GNUNET_PeerIdentity *) &dvb[1];
6985 
6986  (void) cls;
6987  if (size < sizeof(*dvb) + num_hops * sizeof(struct GNUNET_PeerIdentity)
6988  + sizeof(struct GNUNET_MessageHeader))
6989  {
6990  GNUNET_break_op (0);
6991  return GNUNET_SYSERR;
6992  }
6993  /* This peer must not be on the path */
6994  for (unsigned int i = 0; i < num_hops; i++)
6995  if (0 == GNUNET_memcmp (&hops[i], &GST_my_identity))
6996  {
6997  GNUNET_break_op (0);
6998  return GNUNET_SYSERR;
6999  }
7000  return GNUNET_YES;
7001 }
7002 
7003 
7016 static void
7017 forward_dv_box (struct Neighbour *next_hop,
7018  const struct TransportDVBoxMessage *hdr,
7019  uint16_t total_hops,
7020  uint16_t num_hops,
7021  const struct GNUNET_PeerIdentity *hops,
7022  const void *enc_payload,
7023  uint16_t enc_payload_size)
7024 {
7025  struct VirtualLink *vl = next_hop->vl;
7026  struct PendingMessage *pm;
7027  size_t msg_size;
7028  char *buf;
7029  struct GNUNET_PeerIdentity *dhops;
7030 
7031  GNUNET_assert (NULL != vl);
7032  msg_size = sizeof(struct TransportDVBoxMessage)
7033  + num_hops * sizeof(struct GNUNET_PeerIdentity) + enc_payload_size;
7034  pm = GNUNET_malloc (sizeof(struct PendingMessage) + msg_size);
7035  pm->pmt = PMT_DV_BOX;
7036  pm->vl = vl;
7038  pm->logging_uuid = logging_uuid_gen++;
7039  pm->prefs = GNUNET_MQ_PRIO_BACKGROUND;
7040  pm->bytes_msg = msg_size;
7041  buf = (char *) &pm[1];
7042  memcpy (buf, hdr, sizeof(*hdr));
7043  dhops =
7044  (struct GNUNET_PeerIdentity *) &buf[sizeof(struct TransportDVBoxMessage)];
7045  memcpy (dhops, hops, num_hops * sizeof(struct GNUNET_PeerIdentity));
7046  memcpy (&dhops[num_hops], enc_payload, enc_payload_size);
7048  vl->pending_msg_head,
7049  vl->pending_msg_tail,
7050  pm);
7052  "Created pending message %llu for DV Box with next hop %s (%u/%u)\n",
7053  pm->logging_uuid,
7054  GNUNET_i2s (&next_hop->pid),
7055  (unsigned int) num_hops,
7056  (unsigned int) total_hops);
7057  check_vl_transmission (vl);
7058 }
7059 
7060 
7066 static void
7068 {
7069  if (NULL != b->get)
7070  {
7072  b->get = NULL;
7073  GNUNET_assert (NULL != b->cmc);
7074  finish_cmc_handling (b->cmc);
7075  b->cmc = NULL;
7076  }
7077  if (NULL != b->task)
7078  {
7080  b->task = NULL;
7081  }
7082  if (NULL != b->sc)
7083  {
7085  b->sc = NULL;
7086  }
7087  GNUNET_assert (
7088  GNUNET_YES ==
7089  GNUNET_CONTAINER_multipeermap_remove (backtalkers, &b->pid, b));
7090  GNUNET_free (b);
7091 }
7092 
7093 
7102 static int
7104  const struct GNUNET_PeerIdentity *pid,
7105  void *value)
7106 {
7107  struct Backtalker *b = value;
7108 
7109  (void) cls;
7110  (void) pid;
7111  free_backtalker (b);
7112  return GNUNET_OK;
7113 }
7114 
7115 
7121 static void
7123 {
7124  struct Backtalker *b = cls;
7125 
7126  b->task = NULL;
7128  {
7130  return;
7131  }
7132  GNUNET_assert (NULL == b->sc);
7133  free_backtalker (b);
7134 }
7135 
7136 
7145 static void
7147  const struct GNUNET_PEERSTORE_Record *record,
7148  const char *emsg)
7149 {
7150  struct Backtalker *b = cls;
7151  struct GNUNET_TIME_AbsoluteNBO *mtbe;
7152  struct GNUNET_TIME_Absolute mt;
7153 
7154  (void) emsg;
7155  if (NULL == record)
7156  {
7157  /* we're done with #backtalker_monotime_cb() invocations,
7158  continue normal processing */
7159  b->get = NULL;
7160  GNUNET_assert (NULL != b->cmc);
7161  if (0 != b->body_size)
7163  (const struct GNUNET_MessageHeader *) &b[1]);
7164  else
7165  finish_cmc_handling (b->cmc);
7166  b->cmc = NULL;
7167  return;
7168  }
7169  if (sizeof(*mtbe) != record->value_size)
7170  {
7171  GNUNET_break (0);
7172  return;
7173  }
7174  mtbe = record->value;
7175  mt = GNUNET_TIME_absolute_ntoh (*mtbe);
7177  {
7179  "Backtalker message from %s dropped, monotime in the past\n",
7180  GNUNET_i2s (&b->pid));
7182  GST_stats,
7183  "# Backchannel messages dropped: monotonic time not increasing",
7184  1,
7185  GNUNET_NO);
7186  b->monotonic_time = mt;
7187  /* Setting body_size to 0 prevents call to #forward_backchannel_payload()
7188  */
7189  b->body_size = 0;
7190  return;
7191  }
7192 }
7193 
7194 
7202 static void
7203 backtalker_monotime_store_cb (void *cls, int success)
7204 {
7205  struct Backtalker *b = cls;
7206 
7207  if (GNUNET_OK != success)
7208  {
7210  "Failed to store backtalker's monotonic time in PEERSTORE!\n");
7211  }
7212  b->sc = NULL;
7214 }
7215 
7216 
7222 static void
7224 {
7225  struct GNUNET_TIME_AbsoluteNBO mtbe;
7226 
7227  if (NULL != b->sc)
7228  {
7230  b->sc = NULL;
7231  }
7232  else
7233  {
7235  b->task = NULL;
7236  }
7238  b->sc =
7239  GNUNET_PEERSTORE_store (peerstore,
7240  "transport",
7241  &b->pid,
7243  &mtbe,
7244  sizeof(mtbe),
7248  b);
7249 }
7250 
7251 
7259 static void
7260 handle_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
7261 {
7262  struct CommunicatorMessageContext *cmc = cls;
7263  uint16_t size = ntohs (dvb->header.size) - sizeof(*dvb);
7264  uint16_t num_hops = ntohs (dvb->num_hops);
7265  const struct GNUNET_PeerIdentity *hops =
7266  (const struct GNUNET_PeerIdentity *) &dvb[1];
7267  const char *enc_payload = (const char *) &hops[num_hops];
7268  uint16_t enc_payload_size =
7269  size - (num_hops * sizeof(struct GNUNET_PeerIdentity));
7270  struct DVKeyState key;
7271  struct GNUNET_HashCode hmac;
7272  const char *hdr;
7273  size_t hdr_len;
7274 
7275  if (GNUNET_EXTRA_LOGGING > 0)
7276  {
7277  char *path;
7278 
7280  for (unsigned int i = 0; i < num_hops; i++)
7281  {
7282  char *tmp;
7283 
7284  GNUNET_asprintf (&tmp, "%s->%s", path, GNUNET_i2s (&hops[i]));
7285  GNUNET_free (path);
7286  path = tmp;
7287  }
7289  "Received DVBox with remainig path %s\n",
7290  path);
7291  GNUNET_free (path);
7292  }
7293 
7294  if (num_hops > 0)
7295  {
7296  /* We're trying from the end of the hops array, as we may be
7297  able to find a shortcut unknown to the origin that way */
7298  for (int i = num_hops - 1; i >= 0; i--)
7299  {
7300  struct Neighbour *n;
7301 
7302  if (0 == GNUNET_memcmp (&hops[i], &GST_my_identity))
7303  {
7304  GNUNET_break_op (0);
7305  finish_cmc_handling (cmc);
7306  return;
7307  }
7308  n = lookup_neighbour (&hops[i]);
7309  if (NULL == n)
7310  continue;
7312  "Skipping %u/%u hops ahead while routing DV Box\n",
7313  i,
7314  num_hops);
7315  forward_dv_box (n,
7316  dvb,
7317  ntohs (dvb->total_hops) + 1,
7318  num_hops - i - 1, /* number of hops left */
7319  &hops[i + 1], /* remaining hops */
7320  enc_payload,
7321  enc_payload_size);
7322  GNUNET_STATISTICS_update (GST_stats,
7323  "# DV hops skipped routing boxes",
7324  i,
7325  GNUNET_NO);
7326  GNUNET_STATISTICS_update (GST_stats,
7327  "# DV boxes routed (total)",
7328  1,
7329  GNUNET_NO);
7330  finish_cmc_handling (cmc);
7331  return;
7332  }
7333  /* Woopsie, next hop not in neighbours, drop! */
7334  GNUNET_STATISTICS_update (GST_stats,
7335  "# DV Boxes dropped: next hop unknown",
7336  1,
7337  GNUNET_NO);
7338  finish_cmc_handling (cmc);
7339  return;
7340  }
7341  /* We are the target. Unbox and handle message. */
7342  GNUNET_STATISTICS_update (GST_stats,
7343  "# DV boxes opened (ultimate target)",
7344  1,
7345  GNUNET_NO);
7346  cmc->total_hops = ntohs (dvb->total_hops);
7347 
7348  dh_key_derive_eph_pub (&dvb->ephemeral_key, &dvb->iv, &key);
7349  hdr = (const char *) &dvb[1];
7350  hdr_len = ntohs (dvb->header.size) - sizeof(*dvb);
7351  dv_hmac (&key, &hmac, hdr, hdr_len);
7352  if (0 != GNUNET_memcmp (&hmac, &dvb->hmac))
7353  {
7354  /* HMAC missmatch, disard! */
7355  GNUNET_break_op (0);
7356  finish_cmc_handling (cmc);
7357  return;
7358  }
7359  /* begin actual decryption */
7360  {
7361  struct Backtalker *b;
7362  struct GNUNET_TIME_Absolute monotime;
7363  struct TransportDVBoxPayloadP ppay;
7364  char body[hdr_len - sizeof(ppay)] GNUNET_ALIGN;
7365  const struct GNUNET_MessageHeader *mh =
7366  (const struct GNUNET_MessageHeader *) body;
7367 
7368  GNUNET_assert (hdr_len >=
7369  sizeof(ppay) + sizeof(struct GNUNET_MessageHeader));
7370  dv_decrypt (&key, &ppay, hdr, sizeof(ppay));
7371  dv_decrypt (&key, &body, &hdr[sizeof(ppay)], hdr_len - sizeof(ppay));
7372  dv_key_clean (&key);
7373  if (ntohs (mh->size) != sizeof(body))
7374  {
7375  GNUNET_break_op (0);
7376  finish_cmc_handling (cmc);
7377  return;
7378  }
7379  /* need to prevent box-in-a-box (and DV_LEARN) so check inbox type! */
7380  switch (ntohs (mh->type))
7381  {
7383  GNUNET_break_op (0);
7384  finish_cmc_handling (cmc);
7385  return;
7386 
7388  GNUNET_break_op (0);
7389  finish_cmc_handling (cmc);
7390  return;
7391 
7392  default:
7393  /* permitted, continue */
7394  break;
7395  }
7396  monotime = GNUNET_TIME_absolute_ntoh (ppay.monotonic_time);
7398  "Decrypted backtalk from %s\n",
7399  GNUNET_i2s (&ppay.sender));
7400  b = GNUNET_CONTAINER_multipeermap_get (backtalkers, &ppay.sender);
7401  if ((NULL != b) && (monotime.abs_value_us < b->monotonic_time.abs_value_us))
7402  {
7404  GST_stats,
7405  "# Backchannel messages dropped: monotonic time not increasing",
7406  1,
7407  GNUNET_NO);
7408  finish_cmc_handling (cmc);
7409  return;
7410  }
7411  if ((NULL == b) ||
7412  (0 != GNUNET_memcmp (&b->last_ephemeral, &dvb->ephemeral_key)))
7413  {
7414  /* Check signature */
7415  struct EphemeralConfirmationPS ec;
7416 
7418  ec.purpose.size = htonl (sizeof(ec));
7419  ec.target = GST_my_identity;
7420  ec.ephemeral_key = dvb->ephemeral_key;
7421  if (
7422  GNUNET_OK !=
7425  &ec.purpose,
7426  &ppay.sender_sig,
7427  &ppay.sender.public_key))
7428  {
7429  /* Signature invalid, disard! */
7430  GNUNET_break_op (0);
7431  finish_cmc_handling (cmc);
7432  return;
7433  }
7434  }
7435  /* Update sender, we now know the real origin! */
7437  "DVBox received for me from %s via %s\n",
7438  GNUNET_i2s2 (&ppay.sender),
7439  GNUNET_i2s (&cmc->im.sender));
7440  cmc->im.sender = ppay.sender;
7441 
7442  if (NULL != b)
7443  {
7444  /* update key cache and mono time */
7445  b->last_ephemeral = dvb->ephemeral_key;
7446  b->monotonic_time = monotime;
7448  b->timeout =
7450 
7451  demultiplex_with_cmc (cmc, mh);
7452  return;
7453  }
7454  /* setup data structure to cache signature AND check
7455  monotonic time with PEERSTORE before forwarding backchannel payload */
7456  b = GNUNET_malloc (sizeof(struct Backtalker) + sizeof(body));
7457  b->pid = ppay.sender;
7458  b->body_size = sizeof(body);
7459  memcpy (&b[1], body, sizeof(body));
7462  backtalkers,
7463  &b->pid,
7464  b,
7466  b->monotonic_time = monotime; /* NOTE: to be checked still! */
7467  b->cmc = cmc;
7468  b->timeout =
7471  b->get =
7472  GNUNET_PEERSTORE_iterate (peerstore,
7473  "transport",
7474  &b->pid,
7477  b);
7478  } /* end actual decryption */
7479 }
7480 
7481 
7489 static int
7491  const struct GNUNET_TRANSPORT_IncomingMessage *im)
7492 {
7493  struct TransportClient *tc = cls;
7494 
7495  if (CT_COMMUNICATOR != tc->type)
7496  {
7497  GNUNET_break (0);
7498  return GNUNET_SYSERR;
7499  }
7501  return GNUNET_OK;
7502 }
7503 
7504 
7509 {
7513  const char *address;
7514 
7519 };
7520 
7521 
7531 static int
7533  const struct GNUNET_PeerIdentity *pid,
7534  void *value)
7535 {
7536  struct CheckKnownAddressContext *ckac = cls;
7537  struct ValidationState *vs = value;
7538 
7539  (void) pid;
7540  if (0 != strcmp (vs->address, ckac->address))
7541  return GNUNET_OK;
7542  ckac->vs = vs;
7543  return GNUNET_NO;
7544 }
7545 
7546 
7552 static void
7553 validation_start_cb (void *cls);
7554 
7555 
7563 static void
7565  struct GNUNET_TIME_Absolute new_time)
7566 {
7567  struct GNUNET_TIME_Relative delta;
7568 
7569  if (new_time.abs_value_us == vs->next_challenge.abs_value_us)
7570  return; /* be lazy */
7571  vs->next_challenge = new_time;
7572  if (NULL == vs->hn)
7573  vs->hn =
7574  GNUNET_CONTAINER_heap_insert (validation_heap, vs, new_time.abs_value_us);
7575  else
7577  if ((vs != GNUNET_CONTAINER_heap_peek (validation_heap)) &&
7578  (NULL != validation_task))
7579  return;
7580  if (NULL != validation_task)
7581  GNUNET_SCHEDULER_cancel (validation_task);
7582  /* randomize a bit */
7583  delta.rel_value_us =
7585  MIN_DELAY_ADDRESS_VALIDATION.rel_value_us);
7586  new_time = GNUNET_TIME_absolute_add (new_time, delta);
7587  validation_task =
7588  GNUNET_SCHEDULER_add_at (new_time, &validation_start_cb, NULL);
7589 }
7590 
7591 
7598 static void
7600  const char *address)
7601 {
7602  struct GNUNET_TIME_Absolute now;
7603  struct ValidationState *vs;
7604  struct CheckKnownAddressContext ckac = { .address = address, .vs = NULL };
7605 
7606  (void) GNUNET_CONTAINER_multipeermap_get_multiple (validation_map,
7607  pid,
7609  &ckac);
7610  if (NULL != (vs = ckac.vs))
7611  {
7612  /* if 'vs' is not currently valid, we need to speed up retrying the
7613  * validation */
7614  if (vs->validated_until.abs_value_us < vs->next_challenge.abs_value_us)
7615  {
7616  /* reduce backoff as we got a fresh advertisement */
7617  vs->challenge_backoff =
7620  vs->challenge_backoff,
7621  2));
7624  vs->challenge_backoff));
7625  }
7626  return;
7627  }
7628  now = GNUNET_TIME_absolute_get ();
7629  vs = GNUNET_new (struct ValidationState);
7630  vs->pid = *pid;
7631  vs->valid_until =
7633  vs->first_challenge_use = now;
7634  vs->validation_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
7636  &vs->challenge,
7637  sizeof(vs->challenge));
7638  vs->address = GNUNET_strdup (address);
7640  "Starting address validation `%s' of peer %s using challenge %s\n",
7641  address,
7642  GNUNET_i2s (pid),
7643  GNUNET_sh2s (&vs->challenge.value));
7646  validation_map,
7647  &vs->pid,
7648  vs,
7650  update_next_challenge_time (vs, now);
7651 }
7652 
7653 
7661 static void
7663  const struct GNUNET_PEERSTORE_Record *record,
7664  const char *emsg)
7665 {
7666  struct IncomingRequest *ir = cls;
7667  const char *val;
7668 
7669  if (NULL != emsg)
7670  {
7672  "Got failure from PEERSTORE: %s\n",
7673  emsg);
7674  return;
7675  }
7676  val = record->value;
7677  if ((0 == record->value_size) || ('\0' != val[record->value_size - 1]))
7678  {
7679  GNUNET_break (0);
7680  return;
7681  }
7682  start_address_validation (&ir->pid, (const char *) record->value);
7683 }
7684 
7685 
7694 static void
7696  void *cls,
7697  const struct TransportValidationChallengeMessage *tvc)
7698 {
7699  struct CommunicatorMessageContext *cmc = cls;
7701  struct VirtualLink *vl;
7702  struct GNUNET_TIME_RelativeNBO validity_duration;
7703  struct IncomingRequest *ir;
7704  struct Neighbour *n;
7705  struct GNUNET_PeerIdentity sender;
7706 
7707  /* DV-routed messages are not allowed for validation challenges */
7708  if (cmc->total_hops > 0)
7709  {
7710  GNUNET_break_op (0);
7711  finish_cmc_handling (cmc);
7712  return;
7713  }
7714  validity_duration = cmc->im.expected_address_validity;
7716  "Received address validation challenge %s\n",
7717  GNUNET_sh2s (&tvc->challenge.value));
7718  /* If we have a virtual link, we use this mechanism to signal the
7719  size of the flow control window, and to allow the sender
7720  to ask for increases. If for us the virtual link is still down,
7721  we will always give a window size of zero. */
7722  tvr.header.type =
7724  tvr.header.size = htons (sizeof(tvr));
7725  tvr.reserved = htonl (0);
7726  tvr.challenge = tvc->challenge;
7727  tvr.origin_time = tvc->sender_time;
7728  tvr.validity_duration = validity_duration;
7729  {
7730  /* create signature */
7731  struct TransportValidationPS tvp =
7733  .purpose.size = htonl (sizeof(tvp)),
7734  .validity_duration = validity_duration,
7735  .challenge = tvc->challenge };
7736 
7737  GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign (GST_my_private_key,
7738  &tvp.purpose,
7739  &tvr.signature));
7740  }
7741  route_control_message_without_fc (&cmc->im.sender,
7742  &tvr.header,
7744  sender = cmc->im.sender;
7745  finish_cmc_handling (cmc);
7746  vl = lookup_virtual_link (&sender);
7747  if (NULL != vl)
7748  return;
7749 
7750  /* For us, the link is still down, but we need bi-directional
7751  connections (for flow-control and for this to be useful for
7752  CORE), so we must try to bring the link up! */
7753 
7754  /* (1) Check existing queues, if any, we may be lucky! */
7755  n = lookup_neighbour (&sender);
7756  if (NULL != n)
7757  for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
7758  start_address_validation (&sender, q->address);
7759  /* (2) Also try to see if we have addresses in PEERSTORE for this peer
7760  we could use */
7761  for (ir = ir_head; NULL != ir; ir = ir->next)
7762  if (0 == GNUNET_memcmp (&ir->pid, &sender))
7763  return;
7764  /* we are already trying */
7765  ir = GNUNET_new (struct IncomingRequest);
7766  ir->pid = sender;
7767  GNUNET_CONTAINER_DLL_insert (ir_head, ir_tail, ir);
7768  ir->wc = GNUNET_PEERSTORE_watch (peerstore,
7769  "transport",
7770  &ir->pid,
7773  ir);
7774  ir_total++;
7775  /* Bound attempts we do in parallel here, might otherwise get excessive */
7776  while (ir_total > MAX_INCOMING_REQUEST)
7777  free_incoming_request (ir_head);
7778 }
7779 
7780 
7785 {
7790 
7795 };
7796 
7797 
7807 static int
7809  const struct GNUNET_PeerIdentity *pid,
7810  void *value)
7811 {
7812  struct CheckKnownChallengeContext *ckac = cls;
7813  struct ValidationState *vs = value;
7814 
7815  (void) pid;
7816  if (0 != GNUNET_memcmp (&vs->challenge, ckac->challenge))
7817  return GNUNET_OK;
7818  ckac->vs = vs;
7819  return GNUNET_NO;
7820 }
7821 
7822 
7830 static void
7831 peerstore_store_validation_cb (void *cls, int success)
7832 {
7833  struct ValidationState *vs = cls;
7834 
7835  vs->sc = NULL;
7836  if (GNUNET_YES == success)
7837  return;
7838  GNUNET_STATISTICS_update (GST_stats,
7839  "# Peerstore failed to store foreign address",
7840  1,
7841  GNUNET_NO);
7842 }
7843 
7844 
7852 static struct Queue *
7853 find_queue (const struct GNUNET_PeerIdentity *pid, const char *address)
7854 {
7855  struct Neighbour *n;
7856 
7857  n = lookup_neighbour (pid);
7858  if (NULL == n)
7859  return NULL;
7860  for (struct Queue *pos = n->queue_head; NULL != pos;
7861  pos = pos->next_neighbour)
7862  {
7863  if (0 == strcmp (pos->address, address))
7864  return pos;
7865  }
7866  return NULL;
7867 }
7868 
7869 
7878 static void
7880  void *cls,
7881  const struct TransportValidationResponseMessage *tvr)
7882 {
7883  struct CommunicatorMessageContext *cmc = cls;
7884  struct ValidationState *vs;
7885  struct CheckKnownChallengeContext ckac = { .challenge = &tvr->challenge,
7886  .vs = NULL };
7887  struct GNUNET_TIME_Absolute origin_time;
7888  struct Queue *q;
7889  struct Neighbour *n;
7890  struct VirtualLink *vl;
7891