GNUnet  0.10.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 
311 struct MessageUUIDP {
316  uint64_t uuid GNUNET_PACKED;
317 };
318 
319 
328 };
329 
330 
338  struct GNUNET_ShortHashCode value;
339 };
340 
341 
349  struct GNUNET_MessageHeader header;
350 
351  /* Followed by *another* message header which is the message to
352  the communicator */
353 
354  /* Followed by a 0-terminated name of the communicator */
355 };
356 
357 
366 
381  struct GNUNET_TIME_AbsoluteNBO sender_monotonic_time;
382 
386  struct GNUNET_PeerIdentity target;
387 
392  struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
393 };
394 
395 
404  struct GNUNET_PeerIdentity sender;
405 
410  struct GNUNET_CRYPTO_EddsaSignature sender_sig;
411 
422  struct GNUNET_TIME_AbsoluteNBO monotonic_time;
423 
424  /* Followed by a `struct GNUNET_MessageHeader` with a message
425  for the target peer */
426 };
427 
428 
437  struct GNUNET_MessageHeader header;
438 
445  uint32_t ack_countdown GNUNET_PACKED;
446 
452  struct AcknowledgementUUIDP ack_uuid;
453 };
454 
455 
466  struct GNUNET_TIME_RelativeNBO ack_delay;
467 
471  struct AcknowledgementUUIDP ack_uuid;
472 };
473 
474 
486  struct GNUNET_MessageHeader header;
487 
492  uint32_t ack_counter GNUNET_PACKED;
493 
494  /* followed by any number of `struct TransportCummulativeAckPayloadP`
495  messages providing ACKs */
496 };
497 
498 
506  struct GNUNET_MessageHeader header;
507 
511  uint16_t frag_off GNUNET_PACKED;
512 
516  uint16_t msg_size GNUNET_PACKED;
517 
525  struct AcknowledgementUUIDP ack_uuid;
526 
531  struct MessageUUIDP msg_uuid;
532 };
533 
534 
552 struct DvInitPS {
557 
570  struct GNUNET_TIME_AbsoluteNBO monotonic_time;
571 
575  struct ChallengeNonceP challenge;
576 };
577 
578 
595 struct DvHopPS {
600 
604  struct GNUNET_PeerIdentity pred;
605 
609  struct GNUNET_PeerIdentity succ;
610 
614  struct ChallengeNonceP challenge;
615 };
616 
617 
622 struct DVPathEntryP {
627 
633 };
634 
635 
653  struct GNUNET_MessageHeader header;
654 
659  uint16_t num_hops GNUNET_PACKED;
660 
669  uint16_t bidirectional GNUNET_PACKED;
670 
676  struct GNUNET_TIME_RelativeNBO non_network_delay;
677 
690  struct GNUNET_TIME_AbsoluteNBO monotonic_time;
691 
697 
701  struct GNUNET_PeerIdentity initiator;
702 
706  struct ChallengeNonceP challenge;
707 
708  /* Followed by @e num_hops `struct DVPathEntryP` values,
709  excluding the initiator of the DV trace; the last entry is the
710  current sender; the current peer must not be included. */
711 };
712 
713 
740  struct GNUNET_MessageHeader header;
741 
748  uint16_t total_hops GNUNET_PACKED;
749 
755  uint16_t num_hops GNUNET_PACKED;
756 
761  struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
762 
769 
775  struct GNUNET_HashCode hmac;
776 
777  /* Followed by @e num_hops `struct GNUNET_PeerIdentity` values;
778  excluding the @e origin and the current peer, the last must be
779  the ultimate target; if @e num_hops is zero, the receiver of this
780  message is the ultimate target. */
781 
782  /* Followed by encrypted, variable-size payload, which
783  must begin with a `struct TransportDVBoxPayloadP` */
784 
785  /* Followed by the actual message, which itself must not be a
786  a DV_LEARN or DV_BOX message! */
787 };
788 
789 
798  struct GNUNET_MessageHeader header;
799 
804 
808  struct ChallengeNonceP challenge;
809 
814  struct GNUNET_TIME_AbsoluteNBO sender_time;
815 };
816 
817 
827 
832  struct GNUNET_TIME_RelativeNBO validity_duration;
833 
837  struct ChallengeNonceP challenge;
838 };
839 
840 
849  struct GNUNET_MessageHeader header;
850 
855 
861 
865  struct ChallengeNonceP challenge;
866 
871  struct GNUNET_TIME_AbsoluteNBO origin_time;
872 
877  struct GNUNET_TIME_RelativeNBO validity_duration;
878 };
879 
880 
893  struct GNUNET_MessageHeader header;
894 
902  uint32_t seq GNUNET_PACKED;
903 
908  uint64_t inbound_window_size GNUNET_PACKED;
909 
915  uint64_t outbound_sent GNUNET_PACKED;
916 
925  uint64_t outbound_window_size GNUNET_PACKED;
926 
935  struct GNUNET_TIME_AbsoluteNBO sender_time;
936 };
937 
938 
940 
941 
949  CT_NONE = 0,
950 
954  CT_CORE = 1,
955 
960 
965 
970 };
971 
972 
981  RMO_NONE = 0,
982 
987 
992 
997 
1004 };
1005 
1006 
1015 
1020 
1024  struct ChallengeNonceP challenge;
1025 
1030  struct GNUNET_TIME_Absolute launch_time;
1031 };
1032 
1033 
1042  uint64_t bytes_sent;
1043 
1048  uint64_t bytes_received;
1049 };
1050 
1051 
1059  struct GNUNET_TIME_Relative aged_rtt;
1060 
1066 
1071  unsigned int last_age;
1072 };
1073 
1074 
1078 struct TransportClient;
1079 
1083 struct Neighbour;
1084 
1089 struct DistanceVector;
1090 
1095 struct Queue;
1096 
1100 struct PendingMessage;
1101 
1105 struct DistanceVectorHop;
1106 
1115 struct VirtualLink;
1116 
1117 
1128 
1134 
1139 
1143  struct GNUNET_TRANSPORT_IncomingMessage im;
1144 
1149  uint16_t total_hops;
1150 };
1151 
1152 
1161 
1166 
1170  struct VirtualLink *vl;
1171 
1175  uint16_t size;
1176 
1183  uint16_t isize;
1184 };
1185 
1186 
1195 struct VirtualLink {
1199  struct GNUNET_PeerIdentity target;
1200 
1206 
1212 
1217 
1222 
1227 
1232 
1240 
1246 
1250  struct Neighbour *n;
1251 
1256 
1262  struct GNUNET_TIME_Absolute n_challenge_time;
1263 
1269  struct GNUNET_TIME_Absolute last_fc_transmission;
1270 
1278  struct GNUNET_TIME_Absolute last_fc_timestamp;
1279 
1284  struct GNUNET_TIME_Relative last_fc_rtt;
1285 
1291 
1300 
1308 
1315 
1324 
1337 
1343 
1350 
1361 
1366  uint32_t fc_seq_gen;
1367 
1373  uint32_t last_fc_seq;
1374 
1387 };
1388 
1389 
1399 
1405 
1412 
1419 
1426 
1433 
1440 
1447 
1451  struct AcknowledgementUUIDP ack_uuid;
1452 
1458 
1464 
1469  struct Queue *queue;
1470 
1474  struct GNUNET_TIME_Absolute transmission_time;
1475 
1479  uint16_t message_size;
1480 };
1481 
1482 
1491 
1496 
1501 
1506 
1511 
1516 
1521 
1526 
1532  const struct GNUNET_PeerIdentity *path;
1533 
1539 
1547  struct GNUNET_TIME_Absolute path_valid_until;
1548 
1552  struct PerformanceData pd;
1553 
1559  unsigned int distance;
1560 };
1561 
1562 
1571  struct GNUNET_PeerIdentity target;
1572 
1577 
1582 
1587 
1592  struct VirtualLink *vl;
1593 
1598  struct GNUNET_CRYPTO_EddsaSignature sender_sig;
1599 
1603  struct GNUNET_TIME_Absolute ephemeral_validity;
1604 
1608  struct GNUNET_TIME_Absolute monotime;
1609 
1613  struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
1614 
1618  struct GNUNET_CRYPTO_EcdhePrivateKey private_key;
1619 };
1620 
1621 
1631 struct QueueEntry {
1635  struct QueueEntry *next;
1636 
1640  struct QueueEntry *prev;
1641 
1645  struct Queue *queue;
1646 
1651 
1655  uint64_t mid;
1656 };
1657 
1658 
1663 struct Queue {
1668 
1673 
1678 
1683 
1688 
1693 
1698 
1703 
1708 
1713 
1717  const char *address;
1718 
1724 
1732  struct GNUNET_TIME_Absolute validated_until;
1733 
1737  struct PerformanceData pd;
1738 
1743  uint64_t mid_gen;
1744 
1748  uint32_t qid;
1749 
1753  uint32_t mtu;
1754 
1759 
1764 
1768  unsigned int queue_length;
1769 
1773  enum GNUNET_NetworkType nt;
1774 
1779 
1784  int idle;
1785 };
1786 
1787 
1796  struct MessageUUIDP msg_uuid;
1797 
1802 
1807 
1815  uint8_t *bitfield;
1816 
1820  struct GNUNET_TIME_Absolute reassembly_timeout;
1821 
1826  struct GNUNET_TIME_Absolute last_frag;
1827 
1831  uint16_t msg_size;
1832 
1837  uint16_t msg_missing;
1838 
1839  /* Followed by @e msg_size bytes of the (partially) defragmented original
1840  * message */
1841 
1842  /* Followed by @e bitfield data */
1843 };
1844 
1845 
1849 struct Neighbour {
1854 
1861 
1868 
1873 
1879 
1885 
1890 
1895 
1901 
1907 
1912  struct VirtualLink *vl;
1913 
1918  struct GNUNET_TIME_Absolute last_dv_learn_monotime;
1919 
1925 };
1926 
1927 
1937 
1942 
1947 
1952 };
1953 
1954 
1958 struct PeerRequest {
1963 
1968 
1973 
1980 
1985 };
1986 
1987 
1996 
2001 
2006 
2011 };
2012 
2013 
2040 struct PendingMessage {
2045 
2050 
2055 
2060 
2066 
2072 
2077 
2082 
2088 
2092  struct VirtualLink *vl;
2093 
2102  struct QueueEntry *qe;
2103 
2108 
2113 
2118 
2123 
2128 
2132  struct GNUNET_TIME_Absolute next_attempt;
2133 
2138  struct MessageUUIDP msg_uuid;
2139 
2144  unsigned long long logging_uuid;
2145 
2150 
2156 
2160  uint16_t bytes_msg;
2161 
2165  uint16_t frag_off;
2166 
2170  int16_t msg_uuid_set;
2171 
2172  /* Followed by @e bytes_msg to transmit */
2173 };
2174 
2175 
2184  struct GNUNET_TIME_Absolute receive_time;
2185 
2189  struct AcknowledgementUUIDP ack_uuid;
2190 };
2191 
2192 
2201  struct GNUNET_PeerIdentity target;
2202 
2207 
2214 
2218  struct GNUNET_TIME_Absolute min_transmission_time;
2219 
2225  uint32_t ack_counter;
2226 
2230  unsigned int num_acks;
2231 };
2232 
2233 
2242 
2247 
2252 
2256  const char *address;
2257 
2262 
2267 
2273 
2277  uint32_t aid;
2278 
2283 };
2284 
2285 
2294 
2299 
2304 
2309 
2314 
2315  union {
2319  struct {
2325 
2330  } core;
2331 
2335  struct {
2342 
2347  } monitor;
2348 
2349 
2353  struct {
2359 
2364 
2369 
2375 
2381 
2387  unsigned int total_queue_length;
2388 
2393  } communicator;
2394 
2398  struct {
2404  } application;
2405  } details;
2406 };
2407 
2408 
2419 
2426  struct GNUNET_TIME_Absolute valid_until;
2427 
2432  struct GNUNET_TIME_Absolute validated_until;
2433 
2440  struct GNUNET_TIME_Absolute first_challenge_use;
2441 
2448  struct GNUNET_TIME_Absolute last_challenge_use;
2449 
2457  struct GNUNET_TIME_Absolute next_challenge;
2458 
2467  struct GNUNET_TIME_Relative challenge_backoff;
2468 
2473  struct GNUNET_TIME_Relative validation_rtt;
2474 
2482  struct ChallengeNonceP challenge;
2483 
2487  char *address;
2488 
2494  struct GNUNET_CONTAINER_HeapNode *hn;
2495 
2501 
2507  uint32_t last_window_consum_limit;
2508 
2513  int awaiting_queue;
2514 };
2515 
2516 
2523 struct Backtalker {
2528 
2532  struct GNUNET_TIME_Absolute monotonic_time;
2533 
2538 
2542  struct GNUNET_CRYPTO_EcdhePublicKey last_ephemeral;
2543 
2549 
2554 
2560 
2566 
2571  size_t body_size;
2572 };
2573 
2574 
2579 
2584 
2589 
2594 
2599 
2604 
2610 
2616 
2622 
2628 
2634 
2640 
2646 
2651 
2656 
2661 
2668 
2673 
2678 
2683 
2689 
2695 
2701 static struct IncomingRequest *ir_head;
2702 
2706 static struct IncomingRequest *ir_tail;
2707 
2711 static unsigned int ir_total;
2712 
2716 static unsigned long long logging_uuid_gen;
2717 
2722 static unsigned int pa_count;
2723 
2733 
2734 
2745 static unsigned int
2747 {
2748  struct GNUNET_TIME_Absolute now;
2749 
2750  now = GNUNET_TIME_absolute_get();
2751  return now.abs_value_us / GNUNET_TIME_UNIT_MINUTES.rel_value_us / 15;
2752 }
2753 
2754 
2760 static void
2762 {
2763  GNUNET_CONTAINER_DLL_remove(ir_head, ir_tail, ir);
2764  GNUNET_assert(ir_total > 0);
2765  ir_total--;
2767  GNUNET_free(ir);
2768 }
2769 
2770 
2776 static void
2778 {
2779  struct Queue *q = pa->queue;
2780  struct PendingMessage *pm = pa->pm;
2781  struct DistanceVectorHop *dvh = pa->dvh;
2782 
2783  GNUNET_CONTAINER_MDLL_remove(pa, pa_head, pa_tail, pa);
2784  pa_count--;
2785  if (NULL != q)
2786  {
2788  pa->queue = NULL;
2789  }
2790  if (NULL != pm)
2791  {
2792  GNUNET_CONTAINER_MDLL_remove(pm, pm->pa_head, pm->pa_tail, pa);
2793  pa->pm = NULL;
2794  }
2795  if (NULL != dvh)
2796  {
2797  GNUNET_CONTAINER_MDLL_remove(dvh, dvh->pa_head, dvh->pa_tail, pa);
2798  pa->queue = NULL;
2799  }
2802  &pa->ack_uuid.value,
2803  pa));
2804  GNUNET_free(pa);
2805 }
2806 
2807 
2816 static void
2818 {
2819  struct PendingMessage *frag;
2820 
2821  while (NULL != (frag = root->head_frag))
2822  {
2823  struct PendingAcknowledgement *pa;
2824 
2825  free_fragment_tree(frag);
2826  while (NULL != (pa = frag->pa_head))
2827  {
2828  GNUNET_CONTAINER_MDLL_remove(pm, frag->pa_head, frag->pa_tail, pa);
2829  pa->pm = NULL;
2830  }
2831  GNUNET_CONTAINER_MDLL_remove(frag, root->head_frag, root->tail_frag, frag);
2832  GNUNET_free(frag);
2833  }
2834 }
2835 
2836 
2844 static void
2846 {
2847  struct TransportClient *tc = pm->client;
2848  struct VirtualLink *vl = pm->vl;
2849  struct PendingAcknowledgement *pa;
2850 
2851  if (NULL != tc)
2852  {
2854  tc->details.core.pending_msg_head,
2855  tc->details.core.pending_msg_tail,
2856  pm);
2857  }
2858  if (NULL != vl)
2859  {
2861  vl->pending_msg_head,
2862  vl->pending_msg_tail,
2863  pm);
2864  }
2865  while (NULL != (pa = pm->pa_head))
2866  {
2867  GNUNET_CONTAINER_MDLL_remove(pm, pm->pa_head, pm->pa_tail, pa);
2868  pa->pm = NULL;
2869  }
2870 
2871  free_fragment_tree(pm);
2872  if (NULL != pm->qe)
2873  {
2874  GNUNET_assert(pm == pm->qe->pm);
2875  pm->qe->pm = NULL;
2876  }
2877  if (NULL != pm->bpm)
2878  {
2879  free_fragment_tree(pm->bpm);
2880  GNUNET_free(pm->bpm);
2881  }
2882  GNUNET_free(pm);
2883 }
2884 
2885 
2891 static void
2893 {
2894  struct PendingMessage *pm;
2895  struct CoreSentContext *csc;
2896 
2897  while (NULL != (pm = vl->pending_msg_head))
2900  GNUNET_CONTAINER_multipeermap_remove(links, &vl->target, vl));
2901  if (NULL != vl->visibility_task)
2902  {
2904  vl->visibility_task = NULL;
2905  }
2906  if (NULL != vl->fc_retransmit_task)
2907  {
2909  vl->fc_retransmit_task = NULL;
2910  }
2911  while (NULL != (csc = vl->csc_head))
2912  {
2914  GNUNET_assert(vl == csc->vl);
2915  csc->vl = NULL;
2916  }
2917  GNUNET_break(NULL == vl->n);
2918  GNUNET_break(NULL == vl->dv);
2919  GNUNET_free(vl);
2920 }
2921 
2922 
2928 static void
2930 {
2931  GNUNET_assert(
2932  GNUNET_YES ==
2933  GNUNET_CONTAINER_multipeermap_remove(validation_map, &vs->pid, vs));
2935  vs->hn = NULL;
2936  if (NULL != vs->sc)
2937  {
2939  vs->sc = NULL;
2940  }
2941  GNUNET_free(vs->address);
2942  GNUNET_free(vs);
2943 }
2944 
2945 
2952 static struct Neighbour *
2954 {
2955  return GNUNET_CONTAINER_multipeermap_get(neighbours, pid);
2956 }
2957 
2958 
2965 static struct VirtualLink *
2967 {
2968  return GNUNET_CONTAINER_multipeermap_get(links, pid);
2969 }
2970 
2971 
2979  struct GNUNET_TIME_Absolute last_validation;
2980  struct GNUNET_TIME_Absolute valid_until;
2981  struct GNUNET_TIME_Absolute next_validation;
2982 
2987 
2992 
2997 
3002 };
3003 
3004 
3013 static void
3015 {
3016  struct Neighbour *n = dvh->next_hop;
3017  struct DistanceVector *dv = dvh->dv;
3018  struct PendingAcknowledgement *pa;
3019 
3020  while (NULL != (pa = dvh->pa_head))
3021  {
3022  GNUNET_CONTAINER_MDLL_remove(dvh, dvh->pa_head, dvh->pa_tail, pa);
3023  pa->dvh = NULL;
3024  }
3025  GNUNET_CONTAINER_MDLL_remove(neighbour, n->dv_head, n->dv_tail, dvh);
3026  GNUNET_CONTAINER_MDLL_remove(dv, dv->dv_head, dv->dv_tail, dvh);
3027  GNUNET_free(dvh);
3028 }
3029 
3030 
3037 static void
3038 check_link_down(void *cls);
3039 
3040 
3046 static void
3048 {
3050  "Informing CORE clients about disconnect from %s\n",
3051  GNUNET_i2s(pid));
3052  for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
3053  {
3054  struct GNUNET_MQ_Envelope *env;
3055  struct DisconnectInfoMessage *dim;
3056 
3057  if (CT_CORE != tc->type)
3058  continue;
3060  dim->peer = *pid;
3061  GNUNET_MQ_send(tc->mq, env);
3062  }
3063 }
3064 
3065 
3072 static void
3074 {
3075  struct DistanceVectorHop *dvh;
3076 
3077  while (NULL != (dvh = dv->dv_head))
3079  if (NULL == dv->dv_head)
3080  {
3081  struct VirtualLink *vl;
3082 
3083  GNUNET_assert(
3084  GNUNET_YES ==
3085  GNUNET_CONTAINER_multipeermap_remove(dv_routes, &dv->target, dv));
3086  if (NULL != (vl = dv->vl))
3087  {
3088  GNUNET_assert(dv == vl->dv);
3089  vl->dv = NULL;
3090  if (NULL == vl->n)
3091  {
3093  free_virtual_link(vl);
3094  }
3095  else
3096  {
3099  }
3100  dv->vl = NULL;
3101  }
3102 
3103  if (NULL != dv->timeout_task)
3104  {
3106  dv->timeout_task = NULL;
3107  }
3108  GNUNET_free(dv);
3109  }
3110 }
3111 
3112 
3126 static void
3128  const struct GNUNET_PeerIdentity *peer,
3129  const char *address,
3130  enum GNUNET_NetworkType nt,
3131  const struct MonitorEvent *me)
3132 {
3133  struct GNUNET_MQ_Envelope *env;
3134  struct GNUNET_TRANSPORT_MonitorData *md;
3135  size_t addr_len = strlen(address) + 1;
3136 
3137  env = GNUNET_MQ_msg_extra(md,
3138  addr_len,
3140  md->nt = htonl((uint32_t)nt);
3141  md->peer = *peer;
3142  md->last_validation = GNUNET_TIME_absolute_hton(me->last_validation);
3143  md->valid_until = GNUNET_TIME_absolute_hton(me->valid_until);
3144  md->next_validation = GNUNET_TIME_absolute_hton(me->next_validation);
3145  md->rtt = GNUNET_TIME_relative_hton(me->rtt);
3146  md->cs = htonl((uint32_t)me->cs);
3147  md->num_msg_pending = htonl(me->num_msg_pending);
3148  md->num_bytes_pending = htonl(me->num_bytes_pending);
3149  memcpy(&md[1], address, addr_len);
3150  GNUNET_MQ_send(tc->mq, env);
3151 }
3152 
3153 
3163 static void
3165  const char *address,
3166  enum GNUNET_NetworkType nt,
3167  const struct MonitorEvent *me)
3168 {
3169  for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
3170  {
3171  if (CT_MONITOR != tc->type)
3172  continue;
3173  if (tc->details.monitor.one_shot)
3174  continue;
3175  if ((0 != GNUNET_is_zero(&tc->details.monitor.peer)) &&
3176  (0 != GNUNET_memcmp(&tc->details.monitor.peer, peer)))
3177  continue;
3178  notify_monitor(tc, peer, address, nt, me);
3179  }
3180 }
3181 
3182 
3192 static void *
3194  struct GNUNET_SERVICE_Client *client,
3195  struct GNUNET_MQ_Handle *mq)
3196 {
3197  struct TransportClient *tc;
3198 
3199  (void)cls;
3200  tc = GNUNET_new(struct TransportClient);
3201  tc->client = client;
3202  tc->mq = mq;
3203  GNUNET_CONTAINER_DLL_insert(clients_head, clients_tail, tc);
3204  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", tc);
3205  return tc;
3206 }
3207 
3208 
3214 static void
3216 {
3217  struct Neighbour *n = rc->neighbour;
3218 
3222  rc->msg_uuid.uuid,
3223  rc));
3224  GNUNET_free(rc);
3225 }
3226 
3227 
3233 static void
3235 {
3236  struct Neighbour *n = cls;
3237  struct ReassemblyContext *rc;
3238 
3239  n->reassembly_timeout_task = NULL;
3240  while (NULL != (rc = GNUNET_CONTAINER_heap_peek(n->reassembly_heap)))
3241  {
3243  .rel_value_us)
3244  {
3246  continue;
3247  }
3252  n);
3253  return;
3254  }
3255 }
3256 
3257 
3266 static int
3267 free_reassembly_cb(void *cls, uint32_t key, void *value)
3268 {
3269  struct ReassemblyContext *rc = value;
3270 
3271  (void)cls;
3272  (void)key;
3274  return GNUNET_OK;
3275 }
3276 
3277 
3283 static void
3285 {
3286  struct DistanceVectorHop *dvh;
3287  struct VirtualLink *vl;
3288 
3289  GNUNET_assert(NULL == neighbour->queue_head);
3292  &neighbour->pid,
3293  neighbour));
3294  if (NULL != neighbour->reassembly_map)
3295  {
3298  NULL);
3300  neighbour->reassembly_map = NULL;
3302  neighbour->reassembly_heap = NULL;
3303  }
3304  while (NULL != (dvh = neighbour->dv_head))
3305  {
3306  struct DistanceVector *dv = dvh->dv;
3307 
3309  if (NULL == dv->dv_head)
3310  free_dv_route(dv);
3311  }
3312  if (NULL != neighbour->reassembly_timeout_task)
3313  {
3315  neighbour->reassembly_timeout_task = NULL;
3316  }
3317  if (NULL != neighbour->get)
3318  {
3320  neighbour->get = NULL;
3321  }
3322  if (NULL != neighbour->sc)
3323  {
3324  GNUNET_PEERSTORE_store_cancel(neighbour->sc);
3325  neighbour->sc = NULL;
3326  }
3327  if (NULL != (vl = neighbour->vl))
3328  {
3329  GNUNET_assert(neighbour == vl->n);
3330  vl->n = NULL;
3331  if (NULL == vl->dv)
3332  {
3334  free_virtual_link(vl);
3335  }
3336  else
3337  {
3340  }
3341  neighbour->vl = NULL;
3342  }
3343  GNUNET_free(neighbour);
3344 }
3345 
3346 
3353 static void
3355  const struct GNUNET_PeerIdentity *pid)
3356 {
3357  struct GNUNET_MQ_Envelope *env;
3358  struct ConnectInfoMessage *cim;
3359 
3360  GNUNET_assert(CT_CORE == tc->type);
3362  cim->id = *pid;
3363  GNUNET_MQ_send(tc->mq, env);
3364 }
3365 
3366 
3372 static void
3374 {
3376  "Informing CORE clients about connection to %s\n",
3377  GNUNET_i2s(pid));
3378  for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
3379  {
3380  if (CT_CORE != tc->type)
3381  continue;
3382  core_send_connect_info(tc, pid);
3383  }
3384 }
3385 
3386 
3394 static void
3395 transmit_on_queue(void *cls);
3396 
3397 
3405 static void
3408 {
3409  if (queue->tc->details.communicator.total_queue_length >=
3411  {
3413  GST_stats,
3414  "# Transmission throttled due to communicator queue limit",
3415  1,
3416  GNUNET_NO);
3417  queue->idle = GNUNET_NO;
3418  return;
3419  }
3420  if (queue->queue_length >= QUEUE_LENGTH_LIMIT)
3421  {
3422  GNUNET_STATISTICS_update(GST_stats,
3423  "# Transmission throttled due to queue queue limit",
3424  1,
3425  GNUNET_NO);
3426  queue->idle = GNUNET_NO;
3427  return;
3428  }
3429  /* queue might indeed be ready, schedule it */
3430  if (NULL != queue->transmit_task)
3432  queue->transmit_task =
3435  "Considering transmission on queue `%s' to %s\n",
3436  queue->address,
3437  GNUNET_i2s(&queue->neighbour->pid));
3438 }
3439 
3440 
3447 static void
3449 {
3450  struct VirtualLink *vl = cls;
3451  struct DistanceVector *dv = vl->dv;
3452  struct Neighbour *n = vl->n;
3453  struct GNUNET_TIME_Absolute dvh_timeout;
3454  struct GNUNET_TIME_Absolute q_timeout;
3455 
3456  vl->visibility_task = NULL;
3457  dvh_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
3458  for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
3459  pos = pos->next_dv)
3460  dvh_timeout = GNUNET_TIME_absolute_max(dvh_timeout, pos->path_valid_until);
3461  if (0 == GNUNET_TIME_absolute_get_remaining(dvh_timeout).rel_value_us)
3462  {
3463  vl->dv->vl = NULL;
3464  vl->dv = NULL;
3465  }
3466  q_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
3467  for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
3468  q_timeout = GNUNET_TIME_absolute_max(q_timeout, q->validated_until);
3469  if (0 == GNUNET_TIME_absolute_get_remaining(q_timeout).rel_value_us)
3470  {
3471  vl->n->vl = NULL;
3472  vl->n = NULL;
3473  }
3474  if ((NULL == vl->n) && (NULL == vl->dv))
3475  {
3477  free_virtual_link(vl);
3478  return;
3479  }
3480  vl->visibility_task =
3481  GNUNET_SCHEDULER_add_at(GNUNET_TIME_absolute_max(q_timeout, dvh_timeout),
3482  &check_link_down,
3483  vl);
3484 }
3485 
3486 
3492 static void
3494 {
3495  struct Neighbour *neighbour = queue->neighbour;
3496  struct TransportClient *tc = queue->tc;
3497  struct MonitorEvent me = { .cs = GNUNET_TRANSPORT_CS_DOWN,
3499  struct QueueEntry *qe;
3500  int maxxed;
3501  struct PendingAcknowledgement *pa;
3502  struct VirtualLink *vl;
3503 
3504  if (NULL != queue->transmit_task)
3505  {
3507  queue->transmit_task = NULL;
3508  }
3509  while (NULL != (pa = queue->pa_head))
3510  {
3511  GNUNET_CONTAINER_MDLL_remove(queue, queue->pa_head, queue->pa_tail, pa);
3512  pa->queue = NULL;
3513  }
3514 
3515  GNUNET_CONTAINER_MDLL_remove(neighbour,
3516  neighbour->queue_head,
3517  neighbour->queue_tail,
3518  queue);
3520  tc->details.communicator.queue_head,
3521  tc->details.communicator.queue_tail,
3522  queue);
3523  maxxed = (COMMUNICATOR_TOTAL_QUEUE_LIMIT >=
3524  tc->details.communicator.total_queue_length);
3525  while (NULL != (qe = queue->queue_head))
3526  {
3528  queue->queue_length--;
3529  tc->details.communicator.total_queue_length--;
3530  if (NULL != qe->pm)
3531  {
3532  GNUNET_assert(qe == qe->pm->qe);
3533  qe->pm->qe = NULL;
3534  }
3535  GNUNET_free(qe);
3536  }
3537  GNUNET_assert(0 == queue->queue_length);
3538  if ((maxxed) && (COMMUNICATOR_TOTAL_QUEUE_LIMIT <
3539  tc->details.communicator.total_queue_length))
3540  {
3541  /* Communicator dropped below threshold, resume all _other_ queues */
3543  GST_stats,
3544  "# Transmission throttled due to communicator queue limit",
3545  -1,
3546  GNUNET_NO);
3547  for (struct Queue *s = tc->details.communicator.queue_head; NULL != s;
3548  s = s->next_client)
3550  }
3551  notify_monitors(&neighbour->pid, queue->address, queue->nt, &me);
3552  GNUNET_free(queue);
3553 
3554  vl = lookup_virtual_link(&neighbour->pid);
3555  if ((NULL != vl) && (neighbour == vl->n))
3556  {
3558  check_link_down(vl);
3559  }
3560  if (NULL == neighbour->queue_head)
3561  {
3562  free_neighbour(neighbour);
3563  }
3564 }
3565 
3566 
3572 static void
3574 {
3575  struct TransportClient *tc = ale->tc;
3576 
3578  tc->details.communicator.addr_tail,
3579  ale);
3580  if (NULL != ale->sc)
3581  {
3583  ale->sc = NULL;
3584  }
3585  if (NULL != ale->st)
3586  {
3588  ale->st = NULL;
3589  }
3590  GNUNET_free(ale);
3591 }
3592 
3593 
3602 static int
3604  const struct GNUNET_PeerIdentity *pid,
3605  void *value)
3606 {
3607  struct TransportClient *tc = cls;
3608  struct PeerRequest *pr = value;
3609 
3611  GNUNET_assert(
3612  GNUNET_YES ==
3614  pid,
3615  pr));
3616  GNUNET_free(pr);
3617 
3618  return GNUNET_OK;
3619 }
3620 
3621 
3630 static void
3632  struct GNUNET_SERVICE_Client *client,
3633  void *app_ctx)
3634 {
3635  struct TransportClient *tc = app_ctx;
3636 
3637  (void)cls;
3638  (void)client;
3640  "Client %p disconnected, cleaning up.\n",
3641  tc);
3642  GNUNET_CONTAINER_DLL_remove(clients_head, clients_tail, tc);
3643  switch (tc->type)
3644  {
3645  case CT_NONE:
3646  break;
3647 
3648  case CT_CORE: {
3649  struct PendingMessage *pm;
3650 
3651  while (NULL != (pm = tc->details.core.pending_msg_head))
3652  {
3654  tc->details.core.pending_msg_head,
3655  tc->details.core.pending_msg_tail,
3656  pm);
3657  pm->client = NULL;
3658  }
3659  }
3660  break;
3661 
3662  case CT_MONITOR:
3663  break;
3664 
3665  case CT_COMMUNICATOR: {
3666  struct Queue *q;
3667  struct AddressListEntry *ale;
3668 
3669  while (NULL != (q = tc->details.communicator.queue_head))
3670  free_queue(q);
3671  while (NULL != (ale = tc->details.communicator.addr_head))
3673  GNUNET_free(tc->details.communicator.address_prefix);
3674  }
3675  break;
3676 
3677  case CT_APPLICATION:
3680  tc);
3682  break;
3683  }
3684  GNUNET_free(tc);
3685 }
3686 
3687 
3697 static int
3699  const struct GNUNET_PeerIdentity *pid,
3700  void *value)
3701 {
3702  struct TransportClient *tc = cls;
3703 
3704  (void)value;
3706  "Telling new CORE client about existing connection to %s\n",
3707  GNUNET_i2s(pid));
3708  core_send_connect_info(tc, pid);
3709  return GNUNET_OK;
3710 }
3711 
3712 
3721 static void
3722 handle_client_start(void *cls, const struct StartMessage *start)
3723 {
3724  struct TransportClient *tc = cls;
3725  uint32_t options;
3726 
3727  options = ntohl(start->options);
3728  if ((0 != (1 & options)) &&
3729  (0 != GNUNET_memcmp(&start->self, &GST_my_identity)))
3730  {
3731  /* client thinks this is a different peer, reject */
3732  GNUNET_break(0);
3734  return;
3735  }
3736  if (CT_NONE != tc->type)
3737  {
3738  GNUNET_break(0);
3740  return;
3741  }
3742  tc->type = CT_CORE;
3744  "New CORE client with PID %s registered\n",
3745  GNUNET_i2s(&start->self));
3748  tc);
3750 }
3751 
3752 
3759 static int
3760 check_client_send(void *cls, const struct OutboundMessage *obm)
3761 {
3762  struct TransportClient *tc = cls;
3763  uint16_t size;
3764  const struct GNUNET_MessageHeader *obmm;
3765 
3766  if (CT_CORE != tc->type)
3767  {
3768  GNUNET_break(0);
3769  return GNUNET_SYSERR;
3770  }
3771  size = ntohs(obm->header.size) - sizeof(struct OutboundMessage);
3772  if (size < sizeof(struct GNUNET_MessageHeader))
3773  {
3774  GNUNET_break(0);
3775  return GNUNET_SYSERR;
3776  }
3777  obmm = (const struct GNUNET_MessageHeader *)&obm[1];
3778  if (size != ntohs(obmm->size))
3779  {
3780  GNUNET_break(0);
3781  return GNUNET_SYSERR;
3782  }
3783  return GNUNET_OK;
3784 }
3785 
3786 
3794 static void
3796 {
3797  struct TransportClient *tc = pm->client;
3798  struct VirtualLink *vl = pm->vl;
3799 
3800  if (NULL != tc)
3801  {
3802  struct GNUNET_MQ_Envelope *env;
3803  struct SendOkMessage *som;
3804 
3806  som->peer = vl->target;
3808  "Confirming transmission of <%llu> to %s\n",
3809  pm->logging_uuid,
3810  GNUNET_i2s(&vl->target));
3811  GNUNET_MQ_send(tc->mq, env);
3812  }
3814 }
3815 
3816 
3826 static unsigned int
3829  struct DistanceVectorHop **hops_array,
3830  unsigned int hops_array_length)
3831 {
3832  uint64_t choices[hops_array_length];
3833  uint64_t num_dv;
3834  unsigned int dv_count;
3835 
3836  /* Pick random vectors, but weighted by distance, giving more weight
3837  to shorter vectors */
3838  num_dv = 0;
3839  dv_count = 0;
3840  for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
3841  pos = pos->next_dv)
3842  {
3843  if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) &&
3844  (GNUNET_TIME_absolute_get_remaining(pos->path_valid_until)
3845  .rel_value_us == 0))
3846  continue; /* pos unconfirmed and confirmed required */
3847  num_dv += MAX_DV_HOPS_ALLOWED - pos->distance;
3848  dv_count++;
3849  }
3850  if (0 == dv_count)
3851  return 0;
3852  if (dv_count <= hops_array_length)
3853  {
3854  dv_count = 0;
3855  for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
3856  pos = pos->next_dv)
3857  hops_array[dv_count++] = pos;
3858  return dv_count;
3859  }
3860  for (unsigned int i = 0; i < hops_array_length; i++)
3861  {
3862  int ok = GNUNET_NO;
3863  while (GNUNET_NO == ok)
3864  {
3865  choices[i] =
3867  ok = GNUNET_YES;
3868  for (unsigned int j = 0; j < i; j++)
3869  if (choices[i] == choices[j])
3870  {
3871  ok = GNUNET_NO;
3872  break;
3873  }
3874  }
3875  }
3876  dv_count = 0;
3877  num_dv = 0;
3878  for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
3879  pos = pos->next_dv)
3880  {
3881  uint32_t delta = MAX_DV_HOPS_ALLOWED - pos->distance;
3882 
3883  if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) &&
3884  (GNUNET_TIME_absolute_get_remaining(pos->path_valid_until)
3885  .rel_value_us == 0))
3886  continue; /* pos unconfirmed and confirmed required */
3887  for (unsigned int i = 0; i < hops_array_length; i++)
3888  if ((num_dv <= choices[i]) && (num_dv + delta > choices[i]))
3889  hops_array[dv_count++] = pos;
3890  num_dv += delta;
3891  }
3892  return dv_count;
3893 }
3894 
3895 
3902 static int
3904  void *cls,
3905  const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
3906 {
3907  struct TransportClient *tc = cls;
3908  uint16_t size;
3909 
3910  if (CT_NONE != tc->type)
3911  {
3912  GNUNET_break(0);
3913  return GNUNET_SYSERR;
3914  }
3915  tc->type = CT_COMMUNICATOR;
3916  size = ntohs(cam->header.size) - sizeof(*cam);
3917  if (0 == size)
3918  return GNUNET_OK; /* receive-only communicator */
3920  return GNUNET_OK;
3921 }
3922 
3923 
3929 static void
3931 {
3932  if (0 != ntohl(cmc->im.fc_on))
3933  {
3934  /* send ACK when done to communicator for flow control! */
3935  struct GNUNET_MQ_Envelope *env;
3936  struct GNUNET_TRANSPORT_IncomingMessageAck *ack;
3937 
3939  ack->reserved = htonl(0);
3940  ack->fc_id = cmc->im.fc_id;
3941  ack->sender = cmc->im.sender;
3942  GNUNET_MQ_send(cmc->tc->mq, env);
3943  }
3945  GNUNET_free(cmc);
3946 }
3947 
3948 
3958 static void
3959 handle_client_recv_ok(void *cls, const struct RecvOkMessage *rom)
3960 {
3961  struct TransportClient *tc = cls;
3962  struct VirtualLink *vl;
3963  uint32_t delta;
3964  struct CommunicatorMessageContext *cmc;
3965 
3966  if (CT_CORE != tc->type)
3967  {
3968  GNUNET_break(0);
3970  return;
3971  }
3972  vl = lookup_virtual_link(&rom->peer);
3973  if (NULL == vl)
3974  {
3975  GNUNET_STATISTICS_update(GST_stats,
3976  "# RECV_OK dropped: virtual link unknown",
3977  1,
3978  GNUNET_NO);
3980  return;
3981  }
3982  delta = ntohl(rom->increase_window_delta);
3983  vl->core_recv_window += delta;
3984  if (vl->core_recv_window <= 0)
3985  return;
3986  /* resume communicators */
3987  while (NULL != (cmc = vl->cmc_tail))
3988  {
3990  finish_cmc_handling(cmc);
3991  }
3992 }
3993 
3994 
4001 static void
4003  void *cls,
4004  const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
4005 {
4006  struct TransportClient *tc = cls;
4007  uint16_t size;
4008 
4009  size = ntohs(cam->header.size) - sizeof(*cam);
4010  if (0 == size)
4011  {
4013  "Receive-only communicator connected\n");
4014  return; /* receive-only communicator */
4015  }
4016  tc->details.communicator.address_prefix =
4017  GNUNET_strdup((const char *)&cam[1]);
4018  tc->details.communicator.cc =
4019  (enum GNUNET_TRANSPORT_CommunicatorCharacteristics)ntohl(cam->cc);
4021  "Communicator with prefix `%s' connected\n",
4022  tc->details.communicator.address_prefix);
4024 }
4025 
4026 
4034 static int
4036  void *cls,
4037  const struct GNUNET_TRANSPORT_CommunicatorBackchannel *cb)
4038 {
4039  const struct GNUNET_MessageHeader *inbox;
4040  const char *is;
4041  uint16_t msize;
4042  uint16_t isize;
4043 
4044  (void)cls;
4045  msize = ntohs(cb->header.size) - sizeof(*cb);
4046  inbox = (const struct GNUNET_MessageHeader *)&cb[1];
4047  isize = ntohs(inbox->size);
4048  if (isize >= msize)
4049  {
4050  GNUNET_break(0);
4051  return GNUNET_SYSERR;
4052  }
4053  is = (const char *)inbox;
4054  is += isize;
4055  msize -= isize;
4056  GNUNET_assert(0 < msize);
4057  if ('\0' != is[msize - 1])
4058  {
4059  GNUNET_break(0);
4060  return GNUNET_SYSERR;
4061  }
4062  return GNUNET_OK;
4063 }
4064 
4065 
4072 static void
4074 {
4075  struct EphemeralConfirmationPS ec;
4076 
4077  if (0 !=
4079  return;
4081  dv->ephemeral_validity =
4087  ec.purpose.size = htonl(sizeof(ec));
4088  ec.target = dv->target;
4089  ec.ephemeral_key = dv->ephemeral_key;
4090  GNUNET_assert(GNUNET_OK == GNUNET_CRYPTO_eddsa_sign(GST_my_private_key,
4091  &ec.purpose,
4092  &dv->sender_sig));
4093 }
4094 
4095 
4105 static void
4107  struct PendingMessage *pm,
4108  const void *payload,
4109  size_t payload_size)
4110 {
4111  struct Neighbour *n = queue->neighbour;
4112  struct GNUNET_TRANSPORT_SendMessageTo *smt;
4113  struct GNUNET_MQ_Envelope *env;
4114 
4115  queue->idle = GNUNET_NO;
4116  GNUNET_log(
4118  "Queueing %u bytes of payload for transmission <%llu> on queue %llu to %s\n",
4119  (unsigned int)payload_size,
4120  (NULL == pm) ? 0 : pm->logging_uuid,
4121  (unsigned long long)queue->qid,
4122  GNUNET_i2s(&queue->neighbour->pid));
4123  env = GNUNET_MQ_msg_extra(smt,
4124  payload_size,
4126  smt->qid = queue->qid;
4127  smt->mid = queue->mid_gen;
4128  smt->receiver = n->pid;
4129  memcpy(&smt[1], payload, payload_size);
4130  {
4131  /* Pass the env to the communicator of queue for transmission. */
4132  struct QueueEntry *qe;
4133 
4134  qe = GNUNET_new(struct QueueEntry);
4135  qe->mid = queue->mid_gen++;
4136  qe->queue = queue;
4137  if (NULL != pm)
4138  {
4139  qe->pm = pm;
4140  GNUNET_assert(NULL == pm->qe);
4141  pm->qe = qe;
4142  }
4144  GNUNET_assert(CT_COMMUNICATOR == queue->tc->type);
4145  queue->queue_length++;
4146  queue->tc->details.communicator.total_queue_length++;
4148  queue->tc->details.communicator.total_queue_length)
4149  queue->idle = GNUNET_NO;
4150  if (QUEUE_LENGTH_LIMIT == queue->queue_length)
4151  queue->idle = GNUNET_NO;
4152  GNUNET_MQ_send(queue->tc->mq, env);
4153  }
4154 }
4155 
4156 
4167 static struct GNUNET_TIME_Relative
4169  const struct GNUNET_MessageHeader *hdr,
4171 {
4172  struct GNUNET_TIME_Absolute now;
4173  unsigned int candidates;
4174  unsigned int sel1;
4175  unsigned int sel2;
4176  struct GNUNET_TIME_Relative rtt;
4177 
4178  /* Pick one or two 'random' queues from n (under constraints of options) */
4179  now = GNUNET_TIME_absolute_get();
4180  /* FIXME-OPTIMIZE: give queues 'weights' and pick proportional to
4181  weight in the future; weight could be assigned by observed
4182  bandwidth (note: not sure if we should do this for this type
4183  of control traffic though). */
4184  candidates = 0;
4185  for (struct Queue *pos = n->queue_head; NULL != pos;
4186  pos = pos->next_neighbour)
4187  {
4188  if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) ||
4189  (pos->validated_until.abs_value_us > now.abs_value_us))
4190  candidates++;
4191  }
4192  if (0 == candidates)
4193  {
4194  /* This can happen rarely if the last confirmed queue timed
4195  out just as we were beginning to process this message. */
4197  "Could not route message of type %u to %s: no valid queue\n",
4198  ntohs(hdr->type),
4199  GNUNET_i2s(&n->pid));
4200  GNUNET_STATISTICS_update(GST_stats,
4201  "# route selection failed (all no valid queue)",
4202  1,
4203  GNUNET_NO);
4205  }
4206 
4209  if (0 == (options & RMO_REDUNDANT))
4210  sel2 = candidates; /* picks none! */
4211  else
4213  candidates = 0;
4214  for (struct Queue *pos = n->queue_head; NULL != pos;
4215  pos = pos->next_neighbour)
4216  {
4217  if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) ||
4218  (pos->validated_until.abs_value_us > now.abs_value_us))
4219  {
4220  if ((sel1 == candidates) || (sel2 == candidates))
4221  {
4223  "Routing message of type %u to %s using %s (#%u)\n",
4224  ntohs(hdr->type),
4225  GNUNET_i2s(&n->pid),
4226  pos->address,
4227  (sel1 == candidates) ? 1 : 2);
4228  rtt = GNUNET_TIME_relative_min(rtt, pos->pd.aged_rtt);
4229  queue_send_msg(pos, NULL, hdr, ntohs(hdr->size));
4230  }
4231  candidates++;
4232  }
4233  }
4234  return rtt;
4235 }
4236 
4237 
4241 struct DVKeyState {
4245  gcry_cipher_hd_t cipher;
4246 
4250  struct {
4254  struct GNUNET_CRYPTO_AuthKey hmac_key;
4255 
4259  char aes_key[256 / 8];
4260 
4264  char aes_ctr[128 / 8];
4265  } material;
4266 };
4267 
4268 
4277 static void
4279  const struct GNUNET_ShortHashCode *iv,
4280  struct DVKeyState *key)
4281 {
4282  /* must match #dh_key_derive_eph_pub */
4285  sizeof(key->material),
4286  "transport-backchannel-key",
4287  strlen("transport-backchannel-key"),
4288  &km,
4289  sizeof(km),
4290  iv,
4291  sizeof(*iv)));
4293  "Deriving backchannel key based on KM %s and IV %s\n",
4294  GNUNET_h2s(km),
4295  GNUNET_sh2s(iv));
4296  gcry_cipher_open(&key->cipher,
4297  GCRY_CIPHER_AES256 /* low level: go for speed */,
4298  GCRY_CIPHER_MODE_CTR,
4299  0 /* flags */);
4300  gcry_cipher_setkey(key->cipher,
4301  &key->material.aes_key,
4302  sizeof(key->material.aes_key));
4303  gcry_cipher_setctr(key->cipher,
4304  &key->material.aes_ctr,
4305  sizeof(key->material.aes_ctr));
4306 }
4307 
4308 
4318 static void
4320  const struct GNUNET_CRYPTO_EcdhePrivateKey *priv_ephemeral,
4321  const struct GNUNET_PeerIdentity *target,
4322  const struct GNUNET_ShortHashCode *iv,
4323  struct DVKeyState *key)
4324 {
4325  struct GNUNET_HashCode km;
4326 
4328  &target->public_key,
4329  &km));
4330  dv_setup_key_state_from_km(&km, iv, key);
4331 }
4332 
4333 
4343 static void
4345  const struct GNUNET_ShortHashCode *iv,
4346  struct DVKeyState *key)
4347 {
4348  struct GNUNET_HashCode km;
4349 
4350  GNUNET_assert(GNUNET_YES == GNUNET_CRYPTO_eddsa_ecdh(GST_my_private_key,
4351  pub_ephemeral,
4352  &km));
4353  dv_setup_key_state_from_km(&km, iv, key);
4354 }
4355 
4356 
4366 static void
4367 dv_hmac(const struct DVKeyState *key,
4368  struct GNUNET_HashCode *hmac,
4369  const void *data,
4370  size_t data_size)
4371 {
4372  GNUNET_CRYPTO_hmac(&key->material.hmac_key, data, data_size, hmac);
4373 }
4374 
4375 
4385 static void
4386 dv_encrypt(struct DVKeyState *key, const void *in, void *dst, size_t in_size)
4387 {
4388  GNUNET_assert(0 ==
4389  gcry_cipher_encrypt(key->cipher, dst, in_size, in, in_size));
4390 }
4391 
4392 
4402 static void
4404  void *out,
4405  const void *ciph,
4406  size_t out_size)
4407 {
4408  GNUNET_assert(
4409  0 == gcry_cipher_decrypt(key->cipher, out, out_size, ciph, out_size));
4410 }
4411 
4412 
4418 static void
4420 {
4421  gcry_cipher_close(key->cipher);
4422  GNUNET_CRYPTO_zero_keys(&key->material, sizeof(key->material));
4423 }
4424 
4425 
4436 typedef void (*DVMessageHandler) (void *cls,
4437  struct Neighbour *next_hop,
4438  const struct GNUNET_MessageHeader *hdr,
4440 
4454 static struct GNUNET_TIME_Relative
4456  unsigned int num_dvhs,
4457  struct DistanceVectorHop **dvhs,
4458  const struct GNUNET_MessageHeader *hdr,
4459  DVMessageHandler use,
4460  void *use_cls,
4462 {
4463  struct TransportDVBoxMessage box_hdr;
4464  struct TransportDVBoxPayloadP payload_hdr;
4465  uint16_t enc_body_size = ntohs(hdr->size);
4466  char enc[sizeof(struct TransportDVBoxPayloadP) + enc_body_size] GNUNET_ALIGN;
4467  struct TransportDVBoxPayloadP *enc_payload_hdr =
4468  (struct TransportDVBoxPayloadP *)enc;
4469  struct DVKeyState key;
4470  struct GNUNET_TIME_Relative rtt;
4471 
4472  /* Encrypt payload */
4474  box_hdr.total_hops = htons(0);
4475  update_ephemeral(dv);
4476  box_hdr.ephemeral_key = dv->ephemeral_key;
4477  payload_hdr.sender_sig = dv->sender_sig;
4479  &box_hdr.iv,
4480  sizeof(box_hdr.iv));
4481  dh_key_derive_eph_pid(&dv->private_key, &dv->target, &box_hdr.iv, &key);
4482  payload_hdr.sender = GST_my_identity;
4483  payload_hdr.monotonic_time = GNUNET_TIME_absolute_hton(dv->monotime);
4484  dv_encrypt(&key, &payload_hdr, enc_payload_hdr, sizeof(payload_hdr));
4485  dv_encrypt(&key,
4486  hdr,
4487  &enc[sizeof(struct TransportDVBoxPayloadP)],
4488  enc_body_size);
4489  dv_hmac(&key, &box_hdr.hmac, enc, sizeof(enc));
4490  dv_key_clean(&key);
4492  /* For each selected path, take the pre-computed header and body
4493  and add the path in the middle of the message; then send it. */
4494  for (unsigned int i = 0; i < num_dvhs; i++)
4495  {
4496  struct DistanceVectorHop *dvh = dvhs[i];
4497  unsigned int num_hops = dvh->distance + 1;
4498  char buf[sizeof(struct TransportDVBoxMessage) +
4499  sizeof(struct GNUNET_PeerIdentity) * num_hops +
4500  sizeof(struct TransportDVBoxPayloadP) +
4501  enc_body_size] GNUNET_ALIGN;
4502  struct GNUNET_PeerIdentity *dhops;
4503 
4504  box_hdr.header.size = htons(sizeof(buf));
4505  box_hdr.num_hops = htons(num_hops);
4506  memcpy(buf, &box_hdr, sizeof(box_hdr));
4507  dhops = (struct GNUNET_PeerIdentity *)&buf[sizeof(box_hdr)];
4508  memcpy(dhops,
4509  dvh->path,
4510  dvh->distance * sizeof(struct GNUNET_PeerIdentity));
4511  dhops[dvh->distance] = dv->target;
4512  if (GNUNET_EXTRA_LOGGING > 0)
4513  {
4514  char *path;
4515 
4517  for (unsigned int j = 0; j <= num_hops; j++)
4518  {
4519  char *tmp;
4520 
4521  GNUNET_asprintf(&tmp, "%s-%s", path, GNUNET_i2s(&dhops[j]));
4522  GNUNET_free(path);
4523  path = tmp;
4524  }
4526  "Routing message of type %u to %s using DV (#%u/%u) via %s\n",
4527  ntohs(hdr->type),
4528  GNUNET_i2s(&dv->target),
4529  i + 1,
4530  num_dvhs + 1,
4531  path);
4532  GNUNET_free(path);
4533  }
4534  rtt = GNUNET_TIME_relative_min(rtt, dvh->pd.aged_rtt);
4535  memcpy(&dhops[num_hops], enc, sizeof(enc));
4536  use(use_cls,
4537  dvh->next_hop,
4538  (const struct GNUNET_MessageHeader *)buf,
4539  options);
4540  }
4541  return rtt;
4542 }
4543 
4544 
4554 static void
4556  struct Neighbour *next_hop,
4557  const struct GNUNET_MessageHeader *hdr,
4559 {
4560  (void)cls;
4561  (void)route_via_neighbour(next_hop, hdr, options);
4562 }
4563 
4564 
4576 static struct GNUNET_TIME_Relative
4578  const struct GNUNET_MessageHeader *hdr,
4580 {
4581  struct VirtualLink *vl;
4582  struct Neighbour *n;
4583  struct DistanceVector *dv;
4584  struct GNUNET_TIME_Relative rtt1;
4585  struct GNUNET_TIME_Relative rtt2;
4586 
4587  vl = lookup_virtual_link(target);
4588  GNUNET_assert(NULL != vl);
4589  n = vl->n;
4590  dv = (0 != (options & RMO_DV_ALLOWED)) ? vl->dv : NULL;
4591  if (0 == (options & RMO_UNCONFIRMED_ALLOWED))
4592  {
4593  /* if confirmed is required, and we do not have anything
4594  confirmed, drop respective options */
4595  if (NULL == n)
4596  n = lookup_neighbour(target);
4597  if ((NULL == dv) && (0 != (options & RMO_DV_ALLOWED)))
4598  dv = GNUNET_CONTAINER_multipeermap_get(dv_routes, target);
4599  }
4600  if ((NULL == n) && (NULL == dv))
4601  {
4603  "Cannot route message of type %u to %s: no route\n",
4604  ntohs(hdr->type),
4605  GNUNET_i2s(target));
4606  GNUNET_STATISTICS_update(GST_stats,
4607  "# Messages dropped in routing: no acceptable method",
4608  1,
4609  GNUNET_NO);
4611  }
4613  "Routing message of type %u to %s with options %X\n",
4614  ntohs(hdr->type),
4615  GNUNET_i2s(target),
4616  (unsigned int)options);
4617  /* If both dv and n are possible and we must choose:
4618  flip a coin for the choice between the two; for now 50/50 */
4619  if ((NULL != n) && (NULL != dv) && (0 == (options & RMO_REDUNDANT)))
4620  {
4622  n = NULL;
4623  else
4624  dv = NULL;
4625  }
4626  if ((NULL != n) && (NULL != dv))
4627  options &= ~RMO_REDUNDANT; /* We will do one DV and one direct, that's
4628  enough for redunancy, so clear the flag. */
4631  if (NULL != n)
4632  {
4633  rtt1 = route_via_neighbour(n, hdr, options);
4634  }
4635  if (NULL != dv)
4636  {
4637  struct DistanceVectorHop *hops[2];
4638  unsigned int res;
4639 
4640  res = pick_random_dv_hops(dv,
4641  options,
4642  hops,
4643  (0 == (options & RMO_REDUNDANT)) ? 1 : 2);
4644  if (0 == res)
4645  {
4647  "Failed to route message, could not determine DV path\n");
4648  return rtt1;
4649  }
4650  rtt2 = encapsulate_for_dv(dv,
4651  res,
4652  hops,
4653  hdr,
4655  NULL,
4656  options & (~RMO_REDUNDANT));
4657  }
4658  return GNUNET_TIME_relative_min(rtt1, rtt2);
4659 }
4660 
4661 
4668 static void
4670 {
4671  struct VirtualLink *vl = cls;
4672  struct GNUNET_TIME_Absolute monotime;
4673  struct TransportFlowControlMessage fc;
4674  struct GNUNET_TIME_Relative duration;
4675  struct GNUNET_TIME_Relative rtt;
4676 
4678  /* OPTIMIZE-FC-BDP: decide sane criteria on when to do this, instead of doing
4679  it always! */
4680  /* For example, we should probably ONLY do this if a bit more than
4681  an RTT has passed, or if the window changed "significantly" since
4682  then. See vl->last_fc_rtt! NOTE: to do this properly, we also
4683  need an estimate for the bandwidth-delay-product for the entire
4684  VL, as that determines "significantly". We have the delay, but
4685  the bandwidth statistics need to be added for the VL!*/
4686  (void)duration;
4687 
4689  "Sending FC seq %u to %s with new window %llu\n",
4690  (unsigned int)vl->fc_seq_gen,
4691  GNUNET_i2s(&vl->target),
4692  (unsigned long long)vl->incoming_fc_window_size);
4693  monotime = GNUNET_TIME_absolute_get_monotonic(GST_cfg);
4694  vl->last_fc_transmission = monotime;
4696  fc.header.size = htons(sizeof(fc));
4697  fc.seq = htonl(vl->fc_seq_gen++);
4701  fc.sender_time = GNUNET_TIME_absolute_hton(monotime);
4703  if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == rtt.rel_value_us)
4704  {
4707  "FC retransmission to %s failed, will retry in %s\n",
4708  GNUNET_i2s(&vl->target),
4711  }
4712  else
4713  {
4714  /* OPTIMIZE-FC-BDP: rtt is not ideal, we can do better! */
4715  vl->last_fc_rtt = rtt;
4716  }
4717  if (NULL != vl->fc_retransmit_task)
4719  vl->fc_retransmit_task =
4721 }
4722 
4723 
4740 static void
4742 {
4743  struct Neighbour *n = vl->n;
4744  struct DistanceVector *dv = vl->dv;
4745  struct GNUNET_TIME_Absolute now;
4746  int elig;
4747 
4748  /* Check that we have an eligible pending message!
4749  (cheaper than having #transmit_on_queue() find out!) */
4750  elig = GNUNET_NO;
4751  for (struct PendingMessage *pm = vl->pending_msg_head; NULL != pm;
4752  pm = pm->next_vl)
4753  {
4754  if (NULL != pm->qe)
4755  continue; /* not eligible, is in a queue! */
4756  if (pm->bytes_msg + vl->outbound_fc_window_size_used >
4758  {
4760  "Stalled transmision on VL %s due to flow control: %llu < %llu\n",
4761  GNUNET_i2s(&vl->target),
4762  (unsigned long long)vl->outbound_fc_window_size,
4763  (unsigned long long)(pm->bytes_msg +
4765  consider_sending_fc(vl);
4766  return; /* We have a message, but flow control says "nope" */
4767  }
4768  elig = GNUNET_YES;
4769  break;
4770  }
4771  if (GNUNET_NO == elig)
4772  return;
4773 
4774  /* Notify queues at direct neighbours that we are interested */
4775  now = GNUNET_TIME_absolute_get();
4776  if (NULL != n)
4777  {
4778  for (struct Queue *queue = n->queue_head; NULL != queue;
4779  queue = queue->next_neighbour)
4780  if ((GNUNET_YES == queue->idle) &&
4781  (queue->validated_until.abs_value_us > now.abs_value_us))
4783  }
4784  /* Notify queues via DV that we are interested */
4785  if (NULL != dv)
4786  {
4787  /* Do DV with lower scheduler priority, which effectively means that
4788  IF a neighbour exists and is available, we prefer it. */
4789  for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
4790  pos = pos->next_dv)
4791  {
4792  struct Neighbour *nh = pos->next_hop;
4793 
4794  if (pos->path_valid_until.abs_value_us <= now.abs_value_us)
4795  continue; /* skip this one: path not validated */
4796  for (struct Queue *queue = nh->queue_head; NULL != queue;
4797  queue = queue->next_neighbour)
4798  if ((GNUNET_YES == queue->idle) &&
4799  (queue->validated_until.abs_value_us > now.abs_value_us))
4802  }
4803  }
4804 }
4805 
4806 
4813 static void
4814 handle_client_send(void *cls, const struct OutboundMessage *obm)
4815 {
4816  struct TransportClient *tc = cls;
4817  struct PendingMessage *pm;
4818  const struct GNUNET_MessageHeader *obmm;
4819  uint32_t bytes_msg;
4820  struct VirtualLink *vl;
4822 
4823  GNUNET_assert(CT_CORE == tc->type);
4824  obmm = (const struct GNUNET_MessageHeader *)&obm[1];
4825  bytes_msg = ntohs(obmm->size);
4826  pp = (enum GNUNET_MQ_PriorityPreferences)ntohl(obm->priority);
4827  vl = lookup_virtual_link(&obm->peer);
4828  if (NULL == vl)
4829  {
4830  /* Failure: don't have this peer as a neighbour (anymore).
4831  Might have gone down asynchronously, so this is NOT
4832  a protocol violation by CORE. Still count the event,
4833  as this should be rare. */
4835  GNUNET_STATISTICS_update(GST_stats,
4836  "# messages dropped (neighbour unknown)",
4837  1,
4838  GNUNET_NO);
4839  return;
4840  }
4841 
4842  pm = GNUNET_malloc(sizeof(struct PendingMessage) + bytes_msg);
4844  pm->prefs = pp;
4845  pm->client = tc;
4846  pm->vl = vl;
4847  pm->bytes_msg = bytes_msg;
4848  memcpy(&pm[1], obmm, bytes_msg);
4850  "Sending %u bytes as <%llu> to %s\n",
4851  bytes_msg,
4852  pm->logging_uuid,
4853  GNUNET_i2s(&obm->peer));
4855  tc->details.core.pending_msg_head,
4856  tc->details.core.pending_msg_tail,
4857  pm);
4859  vl->pending_msg_head,
4860  vl->pending_msg_tail,
4861  pm);
4863 }
4864 
4865 
4875 static void
4877  void *cls,
4878  const struct GNUNET_TRANSPORT_CommunicatorBackchannel *cb)
4879 {
4880  struct TransportClient *tc = cls;
4881  const struct GNUNET_MessageHeader *inbox =
4882  (const struct GNUNET_MessageHeader *)&cb[1];
4883  uint16_t isize = ntohs(inbox->size);
4884  const char *is = ((const char *)&cb[1]) + isize;
4885  char
4886  mbuf[isize +
4887  sizeof(struct TransportBackchannelEncapsulationMessage)] GNUNET_ALIGN;
4890 
4891  /* 0-termination of 'is' was checked already in
4892  #check_communicator_backchannel() */
4894  "Preparing backchannel transmission to %s:%s of type %u\n",
4895  GNUNET_i2s(&cb->pid),
4896  is,
4897  ntohs(inbox->size));
4898  /* encapsulate and encrypt message */
4899  be->header.type =
4901  be->header.size = htons(sizeof(mbuf));
4902  memcpy(&be[1], inbox, isize);
4903  memcpy(&mbuf[sizeof(struct TransportBackchannelEncapsulationMessage) +
4904  isize],
4905  is,
4906  strlen(is) + 1);
4909 }
4910 
4911 
4919 static int
4921  const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
4922 {
4923  struct TransportClient *tc = cls;
4924 
4925  if (CT_COMMUNICATOR != tc->type)
4926  {
4927  GNUNET_break(0);
4928  return GNUNET_SYSERR;
4929  }
4931  return GNUNET_OK;
4932 }
4933 
4934 
4940 static void
4941 store_pi(void *cls);
4942 
4943 
4950 static void
4951 peerstore_store_own_cb(void *cls, int success)
4952 {
4953  struct AddressListEntry *ale = cls;
4954 
4955  ale->sc = NULL;
4956  if (GNUNET_YES != success)
4958  "Failed to store our own address `%s' in peerstore!\n",
4959  ale->address);
4960  else
4962  "Successfully stored our own address `%s' in peerstore!\n",
4963  ale->address);
4964  /* refresh period is 1/4 of expiration time, that should be plenty
4965  without being excessive. */
4966  ale->st =
4968  4ULL),
4969  &store_pi,
4970  ale);
4971 }
4972 
4973 
4979 static void
4980 store_pi(void *cls)
4981 {
4982  struct AddressListEntry *ale = cls;
4983  void *addr;
4984  size_t addr_len;
4985  struct GNUNET_TIME_Absolute expiration;
4986 
4987  ale->st = NULL;
4988  expiration = GNUNET_TIME_relative_to_absolute(ale->expiration);
4990  "Storing our address `%s' in peerstore until %s!\n",
4991  ale->address,
4994  ale->nt,
4996  GST_my_private_key,
4997  &addr,
4998  &addr_len);
4999  ale->sc = GNUNET_PEERSTORE_store(peerstore,
5000  "transport",
5001  &GST_my_identity,
5003  addr,
5004  addr_len,
5005  expiration,
5008  ale);
5009  GNUNET_free(addr);
5010  if (NULL == ale->sc)
5011  {
5013  "Failed to store our address `%s' with peerstore\n",
5014  ale->address);
5015  ale->st =
5017  }
5018 }
5019 
5020 
5027 static void
5029  const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
5030 {
5031  struct TransportClient *tc = cls;
5032  struct AddressListEntry *ale;
5033  size_t slen;
5034 
5035  /* 0-termination of &aam[1] was checked in #check_add_address */
5037  "Communicator added address `%s'!\n",
5038  (const char *)&aam[1]);
5039  slen = ntohs(aam->header.size) - sizeof(*aam);
5040  ale = GNUNET_malloc(sizeof(struct AddressListEntry) + slen);
5041  ale->tc = tc;
5042  ale->address = (const char *)&ale[1];
5043  ale->expiration = GNUNET_TIME_relative_ntoh(aam->expiration);
5044  ale->aid = aam->aid;
5045  ale->nt = (enum GNUNET_NetworkType)ntohl(aam->nt);
5046  memcpy(&ale[1], &aam[1], slen);
5048  tc->details.communicator.addr_tail,
5049  ale);
5050  ale->st = GNUNET_SCHEDULER_add_now(&store_pi, ale);
5052 }
5053 
5054 
5061 static void
5063  const struct GNUNET_TRANSPORT_DelAddressMessage *dam)
5064 {
5065  struct TransportClient *tc = cls;
5066  struct AddressListEntry *alen;
5067 
5068  if (CT_COMMUNICATOR != tc->type)
5069  {
5070  GNUNET_break(0);
5072  return;
5073  }
5074  for (struct AddressListEntry *ale = tc->details.communicator.addr_head;
5075  NULL != ale;
5076  ale = alen)
5077  {
5078  alen = ale->next;
5079  if (dam->aid != ale->aid)
5080  continue;
5081  GNUNET_assert(ale->tc == tc);
5083  "Communicator deleted address `%s'!\n",
5084  ale->address);
5087  }
5088  GNUNET_break(0);
5090 }
5091 
5092 
5100 static void
5102  const struct GNUNET_MessageHeader *msg);
5103 
5104 
5112 static void
5114 {
5115  struct CoreSentContext *ctx = cls;
5116  struct VirtualLink *vl = ctx->vl;
5117 
5118  if (NULL == vl)
5119  {
5120  /* lost the link in the meantime, ignore */
5121  GNUNET_free(ctx);
5122  return;
5123  }
5126  vl->incoming_fc_window_size_ram -= ctx->size;
5127  vl->incoming_fc_window_size_used += ctx->isize;
5128  consider_sending_fc(vl);
5129  GNUNET_free(ctx);
5130 }
5131 
5132 
5141 static void
5142 handle_raw_message(void *cls, const struct GNUNET_MessageHeader *mh)
5143 {
5144  struct CommunicatorMessageContext *cmc = cls;
5145  struct VirtualLink *vl;
5146  uint16_t size = ntohs(mh->size);
5147  int have_core;
5148 
5149  if ((size > UINT16_MAX - sizeof(struct InboundMessage)) ||
5150  (size < sizeof(struct GNUNET_MessageHeader)))
5151  {
5152  struct GNUNET_SERVICE_Client *client = cmc->tc->client;
5153 
5154  GNUNET_break(0);
5155  finish_cmc_handling(cmc);
5157  return;
5158  }
5159  vl = lookup_virtual_link(&cmc->im.sender);
5160  if (NULL == vl)
5161  {
5162  /* FIXME: sender is giving us messages for CORE but we don't have
5163  the link up yet! I *suspect* this can happen right now (i.e.
5164  sender has verified us, but we didn't verify sender), but if
5165  we pass this on, CORE would be confused (link down, messages
5166  arrive). We should investigate more if this happens often,
5167  or in a persistent manner, and possibly do "something" about
5168  it. Thus logging as error for now. */
5169  GNUNET_break_op(0);
5170  GNUNET_STATISTICS_update(GST_stats,
5171  "# CORE messages droped (virtual link still down)",
5172  1,
5173  GNUNET_NO);
5174 
5175  finish_cmc_handling(cmc);
5176  return;
5177  }
5178  if (vl->incoming_fc_window_size_ram > UINT_MAX - size)
5179  {
5180  GNUNET_STATISTICS_update(GST_stats,
5181  "# CORE messages droped (FC arithmetic overflow)",
5182  1,
5183  GNUNET_NO);
5184 
5185  finish_cmc_handling(cmc);
5186  return;
5187  }
5189  {
5190  GNUNET_STATISTICS_update(GST_stats,
5191  "# CORE messages droped (FC window overflow)",
5192  1,
5193  GNUNET_NO);
5194  finish_cmc_handling(cmc);
5195  return;
5196  }
5197 
5198  /* Forward to all CORE clients */
5199  have_core = GNUNET_NO;
5200  for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
5201  {
5202  struct GNUNET_MQ_Envelope *env;
5203  struct InboundMessage *im;
5204  struct CoreSentContext *ctx;
5205 
5206  if (CT_CORE != tc->type)
5207  continue;
5210  ctx = GNUNET_new(struct CoreSentContext);
5211  ctx->vl = vl;
5212  ctx->size = size;
5213  ctx->isize = (GNUNET_NO == have_core) ? size : 0;
5214  have_core = GNUNET_YES;
5217  im->peer = cmc->im.sender;
5218  memcpy(&im[1], mh, size);
5219  GNUNET_MQ_send(tc->mq, env);
5220  vl->core_recv_window--;
5221  }
5222  if (GNUNET_NO == have_core)
5223  {
5225  "Dropped message to CORE: no CORE client connected!\n");
5226  /* Nevertheless, count window as used, as it is from the
5227  perspective of the other peer! */
5229  /* TODO-M1 */
5230  finish_cmc_handling(cmc);
5231  return;
5232  }
5234  "Delivered message from %s of type %u to CORE\n",
5235  GNUNET_i2s(&cmc->im.sender),
5236  ntohs(mh->type));
5237  if (vl->core_recv_window > 0)
5238  {
5239  finish_cmc_handling(cmc);
5240  return;
5241  }
5242  /* Wait with calling #finish_cmc_handling(cmc) until the message
5243  was processed by CORE MQs (for CORE flow control)! */
5245 }
5246 
5247 
5255 static int
5257 {
5258  uint16_t size = ntohs(fb->header.size);
5259  uint16_t bsize = size - sizeof(*fb);
5260 
5261  (void)cls;
5262  if (0 == bsize)
5263  {
5264  GNUNET_break_op(0);
5265  return GNUNET_SYSERR;
5266  }
5267  if (bsize + ntohs(fb->frag_off) > ntohs(fb->msg_size))
5268  {
5269  GNUNET_break_op(0);
5270  return GNUNET_SYSERR;
5271  }
5272  if (ntohs(fb->frag_off) >= ntohs(fb->msg_size))
5273  {
5274  GNUNET_break_op(0);
5275  return GNUNET_SYSERR;
5276  }
5277  return GNUNET_YES;
5278 }
5279 
5280 
5286 static void
5288 {
5289  struct AcknowledgementCummulator *ac = cls;
5290 
5291  ac->task = NULL;
5292  GNUNET_assert(0 == ac->num_acks);
5293  GNUNET_assert(
5294  GNUNET_YES ==
5295  GNUNET_CONTAINER_multipeermap_remove(ack_cummulators, &ac->target, ac));
5296  GNUNET_free(ac);
5297 }
5298 
5299 
5305 static void
5307 {
5308  struct AcknowledgementCummulator *ac = cls;
5309  char buf[sizeof(struct TransportReliabilityAckMessage) +
5310  ac->ack_counter *
5311  sizeof(struct TransportCummulativeAckPayloadP)] GNUNET_ALIGN;
5312  struct TransportReliabilityAckMessage *ack =
5315 
5316  ac->task = NULL;
5318  "Sending ACK with %u components to %s\n",
5319  ac->ack_counter,
5320  GNUNET_i2s(&ac->target));
5321  GNUNET_assert(0 < ac->ack_counter);
5323  ack->header.size =
5324  htons(sizeof(*ack) +
5325  ac->ack_counter * sizeof(struct TransportCummulativeAckPayloadP));
5326  ack->ack_counter = htonl(ac->ack_counter++);
5327  ap = (struct TransportCummulativeAckPayloadP *)&ack[1];
5328  for (unsigned int i = 0; i < ac->ack_counter; i++)
5329  {
5330  ap[i].ack_uuid = ac->ack_uuids[i].ack_uuid;
5332  GNUNET_TIME_absolute_get_duration(ac->ack_uuids[i].receive_time));
5333  }
5335  ac->num_acks = 0;
5338  ac);
5339 }
5340 
5341 
5350 static void
5352  const struct AcknowledgementUUIDP *ack_uuid,
5353  struct GNUNET_TIME_Absolute max_delay)
5354 {
5355  struct AcknowledgementCummulator *ac;
5356 
5358  "Scheduling ACK %s for transmission to %s\n",
5359  GNUNET_uuid2s(&ack_uuid->value),
5360  GNUNET_i2s(pid));
5361  ac = GNUNET_CONTAINER_multipeermap_get(ack_cummulators, pid);
5362  if (NULL == ac)
5363  {
5365  ac->target = *pid;
5366  ac->min_transmission_time = max_delay;
5369  ack_cummulators,
5370  &ac->target,
5371  ac,
5373  }
5374  else
5375  {
5376  if (MAX_CUMMULATIVE_ACKS == ac->num_acks)
5377  {
5378  /* must run immediately, ack buffer full! */
5381  }
5383  ac->min_transmission_time =
5385  }
5388  ac->ack_uuids[ac->num_acks].ack_uuid = *ack_uuid;
5389  ac->num_acks++;
5392  ac);
5393 }
5394 
5395 
5403  struct MessageUUIDP message_uuid;
5404 
5409 };
5410 
5411 
5421 static int
5422 find_by_message_uuid(void *cls, uint32_t key, void *value)
5423 {
5424  struct FindByMessageUuidContext *fc = cls;
5425  struct ReassemblyContext *rc = value;
5426 
5427  (void)key;
5428  if (0 == GNUNET_memcmp(&fc->message_uuid, &rc->msg_uuid))
5429  {
5430  fc->rc = rc;
5431  return GNUNET_NO;
5432  }
5433  return GNUNET_YES;
5434 }
5435 
5436 
5444 static void
5446 {
5447  struct CommunicatorMessageContext *cmc = cls;
5448  struct Neighbour *n;
5449  struct ReassemblyContext *rc;
5450  const struct GNUNET_MessageHeader *msg;
5451  uint16_t msize;
5452  uint16_t fsize;
5453  uint16_t frag_off;
5454  char *target;
5455  struct GNUNET_TIME_Relative cdelay;
5456  struct FindByMessageUuidContext fc;
5457 
5458  n = lookup_neighbour(&cmc->im.sender);
5459  if (NULL == n)
5460  {
5461  struct GNUNET_SERVICE_Client *client = cmc->tc->client;
5462 
5463  GNUNET_break(0);
5464  finish_cmc_handling(cmc);
5466  return;
5467  }
5468  if (NULL == n->reassembly_map)
5469  {
5470  n->reassembly_map = GNUNET_CONTAINER_multihashmap32_create(8);
5471  n->reassembly_heap =
5473  n->reassembly_timeout_task =
5476  n);
5477  }
5478  msize = ntohs(fb->msg_size);
5479  fc.message_uuid = fb->msg_uuid;
5480  fc.rc = NULL;
5481  (void)GNUNET_CONTAINER_multihashmap32_get_multiple(n->reassembly_map,
5482  fb->msg_uuid.uuid,
5484  &fc);
5485  if (NULL == (rc = fc.rc))
5486  {
5487  rc = GNUNET_malloc(sizeof(*rc) + msize + /* reassembly payload buffer */
5488  (msize + 7) / 8 * sizeof(uint8_t) /* bitfield */);
5489  rc->msg_uuid = fb->msg_uuid;
5490  rc->neighbour = n;
5491  rc->msg_size = msize;
5492  rc->reassembly_timeout =
5495  rc->hn = GNUNET_CONTAINER_heap_insert(n->reassembly_heap,
5496  rc,
5500  n->reassembly_map,
5501  rc->msg_uuid.uuid,
5502  rc,
5504  target = (char *)&rc[1];
5505  rc->bitfield = (uint8_t *)(target + rc->msg_size);
5506  rc->msg_missing = rc->msg_size;
5508  "Received fragment at offset %u/%u from %s for NEW message %u\n",
5509  ntohs(fb->frag_off),
5510  msize,
5511  GNUNET_i2s(&cmc->im.sender),
5512  (unsigned int)fb->msg_uuid.uuid);
5513  }
5514  else
5515  {
5516  target = (char *)&rc[1];
5518  "Received fragment at offset %u/%u from %s for message %u\n",
5519  ntohs(fb->frag_off),
5520  msize,
5521  GNUNET_i2s(&cmc->im.sender),
5522  (unsigned int)fb->msg_uuid.uuid);
5523  }
5524  if (msize != rc->msg_size)
5525  {
5526  GNUNET_break(0);
5527  finish_cmc_handling(cmc);
5528  return;
5529  }
5530 
5531  /* reassemble */
5532  fsize = ntohs(fb->header.size) - sizeof(*fb);
5533  if (0 == fsize)
5534  {
5535  GNUNET_break(0);
5536  finish_cmc_handling(cmc);
5537  return;
5538  }
5539  frag_off = ntohs(fb->frag_off);
5540  if (frag_off + fsize > msize)
5541  {
5542  /* Fragment (plus fragment size) exceeds message size! */
5543  GNUNET_break_op(0);
5544  finish_cmc_handling(cmc);
5545  return;
5546  }
5547  memcpy(&target[frag_off], &fb[1], fsize);
5548  /* update bitfield and msg_missing */
5549  for (unsigned int i = frag_off; i < frag_off + fsize; i++)
5550  {
5551  if (0 == (rc->bitfield[i / 8] & (1 << (i % 8))))
5552  {
5553  rc->bitfield[i / 8] |= (1 << (i % 8));
5554  rc->msg_missing--;
5555  }
5556  }
5557 
5558  /* Compute cummulative ACK */
5560  cdelay = GNUNET_TIME_relative_multiply(cdelay, rc->msg_missing / fsize);
5561  if (0 == rc->msg_missing)
5562  cdelay = GNUNET_TIME_UNIT_ZERO;
5563  cummulative_ack(&cmc->im.sender,
5564  &fb->ack_uuid,
5567  /* is reassembly complete? */
5568  if (0 != rc->msg_missing)
5569  {
5570  finish_cmc_handling(cmc);
5571  return;
5572  }
5573  /* reassembly is complete, verify result */
5574  msg = (const struct GNUNET_MessageHeader *)&rc[1];
5575  if (ntohs(msg->size) != rc->msg_size)
5576  {
5577  GNUNET_break(0);
5579  finish_cmc_handling(cmc);
5580  return;
5581  }
5582  /* successful reassembly */
5584  "Fragment reassembly complete for message %u\n",
5585  (unsigned int)fb->msg_uuid.uuid);
5586  /* FIXME: check that the resulting msg is NOT a
5587  DV Box or Reliability Box, as that is NOT allowed! */
5588  demultiplex_with_cmc(cmc, msg);
5589  /* FIXME-OPTIMIZE: really free here? Might be bad if fragments are still
5590  en-route and we forget that we finished this reassembly immediately!
5591  -> keep around until timeout?
5592  -> shorten timeout based on ACK? */
5594 }
5595 
5596 
5604 static int
5606  const struct TransportReliabilityBoxMessage *rb)
5607 {
5608  (void)cls;
5610  return GNUNET_YES;
5611 }
5612 
5613 
5621 static void
5623  const struct TransportReliabilityBoxMessage *rb)
5624 {
5625  struct CommunicatorMessageContext *cmc = cls;
5626  const struct GNUNET_MessageHeader *inbox =
5627  (const struct GNUNET_MessageHeader *)&rb[1];
5628  struct GNUNET_TIME_Relative rtt;
5629 
5631  "Received reliability box from %s with UUID %s of type %u\n",
5632  GNUNET_i2s(&cmc->im.sender),
5634  (unsigned int)ntohs(inbox->type));
5635  rtt = GNUNET_TIME_UNIT_SECONDS; /* FIXME: should base this on "RTT", but we
5636  do not really have an RTT for the
5637  * incoming* queue (should we have
5638  the sender add it to the rb message?) */
5640  &cmc->im.sender,
5641  &rb->ack_uuid,
5642  (0 == ntohl(rb->ack_countdown))
5645  GNUNET_TIME_relative_divide(rtt, 8 /* FIXME: magic constant */)));
5646  /* continue with inner message */
5647  /* FIXME: check that inbox is NOT a DV Box, fragment or another
5648  reliability box (not allowed!) */
5649  demultiplex_with_cmc(cmc, inbox);
5650 }
5651 
5652 
5661 static void
5662 update_pd_age(struct PerformanceData *pd, unsigned int age)
5663 {
5664  unsigned int sage;
5665 
5666  if (age == pd->last_age)
5667  return; /* nothing to do */
5668  sage = GNUNET_MAX(pd->last_age, age - 2 * GOODPUT_AGING_SLOTS);
5669  for (unsigned int i = sage; i <= age - GOODPUT_AGING_SLOTS; i++)
5670  {
5671  struct TransmissionHistoryEntry *the = &pd->the[i % GOODPUT_AGING_SLOTS];
5672 
5673  the->bytes_sent = 0;
5674  the->bytes_received = 0;
5675  }
5676  pd->last_age = age;
5677 }
5678 
5679 
5688 static void
5690  struct GNUNET_TIME_Relative rtt,
5691  uint16_t bytes_transmitted_ok)
5692 {
5693  uint64_t nval = rtt.rel_value_us;
5694  uint64_t oval = pd->aged_rtt.rel_value_us;
5695  unsigned int age = get_age();
5696  struct TransmissionHistoryEntry *the = &pd->the[age % GOODPUT_AGING_SLOTS];
5697 
5698  if (oval == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
5699  pd->aged_rtt = rtt;
5700  else
5701  pd->aged_rtt.rel_value_us = (nval + 7 * oval) / 8;
5702  update_pd_age(pd, age);
5703  the->bytes_received += bytes_transmitted_ok;
5704 }
5705 
5706 
5714 static void
5716  struct GNUNET_TIME_Relative rtt,
5717  uint16_t bytes_transmitted_ok)
5718 {
5719  update_performance_data(&q->pd, rtt, bytes_transmitted_ok);
5720 }
5721 
5722 
5730 static void
5732  struct GNUNET_TIME_Relative rtt,
5733  uint16_t bytes_transmitted_ok)
5734 {
5735  update_performance_data(&dvh->pd, rtt, bytes_transmitted_ok);
5736 }
5737 
5738 
5746 static void
5748 {
5749  struct PendingMessage *pos;
5750 
5751  switch (pm->pmt)
5752  {
5753  case PMT_CORE:
5754  case PMT_RELIABILITY_BOX:
5755  /* Full message sent, we are done */
5757  return;
5758 
5759  case PMT_FRAGMENT_BOX:
5760  /* Fragment sent over reliabile channel */
5761  free_fragment_tree(pm);
5762  pos = pm->frag_parent;
5763  GNUNET_CONTAINER_MDLL_remove(frag, pos->head_frag, pos->tail_frag, pm);
5764  GNUNET_free(pm);
5765  /* check if subtree is done */
5766  while ((NULL == pos->head_frag) && (pos->frag_off == pos->bytes_msg) &&
5767  (pos != pm))
5768  {
5769  pm = pos;
5770  pos = pm->frag_parent;
5771  GNUNET_CONTAINER_MDLL_remove(frag, pos->head_frag, pos->tail_frag, pm);
5772  GNUNET_free(pm);
5773  }
5774 
5775  /* Was this the last applicable fragmment? */
5776  if ((NULL == pos->head_frag) && (NULL == pos->frag_parent) &&
5777  (pos->frag_off == pos->bytes_msg))
5778  client_send_response(pos);
5779  return;
5780 
5781  case PMT_DV_BOX:
5783  "Completed transmission of message %llu (DV Box)\n",
5784  pm->logging_uuid);
5786  return;
5787  }
5788 }
5789 
5790 
5798 static void
5800  struct GNUNET_TIME_Relative ack_delay)
5801 {
5802  struct GNUNET_TIME_Relative delay;
5803 
5805  if (delay.rel_value_us > ack_delay.rel_value_us)
5806  delay = GNUNET_TIME_UNIT_ZERO;
5807  else
5808  delay = GNUNET_TIME_relative_subtract(delay, ack_delay);
5809  if (NULL != pa->queue)
5810  update_queue_performance(pa->queue, delay, pa->message_size);
5811  if (NULL != pa->dvh)
5812  update_dvh_performance(pa->dvh, delay, pa->message_size);
5813  if (NULL != pa->pm)
5816 }
5817 
5818 
5826 static int
5828  const struct TransportReliabilityAckMessage *ra)
5829 {
5830  unsigned int n_acks;
5831 
5832  (void)cls;
5833  n_acks = (ntohs(ra->header.size) - sizeof(*ra)) /
5834  sizeof(struct TransportCummulativeAckPayloadP);
5835  if (0 == n_acks)
5836  {
5837  GNUNET_break_op(0);
5838  return GNUNET_SYSERR;
5839  }
5840  if ((ntohs(ra->header.size) - sizeof(*ra)) !=
5841  n_acks * sizeof(struct TransportCummulativeAckPayloadP))
5842  {
5843  GNUNET_break_op(0);
5844  return GNUNET_SYSERR;
5845  }
5846  return GNUNET_OK;
5847 }
5848 
5849 
5857 static void
5859  const struct TransportReliabilityAckMessage *ra)
5860 {
5861  struct CommunicatorMessageContext *cmc = cls;
5862  const struct TransportCummulativeAckPayloadP *ack;
5863  unsigned int n_acks;
5864  uint32_t ack_counter;
5865 
5866  n_acks = (ntohs(ra->header.size) - sizeof(*ra)) /
5867  sizeof(struct TransportCummulativeAckPayloadP);
5868  ack = (const struct TransportCummulativeAckPayloadP *)&ra[1];
5869  for (unsigned int i = 0; i < n_acks; i++)
5870  {
5871  struct PendingAcknowledgement *pa =
5872  GNUNET_CONTAINER_multiuuidmap_get(pending_acks, &ack[i].ack_uuid.value);
5873  if (NULL == pa)
5874  {
5876  "Received ACK from %s with UUID %s which is unknown to us!\n",
5877  GNUNET_i2s(&cmc->im.sender),
5878  GNUNET_uuid2s(&ack[i].ack_uuid.value));
5880  GST_stats,
5881  "# FRAGMENT_ACKS dropped, no matching pending message",
5882  1,
5883  GNUNET_NO);
5884  continue;
5885  }
5887  "Received ACK from %s with UUID %s\n",
5888  GNUNET_i2s(&cmc->im.sender),
5889  GNUNET_uuid2s(&ack[i].ack_uuid.value));
5890  handle_acknowledged(pa, GNUNET_TIME_relative_ntoh(ack[i].ack_delay));
5891  }
5892 
5893  ack_counter = htonl(ra->ack_counter);
5894  (void)ack_counter; /* silence compiler warning for now */
5895  // FIXME-OPTIMIZE: track ACK losses based on ack_counter somewhere!
5896  // (DV and/or Neighbour?)
5897  finish_cmc_handling(cmc);
5898 }
5899 
5900 
5908 static int
5910  void *cls,
5912 {
5913  uint16_t size = ntohs(be->header.size) - sizeof(*be);
5914  const struct GNUNET_MessageHeader *inbox =
5915  (const struct GNUNET_MessageHeader *)&be[1];
5916  const char *is;
5917  uint16_t isize;
5918 
5919  (void)cls;
5920  if (ntohs(inbox->size) >= size)
5921  {
5922  GNUNET_break_op(0);
5923  return GNUNET_SYSERR;
5924  }
5925  isize = ntohs(inbox->size);
5926  is = ((const char *)inbox) + isize;
5927  size -= isize;
5928  if ('\0' != is[size - 1])
5929  {
5930  GNUNET_break_op(0);
5931  return GNUNET_SYSERR;
5932  }
5933  return GNUNET_YES;
5934 }
5935 
5936 
5945 static void
5947  void *cls,
5949 {
5950  struct CommunicatorMessageContext *cmc = cls;
5951  struct GNUNET_TRANSPORT_CommunicatorBackchannelIncoming *cbi;
5952  struct GNUNET_MQ_Envelope *env;
5953  struct TransportClient *tc;
5954  const struct GNUNET_MessageHeader *inbox =
5955  (const struct GNUNET_MessageHeader *)&be[1];
5956  uint16_t isize = ntohs(inbox->size);
5957  const char *target_communicator = ((const char *)inbox) + isize;
5958 
5959  /* Find client providing this communicator */
5960  for (tc = clients_head; NULL != tc; tc = tc->next)
5961  if ((CT_COMMUNICATOR == tc->type) &&
5962  (0 ==
5963  strcmp(tc->details.communicator.address_prefix, target_communicator)))
5964  break;
5965  if (NULL == tc)
5966  {
5967  char *stastr;
5968 
5970  &stastr,
5971  "# Backchannel message dropped: target communicator `%s' unknown",
5972  target_communicator);
5973  GNUNET_STATISTICS_update(GST_stats, stastr, 1, GNUNET_NO);
5974  GNUNET_free(stastr);
5975  return;
5976  }
5977  /* Finally, deliver backchannel message to communicator */
5979  "Delivering backchannel message from %s of type %u to %s\n",
5980  GNUNET_i2s(&cmc->im.sender),
5981  ntohs(inbox->type),
5982  target_communicator);
5983  env = GNUNET_MQ_msg_extra(
5984  cbi,
5985  isize,
5987  cbi->pid = cmc->im.sender;
5988  memcpy(&cbi[1], inbox, isize);
5989  GNUNET_MQ_send(tc->mq, env);
5990 }
5991 
5992 
6002 static void
6004 {
6005  struct DistanceVector *dv = cls;
6006  struct DistanceVectorHop *pos;
6007 
6008  dv->timeout_task = NULL;
6009  while (NULL != (pos = dv->dv_head))
6010  {
6011  GNUNET_assert(dv == pos->dv);
6013  break;
6015  }
6016  if (NULL == pos)
6017  {
6018  free_dv_route(dv);
6019  return;
6020  }
6021  dv->timeout_task =
6023 }
6024 
6025 
6033 static void
6035 {
6036  struct DistanceVector *dv = hop->dv;
6037  struct VirtualLink *vl;
6038 
6039  vl = lookup_virtual_link(&dv->target);
6040  if (NULL != vl)
6041  {
6042  /* Link was already up, remember dv is also now available and we are done */
6043  vl->dv = dv;
6045  "Virtual link to %s could now also use DV!\n",
6046  GNUNET_i2s(&dv->target));
6047  return;
6048  }
6050  "Creating new virtual link to %s using DV!\n",
6051  GNUNET_i2s(&dv->target));
6052  vl = GNUNET_new(struct VirtualLink);
6053  vl->message_uuid_ctr =
6055  vl->target = dv->target;
6056  vl->dv = dv;
6057  dv->vl = vl;
6060  vl->visibility_task =
6064  links,
6065  &vl->target,
6066  vl,
6068  consider_sending_fc(vl);
6069  /* We lacked a confirmed connection to the target
6070  before, so tell CORE about it (finally!) */
6072 }
6073 
6074 
6100 static int
6102  unsigned int path_len,
6103  struct GNUNET_TIME_Relative network_latency,
6104  struct GNUNET_TIME_Absolute path_valid_until)
6105 {
6106  struct DistanceVectorHop *hop;
6107  struct DistanceVector *dv;
6108  struct Neighbour *next_hop;
6109  unsigned int shorter_distance;
6110 
6111  if (path_len < 3)
6112  {
6113  /* what a boring path! not allowed! */
6114  GNUNET_break(0);
6115  return GNUNET_SYSERR;
6116  }
6117  GNUNET_assert(0 == GNUNET_memcmp(&GST_my_identity, &path[0]));
6118  next_hop = lookup_neighbour(&path[1]);
6119  if (NULL == next_hop)
6120  {
6121  /* next hop must be a neighbour, otherwise this whole thing is useless! */
6122  GNUNET_break(0);
6123  return GNUNET_SYSERR;
6124  }
6125  for (unsigned int i = 2; i < path_len; i++)
6126  if (NULL != lookup_neighbour(&path[i]))
6127  {
6128  /* Useless path: we have a direct connection to some hop
6129  in the middle of the path, so this one is not even
6130  terribly useful for redundancy */
6132  "Path of %u hops useless: directly link to hop %u (%s)\n",
6133  path_len,
6134  i,
6135  GNUNET_i2s(&path[i]));
6136  GNUNET_STATISTICS_update(GST_stats,
6137  "# Useless DV path ignored: hop is neighbour",
6138  1,
6139  GNUNET_NO);
6140  return GNUNET_SYSERR;
6141  }
6142  dv = GNUNET_CONTAINER_multipeermap_get(dv_routes, &path[path_len - 1]);
6143  if (NULL == dv)
6144  {
6145  dv = GNUNET_new(struct DistanceVector);
6146  dv->target = path[path_len - 1];
6148  &path_cleanup_cb,
6149  dv);
6152  dv_routes,
6153  &dv->target,
6154  dv,
6156  }
6157  /* Check if we have this path already! */
6158  shorter_distance = 0;
6159  for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
6160  pos = pos->next_dv)
6161  {
6162  if (pos->distance < path_len - 2)
6163  shorter_distance++;
6164  /* Note that the distances in 'pos' excludes us (path[0]) and
6165  the next_hop (path[1]), so we need to subtract two
6166  and check next_hop explicitly */
6167  if ((pos->distance == path_len - 2) && (pos->next_hop == next_hop))
6168  {
6169  int match = GNUNET_YES;
6170 
6171  for (unsigned int i = 0; i < pos->distance; i++)
6172  {
6173  if (0 != GNUNET_memcmp(&pos->path[i], &path[i + 2]))
6174  {
6175  match = GNUNET_NO;
6176  break;
6177  }
6178  }
6179  if (GNUNET_YES == match)
6180  {
6181  struct GNUNET_TIME_Relative last_timeout;
6182 
6183  /* Re-discovered known path, update timeout */
6184  GNUNET_STATISTICS_update(GST_stats,
6185  "# Known DV path refreshed",
6186  1,
6187  GNUNET_NO);
6188  last_timeout = GNUNET_TIME_absolute_get_remaining(pos->timeout);
6189  pos->timeout =
6191  pos->path_valid_until =
6192  GNUNET_TIME_absolute_max(pos->path_valid_until, path_valid_until);
6193  GNUNET_CONTAINER_MDLL_remove(dv, dv->dv_head, dv->dv_tail, pos);
6194  GNUNET_CONTAINER_MDLL_insert(dv, dv->dv_head, dv->dv_tail, pos);
6195  if (0 <
6198  if (last_timeout.rel_value_us <
6201  .rel_value_us)
6202  {
6203  /* Some peer send DV learn messages too often, we are learning
6204  the same path faster than it would be useful; do not forward! */
6206  "Rediscovered path too quickly, not forwarding further\n");
6207  return GNUNET_NO;
6208  }
6210  "Refreshed known path to %s, forwarding further\n",
6211  GNUNET_i2s(&dv->target));
6212  return GNUNET_YES;
6213  }
6214  }
6215  }
6216  /* Count how many shorter paths we have (incl. direct
6217  neighbours) before simply giving up on this one! */
6218  if (shorter_distance >= MAX_DV_PATHS_TO_TARGET)
6219  {
6220  /* We have a shorter path already! */
6222  "Have many shorter DV paths %s, not forwarding further\n",
6223  GNUNET_i2s(&dv->target));
6224  return GNUNET_NO;
6225  }
6226  /* create new DV path entry */
6228  "Discovered new DV path to %s\n",
6229  GNUNET_i2s(&dv->target));
6230  hop = GNUNET_malloc(sizeof(struct DistanceVectorHop) +
6231  sizeof(struct GNUNET_PeerIdentity) * (path_len - 2));
6232  hop->next_hop = next_hop;
6233  hop->dv = dv;
6234  hop->path = (const struct GNUNET_PeerIdentity *)&hop[1];
6235  memcpy(&hop[1],
6236  &path[2],
6237  sizeof(struct GNUNET_PeerIdentity) * (path_len - 2));
6239  hop->path_valid_until = path_valid_until;
6240  hop->distance = path_len - 2;
6241  hop->pd.aged_rtt = network_latency;
6242  GNUNET_CONTAINER_MDLL_insert(dv, dv->dv_head, dv->dv_tail, hop);
6243  GNUNET_CONTAINER_MDLL_insert(neighbour,
6244  next_hop->dv_head,
6245  next_hop->dv_tail,
6246  hop);
6247  if (0 < GNUNET_TIME_absolute_get_remaining(path_valid_until).rel_value_us)
6249  return GNUNET_YES;
6250 }
6251 
6252 
6260 static int
6261 check_dv_learn(void *cls, const struct TransportDVLearnMessage *dvl)
6262 {
6263  uint16_t size = ntohs(dvl->header.size);
6264  uint16_t num_hops = ntohs(dvl->num_hops);
6265  const struct DVPathEntryP *hops = (const struct DVPathEntryP *)&dvl[1];
6266 
6267  (void)cls;
6268  if (size != sizeof(*dvl) + num_hops * sizeof(struct DVPathEntryP))
6269  {
6270  GNUNET_break_op(0);
6271  return GNUNET_SYSERR;
6272  }
6273  if (num_hops > MAX_DV_HOPS_ALLOWED)
6274  {
6275  GNUNET_break_op(0);
6276  return GNUNET_SYSERR;
6277  }
6278  for (unsigned int i = 0; i < num_hops; i++)
6279  {
6280  if (0 == GNUNET_memcmp(&dvl->initiator, &hops[i].hop))
6281  {
6282  GNUNET_break_op(0);
6283  return GNUNET_SYSERR;
6284  }
6285  if (0 == GNUNET_memcmp(&GST_my_identity, &hops[i].hop))
6286  {
6287  GNUNET_break_op(0);
6288  return GNUNET_SYSERR;
6289  }
6290  }
6291  return GNUNET_YES;
6292 }
6293 
6294 
6306 static void
6307 forward_dv_learn(const struct GNUNET_PeerIdentity *next_hop,
6308  const struct TransportDVLearnMessage *msg,
6309  uint16_t bi_history,
6310  uint16_t nhops,
6311  const struct DVPathEntryP *hops,
6312  struct GNUNET_TIME_Absolute in_time)
6313 {
6314  struct DVPathEntryP *dhops;
6315  char buf[sizeof(struct TransportDVLearnMessage) +
6316  (nhops + 1) * sizeof(struct DVPathEntryP)] GNUNET_ALIGN;
6317  struct TransportDVLearnMessage *fwd = (struct TransportDVLearnMessage *)buf;
6318  struct GNUNET_TIME_Relative nnd;
6319 
6320  /* compute message for forwarding */
6322  "Forwarding DV learn message originating from %s to %s\n",
6323  GNUNET_i2s(&msg->initiator),
6324  GNUNET_i2s2(next_hop));
6327  fwd->header.size = htons(sizeof(struct TransportDVLearnMessage) +
6328  (nhops + 1) * sizeof(struct DVPathEntryP));
6329  fwd->num_hops = htons(nhops + 1);
6330  fwd->bidirectional = htons(bi_history);
6333  msg->non_network_delay));
6335  fwd->init_sig = msg->init_sig;
6336  fwd->initiator = msg->initiator;
6337  fwd->challenge = msg->challenge;
6338  dhops = (struct DVPathEntryP *)&fwd[1];
6339  GNUNET_memcpy(dhops, hops, sizeof(struct DVPathEntryP) * nhops);
6340  dhops[nhops].hop = GST_my_identity;
6341  {
6342  struct DvHopPS dhp = { .purpose.purpose =
6344  .purpose.size = htonl(sizeof(dhp)),
6345  .pred = dhops[nhops - 1].hop,
6346  .succ = *next_hop,
6347  .challenge = msg->challenge };
6348 
6350  GNUNET_CRYPTO_eddsa_sign(GST_my_private_key,
6351  &dhp.purpose,
6352  &dhops[nhops].hop_sig));
6353  }
6355  &fwd->header,
6357 }
6358 
6359 
6369 static int
6371  struct GNUNET_TIME_AbsoluteNBO sender_monotonic_time,
6372  const struct GNUNET_PeerIdentity *init,
6373  const struct ChallengeNonceP *challenge,
6374  const struct GNUNET_CRYPTO_EddsaSignature *init_sig)
6375 {
6376  struct DvInitPS ip = { .purpose.purpose = htonl(
6378  .purpose.size = htonl(sizeof(ip)),
6379  .monotonic_time = sender_monotonic_time,
6380  .challenge = *challenge };
6381 
6382  if (
6383  GNUNET_OK !=
6385  &ip.purpose,
6386  init_sig,
6387  &init->public_key))
6388  {
6389  GNUNET_break_op(0);
6390  return GNUNET_SYSERR;
6391  }
6392  return GNUNET_OK;
6393 }
6394 
6395 
6404 
6408  const struct DVPathEntryP *hops;
6409 
6413  struct GNUNET_TIME_Absolute in_time;
6414 
6418  uint32_t selections[MAX_DV_DISCOVERY_SELECTION];
6419 
6423  unsigned int num_eligible;
6424 
6428  unsigned int num_selections;
6429 
6433  uint16_t nhops;
6434 
6438  uint16_t bi_history;
6439 };
6440 
6441 
6450 static int
6452  const struct GNUNET_PeerIdentity *pid,
6453  void *value)
6454 {
6455  struct NeighbourSelectionContext *nsc = cls;
6456 
6457  (void)value;
6458  if (0 == GNUNET_memcmp(pid, &nsc->dvl->initiator))
6459  return GNUNET_YES; /* skip initiator */
6460  for (unsigned int i = 0; i < nsc->nhops; i++)
6461  if (0 == GNUNET_memcmp(pid, &nsc->hops[i].hop))
6462  return GNUNET_YES;
6463  /* skip peers on path */
6464  nsc->num_eligible++;
6465  return GNUNET_YES;
6466 }
6467 
6468 
6479 static int
6481  const struct GNUNET_PeerIdentity *pid,
6482  void *value)
6483 {
6484  struct NeighbourSelectionContext *nsc = cls;
6485 
6486  (void)value;
6487  if (0 == GNUNET_memcmp(pid, &nsc->dvl->initiator))
6488  return GNUNET_YES; /* skip initiator */
6489  for (unsigned int i = 0; i < nsc->nhops; i++)
6490  if (0 == GNUNET_memcmp(pid, &nsc->hops[i].hop))
6491  return GNUNET_YES;
6492  /* skip peers on path */
6493  for (unsigned int i = 0; i < nsc->num_selections; i++)
6494  {
6495  if (nsc->selections[i] == nsc->num_eligible)
6496  {
6497  forward_dv_learn(pid,
6498  nsc->dvl,
6499  nsc->bi_history,
6500  nsc->nhops,
6501  nsc->hops,
6502  nsc->in_time);
6503  break;
6504  }
6505  }
6506  nsc->num_eligible++;
6507  return GNUNET_YES;
6508 }
6509 
6510 
6554 static unsigned int
6555 calculate_fork_degree(unsigned int hops_taken,
6556  unsigned int neighbour_count,
6557  unsigned int eligible_count)
6558 {
6559  double target_total = 50.0; /* FIXME: use LOG(NSE)? */
6560  double eligible_ratio =
6561  ((double)eligible_count) / ((double)neighbour_count);
6562  double boost_factor = eligible_ratio * eligible_ratio;
6563  unsigned int rnd;
6564  double left;
6565 
6566  if (hops_taken >= 64)
6567  {
6568  GNUNET_break(0);
6569  return 0; /* precaution given bitshift below */
6570  }
6571  for (unsigned int i = 1; i < hops_taken; i++)
6572  {
6573  /* For each hop, subtract the expected number of targets
6574  reached at distance d (so what remains divided by 2^d) */
6575  target_total -= (target_total * boost_factor / (1LLU << i));
6576  }
6577  rnd =
6578  (unsigned int)floor(target_total * boost_factor / (1LLU << hops_taken));
6579  /* round up or down probabilistically depending on how close we were
6580  when floor()ing to rnd */
6581  left = target_total - (double)rnd;
6582  if (UINT32_MAX * left >
6584  rnd++; /* round up */
6586  "Forwarding DV learn message of %u hops %u(/%u/%u) times\n",
6587  hops_taken,
6588  rnd,
6589  eligible_count,
6590  neighbour_count);
6591  return rnd;
6592 }
6593 
6594 
6601 static void
6602 neighbour_store_dvmono_cb(void *cls, int success)
6603 {
6604  struct Neighbour *n = cls;
6605 
6606  n->sc = NULL;
6607  if (GNUNET_YES != success)
6609  "Failed to store other peer's monotonic time in peerstore!\n");
6610 }
6611 
6612 
6620 static void
6621 handle_dv_learn(void *cls, const struct TransportDVLearnMessage *dvl)
6622 {
6623  struct CommunicatorMessageContext *cmc = cls;
6625  int bi_hop;
6626  uint16_t nhops;
6627  uint16_t bi_history;
6628  const struct DVPathEntryP *hops;
6629  int do_fwd;
6630  int did_initiator;
6631  struct GNUNET_TIME_Absolute in_time;
6632  struct Neighbour *n;
6633 
6634  nhops = ntohs(dvl->bidirectional); /* 0 = sender is initiator */
6635  bi_history = ntohs(dvl->bidirectional);
6636  hops = (const struct DVPathEntryP *)&dvl[1];
6637  if (0 == nhops)
6638  {
6639  /* sanity check */
6640  if (0 != GNUNET_memcmp(&dvl->initiator, &cmc->im.sender))
6641  {
6642  GNUNET_break(0);
6643  finish_cmc_handling(cmc);
6644  return;
6645  }
6646  }
6647  else
6648  {
6649  /* sanity check */
6650  if (0 != GNUNET_memcmp(&hops[nhops - 1].hop, &cmc->im.sender))
6651  {
6652  GNUNET_break(0);
6653  finish_cmc_handling(cmc);
6654  return;
6655  }
6656  }
6657 
6659  cc = cmc->tc->details.communicator.cc;
6660  bi_hop = (GNUNET_TRANSPORT_CC_RELIABLE ==
6661  cc); // FIXME: add bi-directional flag to cc?
6662  in_time = GNUNET_TIME_absolute_get();
6663 
6664  /* continue communicator here, everything else can happen asynchronous! */
6665  finish_cmc_handling(cmc);
6666 
6667  n = lookup_neighbour(&dvl->initiator);
6668  if (NULL != n)
6669  {
6670  if ((n->dv_monotime_available == GNUNET_YES) &&
6673  {
6674  GNUNET_STATISTICS_update(GST_stats,
6675  "# DV learn discarded due to time travel",
6676  1,
6677  GNUNET_NO);
6678  return;
6679  }
6681  &dvl->initiator,
6682  &dvl->challenge,
6683  &dvl->init_sig))
6684  {
6685  GNUNET_break_op(0);
6686  return;
6687  }
6690  {
6691  if (NULL != n->sc)
6693  n->sc =
6694  GNUNET_PEERSTORE_store(peerstore,
6695  "transport",
6696  &dvl->initiator,
6698  &dvl->monotonic_time,
6699  sizeof(dvl->monotonic_time),
6703  n);
6704  }
6705  }
6706  /* OPTIMIZE-FIXME: asynchronously (!) verify signatures!,
6707  If signature verification load too high, implement random drop strategy */
6708  for (unsigned int i = 0; i < nhops; i++)
6709  {
6710  struct DvHopPS dhp = { .purpose.purpose =
6712  .purpose.size = htonl(sizeof(dhp)),
6713  .pred = (0 == i) ? dvl->initiator : hops[i - 1].hop,
6714  .succ = (nhops == i + 1) ? GST_my_identity
6715  : hops[i + 1].hop,
6716  .challenge = dvl->challenge };
6717 
6718  if (GNUNET_OK !=
6720  &dhp.purpose,
6721  &hops[i].hop_sig,
6722  &hops[i].hop.public_key))
6723  {
6724  GNUNET_break_op(0);
6725  return;
6726  }
6727  }
6728 
6729  if (GNUNET_EXTRA_LOGGING > 0)
6730  {
6731  char *path;
6732 
6733  path = GNUNET_strdup(GNUNET_i2s(&dvl->initiator));
6734  for (unsigned int i = 0; i < nhops; i++)
6735  {
6736  char *tmp;
6737 
6738  GNUNET_asprintf(&tmp,
6739  "%s%s%s",
6740  path,
6741  (bi_history & (1 << (nhops - i))) ? "<->" : "-->",
6742  GNUNET_i2s(&hops[i].hop));
6743  GNUNET_free(path);
6744  path = tmp;
6745  }
6747  "Received DVInit via %s%s%s\n",
6748  path,
6749  bi_hop ? "<->" : "-->",
6751  GNUNET_free(path);
6752  }
6753 
6754  do_fwd = GNUNET_YES;
6755  if (0 == GNUNET_memcmp(&GST_my_identity, &dvl->initiator))
6756  {
6757  struct GNUNET_PeerIdentity path[nhops + 1];
6758  struct GNUNET_TIME_Relative host_latency_sum;
6759  struct GNUNET_TIME_Relative latency;
6760  struct GNUNET_TIME_Relative network_latency;
6761 
6762  /* We initiated this, learn the forward path! */
6763  path[0] = GST_my_identity;
6764  path[1] = hops[0].hop;
6765  host_latency_sum = GNUNET_TIME_relative_ntoh(dvl->non_network_delay);
6766 
6767  // Need also something to lookup initiation time
6768  // to compute RTT! -> add RTT argument here?
6769  latency = GNUNET_TIME_UNIT_FOREVER_REL; // FIXME: initialize properly
6770  // (based on dvl->challenge, we can identify time of origin!)
6771 
6772  network_latency = GNUNET_TIME_relative_subtract(latency, host_latency_sum);
6773  /* assumption: latency on all links is the same */
6774  network_latency = GNUNET_TIME_relative_divide(network_latency, nhops);
6775 
6776  for (unsigned int i = 2; i <= nhops; i++)
6777  {
6778  struct GNUNET_TIME_Relative ilat;
6779 
6780  /* assumption: linear latency increase per hop */
6781  ilat = GNUNET_TIME_relative_multiply(network_latency, i);
6782  path[i] = hops[i - 1].hop;
6784  "Learned path with %u hops to %s with latency %s\n",
6785  i,
6786  GNUNET_i2s(&path[i]),
6788  learn_dv_path(path,
6789  i,
6790  ilat,
6793  }
6794  /* as we initiated, do not forward again (would be circular!) */
6795  do_fwd = GNUNET_NO;
6796  return;
6797  }
6798  if (bi_hop)
6799  {
6800  /* last hop was bi-directional, we could learn something here! */
6801  struct GNUNET_PeerIdentity path[nhops + 2];
6802 
6803  path[0] = GST_my_identity;
6804  path[1] = hops[nhops - 1].hop; /* direct neighbour == predecessor! */
6805  for (unsigned int i = 0; i < nhops; i++)
6806  {
6807  int iret;
6808 
6809  if (0 == (bi_history & (1 << i)))
6810  break; /* i-th hop not bi-directional, stop learning! */
6811  if (i == nhops - 1)
6812  {
6813  path[i + 2] = dvl->initiator;
6814  }
6815  else
6816  {
6817  path[i + 2] = hops[nhops - i - 2].hop;
6818  }
6819 
6821  "Learned inverse path with %u hops to %s\n",
6822  i + 1,
6823  GNUNET_i2s(&path[i + 2]));
6824  iret = learn_dv_path(path,
6825  i + 2,
6828  if (GNUNET_SYSERR == iret)
6829  {
6830  /* path invalid or too long to be interesting for US, thus should also
6831  not be interesting to our neighbours, cut path when forwarding to
6832  'i' hops, except of course for the one that goes back to the
6833  initiator */
6834  GNUNET_STATISTICS_update(GST_stats,
6835  "# DV learn not forwarded due invalidity of path",
6836  1,
6837  GNUNET_NO);
6838  do_fwd = GNUNET_NO;
6839  break;
6840  }
6841  if ((GNUNET_NO == iret) && (nhops == i + 1))
6842  {
6843  /* we have better paths, and this is the longest target,
6844  so there cannot be anything interesting later */
6845  GNUNET_STATISTICS_update(GST_stats,
6846  "# DV learn not forwarded, got better paths",
6847  1,
6848  GNUNET_NO);
6849  do_fwd = GNUNET_NO;
6850  break;
6851  }
6852  }
6853  }
6854 
6855  if (MAX_DV_HOPS_ALLOWED == nhops)
6856  {
6857  /* At limit, we're out of here! */
6858  finish_cmc_handling(cmc);
6859  return;
6860  }
6861 
6862  /* Forward to initiator, if path non-trivial and possible */
6863  bi_history = (bi_history << 1) | (bi_hop ? 1 : 0);
6864  did_initiator = GNUNET_NO;
6865  if ((1 < nhops) &&
6866  (GNUNET_YES ==
6868  {
6869  /* send back to origin! */
6871  "Sending DVL back to initiator %s\n",
6872  GNUNET_i2s(&dvl->initiator));
6873  forward_dv_learn(&dvl->initiator, dvl, bi_history, nhops, hops, in_time);
6874  did_initiator = GNUNET_YES;
6875  }
6876  /* We forward under two conditions: either we still learned something
6877  ourselves (do_fwd), or the path was darn short and thus the initiator is
6878  likely to still be very interested in this (and we did NOT already
6879  send it back to the initiator) */
6880  if ((do_fwd) || ((nhops < MIN_DV_PATH_LENGTH_FOR_INITIATOR) &&
6881  (GNUNET_NO == did_initiator)))
6882  {
6883  /* Pick random neighbours that are not yet on the path */
6884  struct NeighbourSelectionContext nsc;
6885  unsigned int n_cnt;
6886 
6887  n_cnt = GNUNET_CONTAINER_multipeermap_size(neighbours);
6888  nsc.nhops = nhops;
6889  nsc.dvl = dvl;
6890  nsc.bi_history = bi_history;
6891  nsc.hops = hops;
6892  nsc.in_time = in_time;
6893  nsc.num_eligible = 0;
6896  &nsc);
6897  if (0 == nsc.num_eligible)
6898  return; /* done here, cannot forward to anyone else */
6899  nsc.num_selections = calculate_fork_degree(nhops, n_cnt, nsc.num_eligible);
6900  nsc.num_selections =
6903  "Forwarding DVL to %u other peers\n",
6904  nsc.num_selections);
6905  for (unsigned int i = 0; i < nsc.num_selections; i++)
6906  nsc.selections[i] =
6907  (nsc.num_selections == n_cnt)
6908  ? i /* all were selected, avoid collisions by chance */
6910  nsc.num_eligible = 0;
6913  &nsc);
6914  }
6915 }
6916 
6917 
6925 static int
6926 check_dv_box(void *cls, const struct TransportDVBoxMessage *dvb)
6927 {
6928  uint16_t size = ntohs(dvb->header.size);
6929  uint16_t num_hops = ntohs(dvb->num_hops);
6930  const struct GNUNET_PeerIdentity *hops =
6931  (const struct GNUNET_PeerIdentity *)&dvb[1];
6932 
6933  (void)cls;
6934  if (size < sizeof(*dvb) + num_hops * sizeof(struct GNUNET_PeerIdentity) +
6935  sizeof(struct GNUNET_MessageHeader))
6936  {
6937  GNUNET_break_op(0);
6938  return GNUNET_SYSERR;
6939  }
6940  /* This peer must not be on the path */
6941  for (unsigned int i = 0; i < num_hops; i++)
6942  if (0 == GNUNET_memcmp(&hops[i], &GST_my_identity))
6943  {
6944  GNUNET_break_op(0);
6945  return GNUNET_SYSERR;
6946  }
6947  return GNUNET_YES;
6948 }
6949 
6950 
6963 static void
6964 forward_dv_box(struct Neighbour *next_hop,
6965  const struct TransportDVBoxMessage *hdr,
6966  uint16_t total_hops,
6967  uint16_t num_hops,
6968  const struct GNUNET_PeerIdentity *hops,
6969  const void *enc_payload,
6970  uint16_t enc_payload_size)
6971 {
6972  struct VirtualLink *vl = next_hop->vl;
6973  struct PendingMessage *pm;
6974  size_t msg_size;
6975  char *buf;
6976  struct GNUNET_PeerIdentity *dhops;
6977 
6978  GNUNET_assert(NULL != vl);
6979  msg_size = sizeof(struct TransportDVBoxMessage) +
6980  num_hops * sizeof(struct GNUNET_PeerIdentity) + enc_payload_size;
6981  pm = GNUNET_malloc(sizeof(struct PendingMessage) + msg_size);
6982  pm->pmt = PMT_DV_BOX;
6983  pm->vl = vl;
6985  pm->logging_uuid = logging_uuid_gen++;
6986  pm->prefs = GNUNET_MQ_PRIO_BACKGROUND;
6987  pm->bytes_msg = msg_size;
6988  buf = (char *)&pm[1];
6989  memcpy(buf, hdr, sizeof(*hdr));
6990  dhops =
6991  (struct GNUNET_PeerIdentity *)&buf[sizeof(struct TransportDVBoxMessage)];
6992  memcpy(dhops, hops, num_hops * sizeof(struct GNUNET_PeerIdentity));
6993  memcpy(&dhops[num_hops], enc_payload, enc_payload_size);
6995  vl->pending_msg_head,
6996  vl->pending_msg_tail,
6997  pm);
6999  "Created pending message %llu for DV Box with next hop %s (%u/%u)\n",
7000  pm->logging_uuid,
7001  GNUNET_i2s(&next_hop->pid),
7002  (unsigned int)num_hops,
7003  (unsigned int)total_hops);
7005 }
7006 
7007 
7013 static void
7015 {
7016  if (NULL != b->get)
7017  {
7019  b->get = NULL;
7020  GNUNET_assert(NULL != b->cmc);
7022  b->cmc = NULL;
7023  }
7024  if (NULL != b->task)
7025  {
7027  b->task = NULL;
7028  }
7029  if (NULL != b->sc)
7030  {
7032  b->sc = NULL;
7033  }
7034  GNUNET_assert(
7035  GNUNET_YES ==
7036  GNUNET_CONTAINER_multipeermap_remove(backtalkers, &b->pid, b));
7037  GNUNET_free(b);
7038 }
7039 
7040 
7049 static int
7051  const struct GNUNET_PeerIdentity *pid,
7052  void *value)
7053 {
7054  struct Backtalker *b = value;
7055 
7056  (void)cls;
7057  (void)pid;
7058  free_backtalker(b);
7059  return GNUNET_OK;
7060 }
7061 
7062 
7068 static void
7070 {
7071  struct Backtalker *b = cls;
7072 
7073  b->task = NULL;
7075  {
7077  return;
7078  }
7079  GNUNET_assert(NULL == b->sc);
7080  free_backtalker(b);
7081 }
7082 
7083 
7092 static void
7094  const struct GNUNET_PEERSTORE_Record *record,
7095  const char *emsg)
7096 {
7097  struct Backtalker *b = cls;
7098  struct GNUNET_TIME_AbsoluteNBO *mtbe;
7099  struct GNUNET_TIME_Absolute mt;
7100 
7101  (void)emsg;
7102  if (NULL == record)
7103  {
7104  /* we're done with #backtalker_monotime_cb() invocations,
7105  continue normal processing */
7106  b->get = NULL;
7107  GNUNET_assert(NULL != b->cmc);
7108  if (0 != b->body_size)
7110  (const struct GNUNET_MessageHeader *)&b[1]);
7111  else
7112  finish_cmc_handling(b->cmc);
7113  b->cmc = NULL;
7114  return;
7115  }
7116  if (sizeof(*mtbe) != record->value_size)
7117  {
7118  GNUNET_break(0);
7119  return;
7120  }
7121  mtbe = record->value;
7122  mt = GNUNET_TIME_absolute_ntoh(*mtbe);
7124  {
7126  "Backtalker message from %s dropped, monotime in the past\n",
7127  GNUNET_i2s(&b->pid));
7129  GST_stats,
7130  "# Backchannel messages dropped: monotonic time not increasing",
7131  1,
7132  GNUNET_NO);
7133  b->monotonic_time = mt;
7134  /* Setting body_size to 0 prevents call to #forward_backchannel_payload()
7135  */
7136  b->body_size = 0;
7137  return;
7138  }
7139 }
7140 
7141 
7149 static void
7150 backtalker_monotime_store_cb(void *cls, int success)
7151 {
7152  struct Backtalker *b = cls;
7153 
7154  if (GNUNET_OK != success)
7155  {
7157  "Failed to store backtalker's monotonic time in PEERSTORE!\n");
7158  }
7159  b->sc = NULL;
7161 }
7162 
7163 
7169 static void
7171 {
7172  struct GNUNET_TIME_AbsoluteNBO mtbe;
7173 
7174  if (NULL != b->sc)
7175  {
7177  b->sc = NULL;
7178  }
7179  else
7180  {
7182  b->task = NULL;
7183  }
7185  b->sc =
7186  GNUNET_PEERSTORE_store(peerstore,
7187  "transport",
7188  &b->pid,
7190  &mtbe,
7191  sizeof(mtbe),
7195  b);
7196 }
7197 
7198 
7206 static void
7207 handle_dv_box(void *cls, const struct TransportDVBoxMessage *dvb)
7208 {
7209  struct CommunicatorMessageContext *cmc = cls;
7210  uint16_t size = ntohs(dvb->header.size) - sizeof(*dvb);
7211  uint16_t num_hops = ntohs(dvb->num_hops);
7212  const struct GNUNET_PeerIdentity *hops =
7213  (const struct GNUNET_PeerIdentity *)&dvb[1];
7214  const char *enc_payload = (const char *)&hops[num_hops];
7215  uint16_t enc_payload_size =
7216  size - (num_hops * sizeof(struct GNUNET_PeerIdentity));
7217  struct DVKeyState key;
7218  struct GNUNET_HashCode hmac;
7219  const char *hdr;
7220  size_t hdr_len;
7221 
7222  if (GNUNET_EXTRA_LOGGING > 0)
7223  {
7224  char *path;
7225 
7227  for (unsigned int i = 0; i < num_hops; i++)
7228  {
7229  char *tmp;
7230 
7231  GNUNET_asprintf(&tmp, "%s->%s", path, GNUNET_i2s(&hops[i]));
7232  GNUNET_free(path);
7233  path = tmp;
7234  }
7236  "Received DVBox with remainig path %s\n",
7237  path);
7238  GNUNET_free(path);
7239  }
7240 
7241  if (num_hops > 0)
7242  {
7243  /* We're trying from the end of the hops array, as we may be
7244  able to find a shortcut unknown to the origin that way */
7245  for (int i = num_hops - 1; i >= 0; i--)
7246  {
7247  struct Neighbour *n;
7248 
7249  if (0 == GNUNET_memcmp(&hops[i], &GST_my_identity))
7250  {
7251  GNUNET_break_op(0);
7252  finish_cmc_handling(cmc);
7253  return;
7254  }
7255  n = lookup_neighbour(&hops[i]);
7256  if (NULL == n)
7257  continue;
7259  "Skipping %u/%u hops ahead while routing DV Box\n",
7260  i,
7261  num_hops);
7262  forward_dv_box(n,
7263  dvb,
7264  ntohs(dvb->total_hops) + 1,
7265  num_hops - i - 1, /* number of hops left */
7266  &hops[i + 1], /* remaining hops */
7267  enc_payload,
7268  enc_payload_size);
7269  GNUNET_STATISTICS_update(GST_stats,
7270  "# DV hops skipped routing boxes",
7271  i,
7272  GNUNET_NO);
7273  GNUNET_STATISTICS_update(GST_stats,
7274  "# DV boxes routed (total)",
7275  1,
7276  GNUNET_NO);
7277  finish_cmc_handling(cmc);
7278  return;
7279  }
7280  /* Woopsie, next hop not in neighbours, drop! */
7281  GNUNET_STATISTICS_update(GST_stats,
7282  "# DV Boxes dropped: next hop unknown",
7283  1,
7284  GNUNET_NO);
7285  finish_cmc_handling(cmc);
7286  return;
7287  }
7288  /* We are the target. Unbox and handle message. */
7289  GNUNET_STATISTICS_update(GST_stats,
7290  "# DV boxes opened (ultimate target)",
7291  1,
7292  GNUNET_NO);
7293  cmc->total_hops = ntohs(dvb->total_hops);
7294 
7295  dh_key_derive_eph_pub(&dvb->ephemeral_key, &dvb->iv, &key);
7296  hdr = (const char *)&dvb[1];
7297  hdr_len = ntohs(dvb->header.size) - sizeof(*dvb);
7298  dv_hmac(&key, &hmac, hdr, hdr_len);
7299  if (0 != GNUNET_memcmp(&hmac, &dvb->hmac))
7300  {
7301  /* HMAC missmatch, disard! */
7302  GNUNET_break_op(0);
7303  finish_cmc_handling(cmc);
7304  return;
7305  }
7306  /* begin actual decryption */
7307  {
7308  struct Backtalker *b;
7309  struct GNUNET_TIME_Absolute monotime;
7310  struct TransportDVBoxPayloadP ppay;
7311  char body[hdr_len - sizeof(ppay)] GNUNET_ALIGN;
7312  const struct GNUNET_MessageHeader *mh =
7313  (const struct GNUNET_MessageHeader *)body;
7314 
7315  GNUNET_assert(hdr_len >=
7316  sizeof(ppay) + sizeof(struct GNUNET_MessageHeader));
7317  dv_decrypt(&key, &ppay, hdr, sizeof(ppay));
7318  dv_decrypt(&key, &body, &hdr[sizeof(ppay)], hdr_len - sizeof(ppay));
7319  dv_key_clean(&key);
7320  if (ntohs(mh->size) != sizeof(body))
7321  {
7322  GNUNET_break_op(0);
7323  finish_cmc_handling(cmc);
7324  return;
7325  }
7326  /* need to prevent box-in-a-box (and DV_LEARN) so check inbox type! */
7327  switch (ntohs(mh->type))
7328  {
7330  GNUNET_break_op(0);
7331  finish_cmc_handling(cmc);
7332  return;
7333 
7335  GNUNET_break_op(0);
7336  finish_cmc_handling(cmc);
7337  return;
7338 
7339  default:
7340  /* permitted, continue */
7341  break;
7342  }
7343  monotime = GNUNET_TIME_absolute_ntoh(ppay.monotonic_time);
7345  "Decrypted backtalk from %s\n",
7346  GNUNET_i2s(&ppay.sender));
7347  b = GNUNET_CONTAINER_multipeermap_get(backtalkers, &ppay.sender);
7348  if ((NULL != b) && (monotime.abs_value_us < b->monotonic_time.abs_value_us))
7349  {
7351  GST_stats,
7352  "# Backchannel messages dropped: monotonic time not increasing",
7353  1,
7354  GNUNET_NO);
7355  finish_cmc_handling(cmc);
7356  return;
7357  }
7358  if ((NULL == b) ||
7359  (0 != GNUNET_memcmp(&b->last_ephemeral, &dvb->ephemeral_key)))
7360  {
7361  /* Check signature */
7362  struct EphemeralConfirmationPS ec;
7363 
7365  ec.purpose.size = htonl(sizeof(ec));
7366  ec.target = GST_my_identity;
7367  ec.ephemeral_key = dvb->ephemeral_key;
7368  if (
7369  GNUNET_OK !=
7371  &ec.purpose,
7372  &ppay.sender_sig,
7373  &ppay.sender.public_key))
7374  {
7375  /* Signature invalid, disard! */
7376  GNUNET_break_op(0);
7377  finish_cmc_handling(cmc);
7378  return;
7379  }
7380  }
7381  /* Update sender, we now know the real origin! */
7383  "DVBox received for me from %s via %s\n",
7384  GNUNET_i2s2(&ppay.sender),
7385  GNUNET_i2s(&cmc->im.sender));
7386  cmc->im.sender = ppay.sender;
7387 
7388  if (NULL != b)
7389  {
7390  /* update key cache and mono time */
7391  b->last_ephemeral = dvb->ephemeral_key;
7392  b->monotonic_time = monotime;
7394  b->timeout =
7396 
7397  demultiplex_with_cmc(cmc, mh);
7398  return;
7399  }
7400  /* setup data structure to cache signature AND check
7401  monotonic time with PEERSTORE before forwarding backchannel payload */
7402  b = GNUNET_malloc(sizeof(struct Backtalker) + sizeof(body));
7403  b->pid = ppay.sender;
7404  b->body_size = sizeof(body);
7405  memcpy(&b[1], body, sizeof(body));
7408  backtalkers,
7409  &b->pid,
7410  b,
7412  b->monotonic_time = monotime; /* NOTE: to be checked still! */
7413  b->cmc = cmc;
7414  b->timeout =
7417  b->get =
7418  GNUNET_PEERSTORE_iterate(peerstore,
7419  "transport",
7420  &b->pid,
7423  b);
7424  } /* end actual decryption */
7425 }
7426 
7427 
7435 static int
7437  const struct GNUNET_TRANSPORT_IncomingMessage *im)
7438 {
7439  struct TransportClient *tc = cls;
7440 
7441  if (CT_COMMUNICATOR != tc->type)
7442  {
7443  GNUNET_break(0);
7444  return GNUNET_SYSERR;
7445  }
7447  return GNUNET_OK;
7448 }
7449 
7450 
7458  const char *address;
7459 
7464 };
7465 
7466 
7476 static int
7478  const struct GNUNET_PeerIdentity *pid,
7479  void *value)
7480 {
7481  struct CheckKnownAddressContext *ckac = cls;
7482  struct ValidationState *vs = value;
7483 
7484  (void)pid;
7485  if (0 != strcmp(vs->address, ckac->address))
7486  return GNUNET_OK;
7487  ckac->vs = vs;
7488  return GNUNET_NO;
7489 }
7490 
7491 
7497 static void
7498 validation_start_cb(void *cls);
7499 
7500 
7508 static void
7510  struct GNUNET_TIME_Absolute new_time)
7511 {
7512  struct GNUNET_TIME_Relative delta;
7513 
7514  if (new_time.abs_value_us == vs->next_challenge.abs_value_us)
7515  return; /* be lazy */
7516  vs->next_challenge = new_time;
7517  if (NULL == vs->hn)
7518  vs->hn =
7519  GNUNET_CONTAINER_heap_insert(validation_heap, vs, new_time.abs_value_us);
7520  else
7522  if ((vs != GNUNET_CONTAINER_heap_peek(validation_heap)) &&
7523  (NULL != validation_task))
7524  return;
7525  if (NULL != validation_task)
7526  GNUNET_SCHEDULER_cancel(validation_task);
7527  /* randomize a bit */
7528  delta.rel_value_us =
7530  MIN_DELAY_ADDRESS_VALIDATION.rel_value_us);
7531  new_time = GNUNET_TIME_absolute_add(new_time, delta);
7532  validation_task =
7533  GNUNET_SCHEDULER_add_at(new_time, &validation_start_cb, NULL);
7534 }
7535 
7536 
7543 static void
7545  const char *address)
7546 {
7547  struct GNUNET_TIME_Absolute now;
7548  struct ValidationState *vs;
7549  struct CheckKnownAddressContext ckac = { .address = address, .vs = NULL };
7550 
7551  (void)GNUNET_CONTAINER_multipeermap_get_multiple(validation_map,
7552  pid,
7554  &ckac);
7555  if (NULL != (vs = ckac.vs))
7556  {
7557  /* if 'vs' is not currently valid, we need to speed up retrying the
7558  * validation */
7559  if (vs->validated_until.abs_value_us < vs->next_challenge.abs_value_us)
7560  {
7561  /* reduce backoff as we got a fresh advertisement */
7562  vs->challenge_backoff =
7564  GNUNET_TIME_relative_divide(vs->challenge_backoff,
7565  2));
7568  vs->challenge_backoff));
7569  }
7570  return;
7571  }
7572  now = GNUNET_TIME_absolute_get();
7573  vs = GNUNET_new(struct ValidationState);
7574  vs->pid = *pid;
7575  vs->valid_until =
7577  vs->first_challenge_use = now;
7578  vs->validation_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
7580  &vs->challenge,
7581  sizeof(vs->challenge));
7582  vs->address = GNUNET_strdup(address);
7584  "Starting address validation `%s' of peer %s using challenge %s\n",
7585  address,
7586  GNUNET_i2s(pid),
7587  GNUNET_sh2s(&vs->challenge.value));
7590  validation_map,
7591  &vs->pid,
7592  vs,
7594  update_next_challenge_time(vs, now);
7595 }
7596 
7597 
7605 static void
7607  const struct GNUNET_PEERSTORE_Record *record,
7608  const char *emsg)
7609 {
7610  struct IncomingRequest *ir = cls;
7611  const char *val;
7612 
7613  if (NULL != emsg)
7614  {
7616  "Got failure from PEERSTORE: %s\n",
7617  emsg);
7618  return;
7619  }
7620  val = record->value;
7621  if ((0 == record->value_size) || ('\0' != val[record->value_size - 1]))
7622  {
7623  GNUNET_break(0);
7624  return;
7625  }
7626  start_address_validation(&ir->pid, (const char *)record->value);
7627 }
7628 
7629 
7638 static void
7640  void *cls,
7641  const struct TransportValidationChallengeMessage *tvc)
7642 {
7643  struct CommunicatorMessageContext *cmc = cls;
7645  struct VirtualLink *vl;
7646  struct GNUNET_TIME_RelativeNBO validity_duration;
7647  struct IncomingRequest *ir;
7648  struct Neighbour *n;
7649  struct GNUNET_PeerIdentity sender;
7650 
7651  /* DV-routed messages are not allowed for validation challenges */
7652  if (cmc->total_hops > 0)
7653  {
7654  GNUNET_break_op(0);
7655  finish_cmc_handling(cmc);
7656  return;
7657  }
7658  validity_duration = cmc->im.expected_address_validity;
7660  "Received address validation challenge %s\n",
7661  GNUNET_sh2s(&tvc->challenge.value));
7662  /* If we have a virtual link, we use this mechanism to signal the
7663  size of the flow control window, and to allow the sender
7664  to ask for increases. If for us the virtual link is still down,
7665  we will always give a window size of zero. */
7666  tvr.header.type =
7668  tvr.header.size = htons(sizeof(tvr));
7669  tvr.reserved = htonl(0);
7670  tvr.challenge = tvc->challenge;
7671  tvr.origin_time = tvc->sender_time;
7672  tvr.validity_duration = validity_duration;
7673  {
7674  /* create signature */
7675  struct TransportValidationPS tvp =
7677  .purpose.size = htonl(sizeof(tvp)),
7678  .validity_duration = validity_duration,
7679  .challenge = tvc->challenge };
7680 
7681  GNUNET_assert(GNUNET_OK == GNUNET_CRYPTO_eddsa_sign(GST_my_private_key,
7682  &tvp.purpose,
7683  &tvr.signature));
7684  }
7685  route_control_message_without_fc(&cmc->im.sender,
7686  &tvr.header,
7688  sender = cmc->im.sender;
7689  finish_cmc_handling(cmc);
7690  vl = lookup_virtual_link(&sender);
7691  if (NULL != vl)
7692  return;
7693 
7694  /* For us, the link is still down, but we need bi-directional
7695  connections (for flow-control and for this to be useful for
7696  CORE), so we must try to bring the link up! */
7697 
7698  /* (1) Check existing queues, if any, we may be lucky! */
7699  n = lookup_neighbour(&sender);
7700  if (NULL != n)
7701  for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
7702  start_address_validation(&sender, q->address);
7703  /* (2) Also try to see if we have addresses in PEERSTORE for this peer
7704  we could use */
7705  for (ir = ir_head; NULL != ir; ir = ir->next)
7706  if (0 == GNUNET_memcmp(&ir->pid, &sender))
7707  return;
7708  /* we are already trying */
7709  ir = GNUNET_new(struct IncomingRequest);
7710  ir->pid = sender;
7711  GNUNET_CONTAINER_DLL_insert(ir_head, ir_tail, ir);
7712  ir->wc = GNUNET_PEERSTORE_watch(peerstore,
7713  "transport",
7714  &ir->pid,
7717  ir);
7718  ir_total++;
7719  /* Bound attempts we do in parallel here, might otherwise get excessive */
7720  while (ir_total > MAX_INCOMING_REQUEST)
7721  free_incoming_request(ir_head);
7722 }
7723 
7724 
7733 
7738 };
7739 
7740 
7750 static int
7752  const struct GNUNET_PeerIdentity *pid,
7753  void *value)
7754 {
7755  struct CheckKnownChallengeContext *ckac = cls;
7756  struct ValidationState *vs = value;
7757 
7758  (void)pid;
7759  if (0 != GNUNET_memcmp(&vs->challenge, ckac->challenge))
7760  return GNUNET_OK;
7761  ckac->vs = vs;
7762  return GNUNET_NO;
7763 }
7764 
7765 
7773 static void
7774 peerstore_store_validation_cb(void *cls, int success)
7775 {
7776  struct ValidationState *vs = cls;
7777 
7778  vs->sc = NULL;
7779  if (GNUNET_YES == success)
7780  return;
7781  GNUNET_STATISTICS_update(GST_stats,
7782  "# Peerstore failed to store foreign address",
7783  1,
7784  GNUNET_NO);
7785 }
7786 
7787 
7795 static struct Queue *
7796 find_queue(const struct GNUNET_PeerIdentity *pid, const char *address)
7797 {
7798  struct Neighbour *n;
7799 
7800  n = lookup_neighbour(pid);
7801  if (NULL == n)
7802  return NULL;
7803  for (struct Queue *pos = n->queue_head; NULL != pos;
7804  pos = pos->next_neighbour)
7805  {
7806  if (0 == strcmp(pos->address, address))
7807  return pos;
7808  }
7809  return NULL;
7810 }
7811 
7812 
7821 static void
7823  void *cls,
7824  const struct TransportValidationResponseMessage *tvr)
7825 {
7826  struct CommunicatorMessageContext *cmc = cls;
7827  struct ValidationState *vs;
7828  struct CheckKnownChallengeContext ckac = { .challenge = &tvr->challenge,
7829  .vs = NULL };
7830  struct GNUNET_TIME_Absolute origin_time;
7831  struct Queue *q;
7832  struct Neighbour *n;
7833  struct VirtualLink *vl;
7834 
7835  /* check this is one of our challenges */
7836  (void)GNUNET_CONTAINER_multipeermap_get_multiple(validation_map,
7837  &cmc->im.sender,
7839  &ckac);
7840  if (NULL == (vs = ckac.vs))
7841  {
7842  /* This can happen simply if we 'forgot' the challenge by now,
7843  i.e. because we received the validation response twice */
7844  GNUNET_STATISTICS_update(GST_stats,
7845  "# Validations dropped, challenge unknown",
7846  1,
7847