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 
336 {
340  struct GNUNET_MessageHeader header;
341 
342  /* Followed by *another* message header which is the message to
343  the communicator */
344 
345  /* Followed by a 0-terminated name of the communicator */
346 };
347 
348 
353 {
358 
373  struct GNUNET_TIME_AbsoluteNBO sender_monotonic_time;
374 
378  struct GNUNET_PeerIdentity target;
379 
384  struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
385 };
386 
387 
393 {
397  struct GNUNET_PeerIdentity sender;
398 
403  struct GNUNET_CRYPTO_EddsaSignature sender_sig;
404 
415  struct GNUNET_TIME_AbsoluteNBO monotonic_time;
416 
417  /* Followed by a `struct GNUNET_MessageHeader` with a message
418  for the target peer */
419 };
420 
421 
427 {
431  struct GNUNET_MessageHeader header;
432 
439  uint32_t ack_countdown GNUNET_PACKED;
440 
446  struct AcknowledgementUUIDP ack_uuid;
447 };
448 
449 
454 {
461  struct GNUNET_TIME_RelativeNBO ack_delay;
462 
466  struct AcknowledgementUUIDP ack_uuid;
467 };
468 
469 
478 {
482  struct GNUNET_MessageHeader header;
483 
488  uint32_t ack_counter GNUNET_PACKED;
489 
490  /* followed by any number of `struct TransportCummulativeAckPayloadP`
491  messages providing ACKs */
492 };
493 
494 
499 {
503  struct GNUNET_MessageHeader header;
504 
508  uint16_t frag_off GNUNET_PACKED;
509 
513  uint16_t msg_size GNUNET_PACKED;
514 
522  struct AcknowledgementUUIDP ack_uuid;
523 
528  struct MessageUUIDP msg_uuid;
529 };
530 
531 
549 struct DvInitPS
550 {
555 
568  struct GNUNET_TIME_AbsoluteNBO monotonic_time;
569 
573  struct ChallengeNonceP challenge;
574 };
575 
576 
593 struct DvHopPS
594 {
599 
603  struct GNUNET_PeerIdentity pred;
604 
608  struct GNUNET_PeerIdentity succ;
609 
613  struct ChallengeNonceP challenge;
614 };
615 
616 
622 {
627 
633 };
634 
635 
650 {
654  struct GNUNET_MessageHeader header;
655 
660  uint16_t num_hops GNUNET_PACKED;
661 
670  uint16_t bidirectional GNUNET_PACKED;
671 
677  struct GNUNET_TIME_RelativeNBO non_network_delay;
678 
691  struct GNUNET_TIME_AbsoluteNBO monotonic_time;
692 
698 
702  struct GNUNET_PeerIdentity initiator;
703 
707  struct ChallengeNonceP challenge;
708 
709  /* Followed by @e num_hops `struct DVPathEntryP` values,
710  excluding the initiator of the DV trace; the last entry is the
711  current sender; the current peer must not be included. */
712 };
713 
714 
738 {
742  struct GNUNET_MessageHeader header;
743 
750  uint16_t total_hops GNUNET_PACKED;
751 
757  uint16_t num_hops GNUNET_PACKED;
758 
763  struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
764 
771 
777  struct GNUNET_HashCode hmac;
778 
779  /* Followed by @e num_hops `struct GNUNET_PeerIdentity` values;
780  excluding the @e origin and the current peer, the last must be
781  the ultimate target; if @e num_hops is zero, the receiver of this
782  message is the ultimate target. */
783 
784  /* Followed by encrypted, variable-size payload, which
785  must begin with a `struct TransportDVBoxPayloadP` */
786 
787  /* Followed by the actual message, which itself must not be a
788  a DV_LEARN or DV_BOX message! */
789 };
790 
791 
797 {
801  struct GNUNET_MessageHeader header;
802 
807 
811  struct ChallengeNonceP challenge;
812 
817  struct GNUNET_TIME_AbsoluteNBO sender_time;
818 };
819 
820 
826 {
831 
836  struct GNUNET_TIME_RelativeNBO validity_duration;
837 
841  struct ChallengeNonceP challenge;
842 };
843 
844 
850 {
854  struct GNUNET_MessageHeader header;
855 
860 
866 
870  struct ChallengeNonceP challenge;
871 
876  struct GNUNET_TIME_AbsoluteNBO origin_time;
877 
882  struct GNUNET_TIME_RelativeNBO validity_duration;
883 };
884 
885 
895 {
899  struct GNUNET_MessageHeader header;
900 
908  uint32_t seq GNUNET_PACKED;
909 
914  uint64_t inbound_window_size GNUNET_PACKED;
915 
921  uint64_t outbound_sent GNUNET_PACKED;
922 
931  uint64_t outbound_window_size GNUNET_PACKED;
932 
941  struct GNUNET_TIME_AbsoluteNBO sender_time;
942 };
943 
944 
946 
947 
952 {
956  CT_NONE = 0,
957 
961  CT_CORE = 1,
962 
967 
972 
977 };
978 
979 
985 {
989  RMO_NONE = 0,
990 
995 
1000 
1005 
1012 };
1013 
1014 
1019 {
1024 
1029 
1033  struct ChallengeNonceP challenge;
1034 
1039  struct GNUNET_TIME_Absolute launch_time;
1040 };
1041 
1042 
1048 {
1052  uint64_t bytes_sent;
1053 
1058  uint64_t bytes_received;
1059 };
1060 
1061 
1066 {
1070  struct GNUNET_TIME_Relative aged_rtt;
1071 
1077 
1082  unsigned int last_age;
1083 };
1084 
1085 
1089 struct TransportClient;
1090 
1094 struct Neighbour;
1095 
1100 struct DistanceVector;
1101 
1106 struct Queue;
1107 
1111 struct PendingMessage;
1112 
1116 struct DistanceVectorHop;
1117 
1126 struct VirtualLink;
1127 
1128 
1134 {
1140 
1146 
1151 
1155  struct GNUNET_TRANSPORT_IncomingMessage im;
1156 
1161  uint16_t total_hops;
1162 };
1163 
1164 
1169 {
1174 
1179 
1183  struct VirtualLink *vl;
1184 
1188  uint16_t size;
1189 
1196  uint16_t isize;
1197 };
1198 
1199 
1209 {
1213  struct GNUNET_PeerIdentity target;
1214 
1220 
1226 
1231 
1236 
1241 
1246 
1254 
1260 
1264  struct Neighbour *n;
1265 
1270 
1276  struct GNUNET_TIME_Absolute n_challenge_time;
1277 
1283  struct GNUNET_TIME_Absolute last_fc_transmission;
1284 
1292  struct GNUNET_TIME_Absolute last_fc_timestamp;
1293 
1298  struct GNUNET_TIME_Relative last_fc_rtt;
1299 
1305 
1314 
1322 
1329 
1338 
1351 
1357 
1364 
1375 
1380  uint32_t fc_seq_gen;
1381 
1387  uint32_t last_fc_seq;
1388 
1401 };
1402 
1403 
1408 {
1414 
1420 
1427 
1434 
1441 
1448 
1455 
1462 
1466  struct AcknowledgementUUIDP ack_uuid;
1467 
1473 
1479 
1484  struct Queue *queue;
1485 
1489  struct GNUNET_TIME_Absolute transmission_time;
1490 
1494  uint16_t message_size;
1495 };
1496 
1497 
1502 {
1507 
1512 
1517 
1522 
1527 
1532 
1537 
1542 
1548  const struct GNUNET_PeerIdentity *path;
1549 
1555 
1563  struct GNUNET_TIME_Absolute path_valid_until;
1564 
1568  struct PerformanceData pd;
1569 
1575  unsigned int distance;
1576 };
1577 
1578 
1584 {
1588  struct GNUNET_PeerIdentity target;
1589 
1594 
1599 
1604 
1609  struct VirtualLink *vl;
1610 
1615  struct GNUNET_CRYPTO_EddsaSignature sender_sig;
1616 
1620  struct GNUNET_TIME_Absolute ephemeral_validity;
1621 
1625  struct GNUNET_TIME_Absolute monotime;
1626 
1630  struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
1631 
1635  struct GNUNET_CRYPTO_EcdhePrivateKey private_key;
1636 };
1637 
1638 
1648 struct QueueEntry
1649 {
1653  struct QueueEntry *next;
1654 
1658  struct QueueEntry *prev;
1659 
1663  struct Queue *queue;
1664 
1669 
1673  uint64_t mid;
1674 };
1675 
1676 
1681 struct Queue
1682 {
1687 
1692 
1697 
1702 
1707 
1712 
1717 
1722 
1727 
1732 
1736  const char *address;
1737 
1743 
1751  struct GNUNET_TIME_Absolute validated_until;
1752 
1756  struct PerformanceData pd;
1757 
1762  uint64_t mid_gen;
1763 
1767  uint32_t qid;
1768 
1772  uint32_t mtu;
1773 
1778 
1783 
1787  unsigned int queue_length;
1788 
1792  uint32_t priority;
1793 
1797  enum GNUNET_NetworkType nt;
1798 
1803 
1808  int idle;
1809 };
1810 
1811 
1816 {
1821  struct MessageUUIDP msg_uuid;
1822 
1827 
1832 
1840  uint8_t *bitfield;
1841 
1845  struct GNUNET_TIME_Absolute reassembly_timeout;
1846 
1851  struct GNUNET_TIME_Absolute last_frag;
1852 
1856  uint16_t msg_size;
1857 
1862  uint16_t msg_missing;
1863 
1864  /* Followed by @e msg_size bytes of the (partially) defragmented original
1865  * message */
1866 
1867  /* Followed by @e bitfield data */
1868 };
1869 
1870 
1874 struct Neighbour
1875 {
1880 
1887 
1894 
1899 
1905 
1911 
1916 
1921 
1927 
1933 
1938  struct VirtualLink *vl;
1939 
1944  struct GNUNET_TIME_Absolute last_dv_learn_monotime;
1945 
1951 };
1952 
1953 
1959 {
1964 
1969 
1974 
1979 };
1980 
1981 
1985 struct PeerRequest
1986 {
1991 
1996 
2001 
2008 
2013 };
2014 
2015 
2020 {
2025 
2030 
2035 
2040 };
2041 
2042 
2069 struct PendingMessage
2070 {
2075 
2080 
2085 
2090 
2096 
2102 
2107 
2112 
2118 
2122  struct VirtualLink *vl;
2123 
2132  struct QueueEntry *qe;
2133 
2138 
2143 
2148 
2153 
2158 
2162  struct GNUNET_TIME_Absolute next_attempt;
2163 
2168  struct MessageUUIDP msg_uuid;
2169 
2174  unsigned long long logging_uuid;
2175 
2180 
2186 
2190  uint16_t bytes_msg;
2191 
2195  uint16_t frag_off;
2196 
2200  int16_t msg_uuid_set;
2201 
2202  /* Followed by @e bytes_msg to transmit */
2203 };
2204 
2205 
2210 {
2215  struct GNUNET_TIME_Absolute receive_time;
2216 
2220  struct AcknowledgementUUIDP ack_uuid;
2221 };
2222 
2223 
2229 {
2233  struct GNUNET_PeerIdentity target;
2234 
2239 
2246 
2250  struct GNUNET_TIME_Absolute min_transmission_time;
2251 
2257  uint32_t ack_counter;
2258 
2262  unsigned int num_acks;
2263 };
2264 
2265 
2270 {
2275 
2280 
2285 
2289  const char *address;
2290 
2295 
2300 
2306 
2310  uint32_t aid;
2311 
2316 };
2317 
2318 
2323 {
2328 
2333 
2338 
2343 
2348 
2349  union
2350  {
2354  struct
2355  {
2361 
2366  } core;
2367 
2371  struct
2372  {
2379 
2384  } monitor;
2385 
2386 
2390  struct
2391  {
2397 
2402 
2407 
2413 
2419 
2425  unsigned int total_queue_length;
2426 
2431  } communicator;
2432 
2436  struct
2437  {
2443  } application;
2444  } details;
2445 };
2446 
2447 
2453 {
2459 
2466  struct GNUNET_TIME_Absolute valid_until;
2467 
2472  struct GNUNET_TIME_Absolute validated_until;
2473 
2480  struct GNUNET_TIME_Absolute first_challenge_use;
2481 
2488  struct GNUNET_TIME_Absolute last_challenge_use;
2489 
2497  struct GNUNET_TIME_Absolute next_challenge;
2498 
2507  struct GNUNET_TIME_Relative challenge_backoff;
2508 
2513  struct GNUNET_TIME_Relative validation_rtt;
2514 
2522  struct ChallengeNonceP challenge;
2523 
2527  char *address;
2528 
2534  struct GNUNET_CONTAINER_HeapNode *hn;
2535 
2541 
2547  uint32_t last_window_consum_limit;
2548 
2553  int awaiting_queue;
2554 };
2555 
2556 
2564 {
2569 
2573  struct GNUNET_TIME_Absolute monotonic_time;
2574 
2579 
2583  struct GNUNET_CRYPTO_EcdhePublicKey last_ephemeral;
2584 
2590 
2595 
2601 
2607 
2612  size_t body_size;
2613 };
2614 
2615 
2620 
2625 
2630 
2635 
2640 
2645 
2651 
2657 
2663 
2669 
2675 
2681 
2687 
2692 
2696 static struct LearnLaunchEntry *lle_head = NULL;
2697 
2701 static struct LearnLaunchEntry *lle_tail = NULL;
2702 
2709 
2714 
2719 
2724 
2730 
2736 
2742 static struct IncomingRequest *ir_head;
2743 
2747 static struct IncomingRequest *ir_tail;
2748 
2752 static unsigned int ir_total;
2753 
2757 static unsigned long long logging_uuid_gen;
2758 
2763 static unsigned int pa_count;
2764 
2774 
2779 static int in_shutdown;
2780 
2791 static unsigned int
2793 {
2794  struct GNUNET_TIME_Absolute now;
2795 
2796  now = GNUNET_TIME_absolute_get ();
2797  return now.abs_value_us / GNUNET_TIME_UNIT_MINUTES.rel_value_us / 15;
2798 }
2799 
2800 
2806 static void
2808 {
2809  GNUNET_CONTAINER_DLL_remove (ir_head, ir_tail, ir);
2810  GNUNET_assert (ir_total > 0);
2811  ir_total--;
2813  ir->wc = NULL;
2814  GNUNET_free (ir);
2815 }
2816 
2817 
2823 static void
2825 {
2826  struct Queue *q = pa->queue;
2827  struct PendingMessage *pm = pa->pm;
2828  struct DistanceVectorHop *dvh = pa->dvh;
2829 
2830  GNUNET_CONTAINER_MDLL_remove (pa, pa_head, pa_tail, pa);
2831  pa_count--;
2832  if (NULL != q)
2833  {
2835  pa->queue = NULL;
2836  }
2837  if (NULL != pm)
2838  {
2839  GNUNET_CONTAINER_MDLL_remove (pm, pm->pa_head, pm->pa_tail, pa);
2840  pa->pm = NULL;
2841  }
2842  if (NULL != dvh)
2843  {
2844  GNUNET_CONTAINER_MDLL_remove (dvh, dvh->pa_head, dvh->pa_tail, pa);
2845  pa->queue = NULL;
2846  }
2849  &pa->ack_uuid.value,
2850  pa));
2851  GNUNET_free (pa);
2852 }
2853 
2854 
2863 static void
2865 {
2866  struct PendingMessage *frag;
2867 
2868  while (NULL != (frag = root->head_frag))
2869  {
2870  struct PendingAcknowledgement *pa;
2871 
2872  free_fragment_tree (frag);
2873  while (NULL != (pa = frag->pa_head))
2874  {
2875  GNUNET_CONTAINER_MDLL_remove (pm, frag->pa_head, frag->pa_tail, pa);
2876  pa->pm = NULL;
2877  }
2878  GNUNET_CONTAINER_MDLL_remove (frag, root->head_frag, root->tail_frag, frag);
2879  GNUNET_free (frag);
2880  }
2881 }
2882 
2883 
2891 static void
2893 {
2894  struct TransportClient *tc = pm->client;
2895  struct VirtualLink *vl = pm->vl;
2896  struct PendingAcknowledgement *pa;
2897 
2898  if (NULL != tc)
2899  {
2901  tc->details.core.pending_msg_head,
2902  tc->details.core.pending_msg_tail,
2903  pm);
2904  }
2905  if (NULL != vl)
2906  {
2908  vl->pending_msg_head,
2909  vl->pending_msg_tail,
2910  pm);
2911  }
2912  while (NULL != (pa = pm->pa_head))
2913  {
2914  GNUNET_CONTAINER_MDLL_remove (pm, pm->pa_head, pm->pa_tail, pa);
2915  pa->pm = NULL;
2916  }
2917 
2918  free_fragment_tree (pm);
2919  if (NULL != pm->qe)
2920  {
2921  GNUNET_assert (pm == pm->qe->pm);
2922  pm->qe->pm = NULL;
2923  }
2924  if (NULL != pm->bpm)
2925  {
2926  free_fragment_tree (pm->bpm);
2927  GNUNET_free (pm->bpm);
2928  }
2929  GNUNET_free (pm);
2930 }
2931 
2932 
2938 static void
2940 {
2941  struct PendingMessage *pm;
2942  struct CoreSentContext *csc;
2943 
2944  while (NULL != (pm = vl->pending_msg_head))
2945  free_pending_message (pm);
2947  GNUNET_CONTAINER_multipeermap_remove (links, &vl->target, vl));
2948  if (NULL != vl->visibility_task)
2949  {
2951  vl->visibility_task = NULL;
2952  }
2953  if (NULL != vl->fc_retransmit_task)
2954  {
2956  vl->fc_retransmit_task = NULL;
2957  }
2958  while (NULL != (csc = vl->csc_head))
2959  {
2961  GNUNET_assert (vl == csc->vl);
2962  csc->vl = NULL;
2963  }
2964  GNUNET_break (NULL == vl->n);
2965  GNUNET_break (NULL == vl->dv);
2966  GNUNET_free (vl);
2967 }
2968 
2969 
2975 static void
2977 {
2978  GNUNET_assert (
2979  GNUNET_YES ==
2980  GNUNET_CONTAINER_multipeermap_remove (validation_map, &vs->pid, vs));
2982  vs->hn = NULL;
2983  if (NULL != vs->sc)
2984  {
2986  vs->sc = NULL;
2987  }
2988  GNUNET_free (vs->address);
2989  GNUNET_free (vs);
2990 }
2991 
2992 
2999 static struct Neighbour *
3001 {
3002  return GNUNET_CONTAINER_multipeermap_get (neighbours, pid);
3003 }
3004 
3005 
3012 static struct VirtualLink *
3014 {
3015  return GNUNET_CONTAINER_multipeermap_get (links, pid);
3016 }
3017 
3018 
3023 {
3027  struct GNUNET_TIME_Absolute last_validation;
3028  struct GNUNET_TIME_Absolute valid_until;
3029  struct GNUNET_TIME_Absolute next_validation;
3030 
3035 
3040 
3045 
3050 };
3051 
3052 
3061 static void
3063 {
3064  struct Neighbour *n = dvh->next_hop;
3065  struct DistanceVector *dv = dvh->dv;
3066  struct PendingAcknowledgement *pa;
3067 
3068  while (NULL != (pa = dvh->pa_head))
3069  {
3070  GNUNET_CONTAINER_MDLL_remove (dvh, dvh->pa_head, dvh->pa_tail, pa);
3071  pa->dvh = NULL;
3072  }
3073  GNUNET_CONTAINER_MDLL_remove (neighbour, n->dv_head, n->dv_tail, dvh);
3074  GNUNET_CONTAINER_MDLL_remove (dv, dv->dv_head, dv->dv_tail, dvh);
3075  GNUNET_free (dvh);
3076 }
3077 
3078 
3085 static void
3086 check_link_down (void *cls);
3087 
3088 
3094 static void
3096 {
3098  "Informing CORE clients about disconnect from %s\n",
3099  GNUNET_i2s (pid));
3100  for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
3101  {
3102  struct GNUNET_MQ_Envelope *env;
3103  struct DisconnectInfoMessage *dim;
3104 
3105  if (CT_CORE != tc->type)
3106  continue;
3108  dim->peer = *pid;
3109  GNUNET_MQ_send (tc->mq, env);
3110  }
3111 }
3112 
3113 
3120 static void
3122 {
3123  struct DistanceVectorHop *dvh;
3124 
3125  while (NULL != (dvh = dv->dv_head))
3127  if (NULL == dv->dv_head)
3128  {
3129  struct VirtualLink *vl;
3130 
3131  GNUNET_assert (
3132  GNUNET_YES ==
3133  GNUNET_CONTAINER_multipeermap_remove (dv_routes, &dv->target, dv));
3134  if (NULL != (vl = dv->vl))
3135  {
3136  GNUNET_assert (dv == vl->dv);
3137  vl->dv = NULL;
3138  if (NULL == vl->n)
3139  {
3141  free_virtual_link (vl);
3142  }
3143  else
3144  {
3147  }
3148  dv->vl = NULL;
3149  }
3150 
3151  if (NULL != dv->timeout_task)
3152  {
3154  dv->timeout_task = NULL;
3155  }
3156  GNUNET_free (dv);
3157  }
3158 }
3159 
3160 
3174 static void
3176  const struct GNUNET_PeerIdentity *peer,
3177  const char *address,
3178  enum GNUNET_NetworkType nt,
3179  const struct MonitorEvent *me)
3180 {
3181  struct GNUNET_MQ_Envelope *env;
3182  struct GNUNET_TRANSPORT_MonitorData *md;
3183  size_t addr_len = strlen (address) + 1;
3184 
3185  env = GNUNET_MQ_msg_extra (md,
3186  addr_len,
3188  md->nt = htonl ((uint32_t) nt);
3189  md->peer = *peer;
3190  md->last_validation = GNUNET_TIME_absolute_hton (me->last_validation);
3191  md->valid_until = GNUNET_TIME_absolute_hton (me->valid_until);
3192  md->next_validation = GNUNET_TIME_absolute_hton (me->next_validation);
3193  md->rtt = GNUNET_TIME_relative_hton (me->rtt);
3194  md->cs = htonl ((uint32_t) me->cs);
3195  md->num_msg_pending = htonl (me->num_msg_pending);
3196  md->num_bytes_pending = htonl (me->num_bytes_pending);
3197  memcpy (&md[1], address, addr_len);
3198  GNUNET_MQ_send (tc->mq, env);
3199 }
3200 
3201 
3211 static void
3213  const char *address,
3214  enum GNUNET_NetworkType nt,
3215  const struct MonitorEvent *me)
3216 {
3217  for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
3218  {
3219  if (CT_MONITOR != tc->type)
3220  continue;
3221  if (tc->details.monitor.one_shot)
3222  continue;
3223  if ((GNUNET_NO == GNUNET_is_zero (&tc->details.monitor.peer)) &&
3224  (0 != GNUNET_memcmp (&tc->details.monitor.peer, peer)))
3225  continue;
3226  notify_monitor (tc, peer, address, nt, me);
3227  }
3228 }
3229 
3230 
3240 static void *
3242  struct GNUNET_SERVICE_Client *client,
3243  struct GNUNET_MQ_Handle *mq)
3244 {
3245  struct TransportClient *tc;
3246 
3247  (void) cls;
3248  tc = GNUNET_new (struct TransportClient);
3249  tc->client = client;
3250  tc->mq = mq;
3251  GNUNET_CONTAINER_DLL_insert (clients_head, clients_tail, tc);
3252  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", tc);
3253  return tc;
3254 }
3255 
3256 
3262 static void
3264 {
3265  struct Neighbour *n = rc->neighbour;
3266 
3270  rc->msg_uuid.uuid,
3271  rc));
3272  GNUNET_free (rc);
3273 }
3274 
3275 
3281 static void
3283 {
3284  struct Neighbour *n = cls;
3285  struct ReassemblyContext *rc;
3286 
3287  n->reassembly_timeout_task = NULL;
3288  while (NULL != (rc = GNUNET_CONTAINER_heap_peek (n->reassembly_heap)))
3289  {
3291  .rel_value_us)
3292  {
3294  continue;
3295  }
3300  n);
3301  return;
3302  }
3303 }
3304 
3305 
3314 static int
3315 free_reassembly_cb (void *cls, uint32_t key, void *value)
3316 {
3317  struct ReassemblyContext *rc = value;
3318 
3319  (void) cls;
3320  (void) key;
3322  return GNUNET_OK;
3323 }
3324 
3325 
3331 static void
3333 {
3334  struct DistanceVectorHop *dvh;
3335  struct VirtualLink *vl;
3336 
3337  GNUNET_assert (NULL == neighbour->queue_head);
3340  &neighbour->pid,
3341  neighbour));
3343  "Freeing neighbour\n");
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  "Transmission throttled due to communicator queue limit\n");
3465  GST_stats,
3466  "# Transmission throttled due to communicator queue limit",
3467  1,
3468  GNUNET_NO);
3469  queue->idle = GNUNET_NO;
3470  return;
3471  }
3472  if (queue->queue_length >= QUEUE_LENGTH_LIMIT)
3473  {
3475  "Transmission throttled due to communicator queue length limit\n");
3476  GNUNET_STATISTICS_update (GST_stats,
3477  "# Transmission throttled due to queue queue limit",
3478  1,
3479  GNUNET_NO);
3480  queue->idle = GNUNET_NO;
3481  return;
3482  }
3483  /* queue might indeed be ready, schedule it */
3484  if (NULL != queue->transmit_task)
3486  queue->transmit_task =
3489  "Considering transmission on queue `%s' to %s\n",
3490  queue->address,
3491  GNUNET_i2s (&queue->neighbour->pid));
3492 }
3493 
3494 
3501 static void
3502 check_link_down (void *cls)
3503 {
3504  struct VirtualLink *vl = cls;
3505  struct DistanceVector *dv = vl->dv;
3506  struct Neighbour *n = vl->n;
3507  struct GNUNET_TIME_Absolute dvh_timeout;
3508  struct GNUNET_TIME_Absolute q_timeout;
3509 
3511  "Checking if link is down\n");
3512  vl->visibility_task = NULL;
3513  dvh_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
3514  if (NULL != dv)
3515  {
3516  for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
3517  pos = pos->next_dv)
3518  dvh_timeout = GNUNET_TIME_absolute_max (dvh_timeout,
3519  pos->path_valid_until);
3520  if (0 == GNUNET_TIME_absolute_get_remaining (dvh_timeout).rel_value_us)
3521  {
3522  vl->dv->vl = NULL;
3523  vl->dv = NULL;
3524  }
3525  }
3526  q_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
3527  for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
3528  q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
3529  if (0 == GNUNET_TIME_absolute_get_remaining (q_timeout).rel_value_us)
3530  {
3531  vl->n->vl = NULL;
3532  vl->n = NULL;
3533  }
3534  if ((NULL == vl->n) && (NULL == vl->dv))
3535  {
3537  free_virtual_link (vl);
3538  return;
3539  }
3540  vl->visibility_task =
3541  GNUNET_SCHEDULER_add_at (GNUNET_TIME_absolute_max (q_timeout, dvh_timeout),
3542  &check_link_down,
3543  vl);
3544 }
3545 
3546 
3552 static void
3554 {
3555  struct Neighbour *neighbour = queue->neighbour;
3556  struct TransportClient *tc = queue->tc;
3557  struct MonitorEvent me = { .cs = GNUNET_TRANSPORT_CS_DOWN,
3559  struct QueueEntry *qe;
3560  int maxxed;
3561  struct PendingAcknowledgement *pa;
3562  struct VirtualLink *vl;
3563 
3565  "Cleaning up queue %u\n", queue->qid);
3566  if (NULL != queue->transmit_task)
3567  {
3569  queue->transmit_task = NULL;
3570  }
3571  while (NULL != (pa = queue->pa_head))
3572  {
3573  GNUNET_CONTAINER_MDLL_remove (queue, queue->pa_head, queue->pa_tail, pa);
3574  pa->queue = NULL;
3575  }
3576 
3577  GNUNET_CONTAINER_MDLL_remove (neighbour,
3578  neighbour->queue_head,
3579  neighbour->queue_tail,
3580  queue);
3582  tc->details.communicator.queue_head,
3583  tc->details.communicator.queue_tail,
3584  queue);
3585  maxxed = (COMMUNICATOR_TOTAL_QUEUE_LIMIT >=
3586  tc->details.communicator.total_queue_length);
3587  while (NULL != (qe = queue->queue_head))
3588  {
3589  GNUNET_CONTAINER_DLL_remove (queue->queue_head, queue->queue_tail, qe);
3590  queue->queue_length--;
3591  tc->details.communicator.total_queue_length--;
3592  if (NULL != qe->pm)
3593  {
3594  GNUNET_assert (qe == qe->pm->qe);
3595  qe->pm->qe = NULL;
3596  }
3597  GNUNET_free (qe);
3598  }
3599  GNUNET_assert (0 == queue->queue_length);
3600  if ((maxxed) && (COMMUNICATOR_TOTAL_QUEUE_LIMIT <
3601  tc->details.communicator.total_queue_length))
3602  {
3603  /* Communicator dropped below threshold, resume all _other_ queues */
3605  GST_stats,
3606  "# Transmission throttled due to communicator queue limit",
3607  -1,
3608  GNUNET_NO);
3609  for (struct Queue *s = tc->details.communicator.queue_head; NULL != s;
3610  s = s->next_client)
3612  }
3613  notify_monitors (&neighbour->pid, queue->address, queue->nt, &me);
3614  GNUNET_free (queue);
3615 
3616  vl = lookup_virtual_link (&neighbour->pid);
3617  if ((NULL != vl) && (neighbour == vl->n))
3618  {
3620  check_link_down (vl);
3621  }
3622  if (NULL == neighbour->queue_head)
3623  {
3624  free_neighbour (neighbour);
3625  }
3626 }
3627 
3628 
3634 static void
3636 {
3637  struct TransportClient *tc = ale->tc;
3638 
3640  tc->details.communicator.addr_tail,
3641  ale);
3642  if (NULL != ale->sc)
3643  {
3645  ale->sc = NULL;
3646  }
3647  if (NULL != ale->st)
3648  {
3649  GNUNET_SCHEDULER_cancel (ale->st);
3650  ale->st = NULL;
3651  }
3652  GNUNET_free (ale);
3653 }
3654 
3655 
3664 static int
3666  const struct GNUNET_PeerIdentity *pid,
3667  void *value)
3668 {
3669  struct TransportClient *tc = cls;
3670  struct PeerRequest *pr = value;
3671 
3673  pr->wc = NULL;
3674  GNUNET_assert (
3675  GNUNET_YES ==
3677  pid,
3678  pr));
3679  GNUNET_free (pr);
3680 
3681  return GNUNET_OK;
3682 }
3683 
3684 
3685 static void
3686 do_shutdown (void *cls);
3687 
3696 static void
3698  struct GNUNET_SERVICE_Client *client,
3699  void *app_ctx)
3700 {
3701  struct TransportClient *tc = app_ctx;
3702 
3703  (void) cls;
3704  (void) client;
3705  GNUNET_CONTAINER_DLL_remove (clients_head, clients_tail, tc);
3706  switch (tc->type)
3707  {
3708  case CT_NONE:
3710  "Unknown Client %p disconnected, cleaning up.\n",
3711  tc);
3712  break;
3713 
3714  case CT_CORE: {
3716  "CORE Client %p disconnected, cleaning up.\n",
3717  tc);
3718 
3719  struct PendingMessage *pm;
3720 
3721  while (NULL != (pm = tc->details.core.pending_msg_head))
3722  {
3724  tc->details.core.pending_msg_head,
3725  tc->details.core.pending_msg_tail,
3726  pm);
3727  pm->client = NULL;
3728  }
3729  }
3730  break;
3731 
3732  case CT_MONITOR:
3734  "MONITOR Client %p disconnected, cleaning up.\n",
3735  tc);
3736 
3737  break;
3738 
3739  case CT_COMMUNICATOR: {
3741  "COMMUNICATOR Client %p disconnected, cleaning up.\n",
3742  tc);
3743 
3744  struct Queue *q;
3745  struct AddressListEntry *ale;
3746 
3747  while (NULL != (q = tc->details.communicator.queue_head))
3748  free_queue (q);
3749  while (NULL != (ale = tc->details.communicator.addr_head))
3751  GNUNET_free (tc->details.communicator.address_prefix);
3752  }
3753  break;
3754 
3755  case CT_APPLICATION:
3757  "APPLICATION Client %p disconnected, cleaning up.\n",
3758  tc);
3759 
3762  tc);
3764  break;
3765  }
3766  GNUNET_free (tc);
3767  if ((GNUNET_YES == in_shutdown) && (NULL == clients_head))
3768  {
3770  "Our last client disconnected\n");
3771  do_shutdown (cls);
3772  }
3773 }
3774 
3775 
3785 static int
3787  const struct GNUNET_PeerIdentity *pid,
3788  void *value)
3789 {
3790  struct TransportClient *tc = cls;
3791 
3792  (void) value;
3794  "Telling new CORE client about existing connection to %s\n",
3795  GNUNET_i2s (pid));
3796  core_send_connect_info (tc, pid);
3797  return GNUNET_OK;
3798 }
3799 
3800 
3809 static void
3810 handle_client_start (void *cls, const struct StartMessage *start)
3811 {
3812  struct TransportClient *tc = cls;
3813  uint32_t options;
3814 
3815  options = ntohl (start->options);
3816  if ((0 != (1 & options)) &&
3817  (0 != GNUNET_memcmp (&start->self, &GST_my_identity)))
3818  {
3819  /* client thinks this is a different peer, reject */
3820  GNUNET_break (0);
3822  return;
3823  }
3824  if (CT_NONE != tc->type)
3825  {
3826  GNUNET_break (0);
3828  return;
3829  }
3830  tc->type = CT_CORE;
3832  "New CORE client with PID %s registered\n",
3833  GNUNET_i2s (&start->self));
3836  tc);
3838 }
3839 
3840 
3847 static int
3848 check_client_send (void *cls, const struct OutboundMessage *obm)
3849 {
3850  struct TransportClient *tc = cls;
3851  uint16_t size;
3852  const struct GNUNET_MessageHeader *obmm;
3853 
3854  if (CT_CORE != tc->type)
3855  {
3856  GNUNET_break (0);
3857  return GNUNET_SYSERR;
3858  }
3859  size = ntohs (obm->header.size) - sizeof(struct OutboundMessage);
3860  if (size < sizeof(struct GNUNET_MessageHeader))
3861  {
3862  GNUNET_break (0);
3863  return GNUNET_SYSERR;
3864  }
3865  obmm = (const struct GNUNET_MessageHeader *) &obm[1];
3866  if (size != ntohs (obmm->size))
3867  {
3868  GNUNET_break (0);
3869  return GNUNET_SYSERR;
3870  }
3871  return GNUNET_OK;
3872 }
3873 
3874 
3882 static void
3884 {
3885  struct TransportClient *tc = pm->client;
3886  struct VirtualLink *vl = pm->vl;
3887 
3888  if (NULL != tc)
3889  {
3890  struct GNUNET_MQ_Envelope *env;
3891  struct SendOkMessage *so_msg;
3892 
3894  so_msg->peer = vl->target;
3896  "Confirming transmission of <%llu> to %s\n",
3897  pm->logging_uuid,
3898  GNUNET_i2s (&vl->target));
3899  GNUNET_MQ_send (tc->mq, env);
3900  }
3901  free_pending_message (pm);
3902 }
3903 
3904 
3914 static unsigned int
3917  struct DistanceVectorHop **hops_array,
3918  unsigned int hops_array_length)
3919 {
3920  uint64_t choices[hops_array_length];
3921  uint64_t num_dv;
3922  unsigned int dv_count;
3923 
3924  /* Pick random vectors, but weighted by distance, giving more weight
3925  to shorter vectors */
3926  num_dv = 0;
3927  dv_count = 0;
3928  for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
3929  pos = pos->next_dv)
3930  {
3931  if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) &&
3932  (GNUNET_TIME_absolute_get_remaining (pos->path_valid_until)
3933  .rel_value_us == 0))
3934  continue; /* pos unconfirmed and confirmed required */
3935  num_dv += MAX_DV_HOPS_ALLOWED - pos->distance;
3936  dv_count++;
3937  }
3938  if (0 == dv_count)
3939  return 0;
3940  if (dv_count <= hops_array_length)
3941  {
3942  dv_count = 0;
3943  for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
3944  pos = pos->next_dv)
3945  hops_array[dv_count++] = pos;
3946  return dv_count;
3947  }
3948  for (unsigned int i = 0; i < hops_array_length; i++)
3949  {
3950  int ok = GNUNET_NO;
3951  while (GNUNET_NO == ok)
3952  {
3953  choices[i] =
3955  ok = GNUNET_YES;
3956  for (unsigned int j = 0; j < i; j++)
3957  if (choices[i] == choices[j])
3958  {
3959  ok = GNUNET_NO;
3960  break;
3961  }
3962  }
3963  }
3964  dv_count = 0;
3965  num_dv = 0;
3966  for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
3967  pos = pos->next_dv)
3968  {
3969  uint32_t delta = MAX_DV_HOPS_ALLOWED - pos->distance;
3970 
3971  if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) &&
3972  (GNUNET_TIME_absolute_get_remaining (pos->path_valid_until)
3973  .rel_value_us == 0))
3974  continue; /* pos unconfirmed and confirmed required */
3975  for (unsigned int i = 0; i < hops_array_length; i++)
3976  if ((num_dv <= choices[i]) && (num_dv + delta > choices[i]))
3977  hops_array[dv_count++] = pos;
3978  num_dv += delta;
3979  }
3980  return dv_count;
3981 }
3982 
3983 
3990 static int
3992  void *cls,
3993  const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
3994 {
3995  struct TransportClient *tc = cls;
3996  uint16_t size;
3997 
3998  if (CT_NONE != tc->type)
3999  {
4000  GNUNET_break (0);
4001  return GNUNET_SYSERR;
4002  }
4003  tc->type = CT_COMMUNICATOR;
4004  size = ntohs (cam->header.size) - sizeof(*cam);
4005  if (0 == size)
4006  return GNUNET_OK; /* receive-only communicator */
4008  return GNUNET_OK;
4009 }
4010 
4011 
4017 static void
4019 {
4020  if (0 != ntohl (cmc->im.fc_on))
4021  {
4022  /* send ACK when done to communicator for flow control! */
4023  struct GNUNET_MQ_Envelope *env;
4024  struct GNUNET_TRANSPORT_IncomingMessageAck *ack;
4025 
4027  ack->reserved = htonl (0);
4028  ack->fc_id = cmc->im.fc_id;
4029  ack->sender = cmc->im.sender;
4030  GNUNET_MQ_send (cmc->tc->mq, env);
4031  }
4033  GNUNET_free (cmc);
4034 }
4035 
4036 
4046 static void
4047 handle_client_recv_ok (void *cls, const struct RecvOkMessage *rom)
4048 {
4049  struct TransportClient *tc = cls;
4050  struct VirtualLink *vl;
4051  uint32_t delta;
4052  struct CommunicatorMessageContext *cmc;
4053 
4054  if (CT_CORE != tc->type)
4055  {
4056  GNUNET_break (0);
4058  return;
4059  }
4060  vl = lookup_virtual_link (&rom->peer);
4061  if (NULL == vl)
4062  {
4063  GNUNET_STATISTICS_update (GST_stats,
4064  "# RECV_OK dropped: virtual link unknown",
4065  1,
4066  GNUNET_NO);
4068  return;
4069  }
4070  delta = ntohl (rom->increase_window_delta);
4071  vl->core_recv_window += delta;
4072  if (vl->core_recv_window <= 0)
4073  return;
4074  /* resume communicators */
4075  while (NULL != (cmc = vl->cmc_tail))
4076  {
4078  finish_cmc_handling (cmc);
4079  }
4080 }
4081 
4082 
4089 static void
4091  void *cls,
4092  const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
4093 {
4094  struct TransportClient *tc = cls;
4095  uint16_t size;
4096 
4097  size = ntohs (cam->header.size) - sizeof(*cam);
4098  if (0 == size)
4099  {
4101  "Receive-only communicator connected\n");
4102  return; /* receive-only communicator */
4103  }
4104  tc->details.communicator.address_prefix =
4105  GNUNET_strdup ((const char *) &cam[1]);
4106  tc->details.communicator.cc =
4107  (enum GNUNET_TRANSPORT_CommunicatorCharacteristics) ntohl (cam->cc);
4109  "Communicator with prefix `%s' connected\n",
4110  tc->details.communicator.address_prefix);
4112 }
4113 
4114 
4122 static int
4124  void *cls,
4125  const struct GNUNET_TRANSPORT_CommunicatorBackchannel *cb)
4126 {
4127  const struct GNUNET_MessageHeader *inbox;
4128  const char *is;
4129  uint16_t msize;
4130  uint16_t isize;
4131 
4132  (void) cls;
4133  msize = ntohs (cb->header.size) - sizeof(*cb);
4134  inbox = (const struct GNUNET_MessageHeader *) &cb[1];
4135  isize = ntohs (inbox->size);
4136  if (isize >= msize)
4137  {
4138  GNUNET_break (0);
4139  return GNUNET_SYSERR;
4140  }
4141  is = (const char *) inbox;
4142  is += isize;
4143  msize -= isize;
4144  GNUNET_assert (0 < msize);
4145  if ('\0' != is[msize - 1])
4146  {
4147  GNUNET_break (0);
4148  return GNUNET_SYSERR;
4149  }
4150  return GNUNET_OK;
4151 }
4152 
4153 
4160 static void
4162 {
4163  struct EphemeralConfirmationPS ec;
4164 
4165  if (0 !=
4167  return;
4169  dv->ephemeral_validity =
4174  ec.purpose.size = htonl (sizeof(ec));
4175  ec.target = dv->target;
4176  ec.ephemeral_key = dv->ephemeral_key;
4177  GNUNET_CRYPTO_eddsa_sign (GST_my_private_key,
4178  &ec,
4179  &dv->sender_sig);
4180 }
4181 
4182 
4192 static void
4194  struct PendingMessage *pm,
4195  const void *payload,
4196  size_t payload_size)
4197 {
4198  struct Neighbour *n = queue->neighbour;
4199  struct GNUNET_TRANSPORT_SendMessageTo *smt;
4200  struct GNUNET_MQ_Envelope *env;
4201 
4202  GNUNET_log (
4204  "Queueing %u bytes of payload for transmission <%llu> on queue %llu to %s\n",
4205  (unsigned int) payload_size,
4206  (NULL == pm) ? 0 : pm->logging_uuid,
4207  (unsigned long long) queue->qid,
4208  GNUNET_i2s (&queue->neighbour->pid));
4209  env = GNUNET_MQ_msg_extra (smt,
4210  payload_size,
4212  smt->qid = queue->qid;
4213  smt->mid = queue->mid_gen;
4214  smt->receiver = n->pid;
4215  memcpy (&smt[1], payload, payload_size);
4216  {
4217  /* Pass the env to the communicator of queue for transmission. */
4218  struct QueueEntry *qe;
4219 
4220  qe = GNUNET_new (struct QueueEntry);
4221  qe->mid = queue->mid_gen++;
4222  qe->queue = queue;
4223  if (NULL != pm)
4224  {
4225  qe->pm = pm;
4226  GNUNET_assert (NULL == pm->qe);
4227  pm->qe = qe;
4228  }
4229  GNUNET_CONTAINER_DLL_insert (queue->queue_head, queue->queue_tail, qe);
4230  GNUNET_assert (CT_COMMUNICATOR == queue->tc->type);
4231  queue->queue_length++;
4232  queue->tc->details.communicator.total_queue_length++;
4234  queue->tc->details.communicator.total_queue_length)
4235  queue->idle = GNUNET_NO;
4236  if (QUEUE_LENGTH_LIMIT == queue->queue_length)
4237  queue->idle = GNUNET_NO;
4238  GNUNET_MQ_send (queue->tc->mq, env);
4239  }
4240 }
4241 
4242 
4253 static struct GNUNET_TIME_Relative
4255  const struct GNUNET_MessageHeader *hdr,
4257 {
4258  struct GNUNET_TIME_Absolute now;
4259  unsigned int candidates;
4260  unsigned int sel1;
4261  unsigned int sel2;
4262  struct GNUNET_TIME_Relative rtt;
4263 
4264  /* Pick one or two 'random' queues from n (under constraints of options) */
4265  now = GNUNET_TIME_absolute_get ();
4266  /* FIXME-OPTIMIZE: give queues 'weights' and pick proportional to
4267  weight in the future; weight could be assigned by observed
4268  bandwidth (note: not sure if we should do this for this type
4269  of control traffic though). */
4270  candidates = 0;
4271  for (struct Queue *pos = n->queue_head; NULL != pos;
4272  pos = pos->next_neighbour)
4273  {
4274  if ((0 != (options & RMO_UNCONFIRMED_ALLOWED)) ||
4275  (pos->validated_until.abs_value_us > now.abs_value_us))
4276  candidates++;
4277  }
4278  if (0 == candidates)
4279  {
4280  /* This can happen rarely if the last confirmed queue timed
4281  out just as we were beginning to process this message. */
4283  "Could not route message of type %u to %s: no valid queue\n",
4284  ntohs (hdr->type),
4285  GNUNET_i2s (&n->pid));
4286  GNUNET_STATISTICS_update (GST_stats,
4287  "# route selection failed (all no valid queue)",
4288  1,
4289  GNUNET_NO);
4291  }
4292 
4295  if (0 == (options & RMO_REDUNDANT))
4296  sel2 = candidates; /* picks none! */
4297  else
4299  candidates = 0;
4300  for (struct Queue *pos = n->queue_head; NULL != pos;
4301  pos = pos->next_neighbour)
4302  {
4303  if ((0 != (options & RMO_UNCONFIRMED_ALLOWED)) ||
4304  (pos->validated_until.abs_value_us > now.abs_value_us))
4305  {
4306  if ((sel1 == candidates) || (sel2 == candidates))
4307  {
4309  "Routing message of type %u to %s using %s (#%u)\n",
4310  ntohs (hdr->type),
4311  GNUNET_i2s (&n->pid),
4312  pos->address,
4313  (sel1 == candidates) ? 1 : 2);
4314  rtt = GNUNET_TIME_relative_min (rtt, pos->pd.aged_rtt);
4315  queue_send_msg (pos, NULL, hdr, ntohs (hdr->size));
4316  }
4317  candidates++;
4318  }
4319  }
4320  return rtt;
4321 }
4322 
4323 
4328 {
4332  gcry_cipher_hd_t cipher;
4333 
4337  struct
4338  {
4342  struct GNUNET_CRYPTO_AuthKey hmac_key;
4343 
4347  char aes_key[256 / 8];
4348 
4352  char aes_ctr[128 / 8];
4353  } material;
4354 };
4355 
4356 
4365 static void
4367  const struct GNUNET_ShortHashCode *iv,
4368  struct DVKeyState *key)
4369 {
4370  /* must match #dh_key_derive_eph_pub */
4372  GNUNET_CRYPTO_kdf (&key->material,
4373  sizeof(key->material),
4374  "transport-backchannel-key",
4375  strlen ("transport-backchannel-key"),
4376  &km,
4377  sizeof(km),
4378  iv,
4379  sizeof(*iv)));
4381  "Deriving backchannel key based on KM %s and IV %s\n",
4382  GNUNET_h2s (km),
4383  GNUNET_sh2s (iv));
4384  GNUNET_assert (0 == gcry_cipher_open (&key->cipher,
4385  GCRY_CIPHER_AES256 /* low level: go for speed */,
4386  GCRY_CIPHER_MODE_CTR,
4387  0 /* flags */));
4388  GNUNET_assert (0 == gcry_cipher_setkey (key->cipher,
4389  &key->material.aes_key,
4390  sizeof(key->material.aes_key)));
4391  gcry_cipher_setctr (key->cipher,
4392  &key->material.aes_ctr,
4393  sizeof(key->material.aes_ctr));
4394 }
4395 
4396 
4406 static void
4408  const struct GNUNET_CRYPTO_EcdhePrivateKey *priv_ephemeral,
4409  const struct GNUNET_PeerIdentity *target,
4410  const struct GNUNET_ShortHashCode *iv,
4411  struct DVKeyState *key)
4412 {
4413  struct GNUNET_HashCode km;
4414 
4416  &target->public_key,
4417  &km));
4418  dv_setup_key_state_from_km (&km, iv, key);
4419 }
4420 
4421 
4431 static void
4433  const struct GNUNET_ShortHashCode *iv,
4434  struct DVKeyState *key)
4435 {
4436  struct GNUNET_HashCode km;
4437 
4438  GNUNET_assert (GNUNET_YES == GNUNET_CRYPTO_eddsa_ecdh (GST_my_private_key,
4439  pub_ephemeral,
4440  &km));
4441  dv_setup_key_state_from_km (&km, iv, key);
4442 }
4443 
4444 
4454 static void
4455 dv_hmac (const struct DVKeyState *key,
4456  struct GNUNET_HashCode *hmac,
4457  const void *data,
4458  size_t data_size)
4459 {
4460  GNUNET_CRYPTO_hmac (&key->material.hmac_key, data, data_size, hmac);
4461 }
4462 
4463 
4473 static void
4474 dv_encrypt (struct DVKeyState *key, const void *in, void *dst, size_t in_size)
4475 {
4476  GNUNET_assert (0 ==
4477  gcry_cipher_encrypt (key->cipher, dst, in_size, in, in_size));
4478 }
4479 
4480 
4490 static void
4492  void *out,
4493  const void *ciph,
4494  size_t out_size)
4495 {
4496  GNUNET_assert (
4497  0 == gcry_cipher_decrypt (key->cipher, out, out_size, ciph, out_size));
4498 }
4499 
4500 
4506 static void
4508 {
4509  gcry_cipher_close (key->cipher);
4510  GNUNET_CRYPTO_zero_keys (&key->material, sizeof(key->material));
4511 }
4512 
4513 
4524 typedef void (*DVMessageHandler) (void *cls,
4525  struct Neighbour *next_hop,
4526  const struct GNUNET_MessageHeader *hdr,
4528 
4542 static struct GNUNET_TIME_Relative
4544  unsigned int num_dvhs,
4545  struct DistanceVectorHop **dvhs,
4546  const struct GNUNET_MessageHeader *hdr,
4547  DVMessageHandler use,
4548  void *use_cls,
4550 {
4551  struct TransportDVBoxMessage box_hdr;
4552  struct TransportDVBoxPayloadP payload_hdr;
4553  uint16_t enc_body_size = ntohs (hdr->size);
4554  char enc[sizeof(struct TransportDVBoxPayloadP) + enc_body_size] GNUNET_ALIGN;
4555  struct TransportDVBoxPayloadP *enc_payload_hdr =
4556  (struct TransportDVBoxPayloadP *) enc;
4557  struct DVKeyState key;
4558  struct GNUNET_TIME_Relative rtt;
4559 
4560  /* Encrypt payload */
4562  box_hdr.total_hops = htons (0);
4563  update_ephemeral (dv);
4564  box_hdr.ephemeral_key = dv->ephemeral_key;
4565  payload_hdr.sender_sig = dv->sender_sig;
4567  &box_hdr.iv,
4568  sizeof(box_hdr.iv));
4569  dh_key_derive_eph_pid (&dv->private_key, &dv->target, &box_hdr.iv, &key);
4570  payload_hdr.sender = GST_my_identity;
4571  payload_hdr.monotonic_time = GNUNET_TIME_absolute_hton (dv->monotime);
4572  dv_encrypt (&key, &payload_hdr, enc_payload_hdr, sizeof(payload_hdr));
4573  dv_encrypt (&key,
4574  hdr,
4575  &enc[sizeof(struct TransportDVBoxPayloadP)],
4576  enc_body_size);
4577  dv_hmac (&key, &box_hdr.hmac, enc, sizeof(enc));
4578  dv_key_clean (&key);
4580  /* For each selected path, take the pre-computed header and body
4581  and add the path in the middle of the message; then send it. */
4582  for (unsigned int i = 0; i < num_dvhs; i++)
4583  {
4584  struct DistanceVectorHop *dvh = dvhs[i];
4585  unsigned int num_hops = dvh->distance + 1;
4586  char buf[sizeof(struct TransportDVBoxMessage)
4587  + sizeof(struct GNUNET_PeerIdentity) * num_hops
4588  + sizeof(struct TransportDVBoxPayloadP)
4589  + enc_body_size] GNUNET_ALIGN;
4590  struct GNUNET_PeerIdentity *dhops;
4591 
4592  box_hdr.header.size = htons (sizeof(buf));
4593  box_hdr.num_hops = htons (num_hops);
4594  memcpy (buf, &box_hdr, sizeof(box_hdr));
4595  dhops = (struct GNUNET_PeerIdentity *) &buf[sizeof(box_hdr)];
4596  memcpy (dhops,
4597  dvh->path,
4598  dvh->distance * sizeof(struct GNUNET_PeerIdentity));
4599  dhops[dvh->distance] = dv->target;
4600  if (GNUNET_EXTRA_LOGGING > 0)
4601  {
4602  char *path;
4603 
4605  for (unsigned int j = 0; j <= num_hops; j++)
4606  {
4607  char *tmp;
4608 
4609  GNUNET_asprintf (&tmp, "%s-%s", path, GNUNET_i2s (&dhops[j]));
4610  GNUNET_free (path);
4611  path = tmp;
4612  }
4614  "Routing message of type %u to %s using DV (#%u/%u) via %s\n",
4615  ntohs (hdr->type),
4616  GNUNET_i2s (&dv->target),
4617  i + 1,
4618  num_dvhs + 1,
4619  path);
4620  GNUNET_free (path);
4621  }
4622  rtt = GNUNET_TIME_relative_min (rtt, dvh->pd.aged_rtt);
4623  memcpy (&dhops[num_hops], enc, sizeof(enc));
4624  use (use_cls,
4625  dvh->next_hop,
4626  (const struct GNUNET_MessageHeader *) buf,
4627  options);
4628  }
4629  return rtt;
4630 }
4631 
4632 
4642 static void
4644  struct Neighbour *next_hop,
4645  const struct GNUNET_MessageHeader *hdr,
4647 {
4648  (void) cls;
4649  (void) route_via_neighbour (next_hop, hdr, options);
4650 }
4651 
4652 
4664 static struct GNUNET_TIME_Relative
4666  const struct GNUNET_MessageHeader *hdr,
4668 {
4669  struct VirtualLink *vl;
4670  struct Neighbour *n;
4671  struct DistanceVector *dv;
4672  struct GNUNET_TIME_Relative rtt1;
4673  struct GNUNET_TIME_Relative rtt2;
4674 
4675  vl = lookup_virtual_link (target);
4676  GNUNET_assert (NULL != vl);
4677  n = vl->n;
4678  dv = (0 != (options & RMO_DV_ALLOWED)) ? vl->dv : NULL;
4679  if (0 == (options & RMO_UNCONFIRMED_ALLOWED))
4680  {
4681  /* if confirmed is required, and we do not have anything
4682  confirmed, drop respective options */
4683  if (NULL == n)
4684  n = lookup_neighbour (target);
4685  if ((NULL == dv) && (0 != (options & RMO_DV_ALLOWED)))
4686  dv = GNUNET_CONTAINER_multipeermap_get (dv_routes, target);
4687  }
4688  if ((NULL == n) && (NULL == dv))
4689  {
4691  "Cannot route message of type %u to %s: no route\n",
4692  ntohs (hdr->type),
4693  GNUNET_i2s (target));
4694  GNUNET_STATISTICS_update (GST_stats,
4695  "# Messages dropped in routing: no acceptable method",
4696  1,
4697  GNUNET_NO);
4699  }
4701  "Routing message of type %u to %s with options %X\n",
4702  ntohs (hdr->type),
4703  GNUNET_i2s (target),
4704  (unsigned int) options);
4705  /* If both dv and n are possible and we must choose:
4706  flip a coin for the choice between the two; for now 50/50 */
4707  if ((NULL != n) && (NULL != dv) && (0 == (options & RMO_REDUNDANT)))
4708  {
4710  n = NULL;
4711  else
4712  dv = NULL;
4713  }
4714  if ((NULL != n) && (NULL != dv))
4715  options &= ~RMO_REDUNDANT; /* We will do one DV and one direct, that's
4716  enough for redundancy, so clear the flag. */
4719  if (NULL != n)
4720  {
4721  rtt1 = route_via_neighbour (n, hdr, options);
4722  }
4723  if (NULL != dv)
4724  {
4725  struct DistanceVectorHop *hops[2];
4726  unsigned int res;
4727 
4728  res = pick_random_dv_hops (dv,
4729  options,
4730  hops,
4731  (0 == (options & RMO_REDUNDANT)) ? 1 : 2);
4732  if (0 == res)
4733  {
4735  "Failed to route message, could not determine DV path\n");
4736  return rtt1;
4737  }
4738  rtt2 = encapsulate_for_dv (dv,
4739  res,
4740  hops,
4741  hdr,
4743  NULL,
4744  options & (~RMO_REDUNDANT));
4745  }
4746  return GNUNET_TIME_relative_min (rtt1, rtt2);
4747 }
4748 
4749 
4750 static void
4751 consider_sending_fc (void *cls);
4752 
4759 static void
4761 {
4762  struct VirtualLink *vl = cls;
4763  vl->fc_retransmit_task = NULL;
4764  consider_sending_fc (cls);
4765 }
4766 
4767 
4774 static void
4776 {
4777  struct VirtualLink *vl = cls;
4778  struct GNUNET_TIME_Absolute monotime;
4779  struct TransportFlowControlMessage fc;
4780  struct GNUNET_TIME_Relative duration;
4781  struct GNUNET_TIME_Relative rtt;
4782 
4784  /* OPTIMIZE-FC-BDP: decide sane criteria on when to do this, instead of doing
4785  it always! */
4786  /* For example, we should probably ONLY do this if a bit more than
4787  an RTT has passed, or if the window changed "significantly" since
4788  then. See vl->last_fc_rtt! NOTE: to do this properly, we also
4789  need an estimate for the bandwidth-delay-product for the entire
4790  VL, as that determines "significantly". We have the delay, but
4791  the bandwidth statistics need to be added for the VL!*/(void) duration;
4792 
4794  "Sending FC seq %u to %s with new window %llu\n",
4795  (unsigned int) vl->fc_seq_gen,
4796  GNUNET_i2s (&vl->target),
4797  (unsigned long long) vl->incoming_fc_window_size);
4798  monotime = GNUNET_TIME_absolute_get_monotonic (GST_cfg);
4799  vl->last_fc_transmission = monotime;
4801  fc.header.size = htons (sizeof(fc));
4802  fc.seq = htonl (vl->fc_seq_gen++);
4806  fc.sender_time = GNUNET_TIME_absolute_hton (monotime);
4808  if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == rtt.rel_value_us)
4809  {
4812  "FC retransmission to %s failed, will retry in %s\n",
4813  GNUNET_i2s (&vl->target),
4816  }
4817  else
4818  {
4819  /* OPTIMIZE-FC-BDP: rtt is not ideal, we can do better! */
4820  vl->last_fc_rtt = rtt;
4821  }
4822  if (NULL != vl->fc_retransmit_task)
4824  vl->fc_retransmit_task =
4826 }
4827 
4828 
4845 static void
4847 {
4848  struct Neighbour *n = vl->n;
4849  struct DistanceVector *dv = vl->dv;
4850  struct GNUNET_TIME_Absolute now;
4851  int elig;
4852 
4853  /* Check that we have an eligible pending message!
4854  (cheaper than having #transmit_on_queue() find out!) */
4855  elig = GNUNET_NO;
4856  for (struct PendingMessage *pm = vl->pending_msg_head; NULL != pm;
4857  pm = pm->next_vl)
4858  {
4859  if (NULL != pm->qe)
4860  continue; /* not eligible, is in a queue! */
4861  if (pm->bytes_msg + vl->outbound_fc_window_size_used >
4863  {
4865  "Stalled transmission on VL %s due to flow control: %llu < %llu\n",
4866  GNUNET_i2s (&vl->target),
4867  (unsigned long long) vl->outbound_fc_window_size,
4868  (unsigned long long) (pm->bytes_msg
4870  consider_sending_fc (vl);
4871  return; /* We have a message, but flow control says "nope" */
4872  }
4873  elig = GNUNET_YES;
4874  break;
4875  }
4876  if (GNUNET_NO == elig)
4877  return;
4879  "Not stalled. Scheduling transmission on queue\n");
4880  /* Notify queues at direct neighbours that we are interested */
4881  now = GNUNET_TIME_absolute_get ();
4882  if (NULL != n)
4883  {
4884  for (struct Queue *queue = n->queue_head; NULL != queue;
4885  queue = queue->next_neighbour)
4886  {
4887  if ((GNUNET_YES == queue->idle) &&
4888  (queue->validated_until.abs_value_us > now.abs_value_us))
4890  else
4892  "Queue busy or invalid\n");
4893  }
4894  }
4895  /* Notify queues via DV that we are interested */
4896  if (NULL != dv)
4897  {
4898  /* Do DV with lower scheduler priority, which effectively means that
4899  IF a neighbour exists and is available, we prefer it. */
4900  for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
4901  pos = pos->next_dv)
4902  {
4903  struct Neighbour *nh = pos->next_hop;
4904 
4905  if (pos->path_valid_until.abs_value_us <= now.abs_value_us)
4906  continue; /* skip this one: path not validated */
4907  for (struct Queue *queue = nh->queue_head; NULL != queue;
4908  queue = queue->next_neighbour)
4909  if ((GNUNET_YES == queue->idle) &&
4910  (queue->validated_until.abs_value_us > now.abs_value_us))
4913  }
4914  }
4915 }
4916 
4917 
4924 static void
4925 handle_client_send (void *cls, const struct OutboundMessage *obm)
4926 {
4927  struct TransportClient *tc = cls;
4928  struct PendingMessage *pm;
4929  const struct GNUNET_MessageHeader *obmm;
4930  uint32_t bytes_msg;
4931  struct VirtualLink *vl;
4933 
4934  GNUNET_assert (CT_CORE == tc->type);
4935  obmm = (const struct GNUNET_MessageHeader *) &obm[1];
4936  bytes_msg = ntohs (obmm->size);
4937  pp = (enum GNUNET_MQ_PriorityPreferences) ntohl (obm->priority);
4938  vl = lookup_virtual_link (&obm->peer);
4939  if (NULL == vl)
4940  {
4942  "Don't have %s as a neighbour (anymore).\n",
4943  GNUNET_i2s (&obm->peer));
4944  /* Failure: don't have this peer as a neighbour (anymore).
4945  Might have gone down asynchronously, so this is NOT
4946  a protocol violation by CORE. Still count the event,
4947  as this should be rare. */
4949  GNUNET_STATISTICS_update (GST_stats,
4950  "# messages dropped (neighbour unknown)",
4951  1,
4952  GNUNET_NO);
4953  return;
4954  }
4955 
4956  pm = GNUNET_malloc (sizeof(struct PendingMessage) + bytes_msg);
4958  pm->prefs = pp;
4959  pm->client = tc;
4960  pm->vl = vl;
4961  pm->bytes_msg = bytes_msg;
4962  memcpy (&pm[1], obmm, bytes_msg);
4964  "Sending %u bytes as <%llu> to %s\n",
4965  bytes_msg,
4966  pm->logging_uuid,
4967  GNUNET_i2s (&obm->peer));
4969  tc->details.core.pending_msg_head,
4970  tc->details.core.pending_msg_tail,
4971  pm);
4973  vl->pending_msg_head,
4974  vl->pending_msg_tail,
4975  pm);
4976  check_vl_transmission (vl);
4977 }
4978 
4979 
4989 static void
4991  void *cls,
4992  const struct GNUNET_TRANSPORT_CommunicatorBackchannel *cb)
4993 {
4994  struct TransportClient *tc = cls;
4995  const struct GNUNET_MessageHeader *inbox =
4996  (const struct GNUNET_MessageHeader *) &cb[1];
4997  uint16_t isize = ntohs (inbox->size);
4998  const char *is = ((const char *) &cb[1]) + isize;
4999  char
5000  mbuf[isize
5001  + sizeof(struct
5005 
5006  /* 0-termination of 'is' was checked already in
5007  #check_communicator_backchannel() */
5009  "Preparing backchannel transmission to %s:%s of type %u\n",
5010  GNUNET_i2s (&cb->pid),
5011  is,
5012  ntohs (inbox->size));
5013  /* encapsulate and encrypt message */
5014  be->header.type =
5016  be->header.size = htons (sizeof(mbuf));
5017  memcpy (&be[1], inbox, isize);
5018  memcpy (&mbuf[sizeof(struct TransportBackchannelEncapsulationMessage)
5019  + isize],
5020  is,
5021  strlen (is) + 1);
5024 }
5025 
5026 
5034 static int
5036  const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
5037 {
5038  struct TransportClient *tc = cls;
5039 
5040  if (CT_COMMUNICATOR != tc->type)
5041  {
5042  GNUNET_break (0);
5043  return GNUNET_SYSERR;
5044  }
5046  return GNUNET_OK;
5047 }
5048 
5049 
5055 static void
5056 store_pi (void *cls);
5057 
5058 
5065 static void
5066 peerstore_store_own_cb (void *cls, int success)
5067 {
5068  struct AddressListEntry *ale = cls;
5069 
5070  ale->sc = NULL;
5071  if (GNUNET_YES != success)
5073  "Failed to store our own address `%s' in peerstore!\n",
5074  ale->address);
5075  else
5077  "Successfully stored our own address `%s' in peerstore!\n",
5078  ale->address);
5079  /* refresh period is 1/4 of expiration time, that should be plenty
5080  without being excessive. */
5081  ale->st =
5083  4ULL),
5084  &store_pi,
5085  ale);
5086 }
5087 
5088 
5094 static void
5095 store_pi (void *cls)
5096 {
5097  struct AddressListEntry *ale = cls;
5098  void *addr;
5099  size_t addr_len;
5100  struct GNUNET_TIME_Absolute expiration;
5101 
5102  ale->st = NULL;
5103  expiration = GNUNET_TIME_relative_to_absolute (ale->expiration);
5105  "Storing our address `%s' in peerstore until %s!\n",
5106  ale->address,
5109  ale->nt,
5111  GST_my_private_key,
5112  &addr,
5113  &addr_len);
5114  ale->sc = GNUNET_PEERSTORE_store (peerstore,
5115  "transport",
5116  &GST_my_identity,
5118  addr,
5119  addr_len,
5120  expiration,
5123  ale);
5124  GNUNET_free (addr);
5125  if (NULL == ale->sc)
5126  {
5128  "Failed to store our address `%s' with peerstore\n",
5129  ale->address);
5130  ale->st =
5132  }
5133 }
5134 
5135 
5142 static void
5144  const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
5145 {
5146  struct TransportClient *tc = cls;
5147  struct AddressListEntry *ale;
5148  size_t slen;
5149 
5150  /* 0-termination of &aam[1] was checked in #check_add_address */
5152  "Communicator added address `%s'!\n",
5153  (const char *) &aam[1]);
5154  slen = ntohs (aam->header.size) - sizeof(*aam);
5155  ale = GNUNET_malloc (sizeof(struct AddressListEntry) + slen);
5156  ale->tc = tc;
5157  ale->address = (const char *) &ale[1];
5158  ale->expiration = GNUNET_TIME_relative_ntoh (aam->expiration);
5159  ale->aid = aam->aid;
5160  ale->nt = (enum GNUNET_NetworkType) ntohl (aam->nt);
5161  memcpy (&ale[1], &aam[1], slen);
5163  tc->details.communicator.addr_tail,
5164  ale);
5165  ale->st = GNUNET_SCHEDULER_add_now (&store_pi, ale);
5167 }
5168 
5169 
5176 static void
5178  const struct GNUNET_TRANSPORT_DelAddressMessage *dam)
5179 {
5180  struct TransportClient *tc = cls;
5181  struct AddressListEntry *alen;
5182 
5183  if (CT_COMMUNICATOR != tc->type)
5184  {
5185  GNUNET_break (0);
5187  return;
5188  }
5189  for (struct AddressListEntry *ale = tc->details.communicator.addr_head;
5190  NULL != ale;
5191  ale = alen)
5192  {
5193  alen = ale->next;
5194  if (dam->aid != ale->aid)
5195  continue;
5196  GNUNET_assert (ale->tc == tc);
5198  "Communicator deleted address `%s'!\n",
5199  ale->address);
5202  return;
5203  }
5205  "Communicator removed address we did not even have.\n");
5207  // GNUNET_SERVICE_client_drop (tc->client);
5208 }
5209 
5210 
5218 static void
5220  const struct GNUNET_MessageHeader *msg);
5221 
5222 
5230 static void
5231 core_env_sent_cb (void *cls)
5232 {
5233  struct CoreSentContext *ctx = cls;
5234  struct VirtualLink *vl = ctx->vl;
5235 
5236  if (NULL == vl)
5237  {
5238  /* lost the link in the meantime, ignore */
5239  GNUNET_free (ctx);
5240  return;
5241  }
5244  vl->incoming_fc_window_size_ram -= ctx->size;
5245  vl->incoming_fc_window_size_used += ctx->isize;
5246  consider_sending_fc (vl);
5247  GNUNET_free (ctx);
5248 }
5249 
5250 
5259 static void
5260 handle_raw_message (void *cls, const struct GNUNET_MessageHeader *mh)
5261 {
5262  struct CommunicatorMessageContext *cmc = cls;
5263  struct VirtualLink *vl;
5264  uint16_t size = ntohs (mh->size);
5265  int have_core;
5266 
5267  if ((size > UINT16_MAX - sizeof(struct InboundMessage)) ||
5268  (size < sizeof(struct GNUNET_MessageHeader)))
5269  {
5270  struct GNUNET_SERVICE_Client *client = cmc->tc->client;
5271 
5272  GNUNET_break (0);
5273  finish_cmc_handling (cmc);
5274  GNUNET_SERVICE_client_drop (client);
5275  return;
5276  }
5277  vl = lookup_virtual_link (&cmc->im.sender);
5278  if (NULL == vl)
5279  {
5280  /* FIXME: sender is giving us messages for CORE but we don't have
5281  the link up yet! I *suspect* this can happen right now (i.e.
5282  sender has verified us, but we didn't verify sender), but if
5283  we pass this on, CORE would be confused (link down, messages
5284  arrive). We should investigate more if this happens often,
5285  or in a persistent manner, and possibly do "something" about
5286  it. Thus logging as error for now. */
5287  GNUNET_break_op (0);
5288  GNUNET_STATISTICS_update (GST_stats,
5289  "# CORE messages dropped (virtual link still down)",
5290  1,
5291  GNUNET_NO);
5292 
5293  finish_cmc_handling (cmc);
5294  return;
5295  }
5296  if (vl->incoming_fc_window_size_ram > UINT_MAX - size)
5297  {
5298  GNUNET_STATISTICS_update (GST_stats,
5299  "# CORE messages dropped (FC arithmetic overflow)",
5300  1,
5301  GNUNET_NO);
5302 
5303  finish_cmc_handling (cmc);
5304  return;
5305  }
5307  {
5308  GNUNET_STATISTICS_update (GST_stats,
5309  "# CORE messages dropped (FC window overflow)",
5310  1,
5311  GNUNET_NO);
5312  finish_cmc_handling (cmc);
5313  return;
5314  }
5315 
5316  /* Forward to all CORE clients */
5317  have_core = GNUNET_NO;
5318  for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
5319  {
5320  struct GNUNET_MQ_Envelope *env;
5321  struct InboundMessage *im;
5322  struct CoreSentContext *ctx;
5323 
5324  if (CT_CORE != tc->type)
5325  continue;
5328  ctx = GNUNET_new (struct CoreSentContext);
5329  ctx->vl = vl;
5330  ctx->size = size;
5331  ctx->isize = (GNUNET_NO == have_core) ? size : 0;
5332  have_core = GNUNET_YES;
5335  im->peer = cmc->im.sender;
5336  memcpy (&im[1], mh, size);
5337  GNUNET_MQ_send (tc->mq, env);
5338  vl->core_recv_window--;
5339  }
5340  if (GNUNET_NO == have_core)
5341  {
5343  "Dropped message to CORE: no CORE client connected!\n");
5344  /* Nevertheless, count window as used, as it is from the
5345  perspective of the other peer! */
5347  /* TODO-M1 */
5348  finish_cmc_handling (cmc);
5349  return;
5350  }
5352  "Delivered message from %s of type %u to CORE\n",
5353  GNUNET_i2s (&cmc->im.sender),
5354  ntohs (mh->type));
5355  if (vl->core_recv_window > 0)
5356  {
5357  finish_cmc_handling (cmc);
5358  return;
5359  }
5360  /* Wait with calling #finish_cmc_handling(cmc) until the message
5361  was processed by CORE MQs (for CORE flow control)! */
5363 }
5364 
5365 
5373 static int
5375 {
5376  uint16_t size = ntohs (fb->header.size);
5377  uint16_t bsize = size - sizeof(*fb);
5378 
5379  (void) cls;
5380  if (0 == bsize)
5381  {
5382  GNUNET_break_op (0);
5383  return GNUNET_SYSERR;
5384  }
5385  if (bsize + ntohs (fb->frag_off) > ntohs (fb->msg_size))
5386  {
5387  GNUNET_break_op (0);
5388  return GNUNET_SYSERR;
5389  }
5390  if (ntohs (fb->frag_off) >= ntohs (fb->msg_size))
5391  {
5392  GNUNET_break_op (0);
5393  return GNUNET_SYSERR;
5394  }
5395  return GNUNET_YES;
5396 }
5397 
5398 
5404 static void
5406 {
5407  struct AcknowledgementCummulator *ac = cls;
5408 
5409  ac->task = NULL;
5410  GNUNET_assert (0 == ac->num_acks);
5411  GNUNET_assert (
5412  GNUNET_YES ==
5413  GNUNET_CONTAINER_multipeermap_remove (ack_cummulators, &ac->target, ac));
5414  GNUNET_free (ac);
5415 }
5416 
5417 
5423 static void
5425 {
5426  struct AcknowledgementCummulator *ac = cls;
5427  char buf[sizeof(struct TransportReliabilityAckMessage)
5428  + ac->ack_counter
5429  * sizeof(struct TransportCummulativeAckPayloadP)] GNUNET_ALIGN;
5430  struct TransportReliabilityAckMessage *ack =
5433 
5434  ac->task = NULL;
5436  "Sending ACK with %u components to %s\n",
5437  ac->ack_counter,
5438  GNUNET_i2s (&ac->target));
5439  GNUNET_assert (0 < ac->ack_counter);
5441  ack->header.size =
5442  htons (sizeof(*ack)
5443  + ac->ack_counter * sizeof(struct TransportCummulativeAckPayloadP));
5444  ack->ack_counter = htonl (ac->ack_counter++);
5445  ap = (struct TransportCummulativeAckPayloadP *) &ack[1];
5446  for (unsigned int i = 0; i < ac->ack_counter; i++)
5447  {
5448  ap[i].ack_uuid = ac->ack_uuids[i].ack_uuid;
5450  GNUNET_TIME_absolute_get_duration (ac->ack_uuids[i].receive_time));
5451  }
5453  ac->num_acks = 0;
5456  ac);
5457 }
5458 
5459 
5468 static void
5470  const struct AcknowledgementUUIDP *ack_uuid,
5471  struct GNUNET_TIME_Absolute max_delay)
5472 {
5473  struct AcknowledgementCummulator *ac;
5474 
5476  "Scheduling ACK %s for transmission to %s\n",
5477  GNUNET_uuid2s (&ack_uuid->value),
5478  GNUNET_i2s (pid));
5479  ac = GNUNET_CONTAINER_multipeermap_get (ack_cummulators, pid);
5480  if (NULL == ac)
5481  {
5482  ac = GNUNET_new (struct AcknowledgementCummulator);
5483  ac->target = *pid;
5484  ac->min_transmission_time = max_delay;
5487  ack_cummulators,
5488  &ac->target,
5489  ac,
5491  }
5492  else
5493  {
5494  if (MAX_CUMMULATIVE_ACKS == ac->num_acks)
5495  {
5496  /* must run immediately, ack buffer full! */
5499  }
5501  ac->min_transmission_time =
5503  }
5506  ac->ack_uuids[ac->num_acks].ack_uuid = *ack_uuid;
5507  ac->num_acks++;
5510  ac);
5511 }
5512 
5513 
5518 {
5522  struct MessageUUIDP message_uuid;
5523 
5528 };
5529 
5530 
5540 static int
5541 find_by_message_uuid (void *cls, uint32_t key, void *value)
5542 {
5543  struct FindByMessageUuidContext *fc = cls;
5544  struct ReassemblyContext *rc = value;
5545 
5546  (void) key;
5547  if (0 == GNUNET_memcmp (&fc->message_uuid, &rc->msg_uuid))
5548  {
5549  fc->rc = rc;
5550  return GNUNET_NO;
5551  }
5552  return GNUNET_YES;
5553 }
5554 
5555 
5563 static void
5565 {
5566  struct CommunicatorMessageContext *cmc = cls;
5567  struct Neighbour *n;
5568  struct ReassemblyContext *rc;
5569  const struct GNUNET_MessageHeader *msg;
5570  uint16_t msize;
5571  uint16_t fsize;
5572  uint16_t frag_off;
5573  char *target;
5574  struct GNUNET_TIME_Relative cdelay;
5575  struct FindByMessageUuidContext fc;
5576 
5577  n = lookup_neighbour (&cmc->im.sender);
5578  if (NULL == n)
5579  {
5580  struct GNUNET_SERVICE_Client *client = cmc->tc->client;
5581 
5582  GNUNET_break (0);
5583  finish_cmc_handling (cmc);
5584  GNUNET_SERVICE_client_drop (client);
5585  return;
5586  }
5587  if (NULL == n->reassembly_map)
5588  {
5589  n->reassembly_map = GNUNET_CONTAINER_multihashmap32_create (8);
5590  n->reassembly_heap =
5592  n->reassembly_timeout_task =
5595  n);
5596  }
5597  msize = ntohs (fb->msg_size);
5598  fc.message_uuid = fb->msg_uuid;
5599  fc.rc = NULL;
5600  (void) GNUNET_CONTAINER_multihashmap32_get_multiple (n->reassembly_map,
5601  fb->msg_uuid.uuid,
5603  &fc);
5604  if (NULL == (rc = fc.rc))
5605  {
5606  rc = GNUNET_malloc (sizeof(*rc) + msize /* reassembly payload buffer */
5607  + (msize + 7) / 8 * sizeof(uint8_t) /* bitfield */);
5608  rc->msg_uuid = fb->msg_uuid;
5609  rc->neighbour = n;
5610  rc->msg_size = msize;
5611  rc->reassembly_timeout =
5614  rc->hn = GNUNET_CONTAINER_heap_insert (n->reassembly_heap,
5615  rc,
5619  n->reassembly_map,
5620  rc->msg_uuid.uuid,
5621  rc,
5623  target = (char *) &rc[1];
5624  rc->bitfield = (uint8_t *) (target + rc->msg_size);
5625  rc->msg_missing = rc->msg_size;
5627  "Received fragment at offset %u/%u from %s for NEW message %u\n",
5628  ntohs (fb->frag_off),
5629  msize,
5630  GNUNET_i2s (&cmc->im.sender),
5631  (unsigned int) fb->msg_uuid.uuid);
5632  }
5633  else
5634  {
5635  target = (char *) &rc[1];
5637  "Received fragment at offset %u/%u from %s for message %u\n",
5638  ntohs (fb->frag_off),
5639  msize,
5640  GNUNET_i2s (&cmc->im.sender),
5641  (unsigned int) fb->msg_uuid.uuid);
5642  }
5643  if (msize != rc->msg_size)
5644  {
5645  GNUNET_break (0);
5646  finish_cmc_handling (cmc);
5647  return;
5648  }
5649 
5650  /* reassemble */
5651  fsize = ntohs (fb->header.size) - sizeof(*fb);
5652  if (0 == fsize)
5653  {
5654  GNUNET_break (0);
5655  finish_cmc_handling (cmc);
5656  return;
5657  }
5658  frag_off = ntohs (fb->frag_off);
5659  if (frag_off + fsize > msize)
5660  {
5661  /* Fragment (plus fragment size) exceeds message size! */
5662  GNUNET_break_op (0);
5663  finish_cmc_handling (cmc);
5664  return;
5665  }
5666  memcpy (&target[frag_off], &fb[1], fsize);
5667  /* update bitfield and msg_missing */
5668  for (unsigned int i = frag_off; i < frag_off + fsize; i++)
5669  {
5670  if (0 == (rc->bitfield[i / 8] & (1 << (i % 8))))
5671  {
5672  rc->bitfield[i / 8] |= (1 << (i % 8));
5673  rc->msg_missing--;
5674  }
5675  }
5676 
5677  /* Compute cumulative ACK */
5679  cdelay = GNUNET_TIME_relative_multiply (cdelay, rc->msg_missing / fsize);
5680  if (0 == rc->msg_missing)
5681  cdelay = GNUNET_TIME_UNIT_ZERO;
5682  cummulative_ack (&cmc->im.sender,
5683  &fb->ack_uuid,
5686  /* is reassembly complete? */
5687  if (0 != rc->msg_missing)
5688  {
5689  finish_cmc_handling (cmc);
5690  return;
5691  }
5692  /* reassembly is complete, verify result */
5693  msg = (const struct GNUNET_MessageHeader *) &rc[1];
5694  if (ntohs (msg->size) != rc->msg_size)
5695  {
5696  GNUNET_break (0);
5698  finish_cmc_handling (cmc);
5699  return;
5700  }
5701  /* successful reassembly */
5703  "Fragment reassembly complete for message %u\n",
5704  (unsigned int) fb->msg_uuid.uuid);
5705  /* FIXME: check that the resulting msg is NOT a
5706  DV Box or Reliability Box, as that is NOT allowed! */
5707  demultiplex_with_cmc (cmc, msg);
5708  /* FIXME-OPTIMIZE: really free here? Might be bad if fragments are still
5709  en-route and we forget that we finished this reassembly immediately!
5710  -> keep around until timeout?
5711  -> shorten timeout based on ACK? */
5713 }
5714 
5715 
5723 static int
5725  const struct TransportReliabilityBoxMessage *rb)
5726 {
5727  (void) cls;
5729  return GNUNET_YES;
5730 }
5731 
5732 
5740 static void
5742  const struct TransportReliabilityBoxMessage *rb)
5743 {
5744  struct CommunicatorMessageContext *cmc = cls;
5745  const struct GNUNET_MessageHeader *inbox =
5746  (const struct GNUNET_MessageHeader *) &rb[1];
5747  struct GNUNET_TIME_Relative rtt;
5748 
5750  "Received reliability box from %s with UUID %s of type %u\n",
5751  GNUNET_i2s (&cmc->im.sender),
5752  GNUNET_uuid2s (&rb->ack_uuid.value),
5753  (unsigned int) ntohs (inbox->type));
5754  rtt = GNUNET_TIME_UNIT_SECONDS; /* FIXME: should base this on "RTT", but we
5755  do not really have an RTT for the
5756  * incoming* queue (should we have
5757  the sender add it to the rb message?) */
5758  cummulative_ack (
5759  &cmc->im.sender,
5760  &rb->ack_uuid,
5761  (0 == ntohl (rb->ack_countdown))
5764  GNUNET_TIME_relative_divide (rtt, 8 /* FIXME: magic constant */)));
5765  /* continue with inner message */
5766  /* FIXME: check that inbox is NOT a DV Box, fragment or another
5767  reliability box (not allowed!) */
5768  demultiplex_with_cmc (cmc, inbox);
5769 }
5770 
5771 
5780 static void
5781 update_pd_age (struct PerformanceData *pd, unsigned int age)
5782 {
5783  unsigned int sage;
5784 
5785  if (age == pd->last_age)
5786  return; /* nothing to do */
5787  sage = GNUNET_MAX (pd->last_age, age - 2 * GOODPUT_AGING_SLOTS);
5788  for (unsigned int i = sage; i <= age - GOODPUT_AGING_SLOTS; i++)
5789  {
5790  struct TransmissionHistoryEntry *the = &pd->the[i % GOODPUT_AGING_SLOTS];
5791 
5792  the->bytes_sent = 0;
5793  the->bytes_received = 0;
5794  }
5795  pd->last_age = age;
5796 }
5797 
5798 
5807 static void
5809  struct GNUNET_TIME_Relative rtt,
5810  uint16_t bytes_transmitted_ok)
5811 {
5812  uint64_t nval = rtt.rel_value_us;
5813  uint64_t oval = pd->aged_rtt.rel_value_us;
5814  unsigned int age = get_age ();
5815  struct TransmissionHistoryEntry *the = &pd->the[age % GOODPUT_AGING_SLOTS];
5816 
5817  if (oval == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
5818  pd->aged_rtt = rtt;
5819  else
5820  pd->aged_rtt.rel_value_us = (nval + 7 * oval) / 8;
5821  update_pd_age (pd, age);
5822  the->bytes_received += bytes_transmitted_ok;
5823 }
5824 
5825 
5833 static void
5835  struct GNUNET_TIME_Relative rtt,
5836  uint16_t bytes_transmitted_ok)
5837 {
5838  update_performance_data (&q->pd, rtt, bytes_transmitted_ok);
5839 }
5840 
5841 
5849 static void
5851  struct GNUNET_TIME_Relative rtt,
5852  uint16_t bytes_transmitted_ok)
5853 {
5854  update_performance_data (&dvh->pd, rtt, bytes_transmitted_ok);
5855 }
5856 
5857 
5865 static void
5867 {
5868  struct PendingMessage *pos;
5869 
5870  switch (pm->pmt)
5871  {
5872  case PMT_CORE:
5873  case PMT_RELIABILITY_BOX:
5874  /* Full message sent, we are done */
5875  client_send_response (pm);
5876  return;
5877 
5878  case PMT_FRAGMENT_BOX:
5879  /* Fragment sent over reliabile channel */
5880  free_fragment_tree (pm);
5881  pos = pm->frag_parent;
5882  GNUNET_CONTAINER_MDLL_remove (frag, pos->head_frag, pos->tail_frag, pm);
5883  GNUNET_free (pm);
5884  /* check if subtree is done */
5885  while ((NULL == pos->head_frag) && (pos->frag_off == pos->bytes_msg) &&
5886  (pos != pm))
5887  {
5888  pm = pos;
5889  pos = pm->frag_parent;
5890  GNUNET_CONTAINER_MDLL_remove (frag, pos->head_frag, pos->tail_frag, pm);
5891  GNUNET_free (pm);
5892  }
5893 
5894  /* Was this the last applicable fragmment? */
5895  if ((NULL == pos->head_frag) && (NULL == pos->frag_parent) &&
5896  (pos->frag_off == pos->bytes_msg))
5897  client_send_response (pos);
5898  return;
5899 
5900  case PMT_DV_BOX:
5902  "Completed transmission of message %llu (DV Box)\n",
5903  pm->logging_uuid);
5904  free_pending_message (pm);
5905  return;
5906  }
5907 }
5908 
5909 
5917 static void
5919  struct GNUNET_TIME_Relative ack_delay)
5920 {
5921  struct GNUNET_TIME_Relative delay;
5922 
5924  if (delay.rel_value_us > ack_delay.rel_value_us)
5925  delay = GNUNET_TIME_UNIT_ZERO;
5926  else
5927  delay = GNUNET_TIME_relative_subtract (delay, ack_delay);
5928  if (NULL != pa->queue)
5929  update_queue_performance (pa->queue, delay, pa->message_size);
5930  if (NULL != pa->dvh)
5931  update_dvh_performance (pa->dvh, delay, pa->message_size);
5932  if (NULL != pa->pm)
5935 }
5936 
5937 
5945 static int
5947  const struct TransportReliabilityAckMessage *ra)
5948 {
5949  unsigned int n_acks;
5950 
5951  (void) cls;
5952  n_acks = (ntohs (ra->header.size) - sizeof(*ra))
5953  / sizeof(struct TransportCummulativeAckPayloadP);
5954  if (0 == n_acks)
5955  {
5956  GNUNET_break_op (0);
5957  return GNUNET_SYSERR;
5958  }
5959  if ((ntohs (ra->header.size) - sizeof(*ra)) !=
5960  n_acks * sizeof(struct TransportCummulativeAckPayloadP))
5961  {
5962  GNUNET_break_op (0);
5963  return GNUNET_SYSERR;
5964  }
5965  return GNUNET_OK;
5966 }
5967 
5968 
5976 static void
5978  const struct TransportReliabilityAckMessage *ra)
5979 {
5980  struct CommunicatorMessageContext *cmc = cls;
5981  const struct TransportCummulativeAckPayloadP *ack;
5982  unsigned int n_acks;
5983  uint32_t ack_counter;
5984 
5985  n_acks = (ntohs (ra->header.size) - sizeof(*ra))
5986  / sizeof(struct TransportCummulativeAckPayloadP);
5987  ack = (const struct TransportCummulativeAckPayloadP *) &ra[1];
5988  for (unsigned int i = 0; i < n_acks; i++)
5989  {
5990  struct PendingAcknowledgement *pa =
5991  GNUNET_CONTAINER_multiuuidmap_get (pending_acks, &ack[i].ack_uuid.value);
5992  if (NULL == pa)
5993  {
5995  "Received ACK from %s with UUID %s which is unknown to us!\n",
5996  GNUNET_i2s (&cmc->im.sender),
5997  GNUNET_uuid2s (&ack[i].ack_uuid.value));
5999  GST_stats,
6000  "# FRAGMENT_ACKS dropped, no matching pending message",
6001  1,
6002  GNUNET_NO);
6003  continue;
6004  }
6006  "Received ACK from %s with UUID %s\n",
6007  GNUNET_i2s (&cmc->im.sender),
6008  GNUNET_uuid2s (&ack[i].ack_uuid.value));
6009  handle_acknowledged (pa, GNUNET_TIME_relative_ntoh (ack[i].ack_delay));
6010  }
6011 
6012  ack_counter = htonl (ra->ack_counter);
6013  (void) ack_counter; /* silence compiler warning for now */
6014  // FIXME-OPTIMIZE: track ACK losses based on ack_counter somewhere!
6015  // (DV and/or Neighbour?)
6016  finish_cmc_handling (cmc);
6017 }
6018 
6019 
6027 static int
6029  void *cls,
6031 {
6032  uint16_t size = ntohs (be->header.size) - sizeof(*be);
6033  const struct GNUNET_MessageHeader *inbox =
6034  (const struct GNUNET_MessageHeader *) &be[1];
6035  const char *is;
6036  uint16_t isize;
6037 
6038  (void) cls;
6039  if (ntohs (inbox->size) >= size)
6040  {
6041  GNUNET_break_op (0);
6042  return GNUNET_SYSERR;
6043  }
6044  isize = ntohs (inbox->size);
6045  is = ((const char *) inbox) + isize;
6046  size -= isize;
6047  if ('\0' != is[size - 1])
6048  {
6049  GNUNET_break_op (0);
6050  return GNUNET_SYSERR;
6051  }
6052  return GNUNET_YES;
6053 }
6054 
6055 
6064 static void
6066  void *cls,
6068 {
6069  struct CommunicatorMessageContext *cmc = cls;
6070  struct GNUNET_TRANSPORT_CommunicatorBackchannelIncoming *cbi;
6071  struct GNUNET_MQ_Envelope *env;
6072  struct TransportClient *tc;
6073  const struct GNUNET_MessageHeader *inbox =
6074  (const struct GNUNET_MessageHeader *) &be[1];
6075  uint16_t isize = ntohs (inbox->size);
6076  const char *target_communicator = ((const char *) inbox) + isize;
6077 
6078  /* Find client providing this communicator */
6079  for (tc = clients_head; NULL != tc; tc = tc->next)
6080  if ((CT_COMMUNICATOR == tc->type) &&
6081  (0 ==
6082  strcmp (tc->details.communicator.address_prefix, target_communicator)))
6083  break;
6084  if (NULL == tc)
6085  {
6086  char *stastr;
6087 
6088  GNUNET_asprintf (
6089  &stastr,
6090  "# Backchannel message dropped: target communicator `%s' unknown",
6091  target_communicator);
6092  GNUNET_STATISTICS_update (GST_stats, stastr, 1, GNUNET_NO);
6093  GNUNET_free (stastr);
6094  return;
6095  }
6096  /* Finally, deliver backchannel message to communicator */
6098  "Delivering backchannel message from %s of type %u to %s\n",
6099  GNUNET_i2s (&cmc->im.sender),
6100  ntohs (inbox->type),
6101  target_communicator);
6102  env = GNUNET_MQ_msg_extra (
6103  cbi,
6104  isize,
6106  cbi->pid = cmc->im.sender;
6107  memcpy (&cbi[1], inbox, isize);
6108  GNUNET_MQ_send (tc->mq, env);
6109 }
6110 
6111 
6121 static void
6122 path_cleanup_cb (void *cls)
6123 {
6124  struct DistanceVector *dv = cls;
6125  struct DistanceVectorHop *pos;
6126 
6127  dv->timeout_task = NULL;
6128  while (NULL != (pos = dv->dv_head))
6129  {
6130  GNUNET_assert (dv == pos->dv);
6132  break;
6134  }
6135  if (NULL == pos)
6136  {
6137  free_dv_route (dv);
6138  return;
6139  }
6140  dv->timeout_task =
6142 }
6143 
6144 
6152 static void
6154 {
6155  struct DistanceVector *dv = hop->dv;
6156  struct VirtualLink *vl;
6157 
6158  vl = lookup_virtual_link (&dv->target);
6159  if (NULL != vl)
6160  {
6161  /* Link was already up, remember dv is also now available and we are done */
6162  vl->dv = dv;
6164  "Virtual link to %s could now also use DV!\n",
6165  GNUNET_i2s (&dv->target));
6166  return;
6167  }
6169  "Creating new virtual link to %s using DV!\n",
6170  GNUNET_i2s (&dv->target));
6171  vl = GNUNET_new (struct VirtualLink);
6172  vl->message_uuid_ctr =
6174  vl->target = dv->target;
6175  vl->dv = dv;
6176  dv->vl = vl;
6180  vl->visibility_task =
6184  links,
6185  &vl->target,
6186  vl,
6188  consider_sending_fc (vl);
6189  /* We lacked a confirmed connection to the target
6190  before, so tell CORE about it (finally!) */
6192 }
6193 
6194 
6220 static int
6222  unsigned int path_len,
6223  struct GNUNET_TIME_Relative network_latency,
6224  struct GNUNET_TIME_Absolute path_valid_until)
6225 {
6226  struct DistanceVectorHop *hop;
6227  struct DistanceVector *dv;
6228  struct Neighbour *next_hop;
6229  unsigned int shorter_distance;
6230 
6231  if (path_len < 3)
6232  {
6233  /* what a boring path! not allowed! */
6234  GNUNET_break (0);
6235  return GNUNET_SYSERR;
6236  }
6237  GNUNET_assert (0 == GNUNET_memcmp (&GST_my_identity, &path[0]));
6238  next_hop = lookup_neighbour (&path[1]);
6239  if (NULL == next_hop)
6240  {
6241  /* next hop must be a neighbour, otherwise this whole thing is useless! */
6242  GNUNET_break (0);
6243  return GNUNET_SYSERR;
6244  }
6245  for (unsigned int i = 2; i < path_len; i++)
6246  if (NULL != lookup_neighbour (&path[i]))
6247  {
6248  /* Useless path: we have a direct connection to some hop
6249  in the middle of the path, so this one is not even
6250  terribly useful for redundancy */
6252  "Path of %u hops useless: directly link to hop %u (%s)\n",
6253  path_len,
6254  i,
6255  GNUNET_i2s (&path[i]));
6256  GNUNET_STATISTICS_update (GST_stats,
6257  "# Useless DV path ignored: hop is neighbour",
6258  1,
6259  GNUNET_NO);
6260  return GNUNET_SYSERR;
6261  }
6262  dv = GNUNET_CONTAINER_multipeermap_get (dv_routes, &path[path_len - 1]);
6263  if (NULL == dv)
6264  {
6265  dv = GNUNET_new (struct DistanceVector);
6266  dv->target = path[path_len - 1];
6268  &path_cleanup_cb,
6269  dv);
6272  dv_routes,
6273  &dv->target,
6274  dv,
6276  }
6277  /* Check if we have this path already! */
6278  shorter_distance = 0;
6279  for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
6280  pos = pos->next_dv)
6281  {
6282  if (pos->distance < path_len - 2)
6283  shorter_distance++;
6284  /* Note that the distances in 'pos' excludes us (path[0]) and
6285  the next_hop (path[1]), so we need to subtract two
6286  and check next_hop explicitly */
6287  if ((pos->distance == path_len - 2) && (pos->next_hop == next_hop))
6288  {
6289  int match = GNUNET_YES;
6290 
6291  for (unsigned int i = 0; i < pos->distance; i++)
6292  {
6293  if (0 != GNUNET_memcmp (&pos->path[i], &path[i + 2]))
6294  {
6295  match = GNUNET_NO;
6296  break;
6297  }
6298  }
6299  if (GNUNET_YES == match)
6300  {
6301  struct GNUNET_TIME_Relative last_timeout;
6302 
6303  /* Re-discovered known path, update timeout */
6304  GNUNET_STATISTICS_update (GST_stats,
6305  "# Known DV path refreshed",
6306  1,
6307  GNUNET_NO);
6308  last_timeout = GNUNET_TIME_absolute_get_remaining (pos->timeout);
6309  pos->timeout =
6311  pos->path_valid_until =
6312  GNUNET_TIME_absolute_max (pos->path_valid_until, path_valid_until);
6313  GNUNET_CONTAINER_MDLL_remove (dv, dv->dv_head, dv->dv_tail, pos);
6314  GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, pos);
6315  if (0 <
6318  if (last_timeout.rel_value_us <
6321  .rel_value_us)
6322  {
6323  /* Some peer send DV learn messages too often, we are learning
6324  the same path faster than it would be useful; do not forward! */
6326  "Rediscovered path too quickly, not forwarding further\n");
6327  return GNUNET_NO;
6328  }
6330  "Refreshed known path to %s, forwarding further\n",
6331  GNUNET_i2s (&dv->target));
6332  return GNUNET_YES;
6333  }
6334  }
6335  }
6336  /* Count how many shorter paths we have (incl. direct
6337  neighbours) before simply giving up on this one! */
6338  if (shorter_distance >= MAX_DV_PATHS_TO_TARGET)
6339  {
6340  /* We have a shorter path already! */
6342  "Have many shorter DV paths %s, not forwarding further\n",
6343  GNUNET_i2s (&dv->target));
6344  return GNUNET_NO;
6345  }
6346  /* create new DV path entry */
6348  "Discovered new DV path to %s\n",
6349  GNUNET_i2s (&dv->target));
6350  hop = GNUNET_malloc (sizeof(struct DistanceVectorHop)
6351  + sizeof(struct GNUNET_PeerIdentity) * (path_len - 2));
6352  hop->next_hop = next_hop;
6353  hop->dv = dv;
6354  hop->path = (const struct GNUNET_PeerIdentity *) &hop[1];
6355  memcpy (&hop[1],
6356  &path[2],
6357  sizeof(struct GNUNET_PeerIdentity) * (path_len - 2));
6359  hop->path_valid_until = path_valid_until;
6360  hop->distance = path_len - 2;
6361  hop->pd.aged_rtt = network_latency;
6362  GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, hop);
6363  GNUNET_CONTAINER_MDLL_insert (neighbour,
6364  next_hop->dv_head,
6365  next_hop->dv_tail,
6366  hop);
6367  if (0 < GNUNET_TIME_absolute_get_remaining (path_valid_until).rel_value_us)
6369  return GNUNET_YES;
6370 }
6371 
6372 
6380 static int
6381 check_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
6382 {
6383  uint16_t size = ntohs (dvl->header.size);
6384  uint16_t num_hops = ntohs (dvl->num_hops);
6385  const struct DVPathEntryP *hops = (const struct DVPathEntryP *) &dvl[1];
6386 
6387  (void) cls;
6388  if (size != sizeof(*dvl) + num_hops * sizeof(struct DVPathEntryP))
6389  {
6390  GNUNET_break_op (0);
6391  return GNUNET_SYSERR;
6392  }
6393  if (num_hops > MAX_DV_HOPS_ALLOWED)
6394  {
6395  GNUNET_break_op (0);
6396  return GNUNET_SYSERR;
6397  }
6398  for (unsigned int i = 0; i < num_hops; i++)
6399  {
6400  if (0 == GNUNET_memcmp (&dvl->initiator, &hops[i].hop))
6401  {
6402  GNUNET_break_op (0);
6403  return GNUNET_SYSERR;
6404  }
6405  if (0 == GNUNET_memcmp (&GST_my_identity, &hops[i].hop))
6406  {
6407  GNUNET_break_op (0);
6408  return GNUNET_SYSERR;
6409  }
6410  }
6411  return GNUNET_YES;
6412 }
6413 
6414 
6426 static void
6427 forward_dv_learn (const struct GNUNET_PeerIdentity *next_hop,
6428  const struct TransportDVLearnMessage *msg,
6429  uint16_t bi_history,
6430  uint16_t nhops,
6431  const struct DVPathEntryP *hops,
6432  struct GNUNET_TIME_Absolute in_time)
6433 {
6434  struct DVPathEntryP *dhops;
6435  char buf[sizeof(struct TransportDVLearnMessage)
6436  + (nhops + 1) * sizeof(struct DVPathEntryP)] GNUNET_ALIGN;
6437  struct TransportDVLearnMessage *fwd = (struct TransportDVLearnMessage *) buf;
6438  struct GNUNET_TIME_Relative nnd;
6439 
6440  /* compute message for forwarding */
6442  "Forwarding DV learn message originating from %s to %s\n",
6443  GNUNET_i2s (&msg->initiator),
6444  GNUNET_i2s2 (next_hop));
6447  fwd->header.size = htons (sizeof(struct TransportDVLearnMessage)
6448  + (nhops + 1) * sizeof(struct DVPathEntryP));
6449  fwd->num_hops = htons (nhops + 1);
6450  fwd->bidirectional = htons (bi_history);
6453  msg->non_network_delay));
6455  fwd->init_sig = msg->init_sig;
6456  fwd->initiator = msg->initiator;
6457  fwd->challenge = msg->challenge;
6458  dhops = (struct DVPathEntryP *) &fwd[1];
6459  GNUNET_memcpy (dhops, hops, sizeof(struct DVPathEntryP) * nhops);
6460  dhops[nhops].hop = GST_my_identity;
6461  {
6462  struct DvHopPS dhp = {
6464  .purpose.size = htonl (sizeof(dhp)),
6465  .pred = dhops[nhops - 1].hop,
6466  .succ = *next_hop,
6467  .challenge = msg->challenge
6468  };
6469 
6470  GNUNET_CRYPTO_eddsa_sign (GST_my_private_key,
6471  &dhp,
6472  &dhops[nhops].hop_sig);
6473  }
6475  &fwd->header,
6477 }
6478 
6479 
6489 static int
6491  struct GNUNET_TIME_AbsoluteNBO sender_monotonic_time,
6492  const struct GNUNET_PeerIdentity *init,
6493  const struct ChallengeNonceP *challenge,
6494  const struct GNUNET_CRYPTO_EddsaSignature *init_sig)
6495 {
6496  struct DvInitPS ip = { .purpose.purpose = htonl (
6498  .purpose.size = htonl (sizeof(ip)),
6499  .monotonic_time = sender_monotonic_time,
6500  .challenge = *challenge };
6501 
6502  if (
6503  GNUNET_OK !=
6505  &ip,
6506  init_sig,
6507  &init->public_key))
6508  {
6509  GNUNET_break_op (0);
6510  return GNUNET_SYSERR;
6511  }
6512  return GNUNET_OK;
6513 }
6514 
6515 
6520 {
6525 
6529  const struct DVPathEntryP *hops;
6530 
6534  struct GNUNET_TIME_Absolute in_time;
6535 
6539  uint32_t selections[MAX_DV_DISCOVERY_SELECTION];
6540 
6544  unsigned int num_eligible;
6545 
6549  unsigned int num_selections;
6550 
6554  uint16_t nhops;
6555 
6559  uint16_t bi_history;
6560 };
6561 
6562 
6571 static int
6573  const struct GNUNET_PeerIdentity *pid,
6574  void *value)
6575 {
6576  struct NeighbourSelectionContext *nsc = cls;
6577 
6578  (void) value;
6579  if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator))
6580  return GNUNET_YES; /* skip initiator */
6581  for (unsigned int i = 0; i < nsc->nhops; i++)
6582  if (0 == GNUNET_memcmp (pid, &nsc->hops[i].hop))
6583  return GNUNET_YES;
6584  /* skip peers on path */
6585  nsc->num_eligible++;
6586  return GNUNET_YES;
6587 }
6588 
6589 
6600 static int
6602  const struct GNUNET_PeerIdentity *pid,
6603  void *value)
6604 {
6605  struct NeighbourSelectionContext *nsc = cls;
6606 
6607  (void) value;
6608  if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator))
6609  return GNUNET_YES; /* skip initiator */
6610  for (unsigned int i = 0; i < nsc->nhops; i++)
6611  if (0 == GNUNET_memcmp (pid, &nsc->hops[i].hop))
6612  return GNUNET_YES;
6613  /* skip peers on path */
6614  for (unsigned int i = 0; i < nsc->num_selections; i++)
6615  {
6616  if (nsc->selections[i] == nsc->num_eligible)
6617  {
6618  forward_dv_learn (pid,
6619  nsc->dvl,
6620  nsc->bi_history,
6621  nsc->nhops,
6622  nsc->hops,
6623  nsc->in_time);
6624  break;
6625  }
6626  }
6627  nsc->num_eligible++;
6628  return GNUNET_YES;
6629 }
6630 
6631 
6675 static unsigned int
6676 calculate_fork_degree (unsigned int hops_taken,
6677  unsigned int neighbour_count,
6678  unsigned int eligible_count)
6679 {
6680  double target_total = 50.0; /* FIXME: use LOG(NSE)? */
6681  double eligible_ratio =
6682  ((double) eligible_count) / ((double) neighbour_count);
6683  double boost_factor = eligible_ratio * eligible_ratio;
6684  unsigned int rnd;
6685  double left;
6686 
6687  if (hops_taken >= 64)
6688  {
6689  GNUNET_break (0);
6690  return 0; /* precaution given bitshift below */
6691  }
6692  for (unsigned int i = 1; i < hops_taken; i++)
6693  {
6694  /* For each hop, subtract the expected number of targets
6695  reached at distance d (so what remains divided by 2^d) */
6696  target_total -= (target_total * boost_factor / (1LLU << i));
6697  }
6698  rnd =
6699  (unsigned int) floor (target_total * boost_factor / (1LLU << hops_taken));
6700  /* round up or down probabilistically depending on how close we were
6701  when floor()ing to rnd */
6702  left = target_total - (double) rnd;
6703  if (UINT32_MAX * left >
6705  rnd++; /* round up */
6707  "Forwarding DV learn message of %u hops %u(/%u/%u) times\n",
6708  hops_taken,
6709  rnd,
6710  eligible_count,
6711  neighbour_count);
6712  return rnd;
6713 }
6714 
6715 
6722 static void
6723 neighbour_store_dvmono_cb (void *cls, int success)
6724 {
6725  struct Neighbour *n = cls;
6726 
6727  n->sc = NULL;
6728  if (GNUNET_YES != success)
6730  "Failed to store other peer's monotonic time in peerstore!\n");
6731 }
6732 
6733 
6741 static void
6742 handle_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
6743 {
6744  struct CommunicatorMessageContext *cmc = cls;
6746  int bi_hop;
6747  uint16_t nhops;
6748  uint16_t bi_history;
6749  const struct DVPathEntryP *hops;
6750  int do_fwd;
6751  int did_initiator;
6752  struct GNUNET_TIME_Absolute in_time;
6753  struct Neighbour *n;
6754 
6755  nhops = ntohs (dvl->bidirectional); /* 0 = sender is initiator */
6756  bi_history = ntohs (dvl->bidirectional);
6757  hops = (const struct DVPathEntryP *) &dvl[1];
6758  if (0 == nhops)
6759  {
6760  /* sanity check */
6761  if (0 != GNUNET_memcmp (&dvl->initiator, &cmc->im.sender))
6762  {
6763  GNUNET_break (0);
6764  finish_cmc_handling (cmc);
6765  return;
6766  }
6767  }
6768  else
6769  {
6770  /* sanity check */
6771  if (0 != GNUNET_memcmp (&hops[nhops - 1].hop, &cmc->im.sender))
6772  {
6773  GNUNET_break (0);
6774  finish_cmc_handling (cmc);
6775  return;
6776  }
6777  }
6778 
6779  GNUNET_assert (CT_COMMUNICATOR == cmc->tc->type);
6780  cc = cmc->tc->details.communicator.cc;
6781  bi_hop = (GNUNET_TRANSPORT_CC_RELIABLE ==
6782  cc); // FIXME: add bi-directional flag to cc?
6783  in_time = GNUNET_TIME_absolute_get ();
6784 
6785  /* continue communicator here, everything else can happen asynchronous! */
6786  finish_cmc_handling (cmc);
6787 
6788  n = lookup_neighbour (&dvl->initiator);
6789  if (NULL != n)
6790  {
6791  if ((n->dv_monotime_available == GNUNET_YES) &&
6794  {
6795  GNUNET_STATISTICS_update (GST_stats,
6796  "# DV learn discarded due to time travel",
6797  1,
6798  GNUNET_NO);
6799  return;
6800  }
6802  &dvl->initiator,
6803  &dvl->challenge,
6804  &dvl->init_sig))
6805  {
6806  GNUNET_break_op (0);
6807  return;
6808  }
6811  {
6812  if (NULL != n->sc)
6814  n->sc =
6815  GNUNET_PEERSTORE_store (peerstore,
6816  "transport",
6817  &dvl->initiator,
6819  &dvl->monotonic_time,
6820  sizeof(dvl->monotonic_time),
6824  n);
6825  }
6826  }
6827  /* OPTIMIZE-FIXME: asynchronously (!) verify signatures!,
6828  If signature verification load too high, implement random drop strategy */
6829  for (unsigned int i = 0; i < nhops; i++)
6830  {
6831  struct DvHopPS dhp = { .purpose.purpose =
6833  .purpose.size = htonl (sizeof(dhp)),
6834  .pred = (0 == i) ? dvl->initiator : hops[i - 1].hop,
6835  .succ = (nhops == i + 1) ? GST_my_identity
6836  : hops[i + 1].hop,
6837  .challenge = dvl->challenge };
6838 
6839  if (GNUNET_OK !=
6841  &dhp,
6842  &hops[i].hop_sig,
6843  &hops[i].hop.public_key))
6844  {
6845  GNUNET_break_op (0);
6846  return;
6847  }
6848  }
6849 
6850  if (GNUNET_EXTRA_LOGGING > 0)
6851  {
6852  char *path;
6853 
6854  path = GNUNET_strdup (GNUNET_i2s (&dvl->initiator));
6855  for (unsigned int i = 0; i < nhops; i++)
6856  {
6857  char *tmp;
6858 
6859  GNUNET_asprintf (&tmp,
6860  "%s%s%s",
6861  path,
6862  (bi_history & (1 << (nhops - i))) ? "<->" : "-->",
6863  GNUNET_i2s (&hops[i].hop));
6864  GNUNET_free (path);
6865  path = tmp;
6866  }
6868  "Received DVInit via %s%s%s\n",
6869  path,
6870  bi_hop ? "<->" : "-->",
6872  GNUNET_free (path);
6873  }
6874 
6875  do_fwd = GNUNET_YES;
6876  if (0 == GNUNET_memcmp (&GST_my_identity, &dvl->initiator))
6877  {
6878  struct GNUNET_PeerIdentity path[nhops + 1];
6879  struct GNUNET_TIME_Relative host_latency_sum;
6880  struct GNUNET_TIME_Relative latency;
6881  struct GNUNET_TIME_Relative network_latency;
6882 
6883  /* We initiated this, learn the forward path! */
6884  path[0] = GST_my_identity;
6885  path[1] = hops[0].hop;
6886  host_latency_sum = GNUNET_TIME_relative_ntoh (dvl->non_network_delay);
6887 
6888  // Need also something to lookup initiation time
6889  // to compute RTT! -> add RTT argument here?
6890  latency = GNUNET_TIME_UNIT_FOREVER_REL; // FIXME: initialize properly
6891  // (based on dvl->challenge, we can identify time of origin!)
6892 
6893  network_latency = GNUNET_TIME_relative_subtract (latency, host_latency_sum);
6894  /* assumption: latency on all links is the same */
6895  network_latency = GNUNET_TIME_relative_divide (network_latency, nhops);
6896 
6897  for (unsigned int i = 2; i <= nhops; i++)
6898  {
6899  struct GNUNET_TIME_Relative ilat;
6900 
6901  /* assumption: linear latency increase per hop */
6902  ilat = GNUNET_TIME_relative_multiply (network_latency, i);
6903  path[i] = hops[i - 1].hop;
6905  "Learned path with %u hops to %s with latency %s\n",
6906  i,
6907  GNUNET_i2s (&path[i]),
6909  learn_dv_path (path,
6910  i,
6911  ilat,
6914  }
6915  /* as we initiated, do not forward again (would be circular!) */
6916  do_fwd = GNUNET_NO;
6917  return;
6918  }
6919  if (bi_hop)
6920  {
6921  /* last hop was bi-directional, we could learn something here! */
6922  struct GNUNET_PeerIdentity path[nhops + 2];
6923 
6924  path[0] = GST_my_identity;
6925  path[1] = hops[nhops - 1].hop; /* direct neighbour == predecessor! */
6926  for (unsigned int i = 0; i < nhops; i++)
6927  {
6928  int iret;
6929 
6930  if (0 == (bi_history & (1 << i)))
6931  break; /* i-th hop not bi-directional, stop learning! */
6932  if (i == nhops - 1)
6933  {
6934  path[i + 2] = dvl->initiator;
6935  }
6936  else
6937  {
6938  path[i + 2] = hops[nhops - i - 2].hop;
6939  }
6940 
6942  "Learned inverse path with %u hops to %s\n",
6943  i + 1,
6944  GNUNET_i2s (&path[i + 2]));
6945  iret = learn_dv_path (path,
6946  i + 2,
6949  if (GNUNET_SYSERR == iret)
6950  {
6951  /* path invalid or too long to be interesting for US, thus should also
6952  not be interesting to our neighbours, cut path when forwarding to
6953  'i' hops, except of course for the one that goes back to the
6954  initiator */
6955  GNUNET_STATISTICS_update (GST_stats,
6956  "# DV learn not forwarded due invalidity of path",
6957  1,
6958  GNUNET_NO);
6959  do_fwd = GNUNET_NO;
6960  break;
6961  }
6962  if ((GNUNET_NO == iret) && (nhops == i + 1))
6963  {
6964  /* we have better paths, and this is the longest target,
6965  so there cannot be anything interesting later */
6966  GNUNET_STATISTICS_update (GST_stats,
6967  "# DV learn not forwarded, got better paths",
6968  1,
6969  GNUNET_NO);
6970  do_fwd = GNUNET_NO;
6971  break;
6972  }
6973  }
6974  }
6975 
6976  if (MAX_DV_HOPS_ALLOWED == nhops)
6977  {
6978  /* At limit, we're out of here! */
6979  return;
6980  }
6981 
6982  /* Forward to initiator, if path non-trivial and possible */
6983  bi_history = (bi_history << 1) | (bi_hop ? 1 : 0);
6984  did_initiator = GNUNET_NO;
6985  if ((1 < nhops) &&
6986  (GNUNET_YES ==
6988  {
6989  /* send back to origin! */
6991  "Sending DVL back to initiator %s\n",
6992  GNUNET_i2s (&dvl->initiator));
6993  forward_dv_learn (&dvl->initiator, dvl, bi_history, nhops, hops, in_time);
6994  did_initiator = GNUNET_YES;
6995  }
6996  /* We forward under two conditions: either we still learned something
6997  ourselves (do_fwd), or the path was darn short and thus the initiator is
6998  likely to still be very interested in this (and we did NOT already
6999  send it back to the initiator) */
7000  if ((do_fwd) || ((nhops < MIN_DV_PATH_LENGTH_FOR_INITIATOR) &&
7001  (GNUNET_NO == did_initiator)))
7002  {
7003  /* Pick random neighbours that are not yet on the path */
7004  struct NeighbourSelectionContext nsc;
7005  unsigned int n_cnt;
7006 
7007  n_cnt = GNUNET_CONTAINER_multipeermap_size (neighbours);
7008  nsc.nhops = nhops;
7009  nsc.dvl = dvl;
7010  nsc.bi_history = bi_history;
7011  nsc.hops = hops;
7012  nsc.in_time = in_time;
7013  nsc.num_eligible = 0;
7016  &nsc);
7017  if (0 == nsc.num_eligible)
7018  return; /* done here, cannot forward to anyone else */
7019  nsc.num_selections = calculate_fork_degree (nhops, n_cnt, nsc.num_eligible);
7020  nsc.num_selections =
7023  "Forwarding DVL to %u other peers\n",
7024  nsc.num_selections);
7025  for (unsigned int i = 0; i < nsc.num_selections; i++)
7026  nsc.selections[i] =
7027  (nsc.num_selections == n_cnt)
7028  ? i /* all were selected, avoid collisions by chance */
7030  nsc.num_eligible = 0;
7033  &nsc);
7034  }
7035 }
7036 
7037 
7045 static int
7046 check_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
7047 {
7048  uint16_t size = ntohs (dvb->header.size);
7049  uint16_t num_hops = ntohs (dvb->num_hops);
7050  const struct GNUNET_PeerIdentity *hops =
7051  (const struct GNUNET_PeerIdentity *) &dvb[1];
7052 
7053  (void) cls;
7054  if (size < sizeof(*dvb) + num_hops * sizeof(struct GNUNET_PeerIdentity)
7055  + sizeof(struct GNUNET_MessageHeader))
7056  {
7057  GNUNET_break_op (0);
7058  return GNUNET_SYSERR;
7059  }
7060  /* This peer must not be on the path */
7061  for (unsigned int i = 0; i < num_hops; i++)
7062  if (0 == GNUNET_memcmp (&hops[i], &GST_my_identity))
7063  {
7064  GNUNET_break_op (0);
7065  return GNUNET_SYSERR;
7066  }
7067  return GNUNET_YES;
7068 }
7069 
7070 
7083 static void
7084 forward_dv_box (struct Neighbour *next_hop,
7085  const struct TransportDVBoxMessage *hdr,
7086  uint16_t total_hops,
7087  uint16_t num_hops,
7088  const struct GNUNET_PeerIdentity *hops,
7089  const void *enc_payload,
7090  uint16_t enc_payload_size)
7091 {
7092  struct VirtualLink *vl = next_hop->vl;
7093  struct PendingMessage *pm;
7094  size_t msg_size;
7095  char *buf;
7096  struct GNUNET_PeerIdentity *dhops;
7097 
7098  GNUNET_assert (NULL != vl);
7099  msg_size = sizeof(struct TransportDVBoxMessage)
7100  + num_hops * sizeof(struct GNUNET_PeerIdentity) + enc_payload_size;
7101  pm = GNUNET_malloc (sizeof(struct PendingMessage) + msg_size);
7102  pm->pmt = PMT_DV_BOX;
7103  pm->vl = vl;
7105  pm->logging_uuid = logging_uuid_gen++;
7106  pm->prefs = GNUNET_MQ_PRIO_BACKGROUND;
7107  pm->bytes_msg = msg_size;
7108  buf = (char *) &pm[1];
7109  memcpy (buf, hdr, sizeof(*hdr));
7110  dhops =
7111  (struct GNUNET_PeerIdentity *) &buf[sizeof(struct TransportDVBoxMessage)];
7112  memcpy (dhops, hops, num_hops * sizeof(struct GNUNET_PeerIdentity));
7113  memcpy (&dhops[num_hops], enc_payload, enc_payload_size);
7115  vl->pending_msg_head,
7116  vl->pending_msg_tail,
7117  pm);
7119  "Created pending message %llu for DV Box with next hop %s (%u/%u)\n",
7120  pm->logging_uuid,
7121  GNUNET_i2s (&next_hop->pid),
7122  (unsigned int) num_hops,
7123  (unsigned int) total_hops);
7124  check_vl_transmission (vl);
7125 }
7126 
7127 
7133 static void
7135 {
7136  if (NULL != b->get)
7137  {
7139  b->get = NULL;
7140  GNUNET_assert (NULL != b->cmc);
7141  finish_cmc_handling (b->cmc);
7142  b->cmc = NULL;
7143  }
7144  if (NULL != b->task)
7145  {
7147  b->task = NULL;
7148  }
7149  if (NULL != b->sc)
7150  {
7152  b->sc = NULL;
7153  }
7154  GNUNET_assert (
7155  GNUNET_YES ==
7156  GNUNET_CONTAINER_multipeermap_remove (backtalkers, &b->pid, b));
7157  GNUNET_free (b);
7158 }
7159 
7160 
7169 static int
7171  const struct GNUNET_PeerIdentity *pid,
7172  void *value)
7173 {
7174  struct Backtalker *b = value;
7175 
7176  (void) cls;
7177  (void) pid;
7178  free_backtalker (b);
7179  return GNUNET_OK;
7180 }
7181 
7182 
7188 static void
7190 {
7191  struct Backtalker *b = cls;
7192 
7193  b->task = NULL;
7195  {
7197  return;
7198  }
7199  GNUNET_assert (NULL == b->sc);
7200  free_backtalker (b);
7201 }
7202 
7203 
7212 static void
7214  const struct GNUNET_PEERSTORE_Record *record,
7215  const char *emsg)
7216 {
7217  struct Backtalker *b = cls;
7218  struct GNUNET_TIME_AbsoluteNBO *mtbe;
7219  struct GNUNET_TIME_Absolute mt;
7220 
7221  (void) emsg;
7222  if (NULL == record)
7223  {
7224  /* we're done with #backtalker_monotime_cb() invocations,
7225  continue normal processing */
7226  b->get = NULL;
7227  GNUNET_assert (NULL != b->cmc);
7228  if (0 != b->body_size)
7230  (const struct GNUNET_MessageHeader *) &b[1]);
7231  else
7232  finish_cmc_handling (b->cmc);
7233  b->cmc = NULL;
7234  return;
7235  }
7236  if (sizeof(*mtbe) != record->value_size)
7237  {
7238  GNUNET_break (0);
7239  return;
7240  }
7241  mtbe = record->value;
7242  mt = GNUNET_TIME_absolute_ntoh (*mtbe);
7244  {
7246  "Backtalker message from %s dropped, monotime in the past\n",
7247  GNUNET_i2s (&b->pid));
7249  GST_stats,
7250  "# Backchannel messages dropped: monotonic time not increasing",
7251  1,
7252  GNUNET_NO);
7253  b->monotonic_time = mt;
7254  /* Setting body_size to 0 prevents call to #forward_backchannel_payload()
7255  */
7256  b->body_size = 0;
7257  return;
7258  }
7259 }
7260 
7261 
7269 static void
7270 backtalker_monotime_store_cb (void *cls, int success)
7271 {
7272  struct Backtalker *b = cls;
7273 
7274  if (GNUNET_OK != success)
7275  {
7277  "Failed to store backtalker's monotonic time in PEERSTORE!\n");
7278  }
7279  b->sc = NULL;
7281 }
7282 
7283 
7289 static void
7291 {
7292  struct GNUNET_TIME_AbsoluteNBO mtbe;
7293 
7294  if (NULL != b->sc)
7295  {
7297  b->sc = NULL;
7298  }
7299  else
7300  {
7302  b->task = NULL;
7303  }
7305  b->sc =
7306  GNUNET_PEERSTORE_store (peerstore,
7307  "transport",
7308  &b->pid,
7310  &mtbe,
7311  sizeof(mtbe),
7315  b);
7316 }
7317 
7318 
7326 static void
7327 handle_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
7328 {
7329  struct CommunicatorMessageContext *cmc = cls;
7330  uint16_t size = ntohs (dvb->header.size) - sizeof(*dvb);
7331  uint16_t num_hops = ntohs (dvb->num_hops);
7332  const struct GNUNET_PeerIdentity *hops =
7333  (const struct GNUNET_PeerIdentity *) &dvb[1];
7334  const char *enc_payload = (const char *) &hops[num_hops];
7335  uint16_t enc_payload_size =
7336  size - (num_hops * sizeof(struct GNUNET_PeerIdentity));
7337  struct DVKeyState key;
7338  struct GNUNET_HashCode hmac;
7339  const char *hdr;
7340  size_t hdr_len;
7341 
7342  if (GNUNET_EXTRA_LOGGING > 0)
7343  {
7344  char *path;
7345 
7347  for (unsigned int i = 0; i < num_hops; i++)
7348  {
7349  char *tmp;
7350 
7351  GNUNET_asprintf (&tmp, "%s->%s", path, GNUNET_i2s (&hops[i]));
7352  GNUNET_free (path);
7353  path = tmp;
7354  }
7356  "Received DVBox with remaining path %s\n",
7357  path);
7358  GNUNET_free (path);
7359  }
7360 
7361  if (num_hops > 0)
7362  {
7363  /* We're trying from the end of the hops array, as we may be
7364  able to find a shortcut unknown to the origin that way */
7365  for (int i = num_hops - 1; i >= 0; i--)
7366  {
7367  struct Neighbour *n;
7368 
7369  if (0 == GNUNET_memcmp (&hops[i], &GST_my_identity))
7370  {
7371  GNUNET_break_op (0);
7372  finish_cmc_handling (cmc);
7373  return;
7374  }
7375  n = lookup_neighbour (&hops[i]);
7376  if (NULL == n)
7377  continue;
7379  "Skipping %u/%u hops ahead while routing DV Box\n",
7380  i,
7381  num_hops);
7382  forward_dv_box (n,
7383  dvb,
7384  ntohs (dvb->total_hops) + 1,
7385  num_hops - i - 1, /* number of hops left */
7386  &hops[i + 1], /* remaining hops */
7387  enc_payload,
7388  enc_payload_size);
7389  GNUNET_STATISTICS_update (GST_stats,
7390  "# DV hops skipped routing boxes",
7391  i,
7392  GNUNET_NO);
7393  GNUNET_STATISTICS_update (GST_stats,
7394  "# DV boxes routed (total)",
7395  1,
7396  GNUNET_NO);
7397  finish_cmc_handling (cmc);
7398  return;
7399  }
7400  /* Woopsie, next hop not in neighbours, drop! */
7401  GNUNET_STATISTICS_update (GST_stats,
7402  "# DV Boxes dropped: next hop unknown",
7403  1,
7404  GNUNET_NO);
7405  finish_cmc_handling (cmc);
7406  return;
7407  }
7408  /* We are the target. Unbox and handle message. */
7409  GNUNET_STATISTICS_update (GST_stats,
7410  "# DV boxes opened (ultimate target)",
7411  1,
7412  GNUNET_NO);
7413  cmc->total_hops = ntohs (dvb->total_hops);
7414 
7415  dh_key_derive_eph_pub (&dvb->ephemeral_key, &dvb->iv, &key);
7416  hdr = (const char *) &dvb[1];
7417  hdr_len = ntohs (dvb->header.size) - sizeof(*dvb);
7418  dv_hmac (&key, &hmac, hdr, hdr_len);
7419  if (0 != GNUNET_memcmp (&hmac, &dvb->hmac))
7420  {
7421  /* HMAC mismatch, discard! */
7422  GNUNET_break_op (0);
7423  finish_cmc_handling (cmc);
7424  return;
7425  }
7426  /* begin actual decryption */
7427  {
7428  struct Backtalker *b;
7429  struct GNUNET_TIME_Absolute monotime;
7430  struct TransportDVBoxPayloadP ppay;
7431  char body[hdr_len - sizeof(ppay)] GNUNET_ALIGN;
7432  const struct GNUNET_MessageHeader *mh =
7433  (const struct GNUNET_MessageHeader *) body;
7434 
7435  GNUNET_assert (hdr_len >=
7436  sizeof(ppay) + sizeof(struct GNUNET_MessageHeader));
7437  dv_decrypt (&key, &ppay, hdr, sizeof(ppay));
7438  dv_decrypt (&key, &body, &hdr[sizeof(ppay)], hdr_len - sizeof(ppay));
7439  dv_key_clean (&key);
7440  if (ntohs (mh->size) != sizeof(body))
7441  {
7442  GNUNET_break_op (0);
7443  finish_cmc_handling (cmc);
7444  return;
7445  }
7446  /* need to prevent box-in-a-box (and DV_LEARN) so check inbox type! */
7447  switch (ntohs (mh->type))
7448  {
7450  GNUNET_break_op (0);
7451  finish_cmc_handling (cmc);
7452  return;
7453 
7455  GNUNET_break_op (0);
7456  finish_cmc_handling (cmc);
7457  return;
7458 
7459  default:
7460  /* permitted, continue */
7461  break;
7462  }
7463  monotime = GNUNET_TIME_absolute_ntoh (ppay.monotonic_time);
7465  "Decrypted backtalk from %s\n",
7466  GNUNET_i2s (&ppay.sender));
7467  b = GNUNET_CONTAINER_multipeermap_get (backtalkers, &ppay.sender);
7468  if ((NULL != b) && (monotime.abs_value_us < b->monotonic_time.abs_value_us))
7469  {
7471  GST_stats,
7472  "# Backchannel messages dropped: monotonic time not increasing",
7473  1,
7474  GNUNET_NO);
7475  finish_cmc_handling (cmc);
7476  return;
7477  }
7478  if ((NULL == b) ||
7479  (0 != GNUNET_memcmp (&b->last_ephemeral, &dvb->ephemeral_key)))
7480  {
7481  /* Check signature */
7482  struct EphemeralConfirmationPS ec;
7483 
7485  ec.purpose.size = htonl (sizeof(ec));
7486  ec.target = GST_my_identity;
7487  ec.ephemeral_key = dvb->ephemeral_key;
7488  if (
7489  GNUNET_OK !=
7492  &ec,
7493  &ppay.sender_sig,
7494  &ppay.sender.public_key))
7495  {
7496  /* Signature invalid, discard! */
7497  GNUNET_break_op (0);
7498  finish_cmc_handling (cmc);
7499  return;
7500  }
7501  }
7502  /* Update sender, we now know the real origin! */
7504  "DVBox received for me from %s via %s\n",
7505  GNUNET_i2s2 (&ppay.sender),
7506  GNUNET_i2s (&cmc->im.sender));
7507  cmc->im.sender = ppay.sender;
7508 
7509  if (NULL != b)
7510  {
7511  /* update key cache and mono time */
7512  b->last_ephemeral = dvb->ephemeral_key;
7513  b->monotonic_time = monotime;
7515  b->timeout =
7517 
7518  demultiplex_with_cmc (cmc, mh);
7519  return;
7520  }
7521  /* setup data structure to cache signature AND check
7522  monotonic time with PEERSTORE before forwarding backchannel payload */
7523  b = GNUNET_malloc (sizeof(struct Backtalker) + sizeof(body));
7524  b->pid = ppay.sender;
7525  b->body_size = sizeof(body);
7526  memcpy (&b[1], body, sizeof(body));
7529  backtalkers,
7530  &b->pid,
7531  b,
7533  b->monotonic_time = monotime; /* NOTE: to be checked still! */
7534  b->cmc = cmc;
7535  b->timeout =
7538  b->get =
7539  GNUNET_PEERSTORE_iterate (peerstore,
7540  "transport",
7541  &b->pid,
7544  b);
7545  } /* end actual decryption */
7546 }
7547 
7548 
7556 static int
7558  const struct GNUNET_TRANSPORT_IncomingMessage *im)
7559 {
7560  struct TransportClient *tc = cls;
7561 
7562  if (CT_COMMUNICATOR != tc->type)
7563  {
7564  GNUNET_break (0);
7565  return GNUNET_SYSERR;
7566  }
7568  return GNUNET_OK;
7569 }
7570 
7571 
7576 {
7580  const char *address;
7581 
7586 };
7587 
7588 
7598 static int
7600  const struct GNUNET_PeerIdentity *pid,
7601  void *value)
7602 {
7603  struct CheckKnownAddressContext *ckac = cls;
7604  struct ValidationState *vs = value;
7605 
7606  (void) pid;
7607  if (0 != strcmp (vs->address, ckac->address))
7608  return GNUNET_OK;
7609  ckac->vs = vs;
7610  return GNUNET_NO;
7611 }
7612 
7613 
7619 static void
7620 validation_start_cb (void *cls);
7621 
7622 
7630 static void
7632  struct GNUNET_TIME_Absolute new_time)
7633 {
7634  struct GNUNET_TIME_Relative delta;
7635 
7636  if (new_time.abs_value_us == vs->next_challenge.abs_value_us)
7637  return; /* be lazy */
7638  vs->next_challenge = new_time;
7639  if (NULL == vs->hn)
7640  vs->hn =
7641  GNUNET_CONTAINER_heap_insert (validation_heap, vs, new_time.abs_value_us);
7642  else
7644  if ((vs != GNUNET_CONTAINER_heap_peek (validation_heap)) &&
7645  (NULL != validation_task))
7646  return;
7647  if (NULL != validation_task)
7648  GNUNET_SCHEDULER_cancel (validation_task);
7649  /* randomize a bit */
7650  delta.rel_value_us =
7652  MIN_DELAY_ADDRESS_VALIDATION.rel_value_us);
7653  new_time = GNUNET_TIME_absolute_add (new_time, delta);
7654  validation_task =
7655  GNUNET_SCHEDULER_add_at (new_time, &validation_start_cb, NULL);
7656 }
7657 
7658 
7665 static void
7667  const char *address)
7668 {
7669  struct GNUNET_TIME_Absolute now;
7670  struct ValidationState *vs;
7671  struct CheckKnownAddressContext ckac = { .address = address, .vs = NULL };
7672 
7673  (void) GNUNET_CONTAINER_multipeermap_get_multiple (validation_map,
7674  pid,
7676  &ckac);
7677  if (NULL != (vs = ckac.vs))
7678  {
7679  /* if 'vs' is not currently valid, we need to speed up retrying the
7680  * validation */
7681  if (vs->validated_until.abs_value_us < vs->next_challenge.abs_value_us)
7682  {
7683  /* reduce backoff as we got a fresh advertisement */
7684  vs->challenge_backoff =
7687  vs->challenge_backoff,
7688  2));
7691  vs->challenge_backoff));
7692  }
7693  return;
7694  }
7695  now = GNUNET_TIME_absolute_get ();
7696  vs = GNUNET_new (struct ValidationState);
7697  vs->pid = *pid;
7698  vs->valid_until =
7700  vs->first_challenge_use = now;
7701  vs->validation_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
7703  &vs->challenge,
7704  sizeof(vs->challenge));
7705  vs->address = GNUNET_strdup (address);
7707  "Starting address validation `%s' of peer %s using challenge %s\n",
7708  address,
7709  GNUNET_i2s (pid),
7710  GNUNET_sh2s (&vs->challenge.value));
7713  validation_map,
7714  &vs->pid,
7715  vs,
7717  update_next_challenge_time (vs, now);
7718 }
7719 
7720 
7728 static void
7730  const struct GNUNET_PEERSTORE_Record *record,
7731  const char *emsg)
7732 {
7733  struct IncomingRequest *ir = cls;
7734  const char *val;
7735 
7736  if (NULL != emsg)
7737  {
7739  "Got failure from PEERSTORE: %s\n",
7740  emsg);
7741  return;
7742  }
7743  val = record->value;
7744  if ((0 == record->value_size) || ('\0' != val[record->value_size - 1]))
7745  {
7746  GNUNET_break (0);
7747  return;
7748  }
7749  start_address_validation (&ir->pid, (const char *) record->value);
7750 }
7751 
7752 
7761 static void
7763  void *cls,
7764  const struct TransportValidationChallengeMessage *tvc)
7765 {
7766  struct CommunicatorMessageContext *cmc = cls;
7768  struct VirtualLink *vl;
7769  struct GNUNET_TIME_RelativeNBO validity_duration;
7770  struct IncomingRequest *ir;
7771  struct Neighbour *n;
7772  struct GNUNET_PeerIdentity sender;
7773 
7774  /* DV-routed messages are not allowed for validation challenges */
7775  if (cmc->total_hops > 0)
7776  {
7777  GNUNET_break_op (0);
7778  finish_cmc_handling (cmc);
7779  return;
7780  }
7781  validity_duration = cmc->im.expected_address_validity;
7783  "Received address validation challenge %s\n",
7784  GNUNET_sh2s (&tvc->challenge.value));
7785  /* If we have a virtual link, we use this mechanism to signal the
7786  size of the flow control window, and to allow the sender
7787  to ask for increases. If for us the virtual link is still down,
7788  we will always give a window size of zero. */
7789  tvr.header.type =
7791  tvr.header.size = htons (sizeof(tvr));
7792  tvr.reserved = htonl (0);
7793  tvr.challenge = tvc->challenge;
7794  tvr.origin_time = tvc->sender_time;
7795  tvr.validity_duration = validity_duration;
7796  {
7797  /* create signature */
7798  struct TransportValidationPS tvp = {
7800  .purpose.size = htonl (sizeof(tvp)),
7801  .validity_duration = validity_duration,
7802  .challenge = tvc->challenge
7803  };
7804 
7805  GNUNET_CRYPTO_eddsa_sign (GST_my_private_key,
7806  &tvp,
7807  &tvr.signature);
7808  }
7809  sender = cmc->im.sender;
7810  vl = lookup_virtual_link (&sender);
7811  if (NULL != vl)
7812  {
7813  route_control_message_without_fc (&cmc->im.sender,
7814  &tvr.header,
7816  }
7817  else
7818  {
7819  /* Use route via neighbour */
7820  n = lookup_neighbour (&sender);
7821  if (NULL != n)
7822  route_via_neighbour (n, &tvr.header,
7825  }
7826 
7827  finish_cmc_handling (cmc);
7828  if (NULL != vl)
7829  return;
7830 
7831  /* For us, the link is still down, but we need bi-directional
7832  connections (for flow-control and for this to be useful for
7833  CORE), so we must try to bring the link up! */
7834 
7835  /* (1) Check existing queues, if any, we may be lucky! */
7836  n = lookup_neighbour (&sender);
7837  if (NULL != n)
7838  for (struct Queue *q = n->qu