aboutsummaryrefslogtreecommitdiff
path: root/src/service/cadet
diff options
context:
space:
mode:
Diffstat (limited to 'src/service/cadet')
-rw-r--r--src/service/cadet/.gitignore2
-rw-r--r--src/service/cadet/Makefile.am81
-rw-r--r--src/service/cadet/TODO36
-rw-r--r--src/service/cadet/cadet.conf.in53
-rw-r--r--src/service/cadet/cadet.h578
-rw-r--r--src/service/cadet/cadet_api.c1072
-rw-r--r--src/service/cadet/cadet_api_drop_message.c59
-rw-r--r--src/service/cadet/cadet_api_get_channel.c260
-rw-r--r--src/service/cadet/cadet_api_get_path.c267
-rw-r--r--src/service/cadet/cadet_api_helper.c54
-rw-r--r--src/service/cadet/cadet_api_list_peers.c238
-rw-r--r--src/service/cadet/cadet_api_list_tunnels.c239
-rw-r--r--src/service/cadet/cadet_protocol.h541
-rw-r--r--src/service/cadet/desirability_table.c34
-rw-r--r--src/service/cadet/gnunet-service-cadet.c1376
-rw-r--r--src/service/cadet/gnunet-service-cadet.h328
-rw-r--r--src/service/cadet/gnunet-service-cadet_channel.c2008
-rw-r--r--src/service/cadet/gnunet-service-cadet_channel.h306
-rw-r--r--src/service/cadet/gnunet-service-cadet_connection.c1079
-rw-r--r--src/service/cadet/gnunet-service-cadet_connection.h363
-rw-r--r--src/service/cadet/gnunet-service-cadet_core.c1337
-rw-r--r--src/service/cadet/gnunet-service-cadet_core.h69
-rw-r--r--src/service/cadet/gnunet-service-cadet_dht.c340
-rw-r--r--src/service/cadet/gnunet-service-cadet_dht.h100
-rw-r--r--src/service/cadet/gnunet-service-cadet_hello.c195
-rw-r--r--src/service/cadet/gnunet-service-cadet_hello.h80
-rw-r--r--src/service/cadet/gnunet-service-cadet_paths.c771
-rw-r--r--src/service/cadet/gnunet-service-cadet_paths.h183
-rw-r--r--src/service/cadet/gnunet-service-cadet_peer.c1554
-rw-r--r--src/service/cadet/gnunet-service-cadet_peer.h433
-rw-r--r--src/service/cadet/gnunet-service-cadet_tunnels.c3668
-rw-r--r--src/service/cadet/gnunet-service-cadet_tunnels.h391
-rwxr-xr-xsrc/service/cadet/loopcheck.sh57
-rw-r--r--src/service/cadet/meson.build72
-rw-r--r--src/service/cadet/profiler.conf19
-rwxr-xr-xsrc/service/cadet/run_profiler.sh25
-rw-r--r--src/service/cadet/small.dat21
-rw-r--r--src/service/cadet/test_cadet.conf109
-rw-r--r--src/service/cadet/test_cadet_local_mq.c338
-rw-r--r--src/service/cadet/valgrind-cadet.supp116
40 files changed, 18852 insertions, 0 deletions
diff --git a/src/service/cadet/.gitignore b/src/service/cadet/.gitignore
new file mode 100644
index 000000000..bed27a3d3
--- /dev/null
+++ b/src/service/cadet/.gitignore
@@ -0,0 +1,2 @@
1gnunet-service-cadet
2test_cadet_local_mq
diff --git a/src/service/cadet/Makefile.am b/src/service/cadet/Makefile.am
new file mode 100644
index 000000000..0046ffc70
--- /dev/null
+++ b/src/service/cadet/Makefile.am
@@ -0,0 +1,81 @@
1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3
4if USE_COVERAGE
5 AM_CFLAGS = --coverage -O0
6 XLIB = -lgcov
7endif
8
9pkgcfgdir= $(pkgdatadir)/config.d/
10
11libexecdir= $(pkglibdir)/libexec/
12
13pkgcfg_DATA = \
14 cadet.conf
15
16plugindir = $(libdir)/gnunet
17
18AM_CLFAGS = -g
19
20libexec_PROGRAMS = \
21 gnunet-service-cadet
22
23lib_LTLIBRARIES = \
24 libgnunetcadet.la
25
26libgnunetcadet_la_SOURCES = \
27 cadet_api.c \
28 cadet_api_drop_message.c \
29 cadet_api_get_channel.c \
30 cadet_api_get_path.c \
31 cadet_api_list_peers.c \
32 cadet_api_list_tunnels.c \
33 cadet_api_helper.c
34libgnunetcadet_la_LIBADD = \
35 $(top_builddir)/src/lib/util/libgnunetutil.la \
36 $(XLIB) \
37 $(LTLIBINTL)
38libgnunetcadet_la_LDFLAGS = \
39 $(GN_LIB_LDFLAGS) \
40 -version-info 7:0:0
41
42gnunet_service_cadet_SOURCES = \
43 gnunet-service-cadet.c gnunet-service-cadet.h \
44 gnunet-service-cadet_channel.c gnunet-service-cadet_channel.h \
45 gnunet-service-cadet_connection.c gnunet-service-cadet_connection.h \
46 gnunet-service-cadet_core.c gnunet-service-cadet_core.h \
47 gnunet-service-cadet_dht.c gnunet-service-cadet_dht.h \
48 gnunet-service-cadet_hello.c gnunet-service-cadet_hello.h \
49 gnunet-service-cadet_tunnels.c gnunet-service-cadet_tunnels.h \
50 gnunet-service-cadet_paths.c gnunet-service-cadet_paths.h \
51 gnunet-service-cadet_peer.c gnunet-service-cadet_peer.h
52gnunet_service_cadet_LDADD = \
53 $(top_builddir)/src/lib/util/libgnunetutil.la \
54 $(top_builddir)/src/service/core/libgnunetcore.la \
55 $(top_builddir)/src/service/dht/libgnunetdht.la \
56 $(top_builddir)/src/service/statistics/libgnunetstatistics.la \
57 $(top_builddir)/src/service/transport/libgnunettransportapplication.la \
58 $(top_builddir)/src/service/peerstore/libgnunetpeerstore.la \
59 $(top_builddir)/src/lib/hello/libgnunethello.la \
60 $(top_builddir)/src/lib/block/libgnunetblock.la
61if LINUX
62gnunet_service_cadet_LDFLAGS = -lrt \
63 $(GN_LIBINTL)
64endif
65
66
67test_cadet_local_mq_SOURCES = \
68 test_cadet_local_mq.c
69test_cadet_local_mq_LDADD = \
70 libgnunetcadet.la \
71 $(top_builddir)/src/service/testing/libgnunettesting.la \
72 $(top_builddir)/src/lib/util/libgnunetutil.la
73
74if ENABLE_TEST_RUN
75AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
76TESTS = $(check_PROGRAMS)
77endif
78
79EXTRA_DIST = \
80 cadet.h cadet_protocol.h \
81 test_cadet.conf
diff --git a/src/service/cadet/TODO b/src/service/cadet/TODO
new file mode 100644
index 000000000..06567b0ad
--- /dev/null
+++ b/src/service/cadet/TODO
@@ -0,0 +1,36 @@
1- URGENT:
2 + if 'client-not-ready', we do not ACK at all, and sender keeps
3 retransmitting again and again; would be good to do flow-control notification instead
4 of not ACKing that we got the data but are simply not ready for more!
5 + Congestion/flow control (CHANNEL):
6 estimate max bandwidth using bursts and use to for CONGESTION CONTROL!
7 (and figure out how/where to use this!)
8
9- HIGH: revisit handling of 'unbuffered' traffic! (CHANNEL/TUNNEL)
10 (need to push down through tunnel into connection selection);
11 At Tunnel-level, try to create connections that match channel
12 preferences (buffered/unbuffered) and select connections for
13 channel traffic that match channel preferences.
14 BUT: not sure this is ideal, discloses traffic type to
15 routers. We don't want that! (Maybe revise decision to do this?)
16
17- HIGH: revisit handling of 'buffered' traffic: 4 is a rather small buffer; (CHANNEL)
18 maybe reserve more bits in 'options' to allow for buffer size control?
19 Or: maybe even better, calculated required buffer size based on latency
20 and throughput (and available memory)
21
22- HIGH: if we receive BROKEN messages, cut down corresponding PATH (up to the
23 point of breakage) as well as connection/route (CORE)
24
25- OPTIMIZATION: proper connection evaluation during connection management:
26 + TUNNELS:
27 * consider quality of current connection set when deciding
28 how often to do maintenance
29 * interact with PEER to drive DHT GET/PUT operations based
30 on how much we like our connections
31
32
33- OPTIMIZATION: optimize stopping/restarting DHT search to situations
34 where we actually need it (i.e. not if we have a direct connection,
35 or if we already have plenty of good short ones, or maybe even
36 to take a break if we have some connections and have searched a lot (?)) (PEER)
diff --git a/src/service/cadet/cadet.conf.in b/src/service/cadet/cadet.conf.in
new file mode 100644
index 000000000..8f700951c
--- /dev/null
+++ b/src/service/cadet/cadet.conf.in
@@ -0,0 +1,53 @@
1[cadet]
2IMMEDIATE_START = YES
3START_ON_DEMAND = @START_ON_DEMAND@
4@JAVAPORT@PORT = 2096
5HOSTNAME = localhost
6BINARY = gnunet-service-cadet
7# PREFIX = valgrind --leak-check=yes
8ACCEPT_FROM = 127.0.0.1;
9ACCEPT_FROM6 = ::1;
10UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-cadet.sock
11UNIX_MATCH_UID = NO
12UNIX_MATCH_GID = YES
13
14
15# How often do we send KEEPALIVE messages on connections to keep them
16# from timing out?
17REFRESH_CONNECTION_TIME = 5 min
18
19# Percentage of packets CADET is artificially dropping. Used for testing only!
20# DROP_PERCENT =
21
22# How frequently do we usually announce our presence in the DHT?
23ID_ANNOUNCE_TIME = 1 h
24
25# FIXME: document
26CONNECT_TIMEOUT = 30 s
27
28# What is the replication level we give to the DHT when announcing our
29# existence? Usually there is no need to change this.
30DHT_REPLICATION_LEVEL = 3
31
32# FIXME: not implemented
33# MAX_TUNNELS = 1000
34
35# FIXME: not implemented, replaced by MAX_ROUTES in NEW CADET!
36MAX_CONNECTIONS = 1000
37
38# How many routes do we participate in at most? Should be smaller
39# than MAX_MSGS_QUEUE
40MAX_ROUTES = 5000
41
42# FIXME: not implemented
43MAX_MSGS_QUEUE = 10000
44
45# FIXME: not implemented
46MAX_PEERS = 1000
47
48# How often do we advance the ratchet even if there is not
49# any traffic?
50RATCHET_TIME = 1 h
51
52# How often do we advance the ratched if there is traffic?
53RATCHET_MESSAGES = 64
diff --git a/src/service/cadet/cadet.h b/src/service/cadet/cadet.h
new file mode 100644
index 000000000..e8caa7d35
--- /dev/null
+++ b/src/service/cadet/cadet.h
@@ -0,0 +1,578 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2001 - 2011 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @author Bartlomiej Polot
23 * @file cadet/cadet.h
24 */
25
26#ifndef CADET_H_
27#define CADET_H_
28
29#ifdef __cplusplus
30extern "C" {
31#if 0 /* keep Emacsens' auto-indent happy */
32}
33#endif
34#endif
35
36#include <stdint.h>
37
38#if ! defined(GNUNET_CULL_LOGGING)
39#define CADET_TIMING_START \
40 struct GNUNET_TIME_Absolute __timestamp; \
41 __timestamp = GNUNET_TIME_absolute_get ()
42
43#define CADET_TIMING_END \
44 struct GNUNET_TIME_Relative __duration; \
45 __duration = GNUNET_TIME_absolute_get_duration (__timestamp); \
46 LOG (GNUNET_ERROR_TYPE_INFO, \
47 " %s duration %s\n", \
48 __FUNCTION__, \
49 GNUNET_STRINGS_relative_time_to_string (__duration, GNUNET_YES));
50#else
51#define CADET_TIMING_START
52#define CADET_TIMING_END
53#endif
54
55
56#include "platform.h"
57#include "gnunet_util_lib.h"
58#include "gnunet_core_service.h"
59#include "gnunet_cadet_service.h"
60#include "gnunet_protocols.h"
61#include "gnunet_cadet_service.h"
62
63/******************************************************************************/
64/************************** CONSTANTS ******************************/
65/******************************************************************************/
66
67/**
68 * Minimum value for channel IDs of local clients.
69 */
70#define GNUNET_CADET_LOCAL_CHANNEL_ID_CLI 0x80000000U
71
72/**
73 * FIXME.
74 */
75#define HIGH_PID 0xFF000000
76
77/**
78 * FIXME.
79 */
80#define LOW_PID 0x00FFFFFF
81
82
83/**
84 * Test if the two PIDs (of type `uint32_t`) are in the range where we
85 * have to worry about overflows. This is the case when @a pid is
86 * large and @a max is small, useful when comparing @a pid smaller
87 * than @a max.
88 */
89#define PID_OVERFLOW(pid, max) (((pid) > HIGH_PID) && ((max) < LOW_PID))
90
91/******************************************************************************/
92/************************** MESSAGES ******************************/
93/******************************************************************************/
94
95GNUNET_NETWORK_STRUCT_BEGIN
96
97/**
98 * Number uniquely identifying a channel of a client.
99 */
100struct GNUNET_CADET_ClientChannelNumber
101{
102 /**
103 * Values for channel numbering.
104 * Local channel numbers given by the service (incoming) are
105 * smaller than #GNUNET_CADET_LOCAL_CHANNEL_ID_CLI.
106 * Local channel numbers given by the client (created) are
107 * larger than #GNUNET_CADET_LOCAL_CHANNEL_ID_CLI.
108 */
109 uint32_t channel_of_client GNUNET_PACKED;
110};
111
112/**
113 * Opaque handle to a channel.
114 */
115struct GNUNET_CADET_Channel
116{
117
118 /**
119 * Other end of the channel.
120 */
121 struct GNUNET_PeerIdentity peer;
122
123 /**
124 * Handle to the cadet this channel belongs to
125 */
126 struct GNUNET_CADET_Handle *cadet;
127
128 /**
129 * Channel's port, if incoming.
130 */
131 struct GNUNET_CADET_Port *incoming_port;
132
133 /**
134 * Any data the caller wants to put in here, used for the
135 * various callbacks (@e disconnects, @e window_changes, handlers).
136 */
137 void *ctx;
138
139 /**
140 * Message Queue for the channel (which we are implementing).
141 */
142 struct GNUNET_MQ_Handle *mq;
143
144 /**
145 * Task to allow mq to send more traffic.
146 */
147 struct GNUNET_SCHEDULER_Task *mq_cont;
148
149 /**
150 * Pending envelope with a message to be transmitted to the
151 * service as soon as we are allowed to. Should only be
152 * non-NULL if @e allow_send is 0.
153 */
154 struct GNUNET_MQ_Envelope *pending_env;
155
156 /**
157 * Window change handler.
158 */
159 GNUNET_CADET_WindowSizeEventHandler window_changes;
160
161 /**
162 * Disconnect handler.
163 */
164 GNUNET_CADET_DisconnectEventHandler disconnects;
165
166 /**
167 * Local ID of the channel, #GNUNET_CADET_LOCAL_CHANNEL_ID_CLI bit is set if outbound.
168 */
169 struct GNUNET_CADET_ClientChannelNumber ccn;
170
171 /**
172 * How many messages are we allowed to send to the service right now?
173 */
174 unsigned int allow_send;
175};
176
177/**
178 * Message for a client to create and destroy channels.
179 */
180struct GNUNET_CADET_PortMessage
181{
182 /**
183 * Type: #GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN
184 * or #GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE
185 *
186 * Size: sizeof(struct GNUNET_CADET_ChannelMessage)
187 */
188 struct GNUNET_MessageHeader header;
189
190 /**
191 * Port to open/close.
192 */
193 struct GNUNET_HashCode port GNUNET_PACKED;
194};
195
196
197/**
198 * Message for a client to create channels.
199 */
200struct GNUNET_CADET_LocalChannelCreateMessage
201{
202 /**
203 * Type: #GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE
204 *
205 * Size: sizeof(struct GNUNET_CADET_ChannelOpenMessageMessage)
206 */
207 struct GNUNET_MessageHeader header;
208
209 /**
210 * ID of a channel controlled by this client.
211 */
212 struct GNUNET_CADET_ClientChannelNumber ccn;
213
214 /**
215 * Channel's peer
216 */
217 struct GNUNET_PeerIdentity peer;
218
219 /**
220 * Port of the channel.
221 */
222 struct GNUNET_HashCode port;
223
224 /**
225 * Options.
226 */
227 uint32_t opt GNUNET_PACKED;
228};
229
230
231/**
232 * Message for or to a client to destroy tunnel.
233 */
234struct GNUNET_CADET_LocalChannelDestroyMessage
235{
236 /**
237 * Type: #GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY
238 */
239 struct GNUNET_MessageHeader header;
240
241 /**
242 * ID of a channel controlled by this client.
243 */
244 struct GNUNET_CADET_ClientChannelNumber ccn;
245};
246
247
248/**
249 * Message for cadet data traffic.
250 */
251struct GNUNET_CADET_LocalData
252{
253 /**
254 * Type: #GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA
255 */
256 struct GNUNET_MessageHeader header;
257
258 /**
259 * ID of the channel
260 */
261 struct GNUNET_CADET_ClientChannelNumber ccn;
262
263 /**
264 * Priority and preferences (an enum GNUNET_MQ_PriorityPreferences)
265 * of the message in NBO.
266 */
267 uint32_t pp GNUNET_PACKED;
268
269 /**
270 * Payload follows
271 */
272};
273
274
275/**
276 * Message to allow the client send more data to the service
277 * (always service -> client).
278 */
279struct GNUNET_CADET_LocalAck
280{
281 /**
282 * Type: #GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK
283 */
284 struct GNUNET_MessageHeader header;
285
286 /**
287 * ID of the channel allowed to send more data.
288 */
289 struct GNUNET_CADET_ClientChannelNumber ccn;
290};
291
292
293/**
294 * Message to inform the client about channels in the service.
295 *
296 * TODO: split into two messages!
297 */
298struct GNUNET_CADET_LocalInfo
299{
300 /**
301 * Type: #GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL or
302 * #GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER
303 */
304 struct GNUNET_MessageHeader header;
305
306 /**
307 * ID of the channel allowed to send more data.
308 */
309 struct GNUNET_CADET_ClientChannelNumber ccn;
310
311 /**
312 * ID of the destination of the channel (can be local peer).
313 */
314 struct GNUNET_PeerIdentity peer;
315};
316
317/**
318 * Message to drop another message of specific type. Used in test context
319 */
320struct GNUNET_CADET_RequestDropCadetMessage
321{
322
323 /**
324 * Type: #GNUNET_MESSAGE_TYPE_CADET_DROP_CADET_MESSAGE
325 */
326 struct GNUNET_MessageHeader header;
327
328 /**
329 * Type of the message this handler covers, in host byte order.
330 */
331 uint16_t type;
332
333 /**
334 * ID of the channel we want to drop a message for.
335 */
336 struct GNUNET_CADET_ClientChannelNumber ccn;
337
338};
339
340/**
341 * Message to inform the client about channels in the service.
342 */
343struct GNUNET_CADET_RequestPathInfoMessage
344{
345 /**
346 * Type: #GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_PATH
347 */
348 struct GNUNET_MessageHeader header;
349
350 /**
351 * Always zero.
352 */
353 uint32_t resered GNUNET_PACKED;
354
355 /**
356 * ID of the destination of the channel (can be local peer).
357 */
358 struct GNUNET_PeerIdentity peer;
359};
360
361
362/**
363 * Message to inform the client about channels in the service.
364 */
365struct GNUNET_CADET_ChannelInfoMessage
366{
367 /**
368 * Type: #GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNEL.
369 */
370 struct GNUNET_MessageHeader header;
371
372 /**
373 * Root of the channel
374 */
375 struct GNUNET_PeerIdentity root;
376
377 /**
378 * Destination of the channel
379 */
380 struct GNUNET_PeerIdentity dest;
381
382 /* FIXME: expand! */
383};
384
385
386/**
387 * Message to as the service about information on a channel.
388 */
389struct GNUNET_CADET_RequestChannelInfoMessage
390{
391 /**
392 * Type: #GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_CHANNEL.
393 */
394 struct GNUNET_MessageHeader header;
395
396 /**
397 * Target of the channel.
398 */
399 struct GNUNET_PeerIdentity target;
400};
401
402
403/**
404 * Message to inform the client about one of the paths known to the service.
405 */
406struct GNUNET_CADET_LocalInfoPath
407{
408 /**
409 * Type: #GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PATH.
410 */
411 struct GNUNET_MessageHeader header;
412
413 /**
414 * Offset of the peer that was requested.
415 */
416 uint32_t off GNUNET_PACKED;
417};
418
419
420/**
421 * Message to inform the client about one of the peers in the service.
422 */
423struct GNUNET_CADET_LocalInfoPeers
424{
425 /**
426 * Type: #GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS
427 */
428 struct GNUNET_MessageHeader header;
429
430 /**
431 * Number of paths.
432 */
433 uint16_t paths GNUNET_PACKED;
434
435 /**
436 * Do we have a tunnel toward this peer?
437 */
438 int16_t tunnel GNUNET_PACKED;
439
440 /**
441 * Shortest known path.
442 */
443 uint32_t best_path_length GNUNET_PACKED;
444
445 /**
446 * ID of the peer (can be local peer).
447 */
448 struct GNUNET_PeerIdentity destination;
449};
450
451
452/**
453 * Message to inform the client about one of the tunnels in the service.
454 *
455 * TODO: split into two messages!
456 */
457struct GNUNET_CADET_LocalInfoTunnel
458{
459 /**
460 * Type: #GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL
461 * or #GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS
462 */
463 struct GNUNET_MessageHeader header;
464
465 /**
466 * Number of channels.
467 */
468 uint32_t channels GNUNET_PACKED;
469
470 /**
471 * ID of the destination of the tunnel (can be local peer).
472 */
473 struct GNUNET_PeerIdentity destination;
474
475 /**
476 * Number of connections.
477 */
478 uint32_t connections GNUNET_PACKED;
479
480 /**
481 * Encryption state.
482 */
483 uint16_t estate GNUNET_PACKED;
484
485 /**
486 * Connection state.
487 */
488 uint16_t cstate GNUNET_PACKED;
489
490 /* If TUNNEL (no 'S'): struct GNUNET_CADET_ConnectionTunnelIdentifier connection_ids[connections] */
491 /* If TUNNEL (no 'S'): uint32_t channel_ids[channels] */
492};
493
494
495GNUNET_NETWORK_STRUCT_END
496
497
498/**
499 * @brief Translate a fwd variable into a string representation, for logging.
500 *
501 * @param fwd Is FWD? (#GNUNET_YES or #GNUNET_NO)
502 *
503 * @return String representing FWD or BCK.
504 */
505char *
506GC_f2s (int fwd);
507
508
509/**
510 * Check if one pid is bigger than other, accounting for overflow.
511 *
512 * @param bigger Argument that should be bigger.
513 * @param smaller Argument that should be smaller.
514 *
515 * @return True if bigger (arg1) has a higher value than smaller (arg 2).
516 */
517int
518GC_is_pid_bigger (uint32_t bigger, uint32_t smaller);
519
520
521/**
522 * Get the higher ACK value out of two values, taking in account overflow.
523 *
524 * @param a First ACK value.
525 * @param b Second ACK value.
526 *
527 * @return Highest ACK value from the two.
528 */
529uint32_t
530GC_max_pid (uint32_t a, uint32_t b);
531
532
533/**
534 * Get the lower ACK value out of two values, taking in account overflow.
535 *
536 * @param a First ACK value.
537 * @param b Second ACK value.
538 *
539 * @return Lowest ACK value from the two.
540 */
541uint32_t
542GC_min_pid (uint32_t a, uint32_t b);
543
544
545/**
546 * Allocate a string with a hexdump of any binary data.
547 *
548 * @param bin Arbitrary binary data.
549 * @param len Length of @a bin in bytes.
550 * @param output Where to write the output (if *output be NULL it's allocated).
551 *
552 * @return The size of the output.
553 */
554size_t
555GC_bin2s (void *bin, unsigned int len, char **output);
556
557
558/**
559 * Convert a message type into a string to help debug
560 * Generated with:
561 * FIND: "#define ([^ ]+)[ ]*([0-9]+)"
562 * REPLACE: " case \2: return "\1"; break;"
563 *
564 * @param m Message type.
565 *
566 * @return Human readable string description.
567 */
568const char *
569GC_m2s (uint16_t m);
570
571#if 0 /* keep Emacsens' auto-indent happy */
572{
573#endif
574#ifdef __cplusplus
575}
576#endif
577
578#endif
diff --git a/src/service/cadet/cadet_api.c b/src/service/cadet/cadet_api.c
new file mode 100644
index 000000000..0bfb01868
--- /dev/null
+++ b/src/service/cadet/cadet_api.c
@@ -0,0 +1,1072 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011, 2017 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file cadet/cadet_api.c
22 * @brief cadet api: client implementation of cadet service
23 * @author Bartlomiej Polot
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_constants.h"
29#include "gnunet_cadet_service.h"
30#include "cadet.h"
31#include "cadet_protocol.h"
32
33#define LOG(kind, ...) GNUNET_log_from (kind, "cadet-api", __VA_ARGS__)
34
35/**
36 * Opaque handle to the service.
37 */
38struct GNUNET_CADET_Handle
39{
40 /**
41 * Message queue.
42 */
43 struct GNUNET_MQ_Handle *mq;
44
45 /**
46 * Ports open.
47 */
48 struct GNUNET_CONTAINER_MultiHashMap *ports;
49
50 /**
51 * Channels open.
52 */
53 struct GNUNET_CONTAINER_MultiHashMap32 *channels;
54
55 /**
56 * child of the next channel to create (to avoid reusing IDs often)
57 */
58 struct GNUNET_CADET_ClientChannelNumber next_ccn;
59
60 /**
61 * Configuration given by the client, in case of reconnection
62 */
63 const struct GNUNET_CONFIGURATION_Handle *cfg;
64
65 /**
66 * Task for trying to reconnect.
67 */
68 struct GNUNET_SCHEDULER_Task *reconnect_task;
69
70 /**
71 * Time to the next reconnect in case one reconnect fails
72 */
73 struct GNUNET_TIME_Relative reconnect_time;
74};
75
76/**
77 * Opaque handle to a port.
78 */
79struct GNUNET_CADET_Port
80{
81 /**
82 * Port "number"
83 */
84 struct GNUNET_HashCode id;
85
86 /**
87 * Handle to the CADET session this port belongs to.
88 */
89 struct GNUNET_CADET_Handle *cadet;
90
91 /**
92 * Closure for @a handler.
93 */
94 void *cls;
95
96 /**
97 * Handler for incoming channels on this port
98 */
99 GNUNET_CADET_ConnectEventHandler connects;
100
101 /**
102 * Closure for @ref connects
103 */
104 void *connects_cls;
105
106 /**
107 * Window size change handler.
108 */
109 GNUNET_CADET_WindowSizeEventHandler window_changes;
110
111 /**
112 * Handler called when an incoming channel is destroyed.
113 */
114 GNUNET_CADET_DisconnectEventHandler disconnects;
115
116 /**
117 * Payload handlers for incoming channels.
118 */
119 struct GNUNET_MQ_MessageHandler *handlers;
120};
121
122
123/**
124 * Find the Port struct for a hash.
125 *
126 * @param h CADET handle.
127 * @param hash HashCode for the port number.
128 * @return The port handle if known, NULL otherwise.
129 */
130static struct GNUNET_CADET_Port *
131find_port (const struct GNUNET_CADET_Handle *h,
132 const struct GNUNET_HashCode *hash)
133{
134 return GNUNET_CONTAINER_multihashmap_get (h->ports, hash);
135}
136
137
138/**
139 * Get the channel handler for the channel specified by id from the given handle
140 *
141 * @param h Cadet handle
142 * @param ccn ID of the wanted channel
143 * @return handle to the required channel or NULL if not found
144 */
145static struct GNUNET_CADET_Channel *
146find_channel (struct GNUNET_CADET_Handle *h,
147 struct GNUNET_CADET_ClientChannelNumber ccn)
148{
149 return GNUNET_CONTAINER_multihashmap32_get (h->channels,
150 ntohl (ccn.channel_of_client));
151}
152
153
154/**
155 * Create a new channel and insert it in the channel list of the cadet handle
156 *
157 * @param h Cadet handle
158 * @param ccnp pointer to desired ccn of the channel, NULL to assign one automatically.
159 * @return Handle to the created channel.
160 */
161static struct GNUNET_CADET_Channel *
162create_channel (struct GNUNET_CADET_Handle *h,
163 const struct GNUNET_CADET_ClientChannelNumber *ccnp)
164{
165 struct GNUNET_CADET_Channel *ch;
166 struct GNUNET_CADET_ClientChannelNumber ccn;
167
168 ch = GNUNET_new (struct GNUNET_CADET_Channel);
169 ch->cadet = h;
170 if (NULL == ccnp)
171 {
172 while (NULL != find_channel (h, h->next_ccn))
173 h->next_ccn.channel_of_client =
174 htonl (GNUNET_CADET_LOCAL_CHANNEL_ID_CLI
175 | (1 + ntohl (h->next_ccn.channel_of_client)));
176 ccn = h->next_ccn;
177 }
178 else
179 {
180 ccn = *ccnp;
181 }
182 ch->ccn = ccn;
183 GNUNET_assert (GNUNET_OK ==
184 GNUNET_CONTAINER_multihashmap32_put (
185 h->channels,
186 ntohl (ch->ccn.channel_of_client),
187 ch,
188 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
189 return ch;
190}
191
192
193/**
194 * Destroy the specified channel.
195 * - Destroys all peers, calling the disconnect callback on each if needed
196 * - Cancels all outgoing traffic for that channel, calling respective notifys
197 * - Calls cleaner if channel was inbound
198 * - Frees all memory used
199 *
200 * @param ch Pointer to the channel.
201 */
202static void
203destroy_channel (struct GNUNET_CADET_Channel *ch)
204{
205 struct GNUNET_CADET_Handle *h = ch->cadet;
206
207 LOG (GNUNET_ERROR_TYPE_DEBUG,
208 "Destroying channel %X of %p\n",
209 htonl (ch->ccn.channel_of_client),
210 h);
211 GNUNET_assert (
212 GNUNET_YES ==
213 GNUNET_CONTAINER_multihashmap32_remove (h->channels,
214 ntohl (ch->ccn.channel_of_client),
215 ch));
216 if (NULL != ch->mq_cont)
217 {
218 GNUNET_SCHEDULER_cancel (ch->mq_cont);
219 ch->mq_cont = NULL;
220 }
221 /* signal channel destruction */
222 if (NULL != ch->disconnects)
223 ch->disconnects (ch->ctx, ch);
224 if (NULL != ch->pending_env)
225 GNUNET_MQ_discard (ch->pending_env);
226 GNUNET_MQ_destroy (ch->mq);
227 GNUNET_free (ch);
228}
229
230
231/**
232 * Reconnect to the service, retransmit all information to try to restore the
233 * original state.
234 *
235 * @param h handle to the cadet
236 */
237static void
238reconnect (struct GNUNET_CADET_Handle *h);
239
240
241/**
242 * Function called during #reconnect_cbk() to (re)open
243 * all ports that are still open.
244 *
245 * @param cls the `struct GNUNET_CADET_Handle`
246 * @param id port ID
247 * @param value a `struct GNUNET_CADET_Channel` to open
248 * @return #GNUNET_OK (continue to iterate)
249 */
250static int
251open_port_cb (void *cls, const struct GNUNET_HashCode *id, void *value)
252{
253 struct GNUNET_CADET_Handle *h = cls;
254 struct GNUNET_CADET_Port *port = value;
255 struct GNUNET_CADET_PortMessage *msg;
256 struct GNUNET_MQ_Envelope *env;
257
258 (void) id;
259 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN);
260 msg->port = port->id;
261 GNUNET_MQ_send (h->mq, env);
262 return GNUNET_OK;
263}
264
265
266/**
267 * Reconnect callback: tries to reconnect again after a failed previous
268 * connection
269 *
270 * @param cls closure (cadet handle)
271 */
272static void
273reconnect_cbk (void *cls)
274{
275 struct GNUNET_CADET_Handle *h = cls;
276
277 h->reconnect_task = NULL;
278 h->reconnect_time = GNUNET_TIME_STD_BACKOFF (h->reconnect_time);
279 reconnect (h);
280 GNUNET_CONTAINER_multihashmap_iterate (h->ports, &open_port_cb, h);
281}
282
283
284/**
285 * Notify the application about a change in the window size (if needed).
286 *
287 * @param ch Channel to notify about.
288 */
289static void
290notify_window_size (struct GNUNET_CADET_Channel *ch)
291{
292 if (NULL != ch->window_changes)
293 ch->window_changes (ch->ctx,
294 ch, /* FIXME: remove 'ch'? */
295 ch->allow_send);
296}
297
298
299/**
300 * Transmit the next message from our queue.
301 *
302 * @param cls Closure (channel whose mq to activate).
303 */
304static void
305cadet_mq_send_now (void *cls)
306{
307 struct GNUNET_CADET_Channel *ch = cls;
308 struct GNUNET_MQ_Envelope *env = ch->pending_env;
309
310 ch->mq_cont = NULL;
311 if (0 == ch->allow_send)
312 {
313 /* how did we get here? */
314 GNUNET_break (0);
315 return;
316 }
317 if (NULL == env)
318 {
319 /* how did we get here? */
320 GNUNET_break (0);
321 return;
322 }
323 ch->allow_send--;
324 ch->pending_env = NULL;
325 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
326 "Sending message on channel %s to CADET, new window size is %u\n",
327 GNUNET_i2s (&ch->peer),
328 ch->allow_send);
329 GNUNET_MQ_send (ch->cadet->mq, env);
330 GNUNET_MQ_impl_send_continue (ch->mq);
331}
332
333
334/**
335 * Implement sending functionality of a message queue for
336 * us sending messages to a peer.
337 *
338 * Encapsulates the payload message in a #GNUNET_CADET_LocalData message
339 * in order to label the message with the channel ID and send the
340 * encapsulated message to the service.
341 *
342 * @param mq the message queue
343 * @param msg the message to send
344 * @param impl_state state of the implementation
345 */
346static void
347cadet_mq_send_impl (struct GNUNET_MQ_Handle *mq,
348 const struct GNUNET_MessageHeader *msg,
349 void *impl_state)
350{
351 struct GNUNET_CADET_Channel *ch = impl_state;
352 struct GNUNET_CADET_Handle *h = ch->cadet;
353 uint16_t msize;
354 struct GNUNET_MQ_Envelope *orig_env;
355 struct GNUNET_MQ_Envelope *env;
356 struct GNUNET_CADET_LocalData *cadet_msg;
357 enum GNUNET_MQ_PriorityPreferences pp;
358
359 if (NULL == h->mq)
360 {
361 /* We're currently reconnecting, pretend this worked */
362 GNUNET_MQ_impl_send_continue (mq);
363 return;
364 }
365 orig_env = GNUNET_MQ_get_current_envelope (mq);
366 pp = GNUNET_MQ_env_get_options (orig_env);
367
368 /* check message size for sanity */
369 msize = ntohs (msg->size);
370 if (msize > GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE)
371 {
372 GNUNET_break (0);
373 GNUNET_MQ_impl_send_continue (mq);
374 return;
375 }
376 env = GNUNET_MQ_msg_nested_mh (cadet_msg,
377 GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA,
378 msg);
379 cadet_msg->ccn = ch->ccn;
380 cadet_msg->pp = htonl ((uint32_t) pp);
381 GNUNET_assert (NULL == ch->pending_env);
382 ch->pending_env = env;
383 if (0 < ch->allow_send)
384 ch->mq_cont = GNUNET_SCHEDULER_add_now (&cadet_mq_send_now, ch);
385}
386
387
388/**
389 * Handle destruction of a message queue. Implementations must not
390 * free @a mq, but should take care of @a impl_state.
391 *
392 * @param mq the message queue to destroy
393 * @param impl_state state of the implementation
394 */
395static void
396cadet_mq_destroy_impl (struct GNUNET_MQ_Handle *mq, void *impl_state)
397{
398 struct GNUNET_CADET_Channel *ch = impl_state;
399
400 GNUNET_assert (mq == ch->mq);
401 ch->mq = NULL;
402}
403
404
405/**
406 * We had an error processing a message we forwarded from a peer to
407 * the CADET service. We should just complain about it but otherwise
408 * continue processing.
409 *
410 * @param cls closure with our `struct GNUNET_CADET_Channel`
411 * @param error error code
412 */
413static void
414cadet_mq_error_handler (void *cls, enum GNUNET_MQ_Error error)
415{
416 struct GNUNET_CADET_Channel *ch = cls;
417
418 if (GNUNET_MQ_ERROR_NO_MATCH == error)
419 {
420 /* Got a message we did not understand, still try to continue! */
421 GNUNET_break_op (0);
422 GNUNET_CADET_receive_done (ch);
423 }
424 else
425 {
426 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
427 "MQ error in communication with CADET: %d\n",
428 error);
429 if (NULL != ch->disconnects)
430 ch->disconnects (ch->ctx, ch);
431 GNUNET_CADET_channel_destroy (ch);
432 }
433}
434
435
436/**
437 * Implementation function that cancels the currently sent message.
438 * Should basically undo whatever #mq_send_impl() did.
439 *
440 * @param mq message queue
441 * @param impl_state state specific to the implementation
442 */
443static void
444cadet_mq_cancel_impl (struct GNUNET_MQ_Handle *mq, void *impl_state)
445{
446 struct GNUNET_CADET_Channel *ch = impl_state;
447
448 (void) mq;
449 GNUNET_assert (NULL != ch->pending_env);
450 GNUNET_MQ_discard (ch->pending_env);
451 ch->pending_env = NULL;
452 if (NULL != ch->mq_cont)
453 {
454 GNUNET_SCHEDULER_cancel (ch->mq_cont);
455 ch->mq_cont = NULL;
456 }
457}
458
459
460/**
461 * Process the new channel notification and add it to the channels in the handle
462 *
463 * @param cls The cadet handle
464 * @param msg A message with the details of the new incoming channel
465 */
466static void
467handle_channel_created (
468 void *cls,
469 const struct GNUNET_CADET_LocalChannelCreateMessage *msg)
470{
471 struct GNUNET_CADET_Handle *h = cls;
472 struct GNUNET_CADET_Channel *ch;
473 struct GNUNET_CADET_Port *port;
474 const struct GNUNET_HashCode *port_number;
475 struct GNUNET_CADET_ClientChannelNumber ccn;
476
477 ccn = msg->ccn;
478 port_number = &msg->port;
479 if (ntohl (ccn.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
480 {
481 GNUNET_break (0);
482 return;
483 }
484 port = find_port (h, port_number);
485 if (NULL == port)
486 {
487 /* We could have closed the port but the service didn't know about it yet
488 * This is not an error.
489 */
490 struct GNUNET_CADET_LocalChannelDestroyMessage *d_msg;
491 struct GNUNET_MQ_Envelope *env;
492
493 LOG (GNUNET_ERROR_TYPE_DEBUG,
494 "No handler for incoming channel %X (on port %s, recently closed?)\n",
495 ntohl (ccn.channel_of_client),
496 GNUNET_h2s (port_number));
497 env =
498 GNUNET_MQ_msg (d_msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY);
499 d_msg->ccn = msg->ccn;
500 GNUNET_MQ_send (h->mq, env);
501 return;
502 }
503
504 ch = create_channel (h, &ccn);
505 ch->peer = msg->peer;
506 ch->incoming_port = port;
507 LOG (GNUNET_ERROR_TYPE_DEBUG,
508 "Creating incoming channel %X [%s] %p\n",
509 ntohl (ccn.channel_of_client),
510 GNUNET_h2s (port_number),
511 ch);
512
513 GNUNET_assert (NULL != port->connects);
514 ch->window_changes = port->window_changes;
515 ch->disconnects = port->disconnects;
516 ch->mq = GNUNET_MQ_queue_for_callbacks (&cadet_mq_send_impl,
517 &cadet_mq_destroy_impl,
518 &cadet_mq_cancel_impl,
519 ch,
520 port->handlers,
521 &cadet_mq_error_handler,
522 ch);
523 ch->ctx = port->connects (port->cls, ch, &msg->peer);
524 GNUNET_MQ_set_handlers_closure (ch->mq, ch->ctx);
525}
526
527
528/**
529 * Process the channel destroy notification and free associated resources
530 *
531 * @param cls The cadet handle
532 * @param msg A message with the details of the channel being destroyed
533 */
534static void
535handle_channel_destroy (
536 void *cls,
537 const struct GNUNET_CADET_LocalChannelDestroyMessage *msg)
538{
539 struct GNUNET_CADET_Handle *h = cls;
540 struct GNUNET_CADET_Channel *ch;
541
542 ch = find_channel (h, msg->ccn);
543 if (NULL == ch)
544 {
545 LOG (GNUNET_ERROR_TYPE_DEBUG,
546 "Received channel destroy for unknown channel %X from CADET service (recently close?)\n",
547 ntohl (msg->ccn.channel_of_client));
548 return;
549 }
550 LOG (GNUNET_ERROR_TYPE_DEBUG,
551 "Received channel destroy for channel %X from CADET service\n",
552 ntohl (msg->ccn.channel_of_client));
553 destroy_channel (ch);
554}
555
556
557/**
558 * Check that message received from CADET service is well-formed.
559 *
560 * @param cls the `struct GNUNET_CADET_Handle`
561 * @param message the message we got
562 * @return #GNUNET_OK if the message is well-formed,
563 * #GNUNET_SYSERR otherwise
564 */
565static int
566check_local_data (void *cls, const struct GNUNET_CADET_LocalData *message)
567{
568 uint16_t size;
569
570 (void) cls;
571 size = ntohs (message->header.size);
572 if (sizeof(*message) + sizeof(struct GNUNET_MessageHeader) > size)
573 {
574 GNUNET_break (0);
575 return GNUNET_SYSERR;
576 }
577 return GNUNET_OK;
578}
579
580
581/**
582 * Process the incoming data packets, call appropriate handlers.
583 *
584 * @param cls The cadet handle
585 * @param message A message encapsulating the data
586 */
587static void
588handle_local_data (void *cls, const struct GNUNET_CADET_LocalData *message)
589{
590 struct GNUNET_CADET_Handle *h = cls;
591 const struct GNUNET_MessageHeader *payload;
592 struct GNUNET_CADET_Channel *ch;
593 uint16_t type;
594 int fwd;
595
596 ch = find_channel (h, message->ccn);
597 if (NULL == ch)
598 {
599 LOG (GNUNET_ERROR_TYPE_DEBUG,
600 "Unknown channel %X for incoming data (recently closed?)\n",
601 ntohl (message->ccn.channel_of_client));
602 return;
603 }
604
605 payload = (const struct GNUNET_MessageHeader *) &message[1];
606 type = ntohs (payload->type);
607 fwd = ntohl (ch->ccn.channel_of_client) <= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI;
608 LOG (GNUNET_ERROR_TYPE_DEBUG,
609 "Got a %s data on channel %s [%X] of type %u\n",
610 fwd ? "FWD" : "BWD",
611 GNUNET_i2s (&ch->peer),
612 ntohl (message->ccn.channel_of_client),
613 type);
614 GNUNET_MQ_inject_message (ch->mq, payload);
615}
616
617
618/**
619 * Process a local ACK message, enabling the client to send
620 * more data to the service.
621 *
622 * @param cls Cadet handle.
623 * @param message Message itself.
624 */
625static void
626handle_local_ack (void *cls, const struct GNUNET_CADET_LocalAck *message)
627{
628 struct GNUNET_CADET_Handle *h = cls;
629 struct GNUNET_CADET_Channel *ch;
630
631 ch = find_channel (h, message->ccn);
632 if (NULL == ch)
633 {
634 LOG (GNUNET_ERROR_TYPE_DEBUG,
635 "ACK on unknown channel %X\n",
636 ntohl (message->ccn.channel_of_client));
637 return;
638 }
639 ch->allow_send++;
640 LOG (GNUNET_ERROR_TYPE_DEBUG,
641 "Got an ACK on mq channel %X (peer %s); new window size is %u!\n",
642 ntohl (ch->ccn.channel_of_client),
643 GNUNET_i2s (&ch->peer),
644 ch->allow_send);
645 if (NULL == ch->pending_env)
646 {
647 LOG (GNUNET_ERROR_TYPE_DEBUG,
648 "Got an ACK on mq channel %X, allow send now %u!\n",
649 ntohl (ch->ccn.channel_of_client),
650 ch->allow_send);
651 notify_window_size (ch);
652 return;
653 }
654 if (NULL != ch->mq_cont)
655 return; /* already working on it! */
656 ch->mq_cont = GNUNET_SCHEDULER_add_now (&cadet_mq_send_now, ch);
657}
658
659
660/**
661 * Function called during #GNUNET_CADET_disconnect() to destroy
662 * all channels that are still open.
663 *
664 * @param cls the `struct GNUNET_CADET_Handle`
665 * @param cid chanenl ID
666 * @param value a `struct GNUNET_CADET_Channel` to destroy
667 * @return #GNUNET_OK (continue to iterate)
668 */
669static int
670destroy_channel_cb (void *cls, uint32_t cid, void *value)
671{
672 /* struct GNUNET_CADET_Handle *handle = cls; */
673 struct GNUNET_CADET_Channel *ch = value;
674
675 (void) cls;
676 (void) cid;
677 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
678 "Destroying channel due to GNUNET_CADET_disconnect()\n");
679 destroy_channel (ch);
680 return GNUNET_OK;
681}
682
683
684/**
685 * Generic error handler, called with the appropriate error code and
686 * the same closure specified at the creation of the message queue.
687 * Not every message queue implementation supports an error handler.
688 *
689 * @param cls closure, a `struct GNUNET_CORE_Handle *`
690 * @param error error code
691 */
692static void
693handle_mq_error (void *cls, enum GNUNET_MQ_Error error)
694{
695 struct GNUNET_CADET_Handle *h = cls;
696
697 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MQ ERROR: %u\n", error);
698 GNUNET_CONTAINER_multihashmap32_iterate (h->channels, &destroy_channel_cb, h);
699 GNUNET_MQ_destroy (h->mq);
700 h->mq = NULL;
701 GNUNET_assert (NULL == h->reconnect_task);
702 h->reconnect_task =
703 GNUNET_SCHEDULER_add_delayed (h->reconnect_time, &reconnect_cbk, h);
704}
705
706
707/**
708 * Reconnect to the service, retransmit all information to try to restore the
709 * original state.
710 *
711 * @param h handle to the cadet
712 */
713static void
714reconnect (struct GNUNET_CADET_Handle *h)
715{
716 struct GNUNET_MQ_MessageHandler handlers[] =
717 { GNUNET_MQ_hd_fixed_size (channel_created,
718 GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE,
719 struct GNUNET_CADET_LocalChannelCreateMessage,
720 h),
721 GNUNET_MQ_hd_fixed_size (channel_destroy,
722 GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY,
723 struct GNUNET_CADET_LocalChannelDestroyMessage,
724 h),
725 GNUNET_MQ_hd_var_size (local_data,
726 GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA,
727 struct GNUNET_CADET_LocalData,
728 h),
729 GNUNET_MQ_hd_fixed_size (local_ack,
730 GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK,
731 struct GNUNET_CADET_LocalAck,
732 h),
733 GNUNET_MQ_handler_end () };
734
735 GNUNET_assert (NULL == h->mq);
736 h->mq =
737 GNUNET_CLIENT_connect (h->cfg, "cadet", handlers, &handle_mq_error, h);
738}
739
740
741/**
742 * Function called during #GNUNET_CADET_disconnect() to destroy
743 * all ports that are still open.
744 *
745 * @param cls the `struct GNUNET_CADET_Handle`
746 * @param id port ID
747 * @param value a `struct GNUNET_CADET_Channel` to destroy
748 * @return #GNUNET_OK (continue to iterate)
749 */
750static int
751destroy_port_cb (void *cls, const struct GNUNET_HashCode *id, void *value)
752{
753 /* struct GNUNET_CADET_Handle *handle = cls; */
754 struct GNUNET_CADET_Port *port = value;
755
756 (void) cls;
757 (void) id;
758 /* This is a warning, the app should have cleanly closed all open ports */
759 GNUNET_break (0);
760 GNUNET_CADET_close_port (port);
761 return GNUNET_OK;
762}
763
764
765/**
766 * Disconnect from the cadet service. All channels will be destroyed. All channel
767 * disconnect callbacks will be called on any still connected peers, notifying
768 * about their disconnection. The registered inbound channel cleaner will be
769 * called should any inbound channels still exist.
770 *
771 * @param handle connection to cadet to disconnect
772 */
773void
774GNUNET_CADET_disconnect (struct GNUNET_CADET_Handle *handle)
775{
776 GNUNET_CONTAINER_multihashmap_iterate (handle->ports,
777 &destroy_port_cb,
778 handle);
779 GNUNET_CONTAINER_multihashmap_destroy (handle->ports);
780 handle->ports = NULL;
781 GNUNET_CONTAINER_multihashmap32_iterate (handle->channels,
782 &destroy_channel_cb,
783 handle);
784 GNUNET_CONTAINER_multihashmap32_destroy (handle->channels);
785 handle->channels = NULL;
786 if (NULL != handle->mq)
787 {
788 GNUNET_MQ_destroy (handle->mq);
789 handle->mq = NULL;
790 }
791 if (NULL != handle->reconnect_task)
792 {
793 GNUNET_SCHEDULER_cancel (handle->reconnect_task);
794 handle->reconnect_task = NULL;
795 }
796 GNUNET_free (handle);
797}
798
799
800void
801GNUNET_CADET_close_port (struct GNUNET_CADET_Port *p)
802{
803 GNUNET_assert (
804 GNUNET_YES ==
805 GNUNET_CONTAINER_multihashmap_remove (p->cadet->ports, &p->id, p));
806 if (NULL != p->cadet->mq)
807 {
808 struct GNUNET_CADET_PortMessage *msg;
809 struct GNUNET_MQ_Envelope *env;
810
811 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE);
812 msg->port = p->id;
813 GNUNET_MQ_send (p->cadet->mq, env);
814 }
815 GNUNET_free (p->handlers);
816 GNUNET_free (p);
817}
818
819
820/**
821 * Destroy an existing channel.
822 *
823 * The existing end callback for the channel will NOT be called.
824 * Any pending outgoing messages will be sent but no incoming messages will be
825 * accepted and no data callbacks will be called.
826 *
827 * @param channel Channel handle, becomes invalid after this call.
828 */
829void
830GNUNET_CADET_channel_destroy (struct GNUNET_CADET_Channel *channel)
831{
832 struct GNUNET_CADET_Handle *h = channel->cadet;
833 struct GNUNET_CADET_LocalChannelDestroyMessage *msg;
834 struct GNUNET_MQ_Envelope *env;
835
836 if (NULL != h->mq)
837 {
838 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY);
839 msg->ccn = channel->ccn;
840 GNUNET_MQ_send (h->mq, env);
841 }
842 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
843 "Destroying channel due to GNUNET_CADET_channel_destroy()\n");
844 channel->disconnects = NULL;
845 destroy_channel (channel);
846}
847
848
849const union GNUNET_CADET_ChannelInfo *
850GNUNET_CADET_channel_get_info (struct GNUNET_CADET_Channel *channel,
851 enum GNUNET_CADET_ChannelInfoOption option,
852 ...)
853{
854 switch (option)
855 {
856 case GNUNET_CADET_OPTION_PEER:
857 return (const union GNUNET_CADET_ChannelInfo *) &channel->peer;
858
859 default:
860 GNUNET_break (0);
861 return NULL;
862 }
863}
864
865
866/**
867 * Send an ack on the channel to confirm the processing of a message.
868 *
869 * @param ch Channel on which to send the ACK.
870 */
871void
872GNUNET_CADET_receive_done (struct GNUNET_CADET_Channel *channel)
873{
874 struct GNUNET_CADET_LocalAck *msg;
875 struct GNUNET_MQ_Envelope *env;
876
877 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK);
878 LOG (GNUNET_ERROR_TYPE_DEBUG,
879 "Sending ACK on channel %X\n",
880 ntohl (channel->ccn.channel_of_client));
881 msg->ccn = channel->ccn;
882 GNUNET_MQ_send (channel->cadet->mq, env);
883}
884
885
886/**
887 * Connect to the MQ-based cadet service.
888 *
889 * @param cfg Configuration to use.
890 *
891 * @return Handle to the cadet service NULL on error.
892 */
893struct GNUNET_CADET_Handle *
894GNUNET_CADET_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
895{
896 struct GNUNET_CADET_Handle *h;
897
898 LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_CADET_connect()\n");
899 h = GNUNET_new (struct GNUNET_CADET_Handle);
900 h->cfg = cfg;
901 h->ports = GNUNET_CONTAINER_multihashmap_create (4, GNUNET_YES);
902 h->channels = GNUNET_CONTAINER_multihashmap32_create (4);
903 reconnect (h);
904 if (NULL == h->mq)
905 {
906 GNUNET_break (0);
907 GNUNET_CADET_disconnect (h);
908 return NULL;
909 }
910 h->next_ccn.channel_of_client = htonl (GNUNET_CADET_LOCAL_CHANNEL_ID_CLI);
911 return h;
912}
913
914
915/**
916 * Function to return link to AGPL source upon request.
917 *
918 * @param cls closure with the identification of the client
919 * @param msg AGPL request
920 */
921static void
922return_agpl (void *cls, const struct GNUNET_MessageHeader *msg)
923{
924 struct GNUNET_SERVICE_Client *client = cls;
925 struct GNUNET_MQ_Handle *mq;
926 struct GNUNET_MQ_Envelope *env;
927 struct GNUNET_MessageHeader *res;
928 size_t slen;
929 const struct GNUNET_OS_ProjectData *pd = GNUNET_OS_project_data_get ();
930
931 (void) msg;
932 slen = strlen (pd->agpl_url) + 1;
933 env = GNUNET_MQ_msg_extra (res, GNUNET_MESSAGE_TYPE_RESPONSE_AGPL, slen);
934 memcpy (&res[1], GNUNET_AGPL_URL, slen);
935 mq = GNUNET_SERVICE_client_get_mq (client);
936 GNUNET_MQ_send (mq, env);
937 GNUNET_SERVICE_client_continue (client);
938}
939
940
941/**
942 * Open a port to receive incoming MQ-based channels.
943 *
944 * @param h CADET handle.
945 * @param port Hash identifying the port.
946 * @param connects Function called when an incoming channel is connected.
947 * @param connects_cls Closure for the @a connects handler.
948 * @param window_changes Function called when the transmit window size changes.
949 * @param disconnects Function called when a channel is disconnected.
950 * @param handlers Callbacks for messages we care about, NULL-terminated.
951 * @return Port handle, NULL if port is in use
952 */
953struct GNUNET_CADET_Port *
954GNUNET_CADET_open_port (struct GNUNET_CADET_Handle *h,
955 const struct GNUNET_HashCode *port,
956 GNUNET_CADET_ConnectEventHandler connects,
957 void *connects_cls,
958 GNUNET_CADET_WindowSizeEventHandler window_changes,
959 GNUNET_CADET_DisconnectEventHandler disconnects,
960 const struct GNUNET_MQ_MessageHandler *handlers)
961{
962 struct GNUNET_CADET_Port *p;
963 const struct GNUNET_OS_ProjectData *pd = GNUNET_OS_project_data_get ();
964
965 GNUNET_assert (NULL != connects);
966 GNUNET_assert (NULL != disconnects);
967 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
968 "Listening to CADET port %s\n",
969 GNUNET_h2s (port));
970
971 p = GNUNET_new (struct GNUNET_CADET_Port);
972 p->cadet = h;
973 p->id = *port;
974 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (
975 h->ports,
976 &p->id,
977 p,
978 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
979 {
980 GNUNET_free (p);
981 return NULL;
982 }
983 p->connects = connects;
984 p->cls = connects_cls;
985 p->window_changes = window_changes;
986 p->disconnects = disconnects;
987 p->handlers = (NULL == pd->agpl_url)
988 ? GNUNET_MQ_copy_handlers (handlers)
989 : GNUNET_MQ_copy_handlers2 (handlers, &return_agpl, NULL);
990
991 GNUNET_assert (GNUNET_OK == open_port_cb (h, &p->id, p));
992 return p;
993}
994
995
996/**
997 * Create a new channel towards a remote peer.
998 *
999 * If the destination peer closes the channel after accepting it,
1000 * @a disconnects will be called for this channel (unless
1001 * #GNUNET_CADET_channel_destroy() was called on this end first).
1002 *
1003 * @param h CADET handle.
1004 * @param channel_cls Closure for the channel. It's given to:
1005 * - The disconnect handler @a disconnects
1006 * - Each message type callback in @a handlers
1007 * @param destination Peer identity the channel should go to.
1008 * @param port Identification of the destination port.
1009 * @param window_changes Function called when the transmit window size changes.
1010 * @param disconnects Function called when the channel is disconnected.
1011 * @param handlers Callbacks for messages we care about, NULL-terminated.
1012 * @return Handle to the channel.
1013 */
1014struct GNUNET_CADET_Channel *
1015GNUNET_CADET_channel_create (struct GNUNET_CADET_Handle *h,
1016 void *channel_cls,
1017 const struct GNUNET_PeerIdentity *destination,
1018 const struct GNUNET_HashCode *port,
1019 GNUNET_CADET_WindowSizeEventHandler window_changes,
1020 GNUNET_CADET_DisconnectEventHandler disconnects,
1021 const struct GNUNET_MQ_MessageHandler *handlers)
1022{
1023 struct GNUNET_CADET_Channel *ch;
1024 struct GNUNET_CADET_LocalChannelCreateMessage *msg;
1025 struct GNUNET_MQ_Envelope *env;
1026
1027 GNUNET_assert (NULL != disconnects);
1028 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1029 "Creating channel to peer %s at port %s\n",
1030 GNUNET_i2s (destination),
1031 GNUNET_h2s (port));
1032 ch = create_channel (h, NULL);
1033 ch->ctx = channel_cls;
1034 ch->peer = *destination;
1035 ch->window_changes = window_changes;
1036 ch->disconnects = disconnects;
1037
1038 /* Create MQ for channel */
1039 ch->mq = GNUNET_MQ_queue_for_callbacks (&cadet_mq_send_impl,
1040 &cadet_mq_destroy_impl,
1041 &cadet_mq_cancel_impl,
1042 ch,
1043 handlers,
1044 &cadet_mq_error_handler,
1045 ch);
1046 GNUNET_MQ_set_handlers_closure (ch->mq, channel_cls);
1047
1048 /* Request channel creation to service */
1049 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE);
1050 msg->ccn = ch->ccn;
1051 msg->port = *port;
1052 msg->peer = *destination;
1053 GNUNET_MQ_send (h->mq, env);
1054 return ch;
1055}
1056
1057
1058/**
1059 * Obtain the message queue for a connected peer.
1060 *
1061 * @param channel The channel handle from which to get the MQ.
1062 *
1063 * @return NULL if @a channel is not yet connected.
1064 */
1065struct GNUNET_MQ_Handle *
1066GNUNET_CADET_get_mq (const struct GNUNET_CADET_Channel *channel)
1067{
1068 return channel->mq;
1069}
1070
1071
1072/* end of cadet_api.c */
diff --git a/src/service/cadet/cadet_api_drop_message.c b/src/service/cadet/cadet_api_drop_message.c
new file mode 100644
index 000000000..e172418c4
--- /dev/null
+++ b/src/service/cadet/cadet_api_drop_message.c
@@ -0,0 +1,59 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011, 2017, 2019 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19*/
20/**
21 * @file cadet/cadet_api_drop_message.c
22 * @brief cadet api: client implementation of cadet service
23 * @author t3sserakt
24 */
25#include "platform.h"
26#include "cadet.h"
27
28
29/**
30 * Drop the next cadet message of a given type.
31 *
32 * @param mq message queue
33 * @param ccn client channel number.
34 * @param type of cadet message to be dropped.
35 */
36void
37GNUNET_CADET_drop_message (struct GNUNET_MQ_Handle *mq,
38 struct GNUNET_CADET_ClientChannelNumber ccn,
39 uint16_t type)
40{
41 struct GNUNET_CADET_RequestDropCadetMessage *message;
42 struct GNUNET_MQ_Envelope *env;
43
44 env = GNUNET_MQ_msg (message, GNUNET_MESSAGE_TYPE_CADET_DROP_CADET_MESSAGE);
45
46 message->ccn = ccn;
47 message->type = type;
48
49 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
50 "Dropping message for channel of type %s (%d)\n", type ==
51 GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY ?
52 "GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY" : "UNKNOWN", type);
53
54 GNUNET_MQ_send (mq, env);
55
56}
57
58
59/* end of cadet_api_drop_message.c */
diff --git a/src/service/cadet/cadet_api_get_channel.c b/src/service/cadet/cadet_api_get_channel.c
new file mode 100644
index 000000000..05e2a8383
--- /dev/null
+++ b/src/service/cadet/cadet_api_get_channel.c
@@ -0,0 +1,260 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011, 2017, 2019 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file cadet/cadet_api_get_channel.c
22 * @brief cadet api: client implementation of cadet service
23 * @author Bartlomiej Polot
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_constants.h"
29#include "gnunet_cadet_service.h"
30#include "cadet.h"
31#include "cadet_protocol.h"
32
33
34/**
35 * Operation handle.
36 */
37struct GNUNET_CADET_ChannelMonitor
38{
39 /**
40 * Channel callback.
41 */
42 GNUNET_CADET_ChannelCB channel_cb;
43
44 /**
45 * Info callback closure for @c channel_cb.
46 */
47 void *channel_cb_cls;
48
49 /**
50 * Configuration we use.
51 */
52 const struct GNUNET_CONFIGURATION_Handle *cfg;
53
54 /**
55 * Message queue to talk to CADET service.
56 */
57 struct GNUNET_MQ_Handle *mq;
58
59 /**
60 * Task to reconnect.
61 */
62 struct GNUNET_SCHEDULER_Task *reconnect_task;
63
64 /**
65 * Backoff for reconnect attempts.
66 */
67 struct GNUNET_TIME_Relative backoff;
68
69 /**
70 * Peer we want information about.
71 */
72 struct GNUNET_PeerIdentity peer;
73};
74
75
76/**
77 * Check that message received from CADET service is well-formed.
78 *
79 * @param cls unused
80 * @param message the message we got
81 * @return #GNUNET_OK if the message is well-formed,
82 * #GNUNET_SYSERR otherwise
83 */
84static int
85check_channel_info (void *cls,
86 const struct GNUNET_CADET_ChannelInfoMessage *message)
87{
88 (void) cls;
89
90 return GNUNET_OK;
91}
92
93
94/**
95 * Process a local peer info reply, pass info to the user.
96 *
97 * @param cls Closure
98 * @param message Message itself.
99 */
100static void
101handle_channel_info (void *cls,
102 const struct GNUNET_CADET_ChannelInfoMessage *message)
103{
104 struct GNUNET_CADET_ChannelMonitor *cm = cls;
105 struct GNUNET_CADET_ChannelInternals ci;
106
107 ci.root = message->root;
108 ci.dest = message->dest;
109 cm->channel_cb (cm->channel_cb_cls,
110 &ci);
111 GNUNET_CADET_get_channel_cancel (cm);
112}
113
114
115/**
116 * Process a local peer info reply, pass info to the user.
117 *
118 * @param cls Closure
119 * @param message Message itself.
120 */
121static void
122handle_channel_info_end (void *cls,
123 const struct GNUNET_MessageHeader *message)
124{
125 struct GNUNET_CADET_ChannelMonitor *cm = cls;
126
127 cm->channel_cb (cm->channel_cb_cls,
128 NULL);
129 GNUNET_CADET_get_channel_cancel (cm);
130}
131
132
133/**
134 * Reconnect to the service and try again.
135 *
136 * @param cls a `struct GNUNET_CADET_ChannelMonitor` operation
137 */
138static void
139reconnect (void *cls);
140
141
142/**
143 * Function called on connection trouble. Reconnects.
144 *
145 * @param cls a `struct GNUNET_CADET_ChannelMonitor``
146 * @param error error code from MQ
147 */
148static void
149error_handler (void *cls,
150 enum GNUNET_MQ_Error error)
151{
152 struct GNUNET_CADET_ChannelMonitor *cm = cls;
153
154 GNUNET_MQ_destroy (cm->mq);
155 cm->mq = NULL;
156 cm->backoff = GNUNET_TIME_randomized_backoff (cm->backoff,
157 GNUNET_TIME_UNIT_MINUTES);
158 cm->reconnect_task = GNUNET_SCHEDULER_add_delayed (cm->backoff,
159 &reconnect,
160 cm);
161}
162
163
164/**
165 * Reconnect to the service and try again.
166 *
167 * @param cls a `struct GNUNET_CADET_ChannelMonitor` operation
168 */
169static void
170reconnect (void *cls)
171{
172 struct GNUNET_CADET_ChannelMonitor *cm = cls;
173 struct GNUNET_MQ_MessageHandler handlers[] = {
174 GNUNET_MQ_hd_fixed_size (channel_info_end,
175 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNEL_END,
176 struct GNUNET_MessageHeader,
177 cm),
178 GNUNET_MQ_hd_var_size (channel_info,
179 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNEL,
180 struct GNUNET_CADET_ChannelInfoMessage,
181 cm),
182 GNUNET_MQ_handler_end ()
183 };
184 struct GNUNET_CADET_RequestChannelInfoMessage *msg;
185 struct GNUNET_MQ_Envelope *env;
186
187 cm->reconnect_task = NULL;
188 cm->mq = GNUNET_CLIENT_connect (cm->cfg,
189 "cadet",
190 handlers,
191 &error_handler,
192 cm);
193 if (NULL == cm->mq)
194 return;
195 env = GNUNET_MQ_msg (msg,
196 GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_CHANNEL);
197 msg->target = cm->peer;
198 GNUNET_MQ_send (cm->mq,
199 env);
200}
201
202
203/**
204 * Request information about a specific channel of the running cadet peer.
205 *
206 * @param cfg configuration to use
207 * @param peer ID of the other end of the channel.
208 * @param callback Function to call with the requested data.
209 * @param callback_cls Closure for @c callback.
210 * @return NULL on error
211 */
212struct GNUNET_CADET_ChannelMonitor *
213GNUNET_CADET_get_channel (const struct GNUNET_CONFIGURATION_Handle *cfg,
214 struct GNUNET_PeerIdentity *peer,
215 GNUNET_CADET_ChannelCB callback,
216 void *callback_cls)
217{
218 struct GNUNET_CADET_ChannelMonitor *cm;
219
220 if (NULL == callback)
221 {
222 GNUNET_break (0);
223 return NULL;
224 }
225 cm = GNUNET_new (struct GNUNET_CADET_ChannelMonitor);
226 cm->channel_cb = callback;
227 cm->channel_cb_cls = callback_cls;
228 cm->cfg = cfg;
229 cm->peer = *peer;
230 reconnect (cm);
231 if (NULL == cm->mq)
232 {
233 GNUNET_free (cm);
234 return NULL;
235 }
236 return cm;
237}
238
239
240/**
241 * Cancel a channel monitor request. The callback will not be called (anymore).
242 *
243 * @param h Cadet handle.
244 * @return Closure that was given to #GNUNET_CADET_get_channel().
245 */
246void *
247GNUNET_CADET_get_channel_cancel (struct GNUNET_CADET_ChannelMonitor *cm)
248{
249 void *ret = cm->channel_cb_cls;
250
251 if (NULL != cm->mq)
252 GNUNET_MQ_destroy (cm->mq);
253 if (NULL != cm->reconnect_task)
254 GNUNET_SCHEDULER_cancel (cm->reconnect_task);
255 GNUNET_free (cm);
256 return ret;
257}
258
259
260/* end of cadet_api_get_channel.c */
diff --git a/src/service/cadet/cadet_api_get_path.c b/src/service/cadet/cadet_api_get_path.c
new file mode 100644
index 000000000..f32a5e20b
--- /dev/null
+++ b/src/service/cadet/cadet_api_get_path.c
@@ -0,0 +1,267 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011, 2017 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file cadet/cadet_api_get_path.c
22 * @brief cadet api: client implementation of cadet service
23 * @author Bartlomiej Polot
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_constants.h"
29#include "gnunet_cadet_service.h"
30#include "cadet.h"
31#include "cadet_protocol.h"
32
33
34/**
35 * Operation handle.
36 */
37struct GNUNET_CADET_GetPath
38{
39 /**
40 * Monitor callback
41 */
42 GNUNET_CADET_PathCB path_cb;
43
44 /**
45 * Closure for @c path_cb.
46 */
47 void *path_cb_cls;
48
49 /**
50 * Message queue to talk to CADET service.
51 */
52 struct GNUNET_MQ_Handle *mq;
53
54 /**
55 * Configuration we use.
56 */
57 const struct GNUNET_CONFIGURATION_Handle *cfg;
58
59 /**
60 * Task to reconnect.
61 */
62 struct GNUNET_SCHEDULER_Task *reconnect_task;
63
64 /**
65 * Backoff for reconnect attempts.
66 */
67 struct GNUNET_TIME_Relative backoff;
68
69 /**
70 * Peer we want information about.
71 */
72 struct GNUNET_PeerIdentity id;
73};
74
75
76/**
77 * Check that message received from CADET service is well-formed.
78 *
79 * @param cls unused
80 * @param message the message we got
81 * @return #GNUNET_OK if the message is well-formed,
82 * #GNUNET_SYSERR otherwise
83 */
84static int
85check_get_path (void *cls,
86 const struct GNUNET_CADET_LocalInfoPath *message)
87{
88 size_t msize = sizeof(struct GNUNET_CADET_LocalInfoPath);
89 size_t esize;
90
91 (void) cls;
92 esize = ntohs (message->header.size);
93 if (esize < msize)
94 {
95 GNUNET_break (0);
96 return GNUNET_SYSERR;
97 }
98 if (0 != ((esize - msize) % sizeof(struct GNUNET_PeerIdentity)))
99 {
100 GNUNET_break (0);
101 return GNUNET_SYSERR;
102 }
103 return GNUNET_OK;
104}
105
106
107/**
108 * Process a local peer info reply, pass info to the user.
109 *
110 * @param cls Closure
111 * @param message Message itself.
112 */
113static void
114handle_get_path (void *cls,
115 const struct GNUNET_CADET_LocalInfoPath *message)
116{
117 struct GNUNET_CADET_GetPath *gp = cls;
118 struct GNUNET_CADET_PeerPathDetail ppd;
119
120 ppd.peer = gp->id;
121 ppd.path = (const struct GNUNET_PeerIdentity *) &message[1];
122 ppd.target_offset = ntohl (message->off);
123 ppd.path_length = (ntohs (message->header.size) - sizeof(*message))
124 / sizeof(struct GNUNET_PeerIdentity);
125 gp->path_cb (gp->path_cb_cls,
126 &ppd);
127}
128
129
130/**
131 * Process a local peer info reply, pass info to the user.
132 *
133 * @param cls Closure
134 * @param message Message itself.
135 */
136static void
137handle_get_path_end (void *cls,
138 const struct GNUNET_MessageHeader *message)
139{
140 struct GNUNET_CADET_GetPath *gp = cls;
141
142 (void) message;
143 gp->path_cb (gp->path_cb_cls,
144 NULL);
145 GNUNET_CADET_get_path_cancel (gp);
146}
147
148
149/**
150 * Reconnect to the service and try again.
151 *
152 * @param cls a `struct GNUNET_CADET_GetPath` operation
153 */
154static void
155reconnect (void *cls);
156
157
158/**
159 * Function called on connection trouble. Reconnects.
160 *
161 * @param cls a `struct GNUNET_CADET_GetPath`
162 * @param error error code from MQ
163 */
164static void
165error_handler (void *cls,
166 enum GNUNET_MQ_Error error)
167{
168 struct GNUNET_CADET_GetPath *gp = cls;
169
170 GNUNET_MQ_destroy (gp->mq);
171 gp->mq = NULL;
172 gp->backoff = GNUNET_TIME_randomized_backoff (gp->backoff,
173 GNUNET_TIME_UNIT_MINUTES);
174 gp->reconnect_task = GNUNET_SCHEDULER_add_delayed (gp->backoff,
175 &reconnect,
176 gp);
177}
178
179
180/**
181 * Reconnect to the service and try again.
182 *
183 * @param cls a `struct GNUNET_CADET_GetPath` operation
184 */
185static void
186reconnect (void *cls)
187{
188 struct GNUNET_CADET_GetPath *gp = cls;
189 struct GNUNET_MQ_MessageHandler handlers[] = {
190 GNUNET_MQ_hd_var_size (get_path,
191 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PATH,
192 struct GNUNET_CADET_LocalInfoPath,
193 gp),
194 GNUNET_MQ_hd_fixed_size (get_path_end,
195 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PATH_END,
196 struct GNUNET_MessageHeader,
197 gp),
198 GNUNET_MQ_handler_end ()
199 };
200 struct GNUNET_CADET_RequestPathInfoMessage *msg;
201 struct GNUNET_MQ_Envelope *env;
202
203 gp->reconnect_task = NULL;
204 gp->mq = GNUNET_CLIENT_connect (gp->cfg,
205 "cadet",
206 handlers,
207 &error_handler,
208 gp);
209 if (NULL == gp->mq)
210 return;
211 env = GNUNET_MQ_msg (msg,
212 GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_PATH);
213 msg->peer = gp->id;
214 GNUNET_MQ_send (gp->mq,
215 env);
216}
217
218
219struct GNUNET_CADET_GetPath *
220GNUNET_CADET_get_path (const struct GNUNET_CONFIGURATION_Handle *cfg,
221 const struct GNUNET_PeerIdentity *id,
222 GNUNET_CADET_PathCB callback,
223 void *callback_cls)
224{
225 struct GNUNET_CADET_GetPath *gp;
226
227 if (NULL == callback)
228 {
229 GNUNET_break (0);
230 return NULL;
231 }
232 gp = GNUNET_new (struct GNUNET_CADET_GetPath);
233 gp->path_cb = callback;
234 gp->path_cb_cls = callback_cls;
235 gp->cfg = cfg;
236 gp->id = *id;
237 reconnect (gp);
238 if (NULL == gp->mq)
239 {
240 GNUNET_free (gp);
241 return NULL;
242 }
243 return gp;
244}
245
246
247/**
248 * Cancel @a gp operation.
249 *
250 * @param gp operation to cancel
251 * @return closure from #GNUNET_CADET_get_path().
252 */
253void *
254GNUNET_CADET_get_path_cancel (struct GNUNET_CADET_GetPath *gp)
255{
256 void *ret = gp->path_cb_cls;
257
258 if (NULL != gp->mq)
259 GNUNET_MQ_destroy (gp->mq);
260 if (NULL != gp->reconnect_task)
261 GNUNET_SCHEDULER_cancel (gp->reconnect_task);
262 GNUNET_free (gp);
263 return ret;
264}
265
266
267/* end of cadet_api_get_path.c */
diff --git a/src/service/cadet/cadet_api_helper.c b/src/service/cadet/cadet_api_helper.c
new file mode 100644
index 000000000..52aec6cc9
--- /dev/null
+++ b/src/service/cadet/cadet_api_helper.c
@@ -0,0 +1,54 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011, 2017 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file cadet/cadet_api_helper.c
22 * @brief cadet api: client implementation of cadet service
23 * @author Bartlomiej Polot
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_constants.h"
29#include "gnunet_cadet_service.h"
30#include "cadet.h"
31#include "cadet_protocol.h"
32
33
34/**
35 * Transitional function to convert an unsigned int port to a hash value.
36 * WARNING: local static value returned, NOT reentrant!
37 * WARNING: do not use this function for new code!
38 *
39 * @param port Numerical port (unsigned int format).
40 *
41 * @return A GNUNET_HashCode usable for the new CADET API.
42 */
43const struct GNUNET_HashCode *
44GC_u2h (uint32_t port)
45{
46 static struct GNUNET_HashCode hash;
47
48 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
49 "This is a transitional function, use proper crypto hashes as CADET ports\n");
50 GNUNET_CRYPTO_hash (&port,
51 sizeof(port),
52 &hash);
53 return &hash;
54}
diff --git a/src/service/cadet/cadet_api_list_peers.c b/src/service/cadet/cadet_api_list_peers.c
new file mode 100644
index 000000000..52f59cc74
--- /dev/null
+++ b/src/service/cadet/cadet_api_list_peers.c
@@ -0,0 +1,238 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011, 2017, 2019 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file cadet/cadet_api_list_peers.c
22 * @brief cadet api: client implementation of cadet service
23 * @author Bartlomiej Polot
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_constants.h"
29#include "gnunet_cadet_service.h"
30#include "cadet.h"
31#include "cadet_protocol.h"
32
33
34/**
35 * Operation handle.
36 */
37struct GNUNET_CADET_PeersLister
38{
39 /**
40 * Monitor callback
41 */
42 GNUNET_CADET_PeersCB peers_cb;
43
44 /**
45 * Info callback closure for @c info_cb.
46 */
47 void *peers_cb_cls;
48
49 /**
50 * Message queue to talk to CADET service.
51 */
52 struct GNUNET_MQ_Handle *mq;
53
54 /**
55 * Configuration we use.
56 */
57 const struct GNUNET_CONFIGURATION_Handle *cfg;
58
59 /**
60 * Task to reconnect.
61 */
62 struct GNUNET_SCHEDULER_Task *reconnect_task;
63
64 /**
65 * Backoff for reconnect attempts.
66 */
67 struct GNUNET_TIME_Relative backoff;
68};
69
70
71/**
72 * Process a local reply about info on all tunnels, pass info to the user.
73 *
74 * @param cls a `struct GNUNET_CADET_PeersLister`
75 * @param info Message itself.
76 */
77static void
78handle_get_peers (void *cls,
79 const struct GNUNET_CADET_LocalInfoPeers *info)
80{
81 struct GNUNET_CADET_PeersLister *pl = cls;
82 struct GNUNET_CADET_PeerListEntry ple;
83
84 ple.peer = info->destination;
85 ple.have_tunnel = (int) ntohs (info->tunnel);
86 ple.n_paths = (unsigned int) ntohs (info->paths);
87 ple.best_path_length = (unsigned int) ntohl (info->best_path_length);
88 pl->peers_cb (pl->peers_cb_cls,
89 &ple);
90}
91
92
93/**
94 * Process a end of list reply about info on all peers.
95 *
96 * @param cls a `struct GNUNET_CADET_PeersLister`
97 * @param msg Message itself.
98 */
99static void
100handle_get_peers_end (void *cls,
101 const struct GNUNET_MessageHeader *msg)
102{
103 struct GNUNET_CADET_PeersLister *pl = cls;
104
105 (void) msg;
106
107 pl->peers_cb (pl->peers_cb_cls,
108 NULL);
109 GNUNET_CADET_list_peers_cancel (pl);
110}
111
112
113/**
114 * Reconnect to the service and try again.
115 *
116 * @param cls a `struct GNUNET_CADET_PeersLister` operation
117 */
118static void
119reconnect (void *cls);
120
121
122/**
123 * Function called on connection trouble. Reconnects.
124 *
125 * @param cls a `struct GNUNET_CADET_PeersLister`
126 * @param error error code from MQ
127 */
128static void
129error_handler (void *cls,
130 enum GNUNET_MQ_Error error)
131{
132 struct GNUNET_CADET_PeersLister *pl = cls;
133
134 GNUNET_MQ_destroy (pl->mq);
135 pl->mq = NULL;
136 pl->backoff = GNUNET_TIME_randomized_backoff (pl->backoff,
137 GNUNET_TIME_UNIT_MINUTES);
138 pl->reconnect_task = GNUNET_SCHEDULER_add_delayed (pl->backoff,
139 &reconnect,
140 pl);
141}
142
143
144/**
145 * Reconnect to the service and try again.
146 *
147 * @param cls a `struct GNUNET_CADET_PeersLister` operation
148 */
149static void
150reconnect (void *cls)
151{
152 struct GNUNET_CADET_PeersLister *pl = cls;
153 struct GNUNET_MQ_MessageHandler handlers[] = {
154 GNUNET_MQ_hd_fixed_size (get_peers,
155 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS,
156 struct GNUNET_CADET_LocalInfoPeers,
157 pl),
158 GNUNET_MQ_hd_fixed_size (get_peers_end,
159 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS_END,
160 struct GNUNET_MessageHeader,
161 pl),
162 GNUNET_MQ_handler_end ()
163 };
164 struct GNUNET_MessageHeader *msg;
165 struct GNUNET_MQ_Envelope *env;
166
167 pl->reconnect_task = NULL;
168 pl->mq = GNUNET_CLIENT_connect (pl->cfg,
169 "cadet",
170 handlers,
171 &error_handler,
172 pl);
173 if (NULL == pl->mq)
174 return;
175 env = GNUNET_MQ_msg (msg,
176 GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_PEERS);
177 GNUNET_MQ_send (pl->mq,
178 env);
179}
180
181
182/**
183 * Request information about peers known to the running cadet service.
184 * The callback will be called for every peer known to the service.
185 * Only one info request (of any kind) can be active at once.
186 *
187 * @param cfg configuration to use
188 * @param callback Function to call with the requested data.
189 * @param callback_cls Closure for @c callback.
190 * @return NULL on error
191 */
192struct GNUNET_CADET_PeersLister *
193GNUNET_CADET_list_peers (const struct GNUNET_CONFIGURATION_Handle *cfg,
194 GNUNET_CADET_PeersCB callback,
195 void *callback_cls)
196{
197 struct GNUNET_CADET_PeersLister *pl;
198
199 if (NULL == callback)
200 {
201 GNUNET_break (0);
202 return NULL;
203 }
204 pl = GNUNET_new (struct GNUNET_CADET_PeersLister);
205 pl->peers_cb = callback;
206 pl->peers_cb_cls = callback_cls;
207 pl->cfg = cfg;
208 reconnect (pl);
209 if (NULL == pl->mq)
210 {
211 GNUNET_free (pl);
212 return NULL;
213 }
214 return pl;
215}
216
217
218/**
219 * Cancel a peer info request. The callback will not be called (anymore).
220 *
221 * @param pl operation handle
222 * @return Closure given to GNUNET_CADET_get_peers().
223 */
224void *
225GNUNET_CADET_list_peers_cancel (struct GNUNET_CADET_PeersLister *pl)
226{
227 void *ret = pl->peers_cb_cls;
228
229 if (NULL != pl->mq)
230 GNUNET_MQ_destroy (pl->mq);
231 if (NULL != pl->reconnect_task)
232 GNUNET_SCHEDULER_cancel (pl->reconnect_task);
233 GNUNET_free (pl);
234 return ret;
235}
236
237
238/* end of cadet_api_list_peers.c */
diff --git a/src/service/cadet/cadet_api_list_tunnels.c b/src/service/cadet/cadet_api_list_tunnels.c
new file mode 100644
index 000000000..dce12835f
--- /dev/null
+++ b/src/service/cadet/cadet_api_list_tunnels.c
@@ -0,0 +1,239 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011, 2017, 2019 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file cadet/cadet_api_list_tunnels.c
22 * @brief cadet api: client implementation of cadet service
23 * @author Bartlomiej Polot
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_constants.h"
29#include "gnunet_cadet_service.h"
30#include "cadet.h"
31#include "cadet_protocol.h"
32
33
34/**
35 * Operation handle.
36 */
37struct GNUNET_CADET_ListTunnels
38{
39 /**
40 * Monitor callback
41 */
42 GNUNET_CADET_TunnelsCB tunnels_cb;
43
44 /**
45 * Info callback closure for @c tunnels_cb.
46 */
47 void *tunnels_cb_cls;
48
49 /**
50 * Message queue to talk to CADET service.
51 */
52 struct GNUNET_MQ_Handle *mq;
53
54 /**
55 * Configuration we use.
56 */
57 const struct GNUNET_CONFIGURATION_Handle *cfg;
58
59 /**
60 * Task to reconnect.
61 */
62 struct GNUNET_SCHEDULER_Task *reconnect_task;
63
64 /**
65 * Backoff for reconnect attempts.
66 */
67 struct GNUNET_TIME_Relative backoff;
68};
69
70
71/**
72 * Process a local reply about info on all tunnels, pass info to the user.
73 *
74 * @param cls a `struct GNUNET_CADET_ListTunnels *`
75 * @param info Message itself.
76 */
77static void
78handle_get_tunnels (void *cls,
79 const struct GNUNET_CADET_LocalInfoTunnel *info)
80{
81 struct GNUNET_CADET_ListTunnels *lt = cls;
82 struct GNUNET_CADET_TunnelDetails td;
83
84 td.peer = info->destination;
85 td.channels = ntohl (info->channels);
86 td.connections = ntohl (info->connections);
87 td.estate = ntohs (info->estate);
88 td.cstate = ntohs (info->cstate);
89 lt->tunnels_cb (lt->tunnels_cb_cls,
90 &td);
91}
92
93
94/**
95 * Process a local reply about info on all tunnels, pass info to the user.
96 *
97 * @param cls a `struct GNUNET_CADET_ListTunnels *`
98 * @param msg Message itself.
99 */
100static void
101handle_get_tunnels_end (void *cls,
102 const struct GNUNET_MessageHeader *msg)
103{
104 struct GNUNET_CADET_ListTunnels *lt = cls;
105
106 (void) msg;
107
108 lt->tunnels_cb (lt->tunnels_cb_cls,
109 NULL);
110 GNUNET_CADET_list_tunnels_cancel (lt);
111}
112
113
114/**
115 * Reconnect to the service and try again.
116 *
117 * @param cls a `struct GNUNET_CADET_ListTunnels` operation
118 */
119static void
120reconnect (void *cls);
121
122
123/**
124 * Function called on connection trouble. Reconnects.
125 *
126 * @param cls a `struct GNUNET_CADET_ListTunnels`
127 * @param error error code from MQ
128 */
129static void
130error_handler (void *cls,
131 enum GNUNET_MQ_Error error)
132{
133 struct GNUNET_CADET_ListTunnels *lt = cls;
134
135 GNUNET_MQ_destroy (lt->mq);
136 lt->mq = NULL;
137 lt->backoff = GNUNET_TIME_randomized_backoff (lt->backoff,
138 GNUNET_TIME_UNIT_MINUTES);
139 lt->reconnect_task = GNUNET_SCHEDULER_add_delayed (lt->backoff,
140 &reconnect,
141 lt);
142}
143
144
145/**
146 * Reconnect to the service and try again.
147 *
148 * @param cls a `struct GNUNET_CADET_ListTunnels` operation
149 */
150static void
151reconnect (void *cls)
152{
153 struct GNUNET_CADET_ListTunnels *lt = cls;
154 struct GNUNET_MQ_MessageHandler handlers[] = {
155 GNUNET_MQ_hd_fixed_size (get_tunnels,
156 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS,
157 struct GNUNET_CADET_LocalInfoTunnel,
158 lt),
159 GNUNET_MQ_hd_fixed_size (get_tunnels_end,
160 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS_END,
161 struct GNUNET_MessageHeader,
162 lt),
163 GNUNET_MQ_handler_end ()
164 };
165 struct GNUNET_MessageHeader *msg;
166 struct GNUNET_MQ_Envelope *env;
167
168 lt->reconnect_task = NULL;
169 lt->mq = GNUNET_CLIENT_connect (lt->cfg,
170 "cadet",
171 handlers,
172 &error_handler,
173 lt);
174 if (NULL == lt->mq)
175 return;
176 env = GNUNET_MQ_msg (msg,
177 GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_TUNNELS);
178 GNUNET_MQ_send (lt->mq,
179 env);
180}
181
182
183/**
184 * Request information about tunnels of the running cadet peer.
185 * The callback will be called for every tunnel of the service.
186 * Only one info request (of any kind) can be active at once.
187 *
188 * @param cfg configuration to use
189 * @param callback Function to call with the requested data.
190 * @param callback_cls Closure for @c callback.
191 * @return NULL on error
192 */
193struct GNUNET_CADET_ListTunnels *
194GNUNET_CADET_list_tunnels (const struct GNUNET_CONFIGURATION_Handle *cfg,
195 GNUNET_CADET_TunnelsCB callback,
196 void *callback_cls)
197{
198 struct GNUNET_CADET_ListTunnels *lt;
199
200 if (NULL == callback)
201 {
202 GNUNET_break (0);
203 return NULL;
204 }
205 lt = GNUNET_new (struct GNUNET_CADET_ListTunnels);
206 lt->tunnels_cb = callback;
207 lt->tunnels_cb_cls = callback_cls;
208 lt->cfg = cfg;
209 reconnect (lt);
210 if (NULL == lt->mq)
211 {
212 GNUNET_free (lt);
213 return NULL;
214 }
215 return lt;
216}
217
218
219/**
220 * Cancel a monitor request. The monitor callback will not be called.
221 *
222 * @param lt operation handle
223 * @return Closure given to GNUNET_CADET_list_tunnels().
224 */
225void *
226GNUNET_CADET_list_tunnels_cancel (struct GNUNET_CADET_ListTunnels *lt)
227{
228 void *ret = lt->tunnels_cb_cls;
229
230 if (NULL != lt->mq)
231 GNUNET_MQ_destroy (lt->mq);
232 if (NULL != lt->reconnect_task)
233 GNUNET_SCHEDULER_cancel (lt->reconnect_task);
234 GNUNET_free (lt);
235 return ret;
236}
237
238
239/* end of cadet_api_list_tunnels.c */
diff --git a/src/service/cadet/cadet_protocol.h b/src/service/cadet/cadet_protocol.h
new file mode 100644
index 000000000..117a7922e
--- /dev/null
+++ b/src/service/cadet/cadet_protocol.h
@@ -0,0 +1,541 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2007 - 2017 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file cadet/cadet_protocol.h
23 * @brief P2P messages used by CADET
24 * @author Bartlomiej Polot
25 * @author Christian Grothoff
26 */
27
28#ifndef CADET_PROTOCOL_H_
29#define CADET_PROTOCOL_H_
30
31/**
32 * At best, enable when debugging #5328!
33 */
34#define DEBUG_KX 0
35#if DEBUG_KX
36#warning NEVER run this in production! KX debugging is on!
37#endif
38
39#include "platform.h"
40#include "gnunet_util_lib.h"
41#include "cadet.h"
42
43#ifdef __cplusplus
44
45struct GNUNET_CADET_TunnelMessage;
46extern "C"
47{
48#if 0
49/* keep Emacsens' auto-indent happy */
50}
51#endif
52#endif
53
54/******************************************************************************/
55/******************** CADET NETWORK MESSAGES **************************/
56/******************************************************************************/
57
58GNUNET_NETWORK_STRUCT_BEGIN
59
60
61/******************************************************************************/
62/***************************** CONNECTION **********************************/
63/******************************************************************************/
64
65
66/**
67 * Message for cadet connection creation.
68 */
69struct GNUNET_CADET_ConnectionCreateMessage
70{
71 /**
72 * Type: #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE
73 *
74 * Size: sizeof (struct GNUNET_CADET_ConnectionCreateMessage) +
75 * path_length * sizeof (struct GNUNET_PeerIdentity)
76 */
77 struct GNUNET_MessageHeader header;
78
79 /**
80 * Connection options in network byte order.
81 * #GNUNET_CADET_OPTION_DEFAULT for buffered;
82 * #GNUNET_CADET_OPTION_NOBUFFER for unbuffered.
83 * Other flags are ignored and should not be set at this level.
84 */
85 uint32_t options GNUNET_PACKED;
86
87 /**
88 * This flag indicates the peer sending the connection create
89 * meassage likes to trigger a KX handshake.
90 */
91 int has_monotime;
92
93 /**
94 * This monotonic time is set, if a peer likes to trigger a KX, but is not
95 * the peer that should start the KX. (xrs,t3ss)
96 */
97 struct GNUNET_TIME_AbsoluteNBO monotime;
98
99 /**
100 * We sign the monotime. The receiving peer can check the signature, to verify
101 * the sending peer.
102 */
103 struct GNUNET_CRYPTO_EddsaSignature monotime_sig;
104
105 /**
106 * ID of the connection
107 */
108 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
109
110 /**
111 * path_length structs defining the *whole* path from the origin [0] to the
112 * final destination [path_length-1].
113 */
114 /* struct GNUNET_PeerIdentity peers[path_length]; */
115};
116
117
118/**
119 * Message for ack'ing a connection
120 */
121struct GNUNET_CADET_ConnectionCreateAckMessage
122{
123 /**
124 * Type: #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK
125 */
126 struct GNUNET_MessageHeader header;
127
128 /**
129 * For alignment.
130 */
131 uint32_t reserved GNUNET_PACKED;
132
133 /**
134 * ID of the connection.
135 */
136 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
137};
138
139
140/**
141 * Message for notifying a disconnection in a path
142 */
143struct GNUNET_CADET_ConnectionBrokenMessage
144{
145 /**
146 * Type: #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN.
147 */
148 struct GNUNET_MessageHeader header;
149
150 /**
151 * For alignment.
152 */
153 uint32_t reserved GNUNET_PACKED;
154
155 /**
156 * ID of the connection.
157 */
158 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
159
160 /**
161 * ID of the endpoint
162 */
163 struct GNUNET_PeerIdentity peer1;
164
165 /**
166 * ID of the endpoint
167 */
168 struct GNUNET_PeerIdentity peer2;
169};
170
171
172/**
173 * Message to destroy a connection.
174 */
175struct GNUNET_CADET_ConnectionDestroyMessage
176{
177 /**
178 * Type: #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY
179 */
180 struct GNUNET_MessageHeader header;
181
182 /**
183 * For alignment.
184 */
185 uint32_t reserved GNUNET_PACKED;
186
187 /**
188 * ID of the connection.
189 */
190 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
191};
192
193
194/******************************************************************************/
195/******************************* TUNNEL ***********************************/
196/******************************************************************************/
197
198/**
199 * Unique identifier (counter) for an encrypted message in a channel.
200 * Used to match #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK
201 * and #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL messages
202 * against the respective #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED
203 * messages.
204 */
205struct CadetEncryptedMessageIdentifier
206{
207 /**
208 * This number is incremented by one per message. It may wrap around.
209 * In network byte order.
210 */
211 uint32_t pid GNUNET_PACKED;
212};
213
214
215/**
216 * Flags to be used in GNUNET_CADET_KX.
217 */
218enum GNUNET_CADET_KX_Flags
219{
220 /**
221 * Should the peer reply with its KX details?
222 */
223 GNUNET_CADET_KX_FLAG_NONE = 0,
224
225 /**
226 * The peer should reply with its KX details?
227 */
228 GNUNET_CADET_KX_FLAG_FORCE_REPLY = 1
229};
230
231
232/**
233 * Message for a Key eXchange for a tunnel.
234 */
235struct GNUNET_CADET_TunnelKeyExchangeMessage
236{
237 /**
238 * Type: #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX or
239 * #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX_AUTH as part
240 * of `struct GNUNET_CADET_TunnelKeyExchangeAuthMessage`.
241 */
242 struct GNUNET_MessageHeader header;
243
244 /**
245 * Flags for the key exchange in NBO, based on
246 * `enum GNUNET_CADET_KX_Flags`.
247 */
248 uint32_t flags GNUNET_PACKED;
249
250 /**
251 * ID of the connection.
252 */
253 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
254
255 /**
256 * Sender's ephemeral public ECC key encoded in a
257 * format suitable for network transmission, as created
258 * using 'gcry_sexp_sprint'.
259 */
260 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
261
262#if DEBUG_KX
263 /**
264 * Sender's ephemeral public ECC key encoded in a
265 * format suitable for network transmission, as created
266 * using 'gcry_sexp_sprint'.
267 */
268 struct GNUNET_CRYPTO_EcdhePrivateKey ephemeral_key_XXX; // for debugging KX-crypto!
269
270 /**
271 * Sender's ephemeral public ECC key encoded in a
272 * format suitable for network transmission, as created
273 * using 'gcry_sexp_sprint'.
274 */
275 struct GNUNET_CRYPTO_EddsaPrivateKey private_key_XXX; // for debugging KX-crypto!
276#endif
277
278 /**
279 * Sender's next ephemeral public ECC key encoded in a
280 * format suitable for network transmission, as created
281 * using 'gcry_sexp_sprint'.
282 */
283 struct GNUNET_CRYPTO_EcdhePublicKey ratchet_key;
284};
285
286
287/**
288 * Message for a Key eXchange for a tunnel, with authentication.
289 * Used as a response to the initial KX as well as for rekeying.
290 */
291struct GNUNET_CADET_TunnelKeyExchangeAuthMessage
292{
293 /**
294 * Message header with key material.
295 */
296 struct GNUNET_CADET_TunnelKeyExchangeMessage kx;
297
298#if DEBUG_KX
299 /**
300 * Received ephemeral public ECC key encoded in a
301 * format suitable for network transmission, as created
302 * using 'gcry_sexp_sprint'.
303 */
304 struct GNUNET_CRYPTO_EcdhePublicKey r_ephemeral_key_XXX; // for debugging KX-crypto!
305#endif
306
307 /**
308 * KDF-proof that sender could compute the 3-DH, used in lieu of a
309 * signature or payload data.
310 */
311 struct GNUNET_HashCode auth;
312};
313
314
315/**
316 * Encrypted axolotl header with numbers that identify which
317 * keys in which ratchet are to be used to decrypt the body.
318 */
319struct GNUNET_CADET_AxHeader
320{
321 /**
322 * Number of messages sent with the current ratchet key.
323 */
324 uint32_t Ns GNUNET_PACKED;
325
326 /**
327 * Number of messages sent with the previous ratchet key.
328 */
329 uint32_t PNs GNUNET_PACKED;
330
331 /**
332 * Current ratchet key.
333 */
334 struct GNUNET_CRYPTO_EcdhePublicKey DHRs;
335};
336
337
338/**
339 * Axolotl-encrypted tunnel message with application payload.
340 */
341struct GNUNET_CADET_TunnelEncryptedMessage
342{
343 /**
344 * Type: #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED
345 */
346 struct GNUNET_MessageHeader header;
347
348 /**
349 * Reserved, for alignment.
350 */
351 uint32_t reserved GNUNET_PACKED;
352
353 /**
354 * ID of the connection.
355 */
356 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
357
358 /**
359 * MAC of the encrypted message, used to verify message integrity.
360 * Everything after this value will be encrypted with the header key
361 * and authenticated.
362 */
363 struct GNUNET_ShortHashCode hmac;
364
365 /**
366 * Axolotl-header that specifies which keys to use in which ratchet
367 * to decrypt the body that follows.
368 */
369 struct GNUNET_CADET_AxHeader ax_header;
370
371 /**
372 * Encrypted content follows.
373 */
374};
375
376
377/******************************************************************************/
378/******************************* CHANNEL ***********************************/
379/******************************************************************************/
380
381
382/**
383 * Message to create a Channel.
384 */
385struct GNUNET_CADET_ChannelOpenMessage
386{
387 /**
388 * Type: #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN
389 */
390 struct GNUNET_MessageHeader header;
391
392 /**
393 * Channel options.
394 */
395 uint32_t opt GNUNET_PACKED;
396
397 /**
398 * Hash of destination port and listener.
399 */
400 struct GNUNET_HashCode h_port;
401
402 /**
403 * ID of the channel within the tunnel.
404 */
405 struct GNUNET_CADET_ChannelTunnelNumber ctn;
406};
407
408
409/**
410 * Message to acknowledge opening a channel of type
411 * #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK.
412 */
413struct GNUNET_CADET_ChannelOpenAckMessage
414{
415 /**
416 * Type: #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK
417 */
418 struct GNUNET_MessageHeader header;
419
420 /**
421 * For alignment.
422 */
423 uint32_t reserved GNUNET_PACKED;
424
425 /**
426 * ID of the channel
427 */
428 struct GNUNET_CADET_ChannelTunnelNumber ctn;
429
430 /**
431 * Port number of the channel, used to prove to the
432 * initiator that the receiver knows the port.
433 */
434 struct GNUNET_HashCode port;
435};
436
437
438/**
439 * Message to destroy a channel of type
440 * #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY.
441 */
442struct GNUNET_CADET_ChannelDestroyMessage
443{
444 /**
445 * Type: #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY
446 */
447 struct GNUNET_MessageHeader header;
448
449 /**
450 * For alignment.
451 */
452 uint32_t reserved GNUNET_PACKED;
453
454 /**
455 * ID of the channel
456 */
457 struct GNUNET_CADET_ChannelTunnelNumber ctn;
458};
459
460
461/**
462 * Number used to uniquely identify messages in a CADET Channel.
463 */
464struct ChannelMessageIdentifier
465{
466 /**
467 * Unique ID of the message, cycles around, in NBO.
468 */
469 uint32_t mid GNUNET_PACKED;
470};
471
472
473/**
474 * Message for cadet data traffic.
475 */
476struct GNUNET_CADET_ChannelAppDataMessage
477{
478 /**
479 * Type: #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA.
480 */
481 struct GNUNET_MessageHeader header;
482
483 /**
484 * Unique ID of the payload message.
485 */
486 struct ChannelMessageIdentifier mid;
487
488 /**
489 * ID of the channel
490 */
491 struct GNUNET_CADET_ChannelTunnelNumber ctn;
492
493 /**
494 * Payload follows
495 */
496};
497
498
499/**
500 * Message to acknowledge end-to-end data.
501 */
502struct GNUNET_CADET_ChannelDataAckMessage
503{
504 /**
505 * Type: #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK
506 */
507 struct GNUNET_MessageHeader header;
508
509 /**
510 * ID of the channel
511 */
512 struct GNUNET_CADET_ChannelTunnelNumber ctn;
513
514 /**
515 * Bitfield of already-received newer messages. Note that bit 0
516 * corresponds to @e mid + 1.
517 *
518 * pid + 0 @ LSB
519 * pid + 63 @ MSB
520 */
521 uint64_t futures GNUNET_PACKED;
522
523 /**
524 * Next message ID expected.
525 */
526 struct ChannelMessageIdentifier mid;
527};
528
529
530GNUNET_NETWORK_STRUCT_END
531
532#if 0 /* keep Emacsens' auto-indent happy */
533{
534#endif
535#ifdef __cplusplus
536}
537#endif
538
539/* ifndef CADET_PROTOCOL_H */
540#endif
541/* end of cadet_protocol.h */
diff --git a/src/service/cadet/desirability_table.c b/src/service/cadet/desirability_table.c
new file mode 100644
index 000000000..b4db7c2dd
--- /dev/null
+++ b/src/service/cadet/desirability_table.c
@@ -0,0 +1,34 @@
1/* This file is in the public domain. */
2
3/**
4 * @brief Program to simulate results from #GCP_get_desirability_of_path()
5 * for various plausible inputs.
6 * @author Christian Grothoff
7 */
8#include "platform.h"
9#include <stdio.h>
10
11int
12main ()
13{
14 for (unsigned int num_alts = 1; num_alts < 10; num_alts++)
15 for (unsigned int off = 0; off < 10; off++)
16 for (double delta = -(int) off; delta <= 5; delta += 0.25)
17 {
18 double weight_alts;
19
20 if (delta <= -1.0)
21 weight_alts = -1.0 * num_alts / delta; /* discount alternative paths */
22 else if (delta >= 1.0)
23 weight_alts = 1.0 * num_alts * delta; /* overcount alternative paths */
24 else
25 weight_alts = 1.0 * num_alts; /* count alternative paths normally */
26
27 fprintf (stderr,
28 "Paths: %u Offset: %u Delta: %5.2f SCORE: %f\n",
29 num_alts,
30 off,
31 delta,
32 ((off + 1.0) / (weight_alts * weight_alts)));
33 }
34}
diff --git a/src/service/cadet/gnunet-service-cadet.c b/src/service/cadet/gnunet-service-cadet.c
new file mode 100644
index 000000000..620e43cc8
--- /dev/null
+++ b/src/service/cadet/gnunet-service-cadet.c
@@ -0,0 +1,1376 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2001-2013, 2017 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file cadet/gnunet-service-cadet.c
23 * @brief GNUnet CADET service with encryption
24 * @author Bartlomiej Polot
25 * @author Christian Grothoff
26 *
27 * Dictionary:
28 * - peer: other cadet instance. If there is direct connection it's a neighbor.
29 * - path: series of directly connected peer from one peer to another.
30 * - connection: path which is being used in a tunnel.
31 * - tunnel: encrypted connection to a peer, neighbor or not.
32 * - channel: logical link between two clients, on the same or different peers.
33 * have properties like reliability.
34 */
35#include "platform.h"
36#include "gnunet_util_lib.h"
37#include "cadet.h"
38#include "gnunet_statistics_service.h"
39#include "gnunet_transport_application_service.h"
40#include "gnunet-service-cadet.h"
41#include "gnunet-service-cadet_channel.h"
42#include "gnunet-service-cadet_connection.h"
43#include "gnunet-service-cadet_core.h"
44#include "gnunet-service-cadet_dht.h"
45#include "gnunet-service-cadet_hello.h"
46#include "gnunet-service-cadet_tunnels.h"
47#include "gnunet-service-cadet_peer.h"
48#include "gnunet-service-cadet_paths.h"
49#include "gnunet_constants.h"
50
51
52#define LOG(level, ...) GNUNET_log (level, __VA_ARGS__)
53
54
55/**
56 * Struct containing information about a client of the service
57 */
58struct CadetClient
59{
60 /**
61 * Linked list next
62 */
63 struct CadetClient *next;
64
65 /**
66 * Linked list prev
67 */
68 struct CadetClient *prev;
69
70 /**
71 * Tunnels that belong to this client, indexed by local id,
72 * value is a `struct CadetChannel`.
73 */
74 struct GNUNET_CONTAINER_MultiHashMap32 *channels;
75
76 /**
77 * Handle to communicate with the client
78 */
79 struct GNUNET_MQ_Handle *mq;
80
81 /**
82 * Client handle.
83 */
84 struct GNUNET_SERVICE_Client *client;
85
86 /**
87 * Ports that this client has declared interest in.
88 * Indexed by port, contains `struct OpenPort`
89 */
90 struct GNUNET_CONTAINER_MultiHashMap *ports;
91
92 /**
93 * Channel ID to use for the next incoming channel for this client.
94 * Wraps around (in theory).
95 */
96 struct GNUNET_CADET_ClientChannelNumber next_ccn;
97
98 /**
99 * ID of the client, mainly for debug messages. Purely internal to this file.
100 */
101 unsigned int id;
102};
103
104
105/******************************************************************************/
106/*********************** GLOBAL VARIABLES ****************************/
107/******************************************************************************/
108
109/****************************** Global variables ******************************/
110
111/**
112 * Handle to our configuration.
113 */
114const struct GNUNET_CONFIGURATION_Handle *cfg;
115
116/**
117 * Handle to the statistics service.
118 */
119struct GNUNET_STATISTICS_Handle *stats;
120
121/**
122 * Handle to Transport service.
123 */
124struct GNUNET_TRANSPORT_ApplicationHandle *transport;
125
126/**
127 * Local peer own ID.
128 */
129struct GNUNET_PeerIdentity my_full_id;
130
131/**
132 * Own private key.
133 */
134struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key;
135
136/**
137 * Signal that shutdown is happening: prevent recovery measures.
138 */
139int shutting_down;
140
141/**
142 * DLL with all the clients, head.
143 */
144static struct CadetClient *clients_head;
145
146/**
147 * DLL with all the clients, tail.
148 */
149static struct CadetClient *clients_tail;
150
151/**
152 * Next ID to assign to a client.
153 */
154static unsigned int next_client_id;
155
156/**
157 * All ports clients of this peer have opened. Maps from
158 * a hashed port to a `struct OpenPort`.
159 */
160struct GNUNET_CONTAINER_MultiHashMap *open_ports;
161
162/**
163 * Map from ports to channels where the ports were closed at the
164 * time we got the inbound connection.
165 * Indexed by h_port, contains `struct CadetChannel`.
166 */
167struct GNUNET_CONTAINER_MultiHashMap *loose_channels;
168
169/**
170 * Map from PIDs to `struct CadetPeer` entries.
171 */
172struct GNUNET_CONTAINER_MultiPeerMap *peers;
173
174/**
175 * Map from `struct GNUNET_CADET_ConnectionTunnelIdentifier`
176 * hash codes to `struct CadetConnection` objects.
177 */
178struct GNUNET_CONTAINER_MultiShortmap *connections;
179
180/**
181 * How many messages are needed to trigger an AXOLOTL ratchet advance.
182 */
183unsigned long long ratchet_messages;
184
185/**
186 * How long until we trigger a ratched advance due to time.
187 */
188struct GNUNET_TIME_Relative ratchet_time;
189
190/**
191 * How frequently do we send KEEPALIVE messages on idle connections?
192 */
193struct GNUNET_TIME_Relative keepalive_period;
194
195/**
196 * Set to non-zero values to create random drops to test retransmissions.
197 */
198unsigned long long drop_percent;
199
200
201/**
202 * Send a message to a client.
203 *
204 * @param c client to get the message
205 * @param env envelope with the message
206 */
207void
208GSC_send_to_client (struct CadetClient *c,
209 struct GNUNET_MQ_Envelope *env)
210{
211 GNUNET_MQ_send (c->mq,
212 env);
213}
214
215
216/**
217 * Return identifier for a client as a string.
218 *
219 * @param c client to identify
220 * @return string for debugging
221 */
222const char *
223GSC_2s (struct CadetClient *c)
224{
225 static char buf[32];
226
227 GNUNET_snprintf (buf,
228 sizeof(buf),
229 "Client(%u)",
230 c->id);
231 return buf;
232}
233
234
235/**
236 * Lookup channel of client @a c by @a ccn.
237 *
238 * @param c client to look in
239 * @param ccn channel ID to look up
240 * @return NULL if no such channel exists
241 */
242static struct CadetChannel *
243lookup_channel (struct CadetClient *c,
244 struct GNUNET_CADET_ClientChannelNumber ccn)
245{
246 return GNUNET_CONTAINER_multihashmap32_get (c->channels,
247 ntohl (ccn.channel_of_client));
248}
249
250
251/**
252 * Obtain the next LID to use for incoming connections to
253 * the given client.
254 *
255 * @param c client handle
256 */
257static struct GNUNET_CADET_ClientChannelNumber
258client_get_next_ccn (struct CadetClient *c)
259{
260 struct GNUNET_CADET_ClientChannelNumber ccn = c->next_ccn;
261
262 /* increment until we have a free one... */
263 while (NULL !=
264 lookup_channel (c,
265 ccn))
266 {
267 ccn.channel_of_client
268 = htonl (1 + (ntohl (ccn.channel_of_client)));
269 if (ntohl (ccn.channel_of_client) >=
270 GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
271 ccn.channel_of_client = htonl (0);
272 }
273 c->next_ccn.channel_of_client
274 = htonl (1 + (ntohl (ccn.channel_of_client)));
275 return ccn;
276}
277
278
279/**
280 * Bind incoming channel to this client, and notify client about
281 * incoming connection. Caller is responsible for notifying the other
282 * peer about our acceptance of the channel.
283 *
284 * @param c client to bind to
285 * @param ch channel to be bound
286 * @param dest peer that establishes the connection
287 * @param port port number
288 * @param options options
289 * @return local channel number assigned to the new client
290 */
291struct GNUNET_CADET_ClientChannelNumber
292GSC_bind (struct CadetClient *c,
293 struct CadetChannel *ch,
294 struct CadetPeer *dest,
295 const struct GNUNET_HashCode *port,
296 uint32_t options)
297{
298 struct GNUNET_MQ_Envelope *env;
299 struct GNUNET_CADET_LocalChannelCreateMessage *cm;
300 struct GNUNET_CADET_ClientChannelNumber ccn;
301
302 ccn = client_get_next_ccn (c);
303 GNUNET_assert (GNUNET_YES ==
304 GNUNET_CONTAINER_multihashmap32_put (c->channels,
305 ntohl (
306 ccn.channel_of_client),
307 ch,
308 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
309 LOG (GNUNET_ERROR_TYPE_DEBUG,
310 "Accepting incoming %s from %s on open port %s (%u), assigning ccn %X\n",
311 GCCH_2s (ch),
312 GCP_2s (dest),
313 GNUNET_h2s (port),
314 (uint32_t) ntohl (options),
315 (uint32_t) ntohl (ccn.channel_of_client));
316 /* notify local client about incoming connection! */
317 env = GNUNET_MQ_msg (cm,
318 GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE);
319 cm->ccn = ccn;
320 cm->port = *port;
321 cm->opt = htonl (options);
322 cm->peer = *GCP_get_id (dest);
323 GSC_send_to_client (c,
324 env);
325 return ccn;
326}
327
328
329/**
330 * Callback invoked on all peers to destroy all tunnels
331 * that may still exist.
332 *
333 * @param cls NULL
334 * @param pid identify of a peer
335 * @param value a `struct CadetPeer` that may still have a tunnel
336 * @return #GNUNET_OK (iterate over all entries)
337 */
338static int
339destroy_tunnels_now (void *cls,
340 const struct GNUNET_PeerIdentity *pid,
341 void *value)
342{
343 struct CadetPeer *cp = value;
344 struct CadetTunnel *t = GCP_get_tunnel (cp,
345 GNUNET_NO);
346
347 if (NULL != t)
348 GCT_destroy_tunnel_now (t);
349 return GNUNET_OK;
350}
351
352
353/**
354 * Callback invoked on all peers to destroy all tunnels
355 * that may still exist.
356 *
357 * @param cls NULL
358 * @param pid identify of a peer
359 * @param value a `struct CadetPeer` that may still have a tunnel
360 * @return #GNUNET_OK (iterate over all entries)
361 */
362static int
363destroy_paths_now (void *cls,
364 const struct GNUNET_PeerIdentity *pid,
365 void *value)
366{
367 struct CadetPeer *cp = value;
368
369 GCP_drop_owned_paths (cp);
370 return GNUNET_OK;
371}
372
373
374/**
375 * Shutdown everything once the clients have disconnected.
376 */
377static void
378shutdown_rest ()
379{
380 if (NULL != stats)
381 {
382 GNUNET_STATISTICS_destroy (stats,
383 GNUNET_NO);
384 stats = NULL;
385 }
386 /* Destroy tunnels. Note that all channels must be destroyed first! */
387 GCP_iterate_all (&destroy_tunnels_now,
388 NULL);
389 /* All tunnels, channels, connections and CORE must be down before this point. */
390 GCP_iterate_all (&destroy_paths_now,
391 NULL);
392 /* All paths, tunnels, channels, connections and CORE must be down before this point. */
393 GCP_destroy_all_peers ();
394 if (NULL != open_ports)
395 {
396 GNUNET_CONTAINER_multihashmap_destroy (open_ports);
397 open_ports = NULL;
398 }
399 if (NULL != loose_channels)
400 {
401 GNUNET_CONTAINER_multihashmap_destroy (loose_channels);
402 loose_channels = NULL;
403 }
404 if (NULL != peers)
405 {
406 GNUNET_CONTAINER_multipeermap_destroy (peers);
407 peers = NULL;
408 }
409 if (NULL != connections)
410 {
411 GNUNET_CONTAINER_multishortmap_destroy (connections);
412 connections = NULL;
413 }
414 if (NULL != transport)
415 {
416 GNUNET_TRANSPORT_application_done (transport);
417 transport = NULL;
418 }
419 GCD_shutdown ();
420 GCH_shutdown ();
421 GNUNET_free (my_private_key);
422 my_private_key = NULL;
423}
424
425
426/**
427 * Task run during shutdown.
428 *
429 * @param cls unused
430 */
431static void
432shutdown_task (void *cls)
433{
434 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
435 "Shutting down\n");
436 shutting_down = GNUNET_YES;
437 GCO_shutdown ();
438 if (NULL == clients_head)
439 shutdown_rest ();
440}
441
442
443/**
444 * We had a remote connection @a value to port @a h_port before
445 * client @a cls opened port @a port. Bind them now.
446 *
447 * @param cls the `struct CadetClient`
448 * @param port the hashed port
449 * @param value the `struct CadetChannel`
450 * @return #GNUNET_YES (iterate over all such channels)
451 */
452static int
453bind_loose_channel (void *cls,
454 const struct GNUNET_HashCode *port,
455 void *value)
456{
457 struct OpenPort *op = cls;
458 struct CadetChannel *ch = value;
459
460 GCCH_bind (ch,
461 op->c,
462 &op->port);
463 GNUNET_assert (GNUNET_YES ==
464 GNUNET_CONTAINER_multihashmap_remove (loose_channels,
465 &op->h_port,
466 ch));
467 return GNUNET_YES;
468}
469
470
471/**
472 * Handle port open request. Creates a mapping from the
473 * port to the respective client and checks whether we have
474 * loose channels trying to bind to the port. If so, those
475 * are bound.
476 *
477 * @param cls Identification of the client.
478 * @param pmsg The actual message.
479 */
480static void
481handle_port_open (void *cls,
482 const struct GNUNET_CADET_PortMessage *pmsg)
483{
484 struct CadetClient *c = cls;
485 struct OpenPort *op;
486
487 LOG (GNUNET_ERROR_TYPE_DEBUG,
488 "Open port %s requested by %s\n",
489 GNUNET_h2s (&pmsg->port),
490 GSC_2s (c));
491 if (NULL == c->ports)
492 c->ports = GNUNET_CONTAINER_multihashmap_create (4,
493 GNUNET_NO);
494 op = GNUNET_new (struct OpenPort);
495 op->c = c;
496 op->port = pmsg->port;
497 GCCH_hash_port (&op->h_port,
498 &pmsg->port,
499 &my_full_id);
500 if (GNUNET_OK !=
501 GNUNET_CONTAINER_multihashmap_put (c->ports,
502 &op->port,
503 op,
504 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
505 {
506 GNUNET_break (0);
507 GNUNET_SERVICE_client_drop (c->client);
508 return;
509 }
510 (void) GNUNET_CONTAINER_multihashmap_put (open_ports,
511 &op->h_port,
512 op,
513 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
514 GNUNET_CONTAINER_multihashmap_get_multiple (loose_channels,
515 &op->h_port,
516 &bind_loose_channel,
517 op);
518 GNUNET_SERVICE_client_continue (c->client);
519}
520
521
522/**
523 * Handler for port close requests. Marks this port as closed
524 * (unless of course we have another client with the same port
525 * open). Note that existing channels accepted on the port are
526 * not affected.
527 *
528 * @param cls Identification of the client.
529 * @param pmsg The actual message.
530 */
531static void
532handle_port_close (void *cls,
533 const struct GNUNET_CADET_PortMessage *pmsg)
534{
535 struct CadetClient *c = cls;
536 struct OpenPort *op;
537
538 LOG (GNUNET_ERROR_TYPE_DEBUG,
539 "Closing port %s as requested by %s\n",
540 GNUNET_h2s (&pmsg->port),
541 GSC_2s (c));
542 if (NULL == c->ports)
543 {
544 /* Client closed a port despite _never_ having opened one? */
545 GNUNET_break (0);
546 GNUNET_SERVICE_client_drop (c->client);
547 return;
548 }
549 op = GNUNET_CONTAINER_multihashmap_get (c->ports,
550 &pmsg->port);
551 if (NULL == op)
552 {
553 GNUNET_break (0);
554 GNUNET_SERVICE_client_drop (c->client);
555 return;
556 }
557 GNUNET_assert (GNUNET_YES ==
558 GNUNET_CONTAINER_multihashmap_remove (c->ports,
559 &op->port,
560 op));
561 GNUNET_assert (GNUNET_YES ==
562 GNUNET_CONTAINER_multihashmap_remove (open_ports,
563 &op->h_port,
564 op));
565 GNUNET_free (op);
566 GNUNET_SERVICE_client_continue (c->client);
567}
568
569
570/**
571 * Handler for requests for us creating a new channel to another peer and port.
572 *
573 * @param cls Identification of the client.
574 * @param tcm The actual message.
575 */
576static void
577handle_channel_create (void *cls,
578 const struct GNUNET_CADET_LocalChannelCreateMessage *tcm)
579{
580 struct CadetClient *c = cls;
581 struct CadetChannel *ch;
582
583 if (ntohl (tcm->ccn.channel_of_client) < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
584 {
585 /* Channel ID not in allowed range. */
586 LOG (GNUNET_ERROR_TYPE_DEBUG,"Channel ID not in allowed range.");
587 GNUNET_break (0);
588 GNUNET_SERVICE_client_drop (c->client);
589 return;
590 }
591 ch = lookup_channel (c,
592 tcm->ccn);
593 if (NULL != ch)
594 {
595 /* Channel ID already in use. Not allowed. */
596 LOG (GNUNET_ERROR_TYPE_DEBUG,"Channel ID already in use. Not allowed.");
597 GNUNET_break (0);
598 GNUNET_SERVICE_client_drop (c->client);
599 return;
600 }
601 LOG (GNUNET_ERROR_TYPE_DEBUG,
602 "New channel to %s at port %s requested by %s\n",
603 GNUNET_i2s (&tcm->peer),
604 GNUNET_h2s (&tcm->port),
605 GSC_2s (c));
606
607 /* Create channel */
608 ch = GCCH_channel_local_new (c,
609 tcm->ccn,
610 GCP_get (&tcm->peer,
611 GNUNET_YES),
612 &tcm->port,
613 ntohl (tcm->opt));
614 if (NULL == ch)
615 {
616 GNUNET_break (0);
617 GNUNET_SERVICE_client_drop (c->client);
618 return;
619 }
620 GNUNET_assert (GNUNET_YES ==
621 GNUNET_CONTAINER_multihashmap32_put (c->channels,
622 ntohl (
623 tcm->ccn.
624 channel_of_client),
625 ch,
626 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
627
628 GNUNET_SERVICE_client_continue (c->client);
629}
630
631
632/**
633 * Handler for requests of destroying an existing channel.
634 *
635 * @param cls client identification of the client
636 * @param msg the actual message
637 */
638static void
639handle_channel_destroy (void *cls,
640 const struct
641 GNUNET_CADET_LocalChannelDestroyMessage *msg)
642{
643 struct CadetClient *c = cls;
644 struct CadetChannel *ch;
645
646 ch = lookup_channel (c,
647 msg->ccn);
648 if (NULL == ch)
649 {
650 /* Client attempted to destroy unknown channel.
651 Can happen if the other side went down at the same time.*/
652 LOG (GNUNET_ERROR_TYPE_DEBUG,
653 "%s tried to destroy unknown channel %X\n",
654 GSC_2s (c),
655 (uint32_t) ntohl (msg->ccn.channel_of_client));
656 GNUNET_SERVICE_client_continue (c->client);
657 return;
658 }
659 LOG (GNUNET_ERROR_TYPE_DEBUG,
660 "%s is destroying %s\n",
661 GSC_2s (c),
662 GCCH_2s (ch));
663 GNUNET_assert (GNUNET_YES ==
664 GNUNET_CONTAINER_multihashmap32_remove (c->channels,
665 ntohl (
666 msg->ccn.
667 channel_of_client),
668 ch));
669 GCCH_channel_local_destroy (ch,
670 c,
671 msg->ccn);
672 GNUNET_SERVICE_client_continue (c->client);
673}
674
675
676/**
677 * Check for client traffic data message is well-formed.
678 *
679 * @param cls identification of the client
680 * @param msg the actual message
681 * @return #GNUNET_OK if @a msg is OK, #GNUNET_SYSERR if not
682 */
683static int
684check_local_data (void *cls,
685 const struct GNUNET_CADET_LocalData *msg)
686{
687 size_t payload_size;
688 size_t payload_claimed_size;
689 const char *buf;
690 struct GNUNET_MessageHeader pa;
691
692 /* FIXME: what is the format we shall allow for @a msg?
693 ONE payload item or multiple? Seems current cadet_api
694 at least in theory allows more than one. Next-gen
695 cadet_api will likely no more, so we could then
696 simplify this mess again. *//* Sanity check for message size */payload_size = ntohs (msg->header.size) - sizeof(*msg);
697 buf = (const char *) &msg[1];
698 while (payload_size >= sizeof(struct GNUNET_MessageHeader))
699 {
700 /* need to memcpy() for alignment */
701 GNUNET_memcpy (&pa,
702 buf,
703 sizeof(pa));
704 payload_claimed_size = ntohs (pa.size);
705 if ((payload_size < payload_claimed_size) ||
706 (payload_claimed_size < sizeof(struct GNUNET_MessageHeader)) ||
707 (GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE < payload_claimed_size))
708 {
709 GNUNET_break (0);
710 LOG (GNUNET_ERROR_TYPE_DEBUG,
711 "Local data of %u total size had sub-message %u at %u with %u bytes\n",
712 ntohs (msg->header.size),
713 ntohs (pa.type),
714 (unsigned int) (buf - (const char *) &msg[1]),
715 (unsigned int) payload_claimed_size);
716 return GNUNET_SYSERR;
717 }
718 payload_size -= payload_claimed_size;
719 buf += payload_claimed_size;
720 }
721 if (0 != payload_size)
722 {
723 GNUNET_break_op (0);
724 return GNUNET_SYSERR;
725 }
726 return GNUNET_OK;
727}
728
729
730/**
731 * Handler for client payload traffic to be send on a channel to
732 * another peer.
733 *
734 * @param cls identification of the client
735 * @param msg the actual message
736 */
737static void
738handle_local_data (void *cls,
739 const struct GNUNET_CADET_LocalData *msg)
740{
741 struct CadetClient *c = cls;
742 struct CadetChannel *ch;
743 size_t payload_size;
744 const char *buf;
745
746 ch = lookup_channel (c,
747 msg->ccn);
748 if (NULL == ch)
749 {
750 /* Channel does not exist (anymore) */
751 LOG (GNUNET_ERROR_TYPE_WARNING,
752 "Dropping payload for channel %u from client (channel unknown, other endpoint may have disconnected)\n",
753 (unsigned int) ntohl (msg->ccn.channel_of_client));
754 GNUNET_SERVICE_client_continue (c->client);
755 return;
756 }
757 payload_size = ntohs (msg->header.size) - sizeof(*msg);
758 GNUNET_STATISTICS_update (stats,
759 "# payload received from clients",
760 payload_size,
761 GNUNET_NO);
762 buf = (const char *) &msg[1];
763 LOG (GNUNET_ERROR_TYPE_DEBUG,
764 "Received %u bytes payload from %s for %s\n",
765 (unsigned int) payload_size,
766 GSC_2s (c),
767 GCCH_2s (ch));
768 if (GNUNET_OK !=
769 GCCH_handle_local_data (ch,
770 msg->ccn,
771 buf,
772 payload_size))
773 {
774 GNUNET_break (0);
775 GNUNET_SERVICE_client_drop (c->client);
776 return;
777 }
778 GNUNET_SERVICE_client_continue (c->client);
779}
780
781
782/**
783 * Handler for client's ACKs for payload traffic.
784 *
785 * @param cls identification of the client.
786 * @param msg The actual message.
787 */
788static void
789handle_local_ack (void *cls,
790 const struct GNUNET_CADET_LocalAck *msg)
791{
792 struct CadetClient *c = cls;
793 struct CadetChannel *ch;
794
795 ch = lookup_channel (c,
796 msg->ccn);
797 if (NULL == ch)
798 {
799 /* Channel does not exist (anymore) */
800 LOG (GNUNET_ERROR_TYPE_WARNING,
801 "Ignoring local ACK for channel %u from client (channel unknown, other endpoint may have disconnected)\n",
802 (unsigned int) ntohl (msg->ccn.channel_of_client));
803 GNUNET_SERVICE_client_continue (c->client);
804 return;
805 }
806 LOG (GNUNET_ERROR_TYPE_DEBUG,
807 "Got a local ACK from %s for %s\n",
808 GSC_2s (c),
809 GCCH_2s (ch));
810 GCCH_handle_local_ack (ch,
811 msg->ccn);
812 GNUNET_SERVICE_client_continue (c->client);
813}
814
815
816/**
817 * Iterator over all peers to send a monitoring client info about each peer.
818 *
819 * @param cls Closure ().
820 * @param peer Peer ID (tunnel remote peer).
821 * @param value Peer info.
822 * @return #GNUNET_YES, to keep iterating.
823 */
824static int
825get_all_peers_iterator (void *cls,
826 const struct GNUNET_PeerIdentity *peer,
827 void *value)
828{
829 struct CadetClient *c = cls;
830 struct CadetPeer *p = value;
831 struct GNUNET_MQ_Envelope *env;
832 struct GNUNET_CADET_LocalInfoPeers *msg;
833
834 env = GNUNET_MQ_msg (msg,
835 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS);
836 msg->destination = *peer;
837 msg->paths = htons (GCP_count_paths (p));
838 msg->tunnel = htons (NULL != GCP_get_tunnel (p,
839 GNUNET_NO));
840 msg->best_path_length = htonl (0); // FIXME: get length of shortest known path!
841 GNUNET_MQ_send (c->mq,
842 env);
843 return GNUNET_YES;
844}
845
846
847/**
848 * Handler for client's INFO PEERS request.
849 *
850 * @param cls Identification of the client.
851 * @param message The actual message.
852 */
853static void
854handle_get_peers (void *cls,
855 const struct GNUNET_MessageHeader *message)
856{
857 struct CadetClient *c = cls;
858 struct GNUNET_MQ_Envelope *env;
859 struct GNUNET_MessageHeader *reply;
860
861 GCP_iterate_all (&get_all_peers_iterator,
862 c);
863 env = GNUNET_MQ_msg (reply,
864 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS_END);
865 GNUNET_MQ_send (c->mq,
866 env);
867 GNUNET_SERVICE_client_continue (c->client);
868}
869
870
871/**
872 * Iterator over all paths of a peer to build an InfoPeer message.
873 * Message contains blocks of peers, first not included.
874 *
875 * @param cls message queue for transmission
876 * @param path Path itself
877 * @param off offset of the peer on @a path
878 * @return #GNUNET_YES if should keep iterating.
879 * #GNUNET_NO otherwise.
880 */
881static int
882path_info_iterator (void *cls,
883 struct CadetPeerPath *path,
884 unsigned int off)
885{
886 struct GNUNET_MQ_Handle *mq = cls;
887 struct GNUNET_MQ_Envelope *env;
888 struct GNUNET_CADET_LocalInfoPath *resp;
889 struct GNUNET_PeerIdentity *id;
890 size_t path_size;
891 unsigned int path_length;
892
893 path_length = GCPP_get_length (path);
894 path_size = sizeof(struct GNUNET_PeerIdentity) * path_length;
895 if (sizeof(*resp) + path_size > UINT16_MAX)
896 {
897 /* try just giving the relevant path */
898 path_length = GNUNET_MIN ((UINT16_MAX - sizeof(*resp)) / sizeof(struct
899 GNUNET_PeerIdentity),
900 off);
901 path_size = sizeof(struct GNUNET_PeerIdentity) * path_length;
902 }
903 if (sizeof(*resp) + path_size > UINT16_MAX)
904 {
905 LOG (GNUNET_ERROR_TYPE_WARNING,
906 "Path of %u entries is too long for info message\n",
907 path_length);
908 return GNUNET_YES;
909 }
910 env = GNUNET_MQ_msg_extra (resp,
911 path_size,
912 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PATH);
913 id = (struct GNUNET_PeerIdentity *) &resp[1];
914
915 /* Don't copy first peer. First peer is always the local one. Last
916 * peer is always the destination (leave as 0, EOL).
917 */
918 for (unsigned int i = 0; i < path_length; i++)
919 id[i] = *GCP_get_id (GCPP_get_peer_at_offset (path,
920 i));
921 resp->off = htonl (off);
922 GNUNET_MQ_send (mq,
923 env);
924 return GNUNET_YES;
925}
926
927
928/**
929 * Handler for client's #GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_PATH request.
930 *
931 * @param cls Identification of the client.
932 * @param msg The actual message.
933 */
934static void
935handle_show_path (void *cls,
936 const struct GNUNET_CADET_RequestPathInfoMessage *msg)
937{
938 struct CadetClient *c = cls;
939 struct CadetPeer *p;
940 struct GNUNET_MQ_Envelope *env;
941 struct GNUNET_MessageHeader *resp;
942
943 p = GCP_get (&msg->peer,
944 GNUNET_NO);
945 if (NULL != p)
946 GCP_iterate_indirect_paths (p,
947 &path_info_iterator,
948 c->mq);
949 env = GNUNET_MQ_msg (resp,
950 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PATH_END);
951 GNUNET_MQ_send (c->mq,
952 env);
953 GNUNET_SERVICE_client_continue (c->client);
954}
955
956
957/**
958 * Iterator over all tunnels to send a monitoring client info about each tunnel.
959 *
960 * @param cls Closure ().
961 * @param peer Peer ID (tunnel remote peer).
962 * @param value a `struct CadetPeer`
963 * @return #GNUNET_YES, to keep iterating.
964 */
965static int
966get_all_tunnels_iterator (void *cls,
967 const struct GNUNET_PeerIdentity *peer,
968 void *value)
969{
970 struct CadetClient *c = cls;
971 struct CadetPeer *p = value;
972 struct GNUNET_MQ_Envelope *env;
973 struct GNUNET_CADET_LocalInfoTunnel *msg;
974 struct CadetTunnel *t;
975
976 t = GCP_get_tunnel (p,
977 GNUNET_NO);
978 if (NULL == t)
979 return GNUNET_YES;
980 env = GNUNET_MQ_msg (msg,
981 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS);
982 msg->destination = *peer;
983 msg->channels = htonl (GCT_count_channels (t));
984 msg->connections = htonl (GCT_count_any_connections (t));
985 msg->cstate = htons (0);
986 msg->estate = htons ((uint16_t) GCT_get_estate (t));
987 GNUNET_MQ_send (c->mq,
988 env);
989 return GNUNET_YES;
990}
991
992
993/**
994 * Handler for client's #GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_TUNNELS request.
995 *
996 * @param cls client Identification of the client.
997 * @param message The actual message.
998 */
999static void
1000handle_info_tunnels (void *cls,
1001 const struct GNUNET_MessageHeader *message)
1002{
1003 struct CadetClient *c = cls;
1004 struct GNUNET_MQ_Envelope *env;
1005 struct GNUNET_MessageHeader *reply;
1006
1007 GCP_iterate_all (&get_all_tunnels_iterator,
1008 c);
1009 env = GNUNET_MQ_msg (reply,
1010 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS_END);
1011 GNUNET_MQ_send (c->mq,
1012 env);
1013 GNUNET_SERVICE_client_continue (c->client);
1014}
1015
1016
1017/**
1018 * Handler for client's #GNUNET_MESSAGE_TYPE_CADET_DROP_CADET_MESSAGE request.
1019 *
1020 * @param cls client Identification of the client.
1021 * @param message The actual message.
1022 */
1023static void
1024handle_drop_message (void *cls,
1025 const struct GNUNET_CADET_RequestDropCadetMessage *message)
1026{
1027 struct CadetClient *c = cls;
1028 struct CadetChannel *ch;
1029
1030 ch = lookup_channel (c,
1031 message->ccn);
1032
1033 if (NULL != ch)
1034 GCCH_assign_type_to_drop (ch, message);
1035
1036 GNUNET_SERVICE_client_continue (c->client);
1037}
1038
1039
1040/**
1041 * Callback called when a client connects to the service.
1042 *
1043 * @param cls closure for the service
1044 * @param client the new client that connected to the service
1045 * @param mq the message queue used to send messages to the client
1046 * @return @a c
1047 */
1048static void *
1049client_connect_cb (void *cls,
1050 struct GNUNET_SERVICE_Client *client,
1051 struct GNUNET_MQ_Handle *mq)
1052{
1053 struct CadetClient *c;
1054
1055 c = GNUNET_new (struct CadetClient);
1056 c->client = client;
1057 c->mq = mq;
1058 c->id = next_client_id++; /* overflow not important: just for debug */
1059 c->channels
1060 = GNUNET_CONTAINER_multihashmap32_create (32);
1061 GNUNET_CONTAINER_DLL_insert (clients_head,
1062 clients_tail,
1063 c);
1064 GNUNET_STATISTICS_update (stats,
1065 "# clients",
1066 +1,
1067 GNUNET_NO);
1068 LOG (GNUNET_ERROR_TYPE_DEBUG,
1069 "%s connected\n",
1070 GSC_2s (c));
1071 return c;
1072}
1073
1074
1075/**
1076 * A channel was destroyed by the other peer. Tell our client.
1077 *
1078 * @param c client that lost a channel
1079 * @param ccn channel identification number for the client
1080 * @param ch the channel object
1081 */
1082void
1083GSC_handle_remote_channel_destroy (struct CadetClient *c,
1084 struct GNUNET_CADET_ClientChannelNumber ccn,
1085 struct CadetChannel *ch)
1086{
1087 struct GNUNET_MQ_Envelope *env;
1088 struct GNUNET_CADET_LocalChannelDestroyMessage *tdm;
1089
1090 env = GNUNET_MQ_msg (tdm,
1091 GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY);
1092 tdm->ccn = ccn;
1093 GSC_send_to_client (c,
1094 env);
1095 GNUNET_assert (GNUNET_YES ==
1096 GNUNET_CONTAINER_multihashmap32_remove (c->channels,
1097 ntohl (
1098 ccn.channel_of_client),
1099 ch));
1100}
1101
1102
1103void
1104GSC_drop_loose_channel (const struct GNUNET_HashCode *h_port,
1105 struct CadetChannel *ch)
1106{
1107 GNUNET_assert (GNUNET_YES ==
1108 GNUNET_CONTAINER_multihashmap_remove (loose_channels,
1109 h_port,
1110 ch));
1111}
1112
1113
1114/**
1115 * Iterator for deleting each channel whose client endpoint disconnected.
1116 *
1117 * @param cls Closure (client that has disconnected).
1118 * @param key The local channel id in host byte order
1119 * @param value The value stored at the key (channel to destroy).
1120 * @return #GNUNET_OK, keep iterating.
1121 */
1122static int
1123channel_destroy_iterator (void *cls,
1124 uint32_t key,
1125 void *value)
1126{
1127 struct CadetClient *c = cls;
1128 struct GNUNET_CADET_ClientChannelNumber ccn;
1129 struct CadetChannel *ch = value;
1130
1131 LOG (GNUNET_ERROR_TYPE_DEBUG,
1132 "Destroying %s, due to %s disconnecting.\n",
1133 GCCH_2s (ch),
1134 GSC_2s (c));
1135 ccn.channel_of_client = htonl (key);
1136 GNUNET_assert (GNUNET_YES ==
1137 GNUNET_CONTAINER_multihashmap32_remove (c->channels,
1138 key,
1139 ch));
1140 GCCH_channel_local_destroy (ch,
1141 c,
1142 ccn);
1143 return GNUNET_OK;
1144}
1145
1146
1147/**
1148 * Remove client's ports from the global hashmap on disconnect.
1149 *
1150 * @param cls the `struct CadetClient`
1151 * @param port the port.
1152 * @param value the `struct OpenPort` to remove
1153 * @return #GNUNET_OK, keep iterating.
1154 */
1155static int
1156client_release_ports (void *cls,
1157 const struct GNUNET_HashCode *port,
1158 void *value)
1159{
1160 struct CadetClient *c = cls;
1161 struct OpenPort *op = value;
1162
1163 GNUNET_assert (c == op->c);
1164 LOG (GNUNET_ERROR_TYPE_DEBUG,
1165 "Closing port %s due to %s disconnect.\n",
1166 GNUNET_h2s (port),
1167 GSC_2s (c));
1168 GNUNET_assert (GNUNET_YES ==
1169 GNUNET_CONTAINER_multihashmap_remove (open_ports,
1170 &op->h_port,
1171 op));
1172 GNUNET_assert (GNUNET_YES ==
1173 GNUNET_CONTAINER_multihashmap_remove (c->ports,
1174 port,
1175 op));
1176 GNUNET_free (op);
1177 return GNUNET_OK;
1178}
1179
1180
1181/**
1182 * Callback called when a client disconnected from the service
1183 *
1184 * @param cls closure for the service
1185 * @param client the client that disconnected
1186 * @param internal_cls should be equal to @a c
1187 */
1188static void
1189client_disconnect_cb (void *cls,
1190 struct GNUNET_SERVICE_Client *client,
1191 void *internal_cls)
1192{
1193 struct CadetClient *c = internal_cls;
1194
1195 GNUNET_assert (c->client == client);
1196 LOG (GNUNET_ERROR_TYPE_DEBUG,
1197 "%s is disconnecting.\n",
1198 GSC_2s (c));
1199 if (NULL != c->channels)
1200 {
1201 GNUNET_CONTAINER_multihashmap32_iterate (c->channels,
1202 &channel_destroy_iterator,
1203 c);
1204 GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap32_size (c->channels));
1205 GNUNET_CONTAINER_multihashmap32_destroy (c->channels);
1206 }
1207 if (NULL != c->ports)
1208 {
1209 GNUNET_CONTAINER_multihashmap_iterate (c->ports,
1210 &client_release_ports,
1211 c);
1212 GNUNET_CONTAINER_multihashmap_destroy (c->ports);
1213 }
1214 GNUNET_CONTAINER_DLL_remove (clients_head,
1215 clients_tail,
1216 c);
1217 GNUNET_STATISTICS_update (stats,
1218 "# clients",
1219 -1,
1220 GNUNET_NO);
1221 GNUNET_free (c);
1222 if ((NULL == clients_head) &&
1223 (GNUNET_YES == shutting_down))
1224 shutdown_rest ();
1225}
1226
1227
1228/**
1229 * Setup CADET internals.
1230 *
1231 * @param cls closure
1232 * @param c configuration to use
1233 */
1234static void
1235run (void *cls,
1236 const struct GNUNET_CONFIGURATION_Handle *c,
1237 struct GNUNET_SERVICE_Handle *service)
1238{
1239 cfg = c;
1240 if (GNUNET_OK !=
1241 GNUNET_CONFIGURATION_get_value_number (c,
1242 "CADET",
1243 "RATCHET_MESSAGES",
1244 &ratchet_messages))
1245 {
1246 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
1247 "CADET",
1248 "RATCHET_MESSAGES",
1249 "needs to be a number");
1250 ratchet_messages = 64;
1251 }
1252 if (GNUNET_OK !=
1253 GNUNET_CONFIGURATION_get_value_time (c,
1254 "CADET",
1255 "RATCHET_TIME",
1256 &ratchet_time))
1257 {
1258 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
1259 "CADET",
1260 "RATCHET_TIME",
1261 "need delay value");
1262 ratchet_time = GNUNET_TIME_UNIT_HOURS;
1263 }
1264 if (GNUNET_OK !=
1265 GNUNET_CONFIGURATION_get_value_time (c,
1266 "CADET",
1267 "REFRESH_CONNECTION_TIME",
1268 &keepalive_period))
1269 {
1270 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
1271 "CADET",
1272 "REFRESH_CONNECTION_TIME",
1273 "need delay value");
1274 keepalive_period = GNUNET_TIME_UNIT_MINUTES;
1275 }
1276 if (GNUNET_OK !=
1277 GNUNET_CONFIGURATION_get_value_number (c,
1278 "CADET",
1279 "DROP_PERCENT",
1280 &drop_percent))
1281 {
1282 drop_percent = 0;
1283 }
1284 else
1285 {
1286 LOG (GNUNET_ERROR_TYPE_WARNING, "**************************************\n");
1287 LOG (GNUNET_ERROR_TYPE_WARNING, "Cadet is running with DROP enabled.\n");
1288 LOG (GNUNET_ERROR_TYPE_WARNING, "This is NOT a good idea!\n");
1289 LOG (GNUNET_ERROR_TYPE_WARNING, "Remove DROP_PERCENT from config file.\n");
1290 LOG (GNUNET_ERROR_TYPE_WARNING, "**************************************\n");
1291 }
1292 my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (c);
1293 if (NULL == my_private_key)
1294 {
1295 GNUNET_break (0);
1296 GNUNET_SCHEDULER_shutdown ();
1297 return;
1298 }
1299 GNUNET_CRYPTO_eddsa_key_get_public (my_private_key,
1300 &my_full_id.public_key);
1301 stats = GNUNET_STATISTICS_create ("cadet",
1302 c);
1303 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
1304 NULL);
1305 transport = GNUNET_TRANSPORT_application_init (c);
1306 /* FIXME: optimize code to allow GNUNET_YES here! */
1307 open_ports = GNUNET_CONTAINER_multihashmap_create (16,
1308 GNUNET_NO);
1309 loose_channels = GNUNET_CONTAINER_multihashmap_create (16,
1310 GNUNET_NO);
1311 peers = GNUNET_CONTAINER_multipeermap_create (16,
1312 GNUNET_YES);
1313 connections = GNUNET_CONTAINER_multishortmap_create (256,
1314 GNUNET_YES);
1315 GCH_init (c);
1316 GCD_init (c);
1317 GCO_init (c);
1318 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1319 "CADET started for peer %s\n",
1320 GNUNET_i2s (&my_full_id));
1321}
1322
1323
1324/**
1325 * Define "main" method using service macro.
1326 */
1327GNUNET_SERVICE_MAIN
1328 ("cadet",
1329 GNUNET_SERVICE_OPTION_NONE,
1330 &run,
1331 &client_connect_cb,
1332 &client_disconnect_cb,
1333 NULL,
1334 GNUNET_MQ_hd_fixed_size (port_open,
1335 GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN,
1336 struct GNUNET_CADET_PortMessage,
1337 NULL),
1338 GNUNET_MQ_hd_fixed_size (port_close,
1339 GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE,
1340 struct GNUNET_CADET_PortMessage,
1341 NULL),
1342 GNUNET_MQ_hd_fixed_size (channel_create,
1343 GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE,
1344 struct GNUNET_CADET_LocalChannelCreateMessage,
1345 NULL),
1346 GNUNET_MQ_hd_fixed_size (channel_destroy,
1347 GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY,
1348 struct GNUNET_CADET_LocalChannelDestroyMessage,
1349 NULL),
1350 GNUNET_MQ_hd_var_size (local_data,
1351 GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA,
1352 struct GNUNET_CADET_LocalData,
1353 NULL),
1354 GNUNET_MQ_hd_fixed_size (local_ack,
1355 GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK,
1356 struct GNUNET_CADET_LocalAck,
1357 NULL),
1358 GNUNET_MQ_hd_fixed_size (get_peers,
1359 GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_PEERS,
1360 struct GNUNET_MessageHeader,
1361 NULL),
1362 GNUNET_MQ_hd_fixed_size (show_path,
1363 GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_PATH,
1364 struct GNUNET_CADET_RequestPathInfoMessage,
1365 NULL),
1366 GNUNET_MQ_hd_fixed_size (info_tunnels,
1367 GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_TUNNELS,
1368 struct GNUNET_MessageHeader,
1369 NULL),
1370 GNUNET_MQ_hd_fixed_size (drop_message,
1371 GNUNET_MESSAGE_TYPE_CADET_DROP_CADET_MESSAGE,
1372 struct GNUNET_CADET_RequestDropCadetMessage,
1373 NULL),
1374 GNUNET_MQ_handler_end ());
1375
1376/* end of gnunet-service-cadet-new.c */
diff --git a/src/service/cadet/gnunet-service-cadet.h b/src/service/cadet/gnunet-service-cadet.h
new file mode 100644
index 000000000..8f2386d00
--- /dev/null
+++ b/src/service/cadet/gnunet-service-cadet.h
@@ -0,0 +1,328 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2001-2017 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file cadet/gnunet-service-cadet.h
23 * @brief Information we track per peer.
24 * @author Bartlomiej Polot
25 * @author Christian Grothoff
26 */
27#ifndef GNUNET_SERVICE_CADET_H
28#define GNUNET_SERVICE_CADET_H
29
30#include "gnunet_util_lib.h"
31#include "cadet_protocol.h"
32
33/**
34 * A client to the CADET service. Each client gets a unique handle.
35 */
36struct CadetClient;
37
38/**
39 * A peer in the GNUnet network. Each peer we care about must have one globally
40 * unique such handle within this process.
41 */
42struct CadetPeer;
43
44/**
45 * Tunnel from us to another peer. There can only be at most one
46 * tunnel per peer.
47 */
48struct CadetTunnel;
49
50/**
51 * Entry in the message queue of a `struct CadetTunnel`.
52 */
53struct CadetTunnelQueueEntry;
54
55/**
56 * A path of peer in the GNUnet network. There must only be at most
57 * once such path. Paths may share disjoint prefixes, but must all
58 * end at a unique suffix. Paths must also not be proper subsets of
59 * other existing paths.
60 */
61struct CadetPeerPath;
62
63/**
64 * Entry in a peer path.
65 */
66struct CadetPeerPathEntry
67{
68 /**
69 * DLL of paths where the same @e peer is at the same offset.
70 */
71 struct CadetPeerPathEntry *next;
72
73 /**
74 * DLL of paths where the same @e peer is at the same offset.
75 */
76 struct CadetPeerPathEntry *prev;
77
78 /**
79 * The peer at this offset of the path.
80 */
81 struct CadetPeer *peer;
82
83 /**
84 * Path this entry belongs to.
85 */
86 struct CadetPeerPath *path;
87
88 /**
89 * Connection using this path, or NULL for none.
90 */
91 struct CadetConnection *cc;
92
93 /**
94 * Path's historic score up to this point. Basically, how often did
95 * we succeed or fail to use the path up to this entry in a
96 * connection. Positive values indicate good experiences, negative
97 * values bad experiences. Code updating the score must guard
98 * against overflows.
99 */
100 int score;
101};
102
103/**
104 * Entry in list of connections used by tunnel, with metadata.
105 */
106struct CadetTConnection
107{
108 /**
109 * Next in DLL.
110 */
111 struct CadetTConnection *next;
112
113 /**
114 * Prev in DLL.
115 */
116 struct CadetTConnection *prev;
117
118 /**
119 * Connection handle.
120 */
121 struct CadetConnection *cc;
122
123 /**
124 * Tunnel this connection belongs to.
125 */
126 struct CadetTunnel *t;
127
128 /**
129 * Creation time, to keep oldest connection alive.
130 */
131 struct GNUNET_TIME_Absolute created;
132
133 /**
134 * Connection throughput, to keep fastest connection alive.
135 */
136 uint32_t throughput;
137
138 /**
139 * Is the connection currently ready for transmission?
140 */
141 int is_ready;
142};
143
144
145/**
146 * Port opened by a client.
147 */
148struct OpenPort
149{
150 /**
151 * Client that opened the port.
152 */
153 struct CadetClient *c;
154
155 /**
156 * Port number.
157 */
158 struct GNUNET_HashCode port;
159
160 /**
161 * Port hashed with our PID (matches incoming OPEN messages).
162 */
163 struct GNUNET_HashCode h_port;
164};
165
166
167/**
168 * Active path through the network (used by a tunnel). There may
169 * be at most one connection per path.
170 */
171struct CadetConnection;
172
173/**
174 * Description of a segment of a `struct CadetConnection` at the
175 * intermediate peers. Routes are basically entries in a peer's
176 * routing table for forwarding traffic. At both endpoints, the
177 * routes are terminated by a `struct CadetConnection`, which knows
178 * the complete `struct CadetPath` that is formed by the individual
179 * routes.
180 */
181struct CadetRoute;
182
183/**
184 * Logical end-to-end connection between clients. There can be
185 * any number of channels between clients.
186 */
187struct CadetChannel;
188
189/**
190 * Handle to our configuration.
191 */
192extern const struct GNUNET_CONFIGURATION_Handle *cfg;
193
194/**
195 * Handle to the statistics service.
196 */
197extern struct GNUNET_STATISTICS_Handle *stats;
198
199/**
200 * Handle to Transport service.
201 */
202extern struct GNUNET_TRANSPORT_ApplicationHandle *transport;
203
204/**
205 * Local peer own ID.
206 */
207extern struct GNUNET_PeerIdentity my_full_id;
208
209/**
210 * Own private key.
211 */
212extern struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key;
213
214/**
215 * All ports clients of this peer have opened. Maps from
216 * a hashed port to a `struct OpenPort`.
217 */
218extern struct GNUNET_CONTAINER_MultiHashMap *open_ports;
219
220/**
221 * Map from `struct GNUNET_CADET_ConnectionTunnelIdentifier`
222 * hash codes to `struct CadetConnection` objects.
223 */
224extern struct GNUNET_CONTAINER_MultiShortmap *connections;
225
226/**
227 * Map from ports to channels where the ports were closed at the
228 * time we got the inbound connection.
229 * Indexed by h_port, contains `struct CadetChannel`.
230 */
231extern struct GNUNET_CONTAINER_MultiHashMap *loose_channels;
232
233/**
234 * Map from PIDs to `struct CadetPeer` entries.
235 */
236extern struct GNUNET_CONTAINER_MultiPeerMap *peers;
237
238/**
239 * How many messages are needed to trigger an AXOLOTL ratchet advance.
240 */
241extern unsigned long long ratchet_messages;
242
243/**
244 * How long until we trigger a ratched advance due to time.
245 */
246extern struct GNUNET_TIME_Relative ratchet_time;
247
248/**
249 * How frequently do we send KEEPALIVE messages on idle connections?
250 */
251extern struct GNUNET_TIME_Relative keepalive_period;
252
253/**
254 * Signal that shutdown is happening: prevent recovery measures.
255 */
256extern int shutting_down;
257
258/**
259 * Set to non-zero values to create random drops to test retransmissions.
260 */
261extern unsigned long long drop_percent;
262
263
264/**
265 * Send a message to a client.
266 *
267 * @param c client to get the message
268 * @param env envelope with the message
269 */
270void
271GSC_send_to_client (struct CadetClient *c,
272 struct GNUNET_MQ_Envelope *env);
273
274
275/**
276 * A channel was destroyed by the other peer. Tell our client.
277 *
278 * @param c client that lost a channel
279 * @param ccn channel identification number for the client
280 * @param ch the channel object
281 */
282void
283GSC_handle_remote_channel_destroy (struct CadetClient *c,
284 struct GNUNET_CADET_ClientChannelNumber ccn,
285 struct CadetChannel *ch);
286
287/**
288 * A client that created a loose channel that was not bound to a port
289 * disconnected, drop it from the #loose_channels list.
290 *
291 * @param h_port the hashed port the channel was trying to bind to
292 * @param ch the channel that was lost
293 */
294void
295GSC_drop_loose_channel (const struct GNUNET_HashCode *h_port,
296 struct CadetChannel *ch);
297
298
299/**
300 * Bind incoming channel to this client, and notify client
301 * about incoming connection.
302 *
303 * @param c client to bind to
304 * @param ch channel to be bound
305 * @param dest peer that establishes the connection
306 * @param port port number
307 * @param options options
308 * @return local channel number assigned to the new client
309 */
310struct GNUNET_CADET_ClientChannelNumber
311GSC_bind (struct CadetClient *c,
312 struct CadetChannel *ch,
313 struct CadetPeer *dest,
314 const struct GNUNET_HashCode *port,
315 uint32_t options);
316
317
318/**
319 * Return identifier for a client as a string.
320 *
321 * @param c client to identify
322 * @return string for debugging
323 */
324const char *
325GSC_2s (struct CadetClient *c);
326
327
328#endif
diff --git a/src/service/cadet/gnunet-service-cadet_channel.c b/src/service/cadet/gnunet-service-cadet_channel.c
new file mode 100644
index 000000000..78658c296
--- /dev/null
+++ b/src/service/cadet/gnunet-service-cadet_channel.c
@@ -0,0 +1,2008 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2001-2017 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file cadet/gnunet-service-cadet_channel.c
22 * @brief logical links between CADET clients
23 * @author Bartlomiej Polot
24 * @author Christian Grothoff
25 *
26 * TODO:
27 * - Congestion/flow control:
28 * + estimate max bandwidth using bursts and use to for CONGESTION CONTROL!
29 * (and figure out how/where to use this!)
30 * + figure out flow control without ACKs (unreliable traffic!)
31 * - revisit handling of 'unbuffered' traffic!
32 * (need to push down through tunnel into connection selection)
33 * - revisit handling of 'buffered' traffic: 4 is a rather small buffer; maybe
34 * reserve more bits in 'options' to allow for buffer size control?
35 */
36#include "platform.h"
37#include "cadet.h"
38#include "gnunet_statistics_service.h"
39#include "gnunet-service-cadet_channel.h"
40#include "gnunet-service-cadet_connection.h"
41#include "gnunet-service-cadet_tunnels.h"
42#include "gnunet-service-cadet_paths.h"
43
44#define LOG(level, ...) GNUNET_log_from (level, "cadet-chn", __VA_ARGS__)
45
46/**
47 * How long do we initially wait before retransmitting?
48 */
49#define CADET_INITIAL_RETRANSMIT_TIME \
50 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 250)
51
52/**
53 * How long do we wait before dropping state about incoming
54 * connection to closed port?
55 */
56#define TIMEOUT_CLOSED_PORT \
57 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
58
59/**
60 * How long do we wait at least before retransmitting ever?
61 */
62#define MIN_RTT_DELAY \
63 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 75)
64
65/**
66 * Maximum message ID into the future we accept for out-of-order messages.
67 * If the message is more than this into the future, we drop it. This is
68 * important both to detect values that are actually in the past, as well
69 * as to limit adversarially triggerable memory consumption.
70 *
71 * Note that right now we have "max_pending_messages = 4" hard-coded in
72 * the logic below, so a value of 4 would suffice here. But we plan to
73 * allow larger windows in the future...
74 */
75#define MAX_OUT_OF_ORDER_DISTANCE 1024
76
77
78/**
79 * All the states a channel can be in.
80 */
81enum CadetChannelState
82{
83 /**
84 * Uninitialized status, should never appear in operation.
85 */
86 CADET_CHANNEL_NEW,
87
88 /**
89 * Channel is to a port that is not open, we're waiting for the
90 * port to be opened.
91 */
92 CADET_CHANNEL_LOOSE,
93
94 /**
95 * CHANNEL_OPEN message sent, waiting for CHANNEL_OPEN_ACK.
96 */
97 CADET_CHANNEL_OPEN_SENT,
98
99 /**
100 * Connection confirmed, ready to carry traffic.
101 */
102 CADET_CHANNEL_READY
103};
104
105
106/**
107 * Info needed to retry a message in case it gets lost.
108 * Note that we DO use this structure also for unreliable
109 * messages.
110 */
111struct CadetReliableMessage
112{
113 /**
114 * Double linked list, FIFO style
115 */
116 struct CadetReliableMessage *next;
117
118 /**
119 * Double linked list, FIFO style
120 */
121 struct CadetReliableMessage *prev;
122
123 /**
124 * Which channel is this message in?
125 */
126 struct CadetChannel *ch;
127
128 /**
129 * Entry in the tunnels queue for this message, NULL if it has left
130 * the tunnel. Used to cancel transmission in case we receive an
131 * ACK in time.
132 */
133 struct CadetTunnelQueueEntry *qe;
134
135 /**
136 * Data message we are trying to send.
137 */
138 struct GNUNET_CADET_ChannelAppDataMessage *data_message;
139
140 /**
141 * How soon should we retry if we fail to get an ACK?
142 * Messages in the queue are sorted by this value.
143 */
144 struct GNUNET_TIME_Absolute next_retry;
145
146 /**
147 * How long do we wait for an ACK after transmission?
148 * Use for the back-off calculation.
149 */
150 struct GNUNET_TIME_Relative retry_delay;
151
152 /**
153 * Time when we first successfully transmitted the message
154 * (that is, set @e num_transmissions to 1).
155 */
156 struct GNUNET_TIME_Absolute first_transmission_time;
157
158 /**
159 * Identifier of the connection that this message took when it
160 * was first transmitted. Only useful if @e num_transmissions is 1.
161 */
162 struct GNUNET_CADET_ConnectionTunnelIdentifier connection_taken;
163
164 /**
165 * How often was this message transmitted? #GNUNET_SYSERR if there
166 * was an error transmitting the message, #GNUNET_NO if it was not
167 * yet transmitted ever, otherwise the number of (re) transmissions.
168 */
169 int num_transmissions;
170};
171
172
173/**
174 * List of received out-of-order data messages.
175 */
176struct CadetOutOfOrderMessage
177{
178 /**
179 * Double linked list, FIFO style
180 */
181 struct CadetOutOfOrderMessage *next;
182
183 /**
184 * Double linked list, FIFO style
185 */
186 struct CadetOutOfOrderMessage *prev;
187
188 /**
189 * ID of the message (messages up to this point needed
190 * before we give this one to the client).
191 */
192 struct ChannelMessageIdentifier mid;
193
194 /**
195 * The envelope with the payload of the out-of-order message
196 */
197 struct GNUNET_MQ_Envelope *env;
198};
199
200
201/**
202 * Client endpoint of a `struct CadetChannel`. A channel may be a
203 * loopback channel, in which case it has two of these endpoints.
204 * Note that flow control also is required in both directions.
205 */
206struct CadetChannelClient
207{
208 /**
209 * Client handle. Not by itself sufficient to designate
210 * the client endpoint, as the same client handle may
211 * be used for both the owner and the destination, and
212 * we thus also need the channel ID to identify the client.
213 */
214 struct CadetClient *c;
215
216 /**
217 * Head of DLL of messages received out of order or while client was unready.
218 */
219 struct CadetOutOfOrderMessage *head_recv;
220
221 /**
222 * Tail DLL of messages received out of order or while client was unready.
223 */
224 struct CadetOutOfOrderMessage *tail_recv;
225
226 /**
227 * Local tunnel number for this client.
228 * (if owner >= #GNUNET_CADET_LOCAL_CHANNEL_ID_CLI,
229 * otherwise < #GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
230 */
231 struct GNUNET_CADET_ClientChannelNumber ccn;
232
233 /**
234 * Number of entries currently in @a head_recv DLL.
235 */
236 unsigned int num_recv;
237
238 /**
239 * Can we send data to the client?
240 */
241 int client_ready;
242};
243
244
245/**
246 * Struct containing all information regarding a channel to a remote client.
247 */
248struct CadetChannel
249{
250 /**
251 * Tunnel this channel is in.
252 */
253 struct CadetTunnel *t;
254
255 /**
256 * Client owner of the tunnel, if any.
257 * (Used if this channel represends the initiating end of the tunnel.)
258 */
259 struct CadetChannelClient *owner;
260
261 /**
262 * Client destination of the tunnel, if any.
263 * (Used if this channel represents the listening end of the tunnel.)
264 */
265 struct CadetChannelClient *dest;
266
267 /**
268 * Last entry in the tunnel's queue relating to control messages
269 * (#GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN or
270 * #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK). Used to cancel
271 * transmission in case we receive updated information.
272 */
273 struct CadetTunnelQueueEntry *last_control_qe;
274
275 /**
276 * Head of DLL of messages sent and not yet ACK'd.
277 */
278 struct CadetReliableMessage *head_sent;
279
280 /**
281 * Tail of DLL of messages sent and not yet ACK'd.
282 */
283 struct CadetReliableMessage *tail_sent;
284
285 /**
286 * Task to resend/poll in case no ACK is received.
287 */
288 struct GNUNET_SCHEDULER_Task *retry_control_task;
289
290 /**
291 * Task to resend/poll in case no ACK is received.
292 */
293 struct GNUNET_SCHEDULER_Task *retry_data_task;
294
295 /**
296 * Last time the channel was used
297 */
298 struct GNUNET_TIME_Absolute timestamp;
299
300 /**
301 * Destination port of the channel.
302 */
303 struct GNUNET_HashCode port;
304
305 /**
306 * Hash'ed port of the channel with initiator and destination PID.
307 */
308 struct GNUNET_HashCode h_port;
309
310 /**
311 * Counter for exponential backoff.
312 */
313 struct GNUNET_TIME_Relative retry_time;
314
315 /**
316 * Bitfield of already-received messages past @e mid_recv.
317 */
318 uint64_t mid_futures;
319
320 /**
321 * Next MID expected for incoming traffic.
322 */
323 struct ChannelMessageIdentifier mid_recv;
324
325 /**
326 * Next MID to use for outgoing traffic.
327 */
328 struct ChannelMessageIdentifier mid_send;
329
330 /**
331 * Total (reliable) messages pending ACK for this channel.
332 */
333 unsigned int pending_messages;
334
335 /**
336 * Maximum (reliable) messages pending ACK for this channel
337 * before we throttle the client.
338 */
339 unsigned int max_pending_messages;
340
341 /**
342 * Number identifying this channel in its tunnel.
343 */
344 struct GNUNET_CADET_ChannelTunnelNumber ctn;
345
346 /**
347 * Channel state.
348 */
349 enum CadetChannelState state;
350
351 /**
352 * Count how many ACKs we skipped, used to prevent long
353 * sequences of ACK skipping.
354 */
355 unsigned int skip_ack_series;
356
357 /**
358 * Is the tunnel bufferless (minimum latency)?
359 */
360 int nobuffer;
361
362 /**
363 * Is the tunnel reliable?
364 */
365 int reliable;
366
367 /**
368 * Is the tunnel out-of-order?
369 */
370 int out_of_order;
371
372 /**
373 * Is this channel a loopback channel, where the destination is us again?
374 */
375 int is_loopback;
376
377 /**
378 * Flag to signal the destruction of the channel. If this is set to
379 * #GNUNET_YES the channel will be destroyed once the queue is
380 * empty.
381 */
382 int destroy;
383
384 /**
385 * Type of message to be dropped. See GCT_send.
386 */
387 uint16_t type GNUNET_PACKED;
388
389};
390
391void
392GCCH_assign_type_to_drop (struct CadetChannel *ch, const struct
393 GNUNET_CADET_RequestDropCadetMessage *message)
394{
395
396 ch->type = message->type;
397
398}
399
400
401/**
402 * Check if type of message is the one to drop.
403 * @param ch CadetChannel to check for message type to drop.
404 * @param message GNUNET_MessageHeader to compare the type with.
405 */
406int
407GCCH_is_type_to_drop (struct CadetChannel *ch, const struct
408 GNUNET_MessageHeader *message)
409{
410
411 if (ch->type == message->type)
412 {
413 ch->type = 0;
414 return GNUNET_YES;
415 }
416 else
417 return GNUNET_NO;
418}
419
420
421/**
422 * Get the static string for identification of the channel.
423 *
424 * @param ch Channel.
425 *
426 * @return Static string with the channel IDs.
427 */
428const char *
429GCCH_2s (const struct CadetChannel *ch)
430{
431 static char buf[128];
432
433 GNUNET_snprintf (buf,
434 sizeof(buf),
435 "Channel %s:%s ctn:%X(%X/%X)",
436 (GNUNET_YES == ch->is_loopback)
437 ? "loopback"
438 : GNUNET_i2s (GCP_get_id (GCT_get_destination (ch->t))),
439 GNUNET_h2s (&ch->port),
440 ch->ctn.cn,
441 (NULL == ch->owner)
442 ? 0
443 : ntohl (ch->owner->ccn.channel_of_client),
444 (NULL == ch->dest)
445 ? 0
446 : ntohl (ch->dest->ccn.channel_of_client));
447 return buf;
448}
449
450
451/**
452 * Hash the @a port and @a initiator and @a listener to
453 * calculate the "challenge" @a h_port we send to the other
454 * peer on #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN.
455 *
456 * @param[out] h_port set to the hash of @a port, @a initiator and @a listener
457 * @param port cadet port, as seen by CADET clients
458 * @param listener peer that is listining on @a port
459 */
460void
461GCCH_hash_port (struct GNUNET_HashCode *h_port,
462 const struct GNUNET_HashCode *port,
463 const struct GNUNET_PeerIdentity *listener)
464{
465 struct GNUNET_HashContext *hc;
466
467 hc = GNUNET_CRYPTO_hash_context_start ();
468 GNUNET_CRYPTO_hash_context_read (hc, port, sizeof(*port));
469 GNUNET_CRYPTO_hash_context_read (hc, listener, sizeof(*listener));
470 GNUNET_CRYPTO_hash_context_finish (hc, h_port);
471 LOG (GNUNET_ERROR_TYPE_DEBUG,
472 "Calculated port hash %s\n",
473 GNUNET_h2s (h_port));
474}
475
476
477/**
478 * Get the channel's public ID.
479 *
480 * @param ch Channel.
481 *
482 * @return ID used to identify the channel with the remote peer.
483 */
484struct GNUNET_CADET_ChannelTunnelNumber
485GCCH_get_id (const struct CadetChannel *ch)
486{
487 return ch->ctn;
488}
489
490
491/**
492 * Release memory associated with @a ccc
493 *
494 * @param ccc data structure to clean up
495 */
496static void
497free_channel_client (struct CadetChannelClient *ccc)
498{
499 struct CadetOutOfOrderMessage *com;
500
501 while (NULL != (com = ccc->head_recv))
502 {
503 GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, com);
504 ccc->num_recv--;
505 GNUNET_MQ_discard (com->env);
506 GNUNET_free (com);
507 }
508 GNUNET_free (ccc);
509}
510
511
512/**
513 * Destroy the given channel.
514 *
515 * @param ch channel to destroy
516 */
517static void
518channel_destroy (struct CadetChannel *ch)
519{
520 struct CadetReliableMessage *crm;
521
522 while (NULL != (crm = ch->head_sent))
523 {
524 GNUNET_assert (ch == crm->ch);
525 if (NULL != crm->qe)
526 {
527 GCT_send_cancel (crm->qe);
528 crm->qe = NULL;
529 }
530 GNUNET_CONTAINER_DLL_remove (ch->head_sent, ch->tail_sent, crm);
531 GNUNET_free (crm->data_message);
532 GNUNET_free (crm);
533 }
534 if (CADET_CHANNEL_LOOSE == ch->state)
535 {
536 GSC_drop_loose_channel (&ch->h_port, ch);
537 }
538 if (NULL != ch->owner)
539 {
540 free_channel_client (ch->owner);
541 ch->owner = NULL;
542 }
543 if (NULL != ch->dest)
544 {
545 free_channel_client (ch->dest);
546 ch->dest = NULL;
547 }
548 if (NULL != ch->last_control_qe)
549 {
550 GCT_send_cancel (ch->last_control_qe);
551 ch->last_control_qe = NULL;
552 }
553 if (NULL != ch->retry_data_task)
554 {
555 GNUNET_SCHEDULER_cancel (ch->retry_data_task);
556 ch->retry_data_task = NULL;
557 }
558 if (NULL != ch->retry_control_task)
559 {
560 GNUNET_SCHEDULER_cancel (ch->retry_control_task);
561 ch->retry_control_task = NULL;
562 }
563 if (GNUNET_NO == ch->is_loopback)
564 {
565 GCT_remove_channel (ch->t, ch, ch->ctn);
566 ch->t = NULL;
567 }
568 GNUNET_free (ch);
569}
570
571
572/**
573 * Send a channel create message.
574 *
575 * @param cls Channel for which to send.
576 */
577static void
578send_channel_open (void *cls);
579
580
581/**
582 * Function called once the tunnel confirms that we sent the
583 * create message. Delays for a bit until we retry.
584 *
585 * @param cls our `struct CadetChannel`.
586 * @param cid identifier of the connection within the tunnel, NULL
587 * if transmission failed
588 */
589static void
590channel_open_sent_cb (void *cls,
591 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
592{
593 struct CadetChannel *ch = cls;
594
595 GNUNET_assert (NULL != ch->last_control_qe);
596 ch->last_control_qe = NULL;
597 ch->retry_time = GNUNET_TIME_STD_BACKOFF (ch->retry_time);
598 LOG (GNUNET_ERROR_TYPE_DEBUG,
599 "Sent CADET_CHANNEL_OPEN on %s, retrying in %s\n",
600 GCCH_2s (ch),
601 GNUNET_STRINGS_relative_time_to_string (ch->retry_time, GNUNET_YES));
602 ch->retry_control_task =
603 GNUNET_SCHEDULER_add_delayed (ch->retry_time, &send_channel_open, ch);
604}
605
606
607/**
608 * Send a channel open message.
609 *
610 * @param cls Channel for which to send.
611 */
612static void
613send_channel_open (void *cls)
614{
615 struct CadetChannel *ch = cls;
616 struct GNUNET_CADET_ChannelOpenMessage msgcc;
617
618 ch->retry_control_task = NULL;
619 LOG (GNUNET_ERROR_TYPE_DEBUG,
620 "Sending CHANNEL_OPEN message for %s\n",
621 GCCH_2s (ch));
622 msgcc.header.size = htons (sizeof(msgcc));
623 msgcc.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN);
624 // TODO This will be removed in a major release, because this will be a protocol breaking change. We set the deprecated "reliable" bit here that was removed.
625 msgcc.opt = 2;
626 msgcc.h_port = ch->h_port;
627 msgcc.ctn = ch->ctn;
628 ch->state = CADET_CHANNEL_OPEN_SENT;
629 if (NULL != ch->last_control_qe)
630 GCT_send_cancel (ch->last_control_qe);
631 ch->last_control_qe =
632 GCT_send (ch->t, &msgcc.header, &channel_open_sent_cb, ch, &msgcc.ctn);
633 GNUNET_assert (NULL == ch->retry_control_task);
634}
635
636
637/**
638 * Function called once and only once after a channel was bound
639 * to its tunnel via #GCT_add_channel() is ready for transmission.
640 * Note that this is only the case for channels that this peer
641 * initiates, as for incoming channels we assume that they are
642 * ready for transmission immediately upon receiving the open
643 * message. Used to bootstrap the #GCT_send() process.
644 *
645 * @param ch the channel for which the tunnel is now ready
646 */
647void
648GCCH_tunnel_up (struct CadetChannel *ch)
649{
650 GNUNET_assert (NULL == ch->retry_control_task);
651 LOG (GNUNET_ERROR_TYPE_DEBUG,
652 "Tunnel up, sending CHANNEL_OPEN on %s now\n",
653 GCCH_2s (ch));
654 ch->retry_control_task = GNUNET_SCHEDULER_add_now (&send_channel_open, ch);
655}
656
657
658struct CadetChannel *
659GCCH_channel_local_new (struct CadetClient *owner,
660 struct GNUNET_CADET_ClientChannelNumber ccn,
661 struct CadetPeer *destination,
662 const struct GNUNET_HashCode *port,
663 uint32_t options)
664{
665 struct CadetChannel *ch;
666 struct CadetChannelClient *ccco;
667
668 ccco = GNUNET_new (struct CadetChannelClient);
669 ccco->c = owner;
670 ccco->ccn = ccn;
671 ccco->client_ready = GNUNET_YES;
672
673 ch = GNUNET_new (struct CadetChannel);
674 ch->mid_recv.mid = htonl (1); /* The OPEN_ACK counts as message 0! */
675 ch->nobuffer = GNUNET_NO;
676 ch->reliable = GNUNET_YES;
677 ch->out_of_order = GNUNET_NO;
678 ch->max_pending_messages =
679 (ch->nobuffer) ? 1 : 4; /* FIXME: 4!? Do not hardcode! */
680 ch->owner = ccco;
681 ch->port = *port;
682 GCCH_hash_port (&ch->h_port, port, GCP_get_id (destination));
683 if (0 == GNUNET_memcmp (&my_full_id, GCP_get_id (destination)))
684 {
685 struct OpenPort *op;
686
687 ch->is_loopback = GNUNET_YES;
688 op = GNUNET_CONTAINER_multihashmap_get (open_ports, &ch->h_port);
689 if (NULL == op)
690 {
691 /* port closed, wait for it to possibly open */
692 ch->state = CADET_CHANNEL_LOOSE;
693 (void) GNUNET_CONTAINER_multihashmap_put (
694 loose_channels,
695 &ch->h_port,
696 ch,
697 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
698 LOG (GNUNET_ERROR_TYPE_DEBUG,
699 "Created loose incoming loopback channel to port %s\n",
700 GNUNET_h2s (&ch->port));
701 }
702 else
703 {
704 GCCH_bind (ch, op->c, &op->port);
705 }
706 }
707 else
708 {
709 ch->t = GCP_get_tunnel (destination, GNUNET_YES);
710 ch->retry_time = CADET_INITIAL_RETRANSMIT_TIME;
711 ch->ctn = GCT_add_channel (ch->t, ch);
712 }
713 GNUNET_STATISTICS_update (stats, "# channels", 1, GNUNET_NO);
714 LOG (GNUNET_ERROR_TYPE_DEBUG,
715 "Created channel to port %s at peer %s for %s using %s\n",
716 GNUNET_h2s (port),
717 GCP_2s (destination),
718 GSC_2s (owner),
719 (GNUNET_YES == ch->is_loopback) ? "loopback" : GCT_2s (ch->t));
720 return ch;
721}
722
723
724/**
725 * We had an incoming channel to a port that is closed.
726 * It has not been opened for a while, drop it.
727 *
728 * @param cls the channel to drop
729 */
730static void
731timeout_closed_cb (void *cls)
732{
733 struct CadetChannel *ch = cls;
734
735 ch->retry_control_task = NULL;
736 LOG (GNUNET_ERROR_TYPE_DEBUG,
737 "Closing incoming channel to port %s from peer %s due to timeout\n",
738 GNUNET_h2s (&ch->port),
739 GCP_2s (GCT_get_destination (ch->t)));
740 channel_destroy (ch);
741}
742
743
744struct CadetChannel *
745GCCH_channel_incoming_new (struct CadetTunnel *t,
746 struct GNUNET_CADET_ChannelTunnelNumber ctn,
747 const struct GNUNET_HashCode *h_port,
748 uint32_t options)
749{
750 struct CadetChannel *ch;
751 struct OpenPort *op;
752
753 ch = GNUNET_new (struct CadetChannel);
754 ch->h_port = *h_port;
755 ch->t = t;
756 ch->ctn = ctn;
757 ch->retry_time = CADET_INITIAL_RETRANSMIT_TIME;
758 ch->nobuffer = GNUNET_NO;
759 ch->reliable = GNUNET_YES;
760 ch->out_of_order = GNUNET_NO;
761 ch->max_pending_messages =
762 (ch->nobuffer) ? 1 : 4; /* FIXME: 4!? Do not hardcode! */
763 GNUNET_STATISTICS_update (stats, "# channels", 1, GNUNET_NO);
764
765 op = GNUNET_CONTAINER_multihashmap_get (open_ports, h_port);
766 if (NULL == op)
767 {
768 /* port closed, wait for it to possibly open */
769 ch->state = CADET_CHANNEL_LOOSE;
770 (void) GNUNET_CONTAINER_multihashmap_put (
771 loose_channels,
772 &ch->h_port,
773 ch,
774 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
775 GNUNET_assert (NULL == ch->retry_control_task);
776 ch->retry_control_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT_CLOSED_PORT,
777 &timeout_closed_cb,
778 ch);
779 LOG (GNUNET_ERROR_TYPE_DEBUG,
780 "Created loose incoming channel to port %s from peer %s\n",
781 GNUNET_h2s (&ch->port),
782 GCP_2s (GCT_get_destination (ch->t)));
783 }
784 else
785 {
786 GCCH_bind (ch, op->c, &op->port);
787 }
788 GNUNET_STATISTICS_update (stats, "# channels", 1, GNUNET_NO);
789 return ch;
790}
791
792
793/**
794 * Function called once the tunnel confirms that we sent the
795 * ACK message. Just remembers it was sent, we do not expect
796 * ACKs for ACKs ;-).
797 *
798 * @param cls our `struct CadetChannel`.
799 * @param cid identifier of the connection within the tunnel, NULL
800 * if transmission failed
801 */
802static void
803send_ack_cb (void *cls,
804 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
805{
806 struct CadetChannel *ch = cls;
807
808 GNUNET_assert (NULL != ch->last_control_qe);
809 ch->last_control_qe = NULL;
810}
811
812
813/**
814 * Compute and send the current #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK to the other peer.
815 *
816 * @param ch channel to send the #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK for
817 */
818static void
819send_channel_data_ack (struct CadetChannel *ch)
820{
821 struct GNUNET_CADET_ChannelDataAckMessage msg;
822
823 if (GNUNET_NO == ch->reliable)
824 return; /* no ACKs */
825 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK);
826 msg.header.size = htons (sizeof(msg));
827 msg.ctn = ch->ctn;
828 msg.mid.mid = htonl (ntohl (ch->mid_recv.mid));
829 msg.futures = GNUNET_htonll (ch->mid_futures);
830 LOG (GNUNET_ERROR_TYPE_DEBUG,
831 "Sending DATA_ACK %u:%llX via %s\n",
832 (unsigned int) ntohl (msg.mid.mid),
833 (unsigned long long) ch->mid_futures,
834 GCCH_2s (ch));
835 if (NULL != ch->last_control_qe)
836 GCT_send_cancel (ch->last_control_qe);
837 ch->last_control_qe = GCT_send (ch->t, &msg.header, &send_ack_cb, ch,
838 &msg.ctn);
839}
840
841
842/**
843 * Send our initial #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK to the client confirming that the
844 * connection is up.
845 *
846 * @param cls the `struct CadetChannel`
847 */
848static void
849send_open_ack (void *cls)
850{
851 struct CadetChannel *ch = cls;
852 struct GNUNET_CADET_ChannelOpenAckMessage msg;
853
854 ch->retry_control_task = NULL;
855 LOG (GNUNET_ERROR_TYPE_DEBUG,
856 "Sending CHANNEL_OPEN_ACK on %s\n",
857 GCCH_2s (ch));
858 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK);
859 msg.header.size = htons (sizeof(msg));
860 msg.reserved = htonl (0);
861 msg.ctn = ch->ctn;
862 msg.port = ch->port;
863 if (NULL != ch->last_control_qe)
864 GCT_send_cancel (ch->last_control_qe);
865 ch->last_control_qe = GCT_send (ch->t, &msg.header, &send_ack_cb, ch,
866 &msg.ctn);
867}
868
869
870/**
871 * We got a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN message again for
872 * this channel. If the binding was successful, (re)transmit the
873 * #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK.
874 *
875 * @param ch channel that got the duplicate open
876 * @param cti identifier of the connection that delivered the message
877 */
878void
879GCCH_handle_duplicate_open (
880 struct CadetChannel *ch,
881 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti)
882{
883 if (NULL == ch->dest)
884 {
885 LOG (GNUNET_ERROR_TYPE_DEBUG,
886 "Ignoring duplicate CHANNEL_OPEN on %s: port is closed\n",
887 GCCH_2s (ch));
888 return;
889 }
890 if (NULL != ch->retry_control_task)
891 {
892 LOG (GNUNET_ERROR_TYPE_DEBUG,
893 "Ignoring duplicate CHANNEL_OPEN on %s: control message is pending\n",
894 GCCH_2s (ch));
895 return;
896 }
897 LOG (GNUNET_ERROR_TYPE_DEBUG,
898 "Retransmitting CHANNEL_OPEN_ACK on %s\n",
899 GCCH_2s (ch));
900 ch->retry_control_task = GNUNET_SCHEDULER_add_now (&send_open_ack, ch);
901}
902
903
904/**
905 * Send a #GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK to the client to solicit more messages.
906 *
907 * @param ch channel the ack is for
908 * @param to_owner #GNUNET_YES to send to owner,
909 * #GNUNET_NO to send to dest
910 */
911static void
912send_ack_to_client (struct CadetChannel *ch, int to_owner)
913{
914 struct GNUNET_MQ_Envelope *env;
915 struct GNUNET_CADET_LocalAck *ack;
916 struct CadetChannelClient *ccc;
917
918 ccc = (GNUNET_YES == to_owner) ? ch->owner : ch->dest;
919 if (NULL == ccc)
920 {
921 /* This can happen if we are just getting ACKs after
922 our local client already disconnected. */
923 GNUNET_assert (GNUNET_YES == ch->destroy);
924 return;
925 }
926 env = GNUNET_MQ_msg (ack, GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK);
927 ack->ccn = ccc->ccn;
928 LOG (GNUNET_ERROR_TYPE_DEBUG,
929 "Sending CADET_LOCAL_ACK to %s (%s) at ccn %X (%u/%u pending)\n",
930 GSC_2s (ccc->c),
931 (GNUNET_YES == to_owner) ? "owner" : "dest",
932 ntohl (ack->ccn.channel_of_client),
933 ch->pending_messages,
934 ch->max_pending_messages);
935 GSC_send_to_client (ccc->c, env);
936}
937
938
939void
940GCCH_bind (struct CadetChannel *ch,
941 struct CadetClient *c,
942 const struct GNUNET_HashCode *port)
943{
944 uint32_t options;
945 struct CadetChannelClient *cccd;
946
947 LOG (GNUNET_ERROR_TYPE_DEBUG,
948 "Binding %s from %s to port %s of %s\n",
949 GCCH_2s (ch),
950 GCT_2s (ch->t),
951 GNUNET_h2s (&ch->port),
952 GSC_2s (c));
953 if (NULL != ch->retry_control_task)
954 {
955 /* there might be a timeout task here */
956 GNUNET_SCHEDULER_cancel (ch->retry_control_task);
957 ch->retry_control_task = NULL;
958 }
959 options = 0;
960 cccd = GNUNET_new (struct CadetChannelClient);
961 GNUNET_assert (NULL == ch->dest);
962 ch->dest = cccd;
963 ch->port = *port;
964 cccd->c = c;
965 cccd->client_ready = GNUNET_YES;
966 cccd->ccn = GSC_bind (c,
967 ch,
968 (GNUNET_YES == ch->is_loopback)
969 ? GCP_get (&my_full_id, GNUNET_YES)
970 : GCT_get_destination (ch->t),
971 port,
972 options);
973 GNUNET_assert (ntohl (cccd->ccn.channel_of_client) <
974 GNUNET_CADET_LOCAL_CHANNEL_ID_CLI);
975 ch->mid_recv.mid = htonl (1); /* The OPEN counts as message 0! */
976 if (GNUNET_YES == ch->is_loopback)
977 {
978 ch->state = CADET_CHANNEL_OPEN_SENT;
979 GCCH_handle_channel_open_ack (ch, NULL, port);
980 }
981 else
982 {
983 /* notify other peer that we accepted the connection */
984 ch->state = CADET_CHANNEL_READY;
985 ch->retry_control_task = GNUNET_SCHEDULER_add_now (&send_open_ack, ch);
986 }
987 /* give client it's initial supply of ACKs */
988 GNUNET_assert (ntohl (cccd->ccn.channel_of_client) <
989 GNUNET_CADET_LOCAL_CHANNEL_ID_CLI);
990 for (unsigned int i = 0; i < ch->max_pending_messages; i++)
991 send_ack_to_client (ch, GNUNET_NO);
992}
993
994
995/**
996 * One of our clients has disconnected, tell the other one that we
997 * are finished. Done asynchronously to avoid concurrent modification
998 * issues if this is the same client.
999 *
1000 * @param cls the `struct CadetChannel` where one of the ends is now dead
1001 */
1002static void
1003signal_remote_destroy_cb (void *cls)
1004{
1005 struct CadetChannel *ch = cls;
1006 struct CadetChannelClient *ccc;
1007
1008 /* Find which end is left... */
1009 ch->retry_control_task = NULL;
1010 ccc = (NULL != ch->owner) ? ch->owner : ch->dest;
1011 GSC_handle_remote_channel_destroy (ccc->c, ccc->ccn, ch);
1012 channel_destroy (ch);
1013}
1014
1015
1016/**
1017 * Destroy locally created channel. Called by the local client, so no
1018 * need to tell the client.
1019 *
1020 * @param ch channel to destroy
1021 * @param c client that caused the destruction
1022 * @param ccn client number of the client @a c
1023 */
1024void
1025GCCH_channel_local_destroy (struct CadetChannel *ch,
1026 struct CadetClient *c,
1027 struct GNUNET_CADET_ClientChannelNumber ccn)
1028{
1029 LOG (GNUNET_ERROR_TYPE_DEBUG,
1030 "%s asks for destruction of %s\n",
1031 GSC_2s (c),
1032 GCCH_2s (ch));
1033 GNUNET_assert (NULL != c);
1034 if ((NULL != ch->owner) && (c == ch->owner->c) &&
1035 (ccn.channel_of_client == ch->owner->ccn.channel_of_client))
1036 {
1037 free_channel_client (ch->owner);
1038 ch->owner = NULL;
1039 }
1040 else if ((NULL != ch->dest) && (c == ch->dest->c) &&
1041 (ccn.channel_of_client == ch->dest->ccn.channel_of_client))
1042 {
1043 free_channel_client (ch->dest);
1044 ch->dest = NULL;
1045 }
1046 else
1047 {
1048 GNUNET_assert (0);
1049 }
1050
1051 if (GNUNET_YES == ch->destroy)
1052 {
1053 /* other end already destroyed, with the local client gone, no need
1054 to finish transmissions, just destroy immediately. */
1055 channel_destroy (ch);
1056 return;
1057 }
1058 if ((NULL != ch->head_sent) && ((NULL != ch->owner) || (NULL != ch->dest)))
1059 {
1060 /* Wait for other end to destroy us as well,
1061 and otherwise allow send queue to be transmitted first */
1062 ch->destroy = GNUNET_YES;
1063 return;
1064 }
1065 if ((GNUNET_YES == ch->is_loopback) &&
1066 ((NULL != ch->owner) || (NULL != ch->dest)))
1067 {
1068 if (NULL != ch->retry_control_task)
1069 GNUNET_SCHEDULER_cancel (ch->retry_control_task);
1070 ch->retry_control_task =
1071 GNUNET_SCHEDULER_add_now (&signal_remote_destroy_cb, ch);
1072 return;
1073 }
1074 if (GNUNET_NO == ch->is_loopback)
1075 {
1076 /* If the we ever sent the CHANNEL_CREATE, we need to send a destroy message. */
1077 switch (ch->state)
1078 {
1079 case CADET_CHANNEL_NEW:
1080 /* We gave up on a channel that we created as a client to a remote
1081 target, but that never went anywhere. Nothing to do here. */
1082 break;
1083
1084 case CADET_CHANNEL_LOOSE:
1085 break;
1086
1087 default:
1088 GCT_send_channel_destroy (ch->t, ch->ctn);
1089 }
1090 }
1091 /* Nothing left to do, just finish destruction */
1092 channel_destroy (ch);
1093}
1094
1095
1096void
1097GCCH_handle_channel_open_ack (
1098 struct CadetChannel *ch,
1099 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti,
1100 const struct GNUNET_HashCode *port)
1101{
1102 switch (ch->state)
1103 {
1104 case CADET_CHANNEL_NEW:
1105 /* this should be impossible */
1106 GNUNET_break (0);
1107 break;
1108
1109 case CADET_CHANNEL_LOOSE:
1110 /* This makes no sense. */
1111 GNUNET_break_op (0);
1112 break;
1113
1114 case CADET_CHANNEL_OPEN_SENT:
1115 if (NULL == ch->owner)
1116 {
1117 /* We're not the owner, wrong direction! */
1118 GNUNET_break_op (0);
1119 return;
1120 }
1121 if (0 != GNUNET_memcmp (&ch->port, port))
1122 {
1123 /* Other peer failed to provide the right port,
1124 refuse connection. */
1125 GNUNET_break_op (0);
1126 return;
1127 }
1128 LOG (GNUNET_ERROR_TYPE_DEBUG,
1129 "Received CHANNEL_OPEN_ACK for waiting %s, entering READY state\n",
1130 GCCH_2s (ch));
1131 if (NULL != ch->retry_control_task) /* can be NULL if ch->is_loopback */
1132 {
1133 GNUNET_SCHEDULER_cancel (ch->retry_control_task);
1134 ch->retry_control_task = NULL;
1135 }
1136 ch->state = CADET_CHANNEL_READY;
1137 /* On first connect, send client as many ACKs as we allow messages
1138 to be buffered! */
1139 for (unsigned int i = 0; i < ch->max_pending_messages; i++)
1140 send_ack_to_client (ch, GNUNET_YES);
1141 break;
1142
1143 case CADET_CHANNEL_READY:
1144 /* duplicate ACK, maybe we retried the CREATE. Ignore. */
1145 LOG (GNUNET_ERROR_TYPE_DEBUG,
1146 "Received duplicate channel OPEN_ACK for %s\n",
1147 GCCH_2s (ch));
1148 GNUNET_STATISTICS_update (stats, "# duplicate CREATE_ACKs", 1, GNUNET_NO);
1149 break;
1150 }
1151}
1152
1153
1154/**
1155 * Test if element @a e1 comes before element @a e2.
1156 *
1157 * @param cls closure, to a flag where we indicate duplicate packets
1158 * @param m1 a message of to sort
1159 * @param m2 another message to sort
1160 * @return #GNUNET_YES if @a e1 < @a e2, otherwise #GNUNET_NO
1161 */
1162static int
1163is_before (void *cls,
1164 struct CadetOutOfOrderMessage *m1,
1165 struct CadetOutOfOrderMessage *m2)
1166{
1167 int *duplicate = cls;
1168 uint32_t v1 = ntohl (m1->mid.mid);
1169 uint32_t v2 = ntohl (m2->mid.mid);
1170 uint32_t delta;
1171
1172 delta = v2 - v1;
1173 if (0 == delta)
1174 *duplicate = GNUNET_YES;
1175 if (delta > (uint32_t) INT_MAX)
1176 {
1177 /* in overflow range, we can safely assume we wrapped around */
1178 return GNUNET_NO;
1179 }
1180 else
1181 {
1182 /* result is small, thus v2 > v1, thus m1 < m2 */
1183 return GNUNET_YES;
1184 }
1185}
1186
1187
1188void
1189GCCH_handle_channel_plaintext_data (
1190 struct CadetChannel *ch,
1191 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti,
1192 const struct GNUNET_CADET_ChannelAppDataMessage *msg)
1193{
1194 struct GNUNET_MQ_Envelope *env;
1195 struct GNUNET_CADET_LocalData *ld;
1196 struct CadetChannelClient *ccc;
1197 size_t payload_size;
1198 struct CadetOutOfOrderMessage *com;
1199 int duplicate;
1200 uint32_t mid_min;
1201 uint32_t mid_max;
1202 uint32_t mid_msg;
1203 uint32_t delta;
1204
1205 GNUNET_assert (GNUNET_NO == ch->is_loopback);
1206 if ((NULL == ch->owner) && (NULL == ch->dest))
1207 {
1208 /* This client is gone, but we still have messages to send to
1209 the other end (which is why @a ch is not yet dead). However,
1210 we cannot pass messages to our client anymore. */
1211 LOG (GNUNET_ERROR_TYPE_DEBUG,
1212 "Dropping incoming payload on %s as this end is already closed\n",
1213 GCCH_2s (ch));
1214 /* send back DESTROY notification to stop further retransmissions! */
1215 if (GNUNET_YES == ch->destroy)
1216 GCT_send_channel_destroy (ch->t, ch->ctn);
1217 return;
1218 }
1219 payload_size = ntohs (msg->header.size) - sizeof(*msg);
1220 env = GNUNET_MQ_msg_extra (ld,
1221 payload_size,
1222 GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA);
1223 ld->ccn = (NULL == ch->dest) ? ch->owner->ccn : ch->dest->ccn;
1224 GNUNET_memcpy (&ld[1], &msg[1], payload_size);
1225 ccc = (NULL != ch->owner) ? ch->owner : ch->dest;
1226 if (GNUNET_YES == ccc->client_ready)
1227 {
1228 /*
1229 * We ad-hoc send the message if
1230 * - The channel is out-of-order
1231 * - The channel is reliable and MID matches next expected MID
1232 * - The channel is unreliable and MID is before lowest seen MID
1233 */if ((GNUNET_YES == ch->out_of_order) ||
1234 ((msg->mid.mid == ch->mid_recv.mid) && (GNUNET_YES == ch->reliable)) ||
1235 ((GNUNET_NO == ch->reliable) &&
1236 (ntohl (msg->mid.mid) >= ntohl (ch->mid_recv.mid)) &&
1237 ((NULL == ccc->head_recv) ||
1238 (ntohl (msg->mid.mid) < ntohl (ccc->head_recv->mid.mid)))))
1239 {
1240 LOG (GNUNET_ERROR_TYPE_DEBUG,
1241 "Giving %u bytes of payload with MID %u from %s to client %s\n",
1242 (unsigned int) payload_size,
1243 ntohl (msg->mid.mid),
1244 GCCH_2s (ch),
1245 GSC_2s (ccc->c));
1246 ccc->client_ready = GNUNET_NO;
1247 GSC_send_to_client (ccc->c, env);
1248 if (GNUNET_NO == ch->out_of_order)
1249 ch->mid_recv.mid = htonl (1 + ntohl (msg->mid.mid));
1250 else
1251 ch->mid_recv.mid = htonl (1 + ntohl (ch->mid_recv.mid));
1252 ch->mid_futures >>= 1;
1253 if ((GNUNET_YES == ch->out_of_order) && (GNUNET_NO == ch->reliable))
1254 {
1255 /* possibly shift by more if we skipped messages */
1256 uint64_t delta = htonl (msg->mid.mid) - 1 - ntohl (ch->mid_recv.mid);
1257
1258 if (delta > 63)
1259 ch->mid_futures = 0;
1260 else
1261 ch->mid_futures >>= delta;
1262 ch->mid_recv.mid = htonl (1 + ntohl (msg->mid.mid));
1263 }
1264 send_channel_data_ack (ch);
1265 return;
1266 }
1267 }
1268
1269 if (GNUNET_YES == ch->reliable)
1270 {
1271 /* check if message ought to be dropped because it is ancient/too distant/duplicate */
1272 mid_min = ntohl (ch->mid_recv.mid);
1273 mid_max = mid_min + ch->max_pending_messages;
1274 mid_msg = ntohl (msg->mid.mid);
1275 if (((uint32_t) (mid_msg - mid_min) > ch->max_pending_messages) ||
1276 ((uint32_t) (mid_max - mid_msg) > ch->max_pending_messages))
1277 {
1278 LOG (GNUNET_ERROR_TYPE_DEBUG,
1279 "%s at %u drops ancient or far-future message %u\n",
1280 GCCH_2s (ch),
1281 (unsigned int) mid_min,
1282 ntohl (msg->mid.mid));
1283
1284 GNUNET_STATISTICS_update (stats,
1285 "# duplicate DATA (ancient or future)",
1286 1,
1287 GNUNET_NO);
1288 GNUNET_MQ_discard (env);
1289 send_channel_data_ack (ch);
1290 return;
1291 }
1292 /* mark bit for future ACKs */
1293 delta = mid_msg - mid_min - 1; /* overflow/underflow are OK here */
1294 if (delta < 64)
1295 {
1296 if (0 != (ch->mid_futures & (1LLU << delta)))
1297 {
1298 /* Duplicate within the queue, drop also */
1299 LOG (GNUNET_ERROR_TYPE_DEBUG,
1300 "Duplicate payload of %u bytes on %s (mid %u) dropped\n",
1301 (unsigned int) payload_size,
1302 GCCH_2s (ch),
1303 ntohl (msg->mid.mid));
1304 GNUNET_STATISTICS_update (stats, "# duplicate DATA", 1, GNUNET_NO);
1305 GNUNET_MQ_discard (env);
1306 send_channel_data_ack (ch);
1307 return;
1308 }
1309 ch->mid_futures |= (1LLU << delta);
1310 LOG (GNUNET_ERROR_TYPE_DEBUG,
1311 "Marked bit %llX for mid %u (base: %u); now: %llX\n",
1312 (1LLU << delta),
1313 mid_msg,
1314 mid_min,
1315 (unsigned long long) ch->mid_futures);
1316 }
1317 }
1318 else /* ! ch->reliable */
1319 {
1320 struct CadetOutOfOrderMessage *next_msg;
1321
1322 /**
1323 * We always send if possible in this case.
1324 * It is guaranteed that the queued MID < received MID
1325 **/
1326 if ((NULL != ccc->head_recv) && (GNUNET_YES == ccc->client_ready))
1327 {
1328 next_msg = ccc->head_recv;
1329 LOG (GNUNET_ERROR_TYPE_DEBUG,
1330 "Giving queued MID %u from %s to client %s\n",
1331 ntohl (next_msg->mid.mid),
1332 GCCH_2s (ch),
1333 GSC_2s (ccc->c));
1334 ccc->client_ready = GNUNET_NO;
1335 GSC_send_to_client (ccc->c, next_msg->env);
1336 ch->mid_recv.mid = htonl (1 + ntohl (next_msg->mid.mid));
1337 ch->mid_futures >>= 1;
1338 send_channel_data_ack (ch);
1339 GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, next_msg);
1340 ccc->num_recv--;
1341 /* Do not process duplicate MID */
1342 if (msg->mid.mid == next_msg->mid.mid) /* Duplicate */
1343 {
1344 /* Duplicate within the queue, drop */
1345 LOG (GNUNET_ERROR_TYPE_DEBUG,
1346 "Message on %s (mid %u) dropped, duplicate\n",
1347 GCCH_2s (ch),
1348 ntohl (msg->mid.mid));
1349 GNUNET_free (next_msg);
1350 GNUNET_MQ_discard (env);
1351 return;
1352 }
1353 GNUNET_free (next_msg);
1354 }
1355
1356 if (ntohl (msg->mid.mid) < ntohl (ch->mid_recv.mid)) /* Old */
1357 {
1358 /* Duplicate within the queue, drop */
1359 LOG (GNUNET_ERROR_TYPE_DEBUG,
1360 "Message on %s (mid %u) dropped, old.\n",
1361 GCCH_2s (ch),
1362 ntohl (msg->mid.mid));
1363 GNUNET_MQ_discard (env);
1364 return;
1365 }
1366
1367 /* Channel is unreliable, so we do not ACK. But we also cannot
1368 allow buffering everything, so check if we have space... */
1369 if (ccc->num_recv >= ch->max_pending_messages)
1370 {
1371 struct CadetOutOfOrderMessage *drop;
1372
1373 /* Yep, need to drop. Drop the oldest message in
1374 the buffer. */
1375 LOG (GNUNET_ERROR_TYPE_DEBUG,
1376 "Queue full due slow client on %s, dropping oldest message\n",
1377 GCCH_2s (ch));
1378 GNUNET_STATISTICS_update (stats,
1379 "# messages dropped due to slow client",
1380 1,
1381 GNUNET_NO);
1382 drop = ccc->head_recv;
1383 GNUNET_assert (NULL != drop);
1384 GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, drop);
1385 ccc->num_recv--;
1386 GNUNET_MQ_discard (drop->env);
1387 GNUNET_free (drop);
1388 }
1389 }
1390
1391 /* Insert message into sorted out-of-order queue */
1392 com = GNUNET_new (struct CadetOutOfOrderMessage);
1393 com->mid = msg->mid;
1394 com->env = env;
1395 duplicate = GNUNET_NO;
1396 GNUNET_CONTAINER_DLL_insert_sorted (struct CadetOutOfOrderMessage,
1397 is_before,
1398 &duplicate,
1399 ccc->head_recv,
1400 ccc->tail_recv,
1401 com);
1402 ccc->num_recv++;
1403 if (GNUNET_YES == duplicate)
1404 {
1405 /* Duplicate within the queue, drop also (this is not covered by
1406 the case above if "delta" >= 64, which could be the case if
1407 max_pending_messages is also >= 64 or if our client is unready
1408 and we are seeing retransmissions of the message our client is
1409 blocked on. */LOG (GNUNET_ERROR_TYPE_DEBUG,
1410 "Duplicate payload of %u bytes on %s (mid %u) dropped\n",
1411 (unsigned int) payload_size,
1412 GCCH_2s (ch),
1413 ntohl (msg->mid.mid));
1414 GNUNET_STATISTICS_update (stats, "# duplicate DATA", 1, GNUNET_NO);
1415 GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, com);
1416 ccc->num_recv--;
1417 GNUNET_MQ_discard (com->env);
1418 GNUNET_free (com);
1419 send_channel_data_ack (ch);
1420 return;
1421 }
1422 LOG (GNUNET_ERROR_TYPE_DEBUG,
1423 "Queued %s payload of %u bytes on %s-%X(%p) (mid %u, need %u first)\n",
1424 (GNUNET_YES == ccc->client_ready) ? "out-of-order" : "client-not-ready",
1425 (unsigned int) payload_size,
1426 GCCH_2s (ch),
1427 ntohl (ccc->ccn.channel_of_client),
1428 ccc,
1429 ntohl (msg->mid.mid),
1430 ntohl (ch->mid_recv.mid));
1431 /* NOTE: this ACK we _could_ skip, as the packet is out-of-order and
1432 the sender may already be transmitting the previous one. Needs
1433 experimental evaluation to see if/when this ACK helps or
1434 hurts. (We might even want another option.) */
1435 send_channel_data_ack (ch);
1436}
1437
1438
1439/**
1440 * Function called once the tunnel has sent one of our messages.
1441 * If the message is unreliable, simply frees the `crm`. If the
1442 * message was reliable, calculate retransmission time and
1443 * wait for ACK (or retransmit).
1444 *
1445 * @param cls the `struct CadetReliableMessage` that was sent
1446 * @param cid identifier of the connection within the tunnel, NULL
1447 * if transmission failed
1448 */
1449static void
1450data_sent_cb (void *cls,
1451 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid);
1452
1453
1454/**
1455 * We need to retry a transmission, the last one took too long to
1456 * be acknowledged.
1457 *
1458 * @param cls the `struct CadetChannel` where we need to retransmit
1459 */
1460static void
1461retry_transmission (void *cls)
1462{
1463 struct CadetChannel *ch = cls;
1464 struct CadetReliableMessage *crm = ch->head_sent;
1465
1466 ch->retry_data_task = NULL;
1467 GNUNET_assert (NULL == crm->qe);
1468 LOG (GNUNET_ERROR_TYPE_DEBUG,
1469 "Retrying transmission on %s of message %u\n",
1470 GCCH_2s (ch),
1471 (unsigned int) ntohl (crm->data_message->mid.mid));
1472 crm->qe = GCT_send (ch->t, &crm->data_message->header, &data_sent_cb, crm,
1473 &crm->data_message->ctn);
1474 GNUNET_assert (NULL == ch->retry_data_task);
1475}
1476
1477
1478/**
1479 * We got an PLAINTEXT_DATA_ACK for a message in our queue, remove it from
1480 * the queue and tell our client that it can send more.
1481 *
1482 * @param ch the channel that got the PLAINTEXT_DATA_ACK
1483 * @param cti identifier of the connection that delivered the message
1484 * @param crm the message that got acknowledged
1485 */
1486static void
1487handle_matching_ack (struct CadetChannel *ch,
1488 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti,
1489 struct CadetReliableMessage *crm)
1490{
1491 GNUNET_CONTAINER_DLL_remove (ch->head_sent, ch->tail_sent, crm);
1492 ch->pending_messages--;
1493 GNUNET_assert (ch->pending_messages < ch->max_pending_messages);
1494 LOG (GNUNET_ERROR_TYPE_DEBUG,
1495 "Received DATA_ACK on %s for message %u (%u ACKs pending)\n",
1496 GCCH_2s (ch),
1497 (unsigned int) ntohl (crm->data_message->mid.mid),
1498 ch->pending_messages);
1499 if (NULL != crm->qe)
1500 {
1501 GCT_send_cancel (crm->qe);
1502 crm->qe = NULL;
1503 }
1504 if ((1 == crm->num_transmissions) && (NULL != cti))
1505 {
1506 GCC_ack_observed (cti);
1507 if (0 == GNUNET_memcmp (cti, &crm->connection_taken))
1508 {
1509 GCC_latency_observed (cti,
1510 GNUNET_TIME_absolute_get_duration (
1511 crm->first_transmission_time));
1512 }
1513 }
1514 GNUNET_free (crm->data_message);
1515 GNUNET_free (crm);
1516 send_ack_to_client (ch, (NULL == ch->owner) ? GNUNET_NO : GNUNET_YES);
1517}
1518
1519
1520/**
1521 * We got an acknowledgement for payload data for a channel.
1522 * Possibly resume transmissions.
1523 *
1524 * @param ch channel that got the ack
1525 * @param cti identifier of the connection that delivered the message
1526 * @param ack details about what was received
1527 */
1528void
1529GCCH_handle_channel_plaintext_data_ack (
1530 struct CadetChannel *ch,
1531 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti,
1532 const struct GNUNET_CADET_ChannelDataAckMessage *ack)
1533{
1534 struct CadetReliableMessage *crm;
1535 struct CadetReliableMessage *crmn;
1536 int found;
1537 uint32_t mid_base;
1538 uint64_t mid_mask;
1539 unsigned int delta;
1540
1541 GNUNET_break (GNUNET_NO == ch->is_loopback);
1542 if (GNUNET_NO == ch->reliable)
1543 {
1544 /* not expecting ACKs on unreliable channel, odd */
1545 GNUNET_break_op (0);
1546 return;
1547 }
1548 /* mid_base is the MID of the next message that the
1549 other peer expects (i.e. that is missing!), everything
1550 LOWER (but excluding mid_base itself) was received. */
1551 mid_base = ntohl (ack->mid.mid);
1552 mid_mask = GNUNET_htonll (ack->futures);
1553 found = GNUNET_NO;
1554 for (crm = ch->head_sent; NULL != crm; crm = crmn)
1555 {
1556 crmn = crm->next;
1557 delta = (unsigned int) (ntohl (crm->data_message->mid.mid) - mid_base);
1558 if (delta >= UINT_MAX - ch->max_pending_messages)
1559 {
1560 /* overflow, means crm was a bit in the past, so this ACK counts for it. */
1561 LOG (GNUNET_ERROR_TYPE_DEBUG,
1562 "Got DATA_ACK with base %u satisfying past message %u on %s\n",
1563 (unsigned int) mid_base,
1564 ntohl (crm->data_message->mid.mid),
1565 GCCH_2s (ch));
1566 handle_matching_ack (ch, cti, crm);
1567 found = GNUNET_YES;
1568 continue;
1569 }
1570 delta--;
1571 if (delta >= 64)
1572 continue;
1573 LOG (GNUNET_ERROR_TYPE_DEBUG,
1574 "Testing bit %llX for mid %u (base: %u)\n",
1575 (1LLU << delta),
1576 ntohl (crm->data_message->mid.mid),
1577 mid_base);
1578 if (0 != (mid_mask & (1LLU << delta)))
1579 {
1580 LOG (GNUNET_ERROR_TYPE_DEBUG,
1581 "Got DATA_ACK with mask for %u on %s\n",
1582 ntohl (crm->data_message->mid.mid),
1583 GCCH_2s (ch));
1584 handle_matching_ack (ch, cti, crm);
1585 found = GNUNET_YES;
1586 }
1587 }
1588 if (GNUNET_NO == found)
1589 {
1590 /* ACK for message we already dropped, might have been a
1591 duplicate ACK? Ignore. */
1592 LOG (GNUNET_ERROR_TYPE_DEBUG,
1593 "Duplicate DATA_ACK on %s, ignoring\n",
1594 GCCH_2s (ch));
1595 GNUNET_STATISTICS_update (stats, "# duplicate DATA_ACKs", 1, GNUNET_NO);
1596 return;
1597 }
1598 if (NULL != ch->retry_data_task)
1599 {
1600 GNUNET_SCHEDULER_cancel (ch->retry_data_task);
1601 ch->retry_data_task = NULL;
1602 }
1603 if ((NULL != ch->head_sent) && (NULL == ch->head_sent->qe))
1604 ch->retry_data_task = GNUNET_SCHEDULER_add_at (ch->head_sent->next_retry,
1605 &retry_transmission,
1606 ch);
1607}
1608
1609
1610void
1611GCCH_handle_remote_destroy (
1612 struct CadetChannel *ch,
1613 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti)
1614{
1615 struct CadetChannelClient *ccc;
1616
1617 GNUNET_assert (GNUNET_NO == ch->is_loopback);
1618 LOG (GNUNET_ERROR_TYPE_DEBUG,
1619 "Received remote channel DESTROY for %s\n",
1620 GCCH_2s (ch));
1621 if (GNUNET_YES == ch->destroy)
1622 {
1623 /* Local client already gone, this is instant-death. */
1624 channel_destroy (ch);
1625 return;
1626 }
1627 ccc = (NULL != ch->owner) ? ch->owner : ch->dest;
1628 if ((NULL != ccc) && (NULL != ccc->head_recv))
1629 {
1630 LOG (GNUNET_ERROR_TYPE_WARNING,
1631 "Lost end of transmission due to remote shutdown on %s\n",
1632 GCCH_2s (ch));
1633 /* FIXME: change API to notify client about truncated transmission! */
1634 }
1635 ch->destroy = GNUNET_YES;
1636 if (NULL != ccc)
1637 GSC_handle_remote_channel_destroy (ccc->c, ccc->ccn, ch);
1638 channel_destroy (ch);
1639}
1640
1641
1642/**
1643 * Test if element @a e1 comes before element @a e2.
1644 *
1645 * @param cls closure, to a flag where we indicate duplicate packets
1646 * @param crm1 an element of to sort
1647 * @param crm2 another element to sort
1648 * @return #GNUNET_YES if @a e1 < @a e2, otherwise #GNUNET_NO
1649 */
1650static int
1651cmp_crm_by_next_retry (void *cls,
1652 struct CadetReliableMessage *crm1,
1653 struct CadetReliableMessage *crm2)
1654{
1655 if (crm1->next_retry.abs_value_us < crm2->next_retry.abs_value_us)
1656 return GNUNET_YES;
1657 return GNUNET_NO;
1658}
1659
1660
1661/**
1662 * Function called once the tunnel has sent one of our messages.
1663 * If the message is unreliable, simply frees the `crm`. If the
1664 * message was reliable, calculate retransmission time and
1665 * wait for ACK (or retransmit).
1666 *
1667 * @param cls the `struct CadetReliableMessage` that was sent
1668 * @param cid identifier of the connection within the tunnel, NULL
1669 * if transmission failed
1670 */
1671static void
1672data_sent_cb (void *cls,
1673 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
1674{
1675 struct CadetReliableMessage *crm = cls;
1676 struct CadetChannel *ch = crm->ch;
1677
1678 GNUNET_assert (GNUNET_NO == ch->is_loopback);
1679 GNUNET_assert (NULL != crm->qe);
1680 crm->qe = NULL;
1681 GNUNET_CONTAINER_DLL_remove (ch->head_sent, ch->tail_sent, crm);
1682 if (GNUNET_NO == ch->reliable)
1683 {
1684 GNUNET_free (crm->data_message);
1685 GNUNET_free (crm);
1686 ch->pending_messages--;
1687 send_ack_to_client (ch, (NULL == ch->owner) ? GNUNET_NO : GNUNET_YES);
1688 return;
1689 }
1690 if (NULL == cid)
1691 {
1692 /* There was an error sending. */
1693 crm->num_transmissions = GNUNET_SYSERR;
1694 }
1695 else if (GNUNET_SYSERR != crm->num_transmissions)
1696 {
1697 /* Increment transmission counter, and possibly store @a cid
1698 if this was the first transmission. */
1699 crm->num_transmissions++;
1700 if (1 == crm->num_transmissions)
1701 {
1702 crm->first_transmission_time = GNUNET_TIME_absolute_get ();
1703 crm->connection_taken = *cid;
1704 GCC_ack_expected (cid);
1705 }
1706 }
1707 if ((0 == crm->retry_delay.rel_value_us) && (NULL != cid))
1708 {
1709 struct CadetConnection *cc = GCC_lookup (cid);
1710
1711 if (NULL != cc)
1712 crm->retry_delay = GCC_get_metrics (cc)->aged_latency;
1713 else
1714 crm->retry_delay = ch->retry_time;
1715 }
1716 crm->retry_delay = GNUNET_TIME_STD_BACKOFF (crm->retry_delay);
1717 crm->retry_delay = GNUNET_TIME_relative_max (crm->retry_delay, MIN_RTT_DELAY);
1718 crm->next_retry = GNUNET_TIME_relative_to_absolute (crm->retry_delay);
1719
1720 GNUNET_CONTAINER_DLL_insert_sorted (struct CadetReliableMessage,
1721 cmp_crm_by_next_retry,
1722 NULL,
1723 ch->head_sent,
1724 ch->tail_sent,
1725 crm);
1726 LOG (GNUNET_ERROR_TYPE_DEBUG,
1727 "Message %u sent, next transmission on %s in %s\n",
1728 (unsigned int) ntohl (crm->data_message->mid.mid),
1729 GCCH_2s (ch),
1730 GNUNET_STRINGS_relative_time_to_string (
1731 GNUNET_TIME_absolute_get_remaining (
1732 ch->head_sent->next_retry),
1733 GNUNET_YES));
1734 if (NULL == ch->head_sent->qe)
1735 {
1736 if (NULL != ch->retry_data_task)
1737 GNUNET_SCHEDULER_cancel (ch->retry_data_task);
1738 ch->retry_data_task = GNUNET_SCHEDULER_add_at (ch->head_sent->next_retry,
1739 &retry_transmission,
1740 ch);
1741 }
1742}
1743
1744
1745/**
1746 * Handle data given by a client.
1747 *
1748 * Check whether the client is allowed to send in this tunnel, save if
1749 * channel is reliable and send an ACK to the client if there is still
1750 * buffer space in the tunnel.
1751 *
1752 * @param ch Channel.
1753 * @param sender_ccn ccn of the sender
1754 * @param buf payload to transmit.
1755 * @param buf_len number of bytes in @a buf
1756 * @return #GNUNET_OK if everything goes well,
1757 * #GNUNET_SYSERR in case of an error.
1758 */
1759int
1760GCCH_handle_local_data (struct CadetChannel *ch,
1761 struct GNUNET_CADET_ClientChannelNumber sender_ccn,
1762 const char *buf,
1763 size_t buf_len)
1764{
1765 struct CadetReliableMessage *crm;
1766
1767 if (ch->pending_messages >= ch->max_pending_messages)
1768 {
1769 GNUNET_break (0); /* Fails: #5370 */
1770 return GNUNET_SYSERR;
1771 }
1772 if (GNUNET_YES == ch->destroy)
1773 {
1774 /* we are going down, drop messages */
1775 return GNUNET_OK;
1776 }
1777 ch->pending_messages++;
1778
1779 if (GNUNET_YES == ch->is_loopback)
1780 {
1781 struct CadetChannelClient *receiver;
1782 struct GNUNET_MQ_Envelope *env;
1783 struct GNUNET_CADET_LocalData *ld;
1784 int ack_to_owner;
1785
1786 env =
1787 GNUNET_MQ_msg_extra (ld, buf_len, GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA);
1788 if ((NULL != ch->owner) &&
1789 (sender_ccn.channel_of_client == ch->owner->ccn.channel_of_client))
1790 {
1791 receiver = ch->dest;
1792 ack_to_owner = GNUNET_YES;
1793 }
1794 else if ((NULL != ch->dest) &&
1795 (sender_ccn.channel_of_client == ch->dest->ccn.channel_of_client))
1796 {
1797 receiver = ch->owner;
1798 ack_to_owner = GNUNET_NO;
1799 }
1800 else
1801 {
1802 GNUNET_free (env);
1803 GNUNET_break (0);
1804 return GNUNET_SYSERR;
1805 }
1806 GNUNET_assert (NULL != receiver);
1807 ld->ccn = receiver->ccn;
1808 GNUNET_memcpy (&ld[1], buf, buf_len);
1809 if (GNUNET_YES == receiver->client_ready)
1810 {
1811 ch->pending_messages--;
1812 GSC_send_to_client (receiver->c, env);
1813 send_ack_to_client (ch, ack_to_owner);
1814 }
1815 else
1816 {
1817 struct CadetOutOfOrderMessage *oom;
1818
1819 oom = GNUNET_new (struct CadetOutOfOrderMessage);
1820 oom->env = env;
1821 GNUNET_CONTAINER_DLL_insert_tail (receiver->head_recv,
1822 receiver->tail_recv,
1823 oom);
1824 receiver->num_recv++;
1825 }
1826 return GNUNET_OK;
1827 }
1828
1829 /* Everything is correct, send the message. */
1830 crm = GNUNET_malloc (sizeof(*crm));
1831 crm->ch = ch;
1832 crm->data_message = GNUNET_malloc (
1833 sizeof(struct GNUNET_CADET_ChannelAppDataMessage) + buf_len);
1834 crm->data_message->header.size =
1835 htons (sizeof(struct GNUNET_CADET_ChannelAppDataMessage) + buf_len);
1836 crm->data_message->header.type =
1837 htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA);
1838 ch->mid_send.mid = htonl (ntohl (ch->mid_send.mid) + 1);
1839 crm->data_message->mid = ch->mid_send;
1840 crm->data_message->ctn = ch->ctn;
1841 GNUNET_memcpy (&crm->data_message[1], buf, buf_len);
1842 GNUNET_CONTAINER_DLL_insert_tail (ch->head_sent, ch->tail_sent, crm);
1843 LOG (GNUNET_ERROR_TYPE_DEBUG,
1844 "Sending message %u from local client to %s with %lu bytes\n",
1845 ntohl (crm->data_message->mid.mid),
1846 GCCH_2s (ch),
1847 (unsigned long) buf_len);
1848 if (NULL != ch->retry_data_task)
1849 {
1850 GNUNET_SCHEDULER_cancel (ch->retry_data_task);
1851 ch->retry_data_task = NULL;
1852 }
1853 crm->qe = GCT_send (ch->t, &crm->data_message->header, &data_sent_cb, crm,
1854 &crm->data_message->ctn);
1855 GNUNET_assert (NULL == ch->retry_data_task);
1856 return GNUNET_OK;
1857}
1858
1859
1860void
1861GCCH_handle_local_ack (struct CadetChannel *ch,
1862 struct GNUNET_CADET_ClientChannelNumber client_ccn)
1863{
1864 struct CadetChannelClient *ccc;
1865 struct CadetOutOfOrderMessage *com;
1866
1867 if ((NULL != ch->owner) &&
1868 (ch->owner->ccn.channel_of_client == client_ccn.channel_of_client))
1869 ccc = ch->owner;
1870 else if ((NULL != ch->dest) &&
1871 (ch->dest->ccn.channel_of_client == client_ccn.channel_of_client))
1872 ccc = ch->dest;
1873 else
1874 GNUNET_assert (0);
1875 ccc->client_ready = GNUNET_YES;
1876 com = ccc->head_recv;
1877 if (NULL == com)
1878 {
1879 LOG (GNUNET_ERROR_TYPE_DEBUG,
1880 "Got LOCAL_ACK, %s-%X ready to receive more data, but none pending on %s-%X(%p)!\n",
1881 GSC_2s (ccc->c),
1882 ntohl (client_ccn.channel_of_client),
1883 GCCH_2s (ch),
1884 ntohl (ccc->ccn.channel_of_client),
1885 ccc);
1886 return; /* none pending */
1887 }
1888 if (GNUNET_YES == ch->is_loopback)
1889 {
1890 int to_owner;
1891
1892 /* Messages are always in-order, just send */
1893 GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, com);
1894 ccc->num_recv--;
1895 GSC_send_to_client (ccc->c, com->env);
1896 /* Notify sender that we can receive more */
1897 if ((NULL != ch->owner) &&
1898 (ccc->ccn.channel_of_client == ch->owner->ccn.channel_of_client))
1899 {
1900 to_owner = GNUNET_NO;
1901 }
1902 else
1903 {
1904 GNUNET_assert ((NULL != ch->dest) && (ccc->ccn.channel_of_client ==
1905 ch->dest->ccn.channel_of_client));
1906 to_owner = GNUNET_YES;
1907 }
1908 send_ack_to_client (ch, to_owner);
1909 GNUNET_free (com);
1910 return;
1911 }
1912
1913 if ((com->mid.mid != ch->mid_recv.mid) && (GNUNET_NO == ch->out_of_order) &&
1914 (GNUNET_YES == ch->reliable))
1915 {
1916 LOG (GNUNET_ERROR_TYPE_DEBUG,
1917 "Got LOCAL_ACK, %s-%X ready to receive more data (but next one is out-of-order %u vs. %u)!\n",
1918 GSC_2s (ccc->c),
1919 ntohl (ccc->ccn.channel_of_client),
1920 ntohl (com->mid.mid),
1921 ntohl (ch->mid_recv.mid));
1922 return; /* missing next one in-order */
1923 }
1924
1925 LOG (GNUNET_ERROR_TYPE_DEBUG,
1926 "Got LOCAL_ACK, giving payload message %u to %s-%X on %s\n",
1927 ntohl (com->mid.mid),
1928 GSC_2s (ccc->c),
1929 ntohl (ccc->ccn.channel_of_client),
1930 GCCH_2s (ch));
1931
1932 /* all good, pass next message to client */
1933 GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, com);
1934 ccc->num_recv--;
1935 /* FIXME: if unreliable, this is not aggressive
1936 enough, as it would be OK to have lost some! */
1937
1938 ch->mid_recv.mid = htonl (1 + ntohl (com->mid.mid));
1939 ch->mid_futures >>= 1; /* equivalent to division by 2 */
1940 ccc->client_ready = GNUNET_NO;
1941 GSC_send_to_client (ccc->c, com->env);
1942 GNUNET_free (com);
1943 send_channel_data_ack (ch);
1944 if (NULL != ccc->head_recv)
1945 return;
1946 if (GNUNET_NO == ch->destroy)
1947 return;
1948 GCT_send_channel_destroy (ch->t, ch->ctn);
1949 channel_destroy (ch);
1950}
1951
1952
1953#define LOG2(level, ...) \
1954 GNUNET_log_from_nocheck (level, "cadet-chn", __VA_ARGS__)
1955
1956
1957/**
1958 * Log channel info.
1959 *
1960 * @param ch Channel.
1961 * @param level Debug level to use.
1962 */
1963void
1964GCCH_debug (struct CadetChannel *ch, enum GNUNET_ErrorType level)
1965{
1966#if ! defined(GNUNET_CULL_LOGGING)
1967 int do_log;
1968
1969 do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
1970 "cadet-chn",
1971 __FILE__,
1972 __FUNCTION__,
1973 __LINE__);
1974 if (0 == do_log)
1975 return;
1976
1977 if (NULL == ch)
1978 {
1979 LOG2 (level, "CHN *** DEBUG NULL CHANNEL ***\n");
1980 return;
1981 }
1982 LOG2 (level, "CHN %s:%X (%p)\n", GCT_2s (ch->t), ch->ctn.cn, ch);
1983 if (NULL != ch->owner)
1984 {
1985 LOG2 (level,
1986 "CHN origin %s ready %s local-id: %u\n",
1987 GSC_2s (ch->owner->c),
1988 ch->owner->client_ready ? "YES" : "NO",
1989 ntohl (ch->owner->ccn.channel_of_client));
1990 }
1991 if (NULL != ch->dest)
1992 {
1993 LOG2 (level,
1994 "CHN destination %s ready %s local-id: %u\n",
1995 GSC_2s (ch->dest->c),
1996 ch->dest->client_ready ? "YES" : "NO",
1997 ntohl (ch->dest->ccn.channel_of_client));
1998 }
1999 LOG2 (level,
2000 "CHN Message IDs recv: %d (%llX), send: %d\n",
2001 ntohl (ch->mid_recv.mid),
2002 (unsigned long long) ch->mid_futures,
2003 ntohl (ch->mid_send.mid));
2004#endif
2005}
2006
2007
2008/* end of gnunet-service-cadet_channel.c */
diff --git a/src/service/cadet/gnunet-service-cadet_channel.h b/src/service/cadet/gnunet-service-cadet_channel.h
new file mode 100644
index 000000000..b09de883f
--- /dev/null
+++ b/src/service/cadet/gnunet-service-cadet_channel.h
@@ -0,0 +1,306 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2001-2017 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file cadet/gnunet-service-cadet_channel.h
23 * @brief GNUnet CADET service with encryption
24 * @author Bartlomiej Polot
25 * @author Christian Grothoff
26 */
27#ifndef GNUNET_SERVICE_CADET_CHANNEL_H
28#define GNUNET_SERVICE_CADET_CHANNEL_H
29
30#include "gnunet-service-cadet.h"
31#include "gnunet-service-cadet_peer.h"
32#include "cadet_protocol.h"
33
34
35/**
36 * A channel is a bidirectional connection between two CADET
37 * clients. Communication can be reliable, unreliable, in-order
38 * or out-of-order. One client is the "local" client, this
39 * one initiated the connection. The other client is the
40 * "incoming" client, this one listened on a port to accept
41 * the connection from the "local" client.
42 */
43struct CadetChannel;
44
45
46/**
47 * Hash the @a port and @a initiator and @a listener to
48 * calculate the "challenge" @a h_port we send to the other
49 * peer on #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN.
50 *
51 * @param[out] h_port set to the hash of @a port, @a initiator and @a listener
52 * @param port cadet port, as seen by CADET clients
53 * @param listener peer that is listining on @a port
54 */
55void
56GCCH_hash_port (struct GNUNET_HashCode *h_port,
57 const struct GNUNET_HashCode *port,
58 const struct GNUNET_PeerIdentity *listener);
59
60/**
61 * Check if type of message is the one to drop.
62 * @param ch CadetChannel to check for message type to drop.
63 * @param message GNUNET_MessageHeader to compare the type with.
64 */
65int
66GCCH_is_type_to_drop (struct CadetChannel *ch, const struct
67 GNUNET_MessageHeader *message);
68
69/**
70 * Assign type of message to drop.
71 * @param ch CadetChannel to assign type to drop.
72 * @param message GNUNET_CADET_RequestDropCadetMessage to get the type from.
73 */
74void
75GCCH_assign_type_to_drop (struct CadetChannel *ch, const struct
76 GNUNET_CADET_RequestDropCadetMessage *message);
77
78/**
79 * Get the static string for identification of the channel.
80 *
81 * @param ch Channel.
82 *
83 * @return Static string with the channel IDs.
84 */
85const char *
86GCCH_2s (const struct CadetChannel *ch);
87
88
89/**
90 * Log channel info.
91 *
92 * @param ch Channel.
93 * @param level Debug level to use.
94 */
95void
96GCCH_debug (struct CadetChannel *ch,
97 enum GNUNET_ErrorType level);
98
99
100/**
101 * Get the channel's public ID.
102 *
103 * @param ch Channel.
104 *
105 * @return ID used to identify the channel with the remote peer.
106 */
107struct GNUNET_CADET_ChannelTunnelNumber
108GCCH_get_id (const struct CadetChannel *ch);
109
110
111/**
112 * Create a new channel.
113 *
114 * @param owner local client owning the channel
115 * @param owner_id local chid of this channel at the @a owner
116 * @param destination peer to which we should build the channel
117 * @param port desired port at @a destination
118 * @param options options for the channel
119 * @return handle to the new channel
120 */
121struct CadetChannel *
122GCCH_channel_local_new (struct CadetClient *owner,
123 struct GNUNET_CADET_ClientChannelNumber owner_id,
124 struct CadetPeer *destination,
125 const struct GNUNET_HashCode *port,
126 uint32_t options);
127
128
129/**
130 * A client is bound to the port that we have a channel
131 * open to. Send the acknowledgement for the connection
132 * request and establish the link with the client.
133 *
134 * @param ch open incoming channel
135 * @param c client listening on the respective @a port
136 * @param port port number @a c is listening on
137 */
138void
139GCCH_bind (struct CadetChannel *ch,
140 struct CadetClient *c,
141 const struct GNUNET_HashCode *port);
142
143
144/**
145 * Destroy locally created channel. Called by the
146 * local client, so no need to tell the client.
147 *
148 * @param ch channel to destroy
149 * @param c client that caused the destruction
150 * @param ccn client number of the client @a c
151 */
152void
153GCCH_channel_local_destroy (struct CadetChannel *ch,
154 struct CadetClient *c,
155 struct GNUNET_CADET_ClientChannelNumber ccn);
156
157
158/**
159 * Function called once and only once after a channel was bound
160 * to its tunnel via #GCT_add_channel() is ready for transmission.
161 * Note that this is only the case for channels that this peer
162 * initiates, as for incoming channels we assume that they are
163 * ready for transmission immediately upon receiving the open
164 * message. Used to bootstrap the #GCT_send() process.
165 *
166 * @param ch the channel for which the tunnel is now ready
167 */
168void
169GCCH_tunnel_up (struct CadetChannel *ch);
170
171
172/**
173 * Create a new channel based on a request coming in over the network.
174 *
175 * @param t tunnel to the remote peer
176 * @param chid identifier of this channel in the tunnel
177 * @param h_port hash of desired local port
178 * @param options options for the channel
179 * @return handle to the new channel
180 */
181struct CadetChannel *
182GCCH_channel_incoming_new (struct CadetTunnel *t,
183 struct GNUNET_CADET_ChannelTunnelNumber chid,
184 const struct GNUNET_HashCode *h_port,
185 uint32_t options);
186
187
188/**
189 * We got a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN message again for
190 * this channel. If the binding was successful, (re)transmit the
191 * #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK.
192 *
193 * @param ch channel that got the duplicate open
194 * @param cti identifier of the connection that delivered the message
195 */
196void
197GCCH_handle_duplicate_open (struct CadetChannel *ch,
198 const struct
199 GNUNET_CADET_ConnectionTunnelIdentifier *cti);
200
201
202/**
203 * We got payload data for a channel. Pass it on to the client
204 * and send an ACK to the other end (once flow control allows it!)
205 *
206 * @param ch channel that got data
207 * @param cti identifier of the connection that delivered the message
208 * @param msg message that was received
209 */
210void
211GCCH_handle_channel_plaintext_data (struct CadetChannel *ch,
212 const struct
213 GNUNET_CADET_ConnectionTunnelIdentifier *cti,
214 const struct
215 GNUNET_CADET_ChannelAppDataMessage *msg);
216
217
218/**
219 * We got an acknowledgement for payload data for a channel.
220 * Possibly resume transmissions.
221 *
222 * @param ch channel that got the ack
223 * @param cti identifier of the connection that delivered the message
224 * @param ack details about what was received
225 */
226void
227GCCH_handle_channel_plaintext_data_ack (struct CadetChannel *ch,
228 const struct
229 GNUNET_CADET_ConnectionTunnelIdentifier
230 *cti,
231 const struct
232 GNUNET_CADET_ChannelDataAckMessage *ack);
233
234
235/**
236 * We got an acknowledgement for the creation of the channel
237 * (the port is open on the other side). Verify that the
238 * other end really has the right port, and begin transmissions.
239 *
240 * @param ch channel to destroy
241 * @param cti identifier of the connection that delivered the message,
242 * NULL if the ACK was inferred because we got payload or are on loopback
243 * @param port port number (needed to verify receiver knows the port)
244 */
245void
246GCCH_handle_channel_open_ack (struct CadetChannel *ch,
247 const struct
248 GNUNET_CADET_ConnectionTunnelIdentifier *cti,
249 const struct GNUNET_HashCode *port);
250
251
252/**
253 * Destroy channel, based on the other peer closing the
254 * connection. Also needs to remove this channel from
255 * the tunnel.
256 *
257 * FIXME: need to make it possible to defer destruction until we have
258 * received all messages up to the destroy, and right now the destroy
259 * message (and this API) fails to give is the information we need!
260 *
261 * FIXME: also need to know if the other peer got a destroy from
262 * us before!
263 *
264 * @param ch channel to destroy
265 * @param cti identifier of the connection that delivered the message,
266 * NULL if we are simulating receiving a destroy due to shutdown
267 */
268void
269GCCH_handle_remote_destroy (struct CadetChannel *ch,
270 const struct
271 GNUNET_CADET_ConnectionTunnelIdentifier *cti);
272
273
274/**
275 * Handle data given by a client.
276 *
277 * Check whether the client is allowed to send in this tunnel, save if
278 * channel is reliable and send an ACK to the client if there is still
279 * buffer space in the tunnel.
280 *
281 * @param ch Channel.
282 * @param sender_ccn ccn of the sender
283 * @param buf payload to transmit.
284 * @param buf_len number of bytes in @a buf
285 * @return #GNUNET_OK if everything goes well,
286 * #GNUNET_SYSERR in case of an error.
287 */
288int
289GCCH_handle_local_data (struct CadetChannel *ch,
290 struct GNUNET_CADET_ClientChannelNumber sender_ccn,
291 const char *buf,
292 size_t buf_len);
293
294
295/**
296 * Handle ACK from client on local channel. Means the client is ready
297 * for more data, see if we have any for it.
298 *
299 * @param ch channel to destroy
300 * @param client_ccn ccn of the client sending the ack
301 */
302void
303GCCH_handle_local_ack (struct CadetChannel *ch,
304 struct GNUNET_CADET_ClientChannelNumber client_ccn);
305
306#endif
diff --git a/src/service/cadet/gnunet-service-cadet_connection.c b/src/service/cadet/gnunet-service-cadet_connection.c
new file mode 100644
index 000000000..f01c1388e
--- /dev/null
+++ b/src/service/cadet/gnunet-service-cadet_connection.c
@@ -0,0 +1,1079 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2001-2017 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file cadet/gnunet-service-cadet_connection.c
23 * @brief management of CORE-level end-to-end connections; establishes
24 * end-to-end routes and transmits messages along the route
25 * @author Bartlomiej Polot
26 * @author Christian Grothoff
27 */
28#include "platform.h"
29#include "gnunet_signatures.h"
30#include "gnunet-service-cadet_connection.h"
31#include "gnunet-service-cadet_channel.h"
32#include "gnunet-service-cadet_paths.h"
33#include "gnunet-service-cadet_tunnels.h"
34#include "gnunet_cadet_service.h"
35#include "gnunet_statistics_service.h"
36#include "cadet_protocol.h"
37
38
39#define LOG(level, ...) GNUNET_log_from (level, "cadet-con", __VA_ARGS__)
40
41
42/**
43 * How long do we wait initially before retransmitting the KX?
44 * TODO: replace by 2 RTT if/once we have connection-level RTT data!
45 */
46#define INITIAL_CONNECTION_CREATE_RETRY_DELAY \
47 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 200)
48
49
50/**
51 * All the states a connection can be in.
52 */
53enum CadetConnectionState
54{
55 /**
56 * Uninitialized status, we have not yet even gotten the message queue.
57 */
58 CADET_CONNECTION_NEW,
59
60 /**
61 * Connection create message in queue, awaiting transmission by CORE.
62 */
63 CADET_CONNECTION_SENDING_CREATE,
64
65 /**
66 * Connection create message sent, waiting for ACK.
67 */
68 CADET_CONNECTION_SENT,
69
70 /**
71 * We are an inbound connection, and received a CREATE. Need to
72 * send an CREATE_ACK back.
73 */
74 CADET_CONNECTION_CREATE_RECEIVED,
75
76 /**
77 * Connection confirmed, ready to carry traffic.
78 */
79 CADET_CONNECTION_READY
80};
81
82/**
83 * Low-level connection to a destination.
84 */
85struct CadetConnection
86{
87 /**
88 * ID of the connection.
89 */
90 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
91
92 /**
93 * To which peer does this connection go?
94 */
95 struct CadetPeer *destination;
96
97 /**
98 * Which tunnel is using this connection?
99 */
100 struct CadetTConnection *ct;
101
102 /**
103 * Path we are using to our destination.
104 */
105 struct CadetPeerPath *path;
106
107 /**
108 * Pending message, NULL if we are ready to transmit.
109 */
110 struct GNUNET_MQ_Envelope *env;
111
112 /**
113 * Handle for calling #GCP_request_mq_cancel() once we are finished.
114 */
115 struct GCP_MessageQueueManager *mq_man;
116
117 /**
118 * Task for connection maintenance.
119 */
120 struct GNUNET_SCHEDULER_Task *task;
121
122 /**
123 * Queue entry for keepalive messages.
124 */
125 struct CadetTunnelQueueEntry *keepalive_qe;
126
127 /**
128 * Function to call once we are ready to transmit.
129 */
130 GCC_ReadyCallback ready_cb;
131
132 /**
133 * Closure for @e ready_cb.
134 */
135 void *ready_cb_cls;
136
137 /**
138 * How long do we wait before we try again with a CREATE message?
139 */
140 struct GNUNET_TIME_Relative retry_delay;
141
142 /**
143 * Earliest time for re-trying CREATE
144 */
145 struct GNUNET_TIME_Absolute create_at;
146
147 /**
148 * Earliest time for re-trying CREATE_ACK
149 */
150 struct GNUNET_TIME_Absolute create_ack_at;
151
152 /**
153 * Performance metrics for this connection.
154 */
155 struct CadetConnectionMetrics metrics;
156
157 /**
158 * State of the connection.
159 */
160 enum CadetConnectionState state;
161
162 /**
163 * How many latency observations did we make for this connection?
164 */
165 unsigned int latency_datapoints;
166
167 /**
168 * Offset of our @e destination in @e path.
169 */
170 unsigned int off;
171
172 /**
173 * Are we ready to transmit via @e mq_man right now?
174 */
175 int mqm_ready;
176};
177
178
179/**
180 * Lookup a connection by its identifier.
181 *
182 * @param cid identifier to resolve
183 * @return NULL if connection was not found
184 */
185struct CadetConnection *
186GCC_lookup (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
187{
188 return GNUNET_CONTAINER_multishortmap_get (connections,
189 &cid->connection_of_tunnel);
190}
191
192
193/**
194 * Update the connection state. Also triggers the necessary
195 * MQM notifications.
196 *
197 * @param cc connection to update the state for
198 * @param new_state new state for @a cc
199 * @param new_mqm_ready new `mqm_ready` state for @a cc
200 */
201static void
202update_state (struct CadetConnection *cc,
203 enum CadetConnectionState new_state,
204 int new_mqm_ready)
205{
206 int old_ready;
207 int new_ready;
208
209 LOG (GNUNET_ERROR_TYPE_DEBUG,
210 "Trying to update connection state for %s having old state %d to new %d and mqm_ready old %d to mqm_ready new %d\n",
211 GCT_2s (cc->ct->t),
212 cc->state,
213 new_state,
214 cc->mqm_ready,
215 new_mqm_ready);
216
217 if ((new_state == cc->state) && (new_mqm_ready == cc->mqm_ready))
218 return; /* no change, nothing to do */
219 old_ready =
220 ((CADET_CONNECTION_READY == cc->state) && (GNUNET_YES == cc->mqm_ready));
221 new_ready =
222 ((CADET_CONNECTION_READY == new_state) && (GNUNET_YES == new_mqm_ready));
223 cc->state = new_state;
224 cc->mqm_ready = new_mqm_ready;
225
226 LOG (GNUNET_ERROR_TYPE_DEBUG,
227 "Updating connection state for %s having old_ready %d and new_rady %d\n",
228 GCT_2s (cc->ct->t),
229 old_ready,
230 new_ready);
231
232 if (old_ready != new_ready)
233 cc->ready_cb (cc->ready_cb_cls, new_ready);
234}
235
236
237/**
238 * Destroy a connection, part of the internal implementation. Called
239 * only from #GCC_destroy_from_core() or #GCC_destroy_from_tunnel().
240 *
241 * @param cc connection to destroy
242 */
243static void
244GCC_destroy (struct CadetConnection *cc)
245{
246 LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroying %s\n", GCC_2s (cc));
247 if (NULL != cc->mq_man)
248 {
249 GCP_request_mq_cancel (cc->mq_man, NULL);
250 cc->mq_man = NULL;
251 }
252 if (NULL != cc->task)
253 {
254 GNUNET_SCHEDULER_cancel (cc->task);
255 cc->task = NULL;
256 }
257 if (NULL != cc->keepalive_qe)
258 {
259 GCT_send_cancel (cc->keepalive_qe);
260 cc->keepalive_qe = NULL;
261 }
262 GCPP_del_connection (cc->path, cc->off, cc);
263 for (unsigned int i = 0; i < cc->off; i++)
264 GCP_remove_connection (GCPP_get_peer_at_offset (cc->path, i), cc);
265 GNUNET_assert (
266 GNUNET_YES ==
267 GNUNET_CONTAINER_multishortmap_remove (connections,
268 &GCC_get_id (cc)
269 ->connection_of_tunnel,
270 cc));
271 GNUNET_free (cc);
272}
273
274
275/**
276 * Destroy a connection, called when the CORE layer is already done
277 * (i.e. has received a BROKEN message), but if we still have to
278 * communicate the destruction of the connection to the tunnel (if one
279 * exists).
280 *
281 * @param cc connection to destroy
282 */
283void
284GCC_destroy_without_core (struct CadetConnection *cc)
285{
286 if (NULL != cc->ct)
287 {
288 GCT_connection_lost (cc->ct);
289 cc->ct = NULL;
290 }
291 GCC_destroy (cc);
292}
293
294
295/**
296 * Destroy a connection, called if the tunnel association with the
297 * connection was already broken, but we still need to notify the CORE
298 * layer about the breakage.
299 *
300 * @param cc connection to destroy
301 */
302void
303GCC_destroy_without_tunnel (struct CadetConnection *cc)
304{
305 cc->ct = NULL;
306 if ((CADET_CONNECTION_SENDING_CREATE != cc->state) && (NULL != cc->mq_man))
307 {
308 struct GNUNET_MQ_Envelope *env;
309 struct GNUNET_CADET_ConnectionDestroyMessage *destroy_msg;
310
311 /* Need to notify next hop that we are down. */
312 env =
313 GNUNET_MQ_msg (destroy_msg, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY);
314 destroy_msg->cid = cc->cid;
315 GCP_request_mq_cancel (cc->mq_man, env);
316 cc->mq_man = NULL;
317 }
318 GCC_destroy (cc);
319}
320
321
322/**
323 * Return the tunnel associated with this connection.
324 *
325 * @param cc connection to query
326 * @return corresponding entry in the tunnel's connection list
327 */
328struct CadetTConnection *
329GCC_get_ct (struct CadetConnection *cc)
330{
331 return cc->ct;
332}
333
334
335/**
336 * Obtain performance @a metrics from @a cc.
337 *
338 * @param cc connection to query
339 * @return the metrics
340 */
341const struct CadetConnectionMetrics *
342GCC_get_metrics (struct CadetConnection *cc)
343{
344 return &cc->metrics;
345}
346
347
348/**
349 * Send a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE through the
350 * tunnel to prevent it from timing out.
351 *
352 * @param cls the `struct CadetConnection` to keep alive.
353 */
354static void
355send_keepalive (void *cls);
356
357
358/**
359 * Keepalive was transmitted. Remember this, and possibly
360 * schedule the next one.
361 *
362 * @param cls the `struct CadetConnection` to keep alive.
363 * @param cid identifier of the connection within the tunnel, NULL
364 * if transmission failed
365 */
366static void
367keepalive_done (void *cls,
368 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
369{
370 struct CadetConnection *cc = cls;
371
372 cc->keepalive_qe = NULL;
373 if ((GNUNET_YES == cc->mqm_ready) && (NULL == cc->task))
374 cc->task =
375 GNUNET_SCHEDULER_add_delayed (keepalive_period, &send_keepalive, cc);
376}
377
378
379/**
380 * Send a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE through the
381 * tunnel to prevent it from timing out.
382 *
383 * @param cls the `struct CadetConnection` to keep alive.
384 */
385static void
386send_keepalive (void *cls)
387{
388 struct CadetConnection *cc = cls;
389 struct GNUNET_MessageHeader msg;
390
391 cc->task = NULL;
392 if (CADET_TUNNEL_KEY_OK != GCT_get_estate (cc->ct->t))
393 {
394 /* Tunnel not yet ready, wait with keepalives... */
395 cc->task =
396 GNUNET_SCHEDULER_add_delayed (keepalive_period, &send_keepalive, cc);
397 return;
398 }
399 GNUNET_assert (NULL != cc->ct);
400 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
401 GNUNET_assert (NULL == cc->keepalive_qe);
402 LOG (GNUNET_ERROR_TYPE_INFO,
403 "Sending KEEPALIVE on behalf of %s via %s\n",
404 GCC_2s (cc),
405 GCT_2s (cc->ct->t));
406 GNUNET_STATISTICS_update (stats, "# keepalives sent", 1, GNUNET_NO);
407 msg.size = htons (sizeof(msg));
408 msg.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE);
409
410 cc->keepalive_qe = GCT_send (cc->ct->t, &msg, &keepalive_done, cc, NULL);
411}
412
413
414/**
415 * We sent a message for which we expect to receive an ACK via
416 * the connection identified by @a cti.
417 *
418 * @param cid connection identifier where we expect an ACK
419 */
420void
421GCC_ack_expected (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
422{
423 struct CadetConnection *cc;
424
425 cc = GCC_lookup (cid);
426 if (NULL == cc)
427 return; /* whopise, connection already down? */
428 cc->metrics.num_acked_transmissions++;
429}
430
431
432/**
433 * We observed an ACK for a message that was originally sent via
434 * the connection identified by @a cid.
435 *
436 * @param cid connection identifier where we got an ACK for a message
437 * that was originally sent via this connection (the ACK
438 * may have gotten back to us via a different connection).
439 */
440void
441GCC_ack_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
442{
443 struct CadetConnection *cc;
444
445 cc = GCC_lookup (cid);
446 if (NULL == cc)
447 return; /* whopise, connection already down? */
448 cc->metrics.num_successes++;
449}
450
451
452void
453GCC_latency_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
454 struct GNUNET_TIME_Relative latency)
455{
456 struct CadetConnection *cc;
457 double weight;
458 double result;
459
460 cc = GCC_lookup (cid);
461 if (NULL == cc)
462 return; /* whopise, connection already down? */
463 GNUNET_STATISTICS_update (stats, "# latencies observed", 1, GNUNET_NO);
464 cc->latency_datapoints++;
465 if (cc->latency_datapoints >= 7)
466 weight = 7.0;
467 else
468 weight = cc->latency_datapoints;
469 /* Compute weighted average, giving at MOST weight 7 to the
470 existing values, or less if that value is based on fewer than 7
471 measurements. */
472 result = (weight * cc->metrics.aged_latency.rel_value_us)
473 + 1.0 * latency.rel_value_us;
474 result /= (weight + 1.0);
475 cc->metrics.aged_latency.rel_value_us = (uint64_t) result;
476}
477
478
479void
480GCC_handle_connection_create_ack (struct CadetConnection *cc)
481{
482 LOG (GNUNET_ERROR_TYPE_DEBUG,
483 "Received CADET_CONNECTION_CREATE_ACK for %s in state %d (%s)\n",
484 GCC_2s (cc),
485 cc->state,
486 (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy");
487 if (CADET_CONNECTION_READY == cc->state)
488 return; /* Duplicate ACK, ignore */
489 if (NULL != cc->task)
490 {
491 GNUNET_SCHEDULER_cancel (cc->task);
492 cc->task = NULL;
493 }
494 cc->metrics.age = GNUNET_TIME_absolute_get ();
495 update_state (cc, CADET_CONNECTION_READY, cc->mqm_ready);
496 if ((NULL == cc->keepalive_qe) && (GNUNET_YES == cc->mqm_ready) &&
497 (NULL == cc->task))
498 cc->task =
499 GNUNET_SCHEDULER_add_delayed (keepalive_period, &send_keepalive, cc);
500}
501
502
503/**
504 * Handle KX message.
505 *
506 * @param cc connection that received encrypted message
507 * @param msg the key exchange message
508 */
509void
510GCC_handle_kx (struct CadetConnection *cc,
511 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
512{
513 LOG (GNUNET_ERROR_TYPE_DEBUG,
514 "Received KX message with ephermal %s on CC %s in state %d\n",
515 GNUNET_e2s (&msg->ephemeral_key),
516 GNUNET_sh2s (&cc->cid.connection_of_tunnel),
517 cc->state);
518 if (CADET_CONNECTION_SENT == cc->state)
519 {
520 /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine,
521 clearly something is working, so pretend we got an ACK. */
522 LOG (GNUNET_ERROR_TYPE_DEBUG,
523 "Faking connection CADET_CONNECTION_CREATE_ACK for %s due to KX\n",
524 GCC_2s (cc));
525 GCC_handle_connection_create_ack (cc);
526 }
527 GCT_handle_kx (cc->ct, msg);
528}
529
530
531/**
532 * Handle KX_AUTH message.
533 *
534 * @param cc connection that received encrypted message
535 * @param msg the key exchange message
536 */
537void
538GCC_handle_kx_auth (struct CadetConnection *cc,
539 const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg)
540{
541 LOG (GNUNET_ERROR_TYPE_DEBUG,
542 "Received KX AUTH message with ephermal %s on CC %s in state %d\n",
543 GNUNET_e2s (&msg->kx.ephemeral_key),
544 GNUNET_sh2s (&cc->cid.connection_of_tunnel),
545 cc->state);
546 if (CADET_CONNECTION_SENT == cc->state)
547 {
548 /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine,
549 clearly something is working, so pretend we got an ACK. */
550 LOG (GNUNET_ERROR_TYPE_DEBUG,
551 "Faking connection CADET_CONNECTION_CREATE_ACK for %s due to KX\n",
552 GCC_2s (cc));
553 GCC_handle_connection_create_ack (cc);
554 }
555 GCT_handle_kx_auth (cc->ct, msg);
556}
557
558
559/**
560 * Handle encrypted message.
561 *
562 * @param cc connection that received encrypted message
563 * @param msg the encrypted message to decrypt
564 */
565void
566GCC_handle_encrypted (struct CadetConnection *cc,
567 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
568{
569 if (CADET_CONNECTION_SENT == cc->state)
570 {
571 /* We didn't get the CREATE_ACK, but instead got payload. That's fine,
572 clearly something is working, so pretend we got an ACK. */
573 LOG (GNUNET_ERROR_TYPE_DEBUG,
574 "Faking connection ACK for %s due to ENCRYPTED payload\n",
575 GCC_2s (cc));
576 GCC_handle_connection_create_ack (cc);
577 }
578 cc->metrics.last_use = GNUNET_TIME_absolute_get ();
579 GCT_handle_encrypted (cc->ct, msg);
580}
581
582
583/**
584 * Set the signature for a monotime value on a GNUNET_CADET_ConnectionCreateMessage.
585 *
586 * @param msg The GNUNET_CADET_ConnectionCreateMessage.
587 */
588void
589set_monotime_sig (struct GNUNET_CADET_ConnectionCreateMessage *msg)
590{
591
592 struct CadetConnectionCreatePS cp = { .purpose.purpose = htonl (
593 GNUNET_SIGNATURE_PURPOSE_CADET_CONNECTION_INITIATOR),
594 .purpose.size = htonl (sizeof(cp)),
595 .monotonic_time = msg->monotime};
596
597 GNUNET_CRYPTO_eddsa_sign (my_private_key, &cp,
598 &msg->monotime_sig);
599
600}
601
602
603/**
604 * Send a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE message to the
605 * first hop.
606 *
607 * @param cls the `struct CadetConnection` to initiate
608 */
609static void
610send_create (void *cls)
611{
612 struct CadetConnection *cc = cls;
613 struct GNUNET_CADET_ConnectionCreateMessage *create_msg;
614 struct GNUNET_PeerIdentity *pids;
615 struct GNUNET_MQ_Envelope *env;
616 struct CadetTunnel *t;
617
618 cc->task = NULL;
619 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
620 env =
621 GNUNET_MQ_msg_extra (create_msg,
622 (2 + cc->off) * sizeof(struct GNUNET_PeerIdentity),
623 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE);
624 // TODO This will be removed in a major release, because this will be a protocol breaking change. We set the deprecated 'reliable' bit here that was removed.
625 create_msg->options = 2;
626 create_msg->cid = cc->cid;
627
628 // check for tunnel state and set signed monotime (xrs,t3ss)
629 t = GCP_get_tunnel (cc->destination, GNUNET_YES);
630 if ((NULL != t) && (GCT_get_estate (t) == CADET_TUNNEL_KEY_UNINITIALIZED) &&
631 (GCT_alice_or_betty (GCP_get_id (cc->destination)) == GNUNET_NO))
632 {
633 create_msg->has_monotime = GNUNET_YES;
634 create_msg->monotime = GNUNET_TIME_absolute_hton (
635 GNUNET_TIME_absolute_get_monotonic (cfg));
636 set_monotime_sig (create_msg);
637 }
638
639 pids = (struct GNUNET_PeerIdentity *) &create_msg[1];
640 pids[0] = my_full_id;
641 for (unsigned int i = 0; i <= cc->off; i++)
642 pids[i + 1] = *GCP_get_id (GCPP_get_peer_at_offset (cc->path, i));
643 LOG (GNUNET_ERROR_TYPE_DEBUG,
644 "Sending CADET_CONNECTION_CREATE message for %s with %u hops\n",
645 GCC_2s (cc),
646 cc->off + 2);
647 cc->env = env;
648 cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay);
649 cc->create_at = GNUNET_TIME_relative_to_absolute (cc->retry_delay);
650 update_state (cc, CADET_CONNECTION_SENT, GNUNET_NO);
651 GCP_send (cc->mq_man, env);
652}
653
654
655/**
656 * Send a CREATE_ACK message towards the origin.
657 *
658 * @param cls the `struct CadetConnection` to initiate
659 */
660static void
661send_create_ack (void *cls)
662{
663 struct CadetConnection *cc = cls;
664 struct GNUNET_CADET_ConnectionCreateAckMessage *ack_msg;
665 struct GNUNET_MQ_Envelope *env;
666
667 cc->task = NULL;
668 LOG (GNUNET_ERROR_TYPE_DEBUG,
669 "Sending CONNECTION_CREATE_ACK message for %s\n",
670 GCC_2s (cc));
671 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
672 env =
673 GNUNET_MQ_msg (ack_msg, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK);
674 ack_msg->cid = cc->cid;
675 cc->env = env;
676 cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay);
677 cc->create_ack_at = GNUNET_TIME_relative_to_absolute (cc->retry_delay);
678 if (CADET_CONNECTION_CREATE_RECEIVED == cc->state)
679 update_state (cc, CADET_CONNECTION_READY, GNUNET_NO);
680 if (CADET_CONNECTION_READY == cc->state)
681 cc->task =
682 GNUNET_SCHEDULER_add_delayed (keepalive_period, &send_keepalive, cc);
683 GCP_send (cc->mq_man, env);
684}
685
686
687/**
688 * We got a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE for a
689 * connection that we already have. Either our ACK got lost
690 * or something is fishy. Consider retransmitting the ACK.
691 *
692 * @param cc connection that got the duplicate CREATE
693 */
694void
695GCC_handle_duplicate_create (struct CadetConnection *cc)
696{
697 if (GNUNET_YES == cc->mqm_ready)
698 {
699 LOG (GNUNET_ERROR_TYPE_DEBUG,
700 "Got duplicate CREATE for %s, scheduling another ACK (%s)\n",
701 GCC_2s (cc),
702 (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy");
703 /* Revert back to the state of having only received the 'CREATE',
704 and immediately proceed to send the CREATE_ACK. */
705 update_state (cc, CADET_CONNECTION_CREATE_RECEIVED, cc->mqm_ready);
706 if (NULL != cc->task)
707 GNUNET_SCHEDULER_cancel (cc->task);
708 cc->task =
709 GNUNET_SCHEDULER_add_at (cc->create_ack_at, &send_create_ack, cc);
710 }
711 else
712 {
713 /* We are currently sending something else back, which
714 can only be an ACK or payload, either of which would
715 do. So actually no need to do anything. */
716 LOG (GNUNET_ERROR_TYPE_DEBUG,
717 "Got duplicate CREATE for %s. MQ is busy, not queueing another ACK\n",
718 GCC_2s (cc));
719 }
720}
721
722
723/**
724 * There has been a change in the message queue existence for our
725 * peer at the first hop. Adjust accordingly.
726 *
727 * @param cls the `struct CadetConnection`
728 * @param available #GNUNET_YES if sending is now possible,
729 * #GNUNET_NO if sending is no longer possible
730 * #GNUNET_SYSERR if sending is no longer possible
731 * and the last envelope was discarded
732 */
733static void
734manage_first_hop_mq (void *cls, int available)
735{
736 struct CadetConnection *cc = cls;
737
738 if (GNUNET_YES != available)
739 {
740 /* Connection is down, for now... */
741 LOG (GNUNET_ERROR_TYPE_DEBUG, "Core MQ for %s went down\n", GCC_2s (cc));
742 update_state (cc, CADET_CONNECTION_NEW, GNUNET_NO);
743 cc->retry_delay = INITIAL_CONNECTION_CREATE_RETRY_DELAY;
744 if (NULL != cc->task)
745 {
746 GNUNET_SCHEDULER_cancel (cc->task);
747 cc->task = NULL;
748 }
749 return;
750 }
751
752 update_state (cc, cc->state, GNUNET_YES);
753 LOG (GNUNET_ERROR_TYPE_DEBUG,
754 "Core MQ for %s became available in state %d\n",
755 GCC_2s (cc),
756 cc->state);
757 switch (cc->state)
758 {
759 case CADET_CONNECTION_NEW:
760 /* Transmit immediately */
761 cc->task = GNUNET_SCHEDULER_add_at (cc->create_at, &send_create, cc);
762 break;
763
764 case CADET_CONNECTION_SENDING_CREATE:
765 /* Should not be possible to be called in this state. */
766 GNUNET_assert (0);
767 break;
768
769 case CADET_CONNECTION_SENT:
770 /* Retry a bit later... */
771 cc->task = GNUNET_SCHEDULER_add_at (cc->create_at, &send_create, cc);
772 break;
773
774 case CADET_CONNECTION_CREATE_RECEIVED:
775 /* We got the 'CREATE' (incoming connection), should send the CREATE_ACK */
776 cc->metrics.age = GNUNET_TIME_absolute_get ();
777 cc->task =
778 GNUNET_SCHEDULER_add_at (cc->create_ack_at, &send_create_ack, cc);
779 break;
780
781 case CADET_CONNECTION_READY:
782 if ((NULL == cc->keepalive_qe) && (GNUNET_YES == cc->mqm_ready) &&
783 (NULL == cc->task))
784 {
785 LOG (GNUNET_ERROR_TYPE_DEBUG,
786 "Scheduling keepalive for %s in %s\n",
787 GCC_2s (cc),
788 GNUNET_STRINGS_relative_time_to_string (keepalive_period,
789 GNUNET_YES));
790 cc->task =
791 GNUNET_SCHEDULER_add_delayed (keepalive_period, &send_keepalive, cc);
792 }
793 break;
794 }
795}
796
797
798/**
799 * Create a connection to @a destination via @a path and notify @a cb
800 * whenever we are ready for more data. Shared logic independent of
801 * who is initiating the connection.
802 *
803 * @param destination where to go
804 * @param path which path to take (may not be the full path)
805 * @param off offset of @a destination on @a path
806 * @param ct which tunnel uses this connection
807 * @param init_state initial state for the connection
808 * @param ready_cb function to call when ready to transmit
809 * @param ready_cb_cls closure for @a cb
810 * @return handle to the connection
811 */
812static struct CadetConnection *
813connection_create (struct CadetPeer *destination,
814 struct CadetPeerPath *path,
815 unsigned int off,
816 struct CadetTConnection *ct,
817 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
818 enum CadetConnectionState init_state,
819 GCC_ReadyCallback ready_cb,
820 void *ready_cb_cls)
821{
822 struct CadetConnection *cc;
823 struct CadetPeer *first_hop;
824
825 cc = GNUNET_new (struct CadetConnection);
826 cc->state = init_state;
827 cc->ct = ct;
828 cc->destination = destination; /* xrs,t3ss,lurchi*/
829 cc->cid = *cid;
830 cc->retry_delay =
831 GNUNET_TIME_relative_multiply (INITIAL_CONNECTION_CREATE_RETRY_DELAY, off);
832 GNUNET_assert (GNUNET_OK ==
833 GNUNET_CONTAINER_multishortmap_put (
834 connections,
835 &GCC_get_id (cc)->connection_of_tunnel,
836 cc,
837 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
838 cc->ready_cb = ready_cb;
839 cc->ready_cb_cls = ready_cb_cls;
840 cc->path = path;
841 cc->off = off;
842 LOG (GNUNET_ERROR_TYPE_DEBUG,
843 "Creating %s using path %s (offset: %u)\n",
844 GCC_2s (cc),
845 GCPP_2s (path),
846 off);
847 GCPP_add_connection (path, off, cc);
848 for (unsigned int i = 0; i < off; i++)
849 GCP_add_connection (GCPP_get_peer_at_offset (path, i), cc);
850 first_hop = GCPP_get_peer_at_offset (path, 0);
851 cc->mq_man = GCP_request_mq (first_hop, &manage_first_hop_mq, cc);
852 return cc;
853}
854
855
856/**
857 * Create a connection to @a destination via @a path and
858 * notify @a cb whenever we are ready for more data. This
859 * is an inbound tunnel, so we must use the existing @a cid
860 *
861 * @param destination where to go
862 * @param path which path to take (may not be the full path)
863 * @param ct which tunnel uses this connection
864 * @param ready_cb function to call when ready to transmit
865 * @param ready_cb_cls closure for @a cb
866 * @return handle to the connection, NULL if we already have
867 * a connection that takes precedence on @a path
868 */
869struct CadetConnection *
870GCC_create_inbound (struct CadetPeer *destination,
871 struct CadetPeerPath *path,
872 struct CadetTConnection *ct,
873 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
874 GCC_ReadyCallback ready_cb,
875 void *ready_cb_cls)
876{
877 struct CadetConnection *cc;
878 unsigned int off;
879
880 off = GCPP_find_peer (path, destination);
881 GNUNET_assert (UINT_MAX != off);
882 cc = GCPP_get_connection (path, destination, off);
883 if (NULL != cc)
884 {
885 int cmp;
886
887 cmp = GNUNET_memcmp (cid, &cc->cid);
888 if (0 == cmp)
889 {
890 /* Two peers picked the SAME random connection identifier at the
891 same time for the same path? Must be malicious. Drop
892 connection (existing and inbound), even if it is the only
893 one. */
894 GNUNET_break_op (0);
895 GCT_connection_lost (cc->ct);
896 GCC_destroy_without_tunnel (cc);
897 return NULL;
898 }
899 if (0 < cmp)
900 {
901 /* drop existing */
902 LOG (GNUNET_ERROR_TYPE_DEBUG,
903 "Got two connections on %s, dropping my existing %s\n",
904 GCPP_2s (path),
905 GCC_2s (cc));
906 GCT_connection_lost (cc->ct);
907 GCC_destroy_without_tunnel (cc);
908 }
909 else
910 {
911 /* keep existing */
912 LOG (GNUNET_ERROR_TYPE_DEBUG,
913 "Got two connections on %s, keeping my existing %s\n",
914 GCPP_2s (path),
915 GCC_2s (cc));
916 return NULL;
917 }
918 }
919
920 return connection_create (destination,
921 path,
922 off,
923 ct,
924 cid,
925 CADET_CONNECTION_CREATE_RECEIVED,
926 ready_cb,
927 ready_cb_cls);
928}
929
930
931struct CadetConnection *
932GCC_create (struct CadetPeer *destination,
933 struct CadetPeerPath *path,
934 unsigned int off,
935 struct CadetTConnection *ct,
936 GCC_ReadyCallback ready_cb,
937 void *ready_cb_cls)
938{
939 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
940
941 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, &cid, sizeof(cid));
942 return connection_create (destination,
943 path,
944 off,
945 ct,
946 &cid,
947 CADET_CONNECTION_NEW,
948 ready_cb,
949 ready_cb_cls);
950}
951
952
953/**
954 * Transmit message @a msg via connection @a cc. Must only be called
955 * (once) after the connection has signalled that it is ready via the
956 * `ready_cb`. Clients can also use #GCC_is_ready() to check if the
957 * connection is right now ready for transmission.
958 *
959 * @param cc connection identification
960 * @param env envelope with message to transmit; must NOT
961 * yet have a #GNUNET_MQ_notify_sent() callback attached to it
962 */
963void
964GCC_transmit (struct CadetConnection *cc, struct GNUNET_MQ_Envelope *env)
965{
966 LOG (GNUNET_ERROR_TYPE_DEBUG,
967 "Scheduling message for transmission on %s\n",
968 GCC_2s (cc));
969 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
970 GNUNET_assert (CADET_CONNECTION_READY == cc->state);
971 cc->metrics.last_use = GNUNET_TIME_absolute_get ();
972 cc->mqm_ready = GNUNET_NO;
973 if (NULL != cc->task)
974 {
975 GNUNET_SCHEDULER_cancel (cc->task);
976 cc->task = NULL;
977 }
978 GCP_send (cc->mq_man, env);
979}
980
981
982/**
983 * Obtain the path used by this connection.
984 *
985 * @param cc connection
986 * @param[out] off set to the length of the path we use
987 * @return path to @a cc
988 */
989struct CadetPeerPath *
990GCC_get_path (struct CadetConnection *cc, unsigned int *off)
991{
992 *off = cc->off;
993 return cc->path;
994}
995
996
997/**
998 * Obtain unique ID for the connection.
999 *
1000 * @param cc connection.
1001 * @return unique number of the connection
1002 */
1003const struct GNUNET_CADET_ConnectionTunnelIdentifier *
1004GCC_get_id (struct CadetConnection *cc)
1005{
1006 return &cc->cid;
1007}
1008
1009
1010/**
1011 * Get a (static) string for a connection.
1012 *
1013 * @param cc Connection.
1014 */
1015const char *
1016GCC_2s (const struct CadetConnection *cc)
1017{
1018 static char buf[128];
1019
1020 if (NULL == cc)
1021 return "Connection(NULL)";
1022
1023 if (NULL != cc->ct)
1024 {
1025 GNUNET_snprintf (buf,
1026 sizeof(buf),
1027 "Connection %s (%s)",
1028 GNUNET_sh2s (&cc->cid.connection_of_tunnel),
1029 GCT_2s (cc->ct->t));
1030 return buf;
1031 }
1032 GNUNET_snprintf (buf,
1033 sizeof(buf),
1034 "Connection %s",
1035 GNUNET_sh2s (&cc->cid.connection_of_tunnel));
1036 return buf;
1037}
1038
1039
1040#define LOG2(level, ...) \
1041 GNUNET_log_from_nocheck (level, "cadet-con", __VA_ARGS__)
1042
1043
1044/**
1045 * Log connection info.
1046 *
1047 * @param cc connection
1048 * @param level Debug level to use.
1049 */
1050void
1051GCC_debug (struct CadetConnection *cc, enum GNUNET_ErrorType level)
1052{
1053#if ! defined(GNUNET_CULL_LOGGING)
1054 int do_log;
1055
1056 do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
1057 "cadet-con",
1058 __FILE__,
1059 __FUNCTION__,
1060 __LINE__);
1061 if (0 == do_log)
1062 return;
1063 if (NULL == cc)
1064 {
1065 LOG2 (level, "Connection (NULL)\n");
1066 return;
1067 }
1068 LOG2 (level,
1069 "%s to %s via path %s in state %d is %s\n",
1070 GCC_2s (cc),
1071 GCP_2s (cc->destination),
1072 GCPP_2s (cc->path),
1073 cc->state,
1074 (GNUNET_YES == cc->mqm_ready) ? "ready" : "busy");
1075#endif
1076}
1077
1078
1079/* end of gnunet-service-cadet_connection.c */
diff --git a/src/service/cadet/gnunet-service-cadet_connection.h b/src/service/cadet/gnunet-service-cadet_connection.h
new file mode 100644
index 000000000..54c845b13
--- /dev/null
+++ b/src/service/cadet/gnunet-service-cadet_connection.h
@@ -0,0 +1,363 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2001-2017 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file cadet/gnunet-service-cadet_connection.h
23 * @brief A connection is a live end-to-end messaging mechanism
24 * where the peers are identified by a path and know how
25 * to forward along the route using a connection identifier
26 * for routing the data.
27 * @author Bartlomiej Polot
28 * @author Christian Grothoff
29 */
30#ifndef GNUNET_SERVICE_CADET_CONNECTION_H
31#define GNUNET_SERVICE_CADET_CONNECTION_H
32
33#include "gnunet_util_lib.h"
34#include "gnunet-service-cadet.h"
35#include "gnunet-service-cadet_peer.h"
36#include "cadet_protocol.h"
37
38
39/**
40 * Function called to notify tunnel about change in our readiness.
41 *
42 * @param cls closure
43 * @param is_ready #GNUNET_YES if the connection is now ready for transmission,
44 * #GNUNET_NO if the connection is no longer ready for transmission
45 */
46typedef void
47(*GCC_ReadyCallback)(void *cls,
48 int is_ready);
49
50
51/**
52 * Destroy a connection, called when the CORE layer is already done
53 * (i.e. has received a BROKEN message), but if we still have to
54 * communicate the destruction of the connection to the tunnel (if one
55 * exists).
56 *
57 * @param cc connection to destroy
58 */
59void
60GCC_destroy_without_core (struct CadetConnection *cc);
61
62
63/**
64 * Destroy a connection, called if the tunnel association with the
65 * connection was already broken, but we still need to notify the CORE
66 * layer about the breakage.
67 *
68 * @param cc connection to destroy
69 */
70void
71GCC_destroy_without_tunnel (struct CadetConnection *cc);
72
73
74/**
75 * Lookup a connection by its identifier.
76 *
77 * @param cid identifier to resolve
78 * @return NULL if connection was not found
79 */
80struct CadetConnection *
81GCC_lookup (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid);
82
83
84/**
85 * Create a connection to @a destination via @a path and
86 * notify @a cb whenever we are ready for more data.
87 *
88 * @param destination where to go
89 * @param path which path to take (may not be the full path)
90 * @param off offset of @a destination on @a path
91 * @param ct which tunnel uses this connection
92 * @param ready_cb function to call when ready to transmit
93 * @param ready_cb_cls closure for @a cb
94 * @return handle to the connection
95 */
96struct CadetConnection *
97GCC_create (struct CadetPeer *destination,
98 struct CadetPeerPath *path,
99 unsigned int off,
100 struct CadetTConnection *ct,
101 GCC_ReadyCallback ready_cb,
102 void *ready_cb_cls);
103
104
105/**
106 * Create a connection to @a destination via @a path and
107 * notify @a cb whenever we are ready for more data. This
108 * is an inbound tunnel, so we must use the existing @a cid
109 *
110 * @param destination where to go
111 * @param path which path to take (may not be the full path)
112 * @param ct which tunnel uses this connection
113 * @param ready_cb function to call when ready to transmit
114 * @param ready_cb_cls closure for @a cb
115 * @return handle to the connection, NULL if we already have
116 * a connection that takes precedence on @a path
117 */
118struct CadetConnection *
119GCC_create_inbound (struct CadetPeer *destination,
120 struct CadetPeerPath *path,
121 struct CadetTConnection *ct,
122 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
123 GCC_ReadyCallback ready_cb,
124 void *ready_cb_cls);
125
126
127/**
128 * Transmit message @a msg via connection @a cc. Must only be called
129 * (once) after the connection has signalled that it is ready via the
130 * `ready_cb`. Clients can also use #GCC_is_ready() to check if the
131 * connection is right now ready for transmission.
132 *
133 * @param cc connection identification
134 * @param env envelope with message to transmit;
135 * the #GNUNET_MQ_notify_send() must not have yet been used
136 * for the envelope. Also, the message better match the
137 * connection identifier of this connection...
138 */
139void
140GCC_transmit (struct CadetConnection *cc,
141 struct GNUNET_MQ_Envelope *env);
142
143
144/**
145 * A #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK was received for
146 * this connection, implying that the end-to-end connection is up.
147 * Process it.
148 *
149 * @param cc the connection that got the ACK.
150 */
151void
152GCC_handle_connection_create_ack (struct CadetConnection *cc);
153
154
155/**
156 * We got a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE for a
157 * connection that we already have. Either our ACK got lost
158 * or something is fishy. Consider retransmitting the ACK.
159 *
160 * @param cc connection that got the duplicate CREATE
161 */
162void
163GCC_handle_duplicate_create (struct CadetConnection *cc);
164
165
166/**
167 * Handle KX message.
168 *
169 * @param cc connection that received encrypted message
170 * @param msg the key exchange message
171 */
172void
173GCC_handle_kx (struct CadetConnection *cc,
174 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg);
175
176
177/**
178 * Handle KX_AUTH message.
179 *
180 * @param cc connection that received encrypted message
181 * @param msg the key exchange message
182 */
183void
184GCC_handle_kx_auth (struct CadetConnection *cc,
185 const struct
186 GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg);
187
188/**
189 * Purpose for the signature of a monotime.
190 */
191struct CadetConnectionCreatePS
192{
193
194 /**
195 * Purpose is #GNUNET_SIGNATURE_PURPOSE_CADET_CONNECTION_INITIATOR
196 */
197 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
198
199 /**
200 * Time at the initiator when generating the signature.
201 *
202 * Note that the receiver MUST IGNORE the absolute time, and only interpret
203 * the value as a mononic time and reject "older" values than the last one
204 * observed. This is necessary as we do not want to require synchronized
205 * clocks and may not have a bidirectional communication channel.
206 *
207 * Even with this, there is no real guarantee against replay achieved here,
208 * unless the latest timestamp is persisted. Persistence should be
209 * provided via PEERSTORE if possible.
210 */
211 struct GNUNET_TIME_AbsoluteNBO monotonic_time;
212
213};
214
215/**
216 * Performance metrics for a connection.
217 */
218struct CadetConnectionMetrics
219{
220 /**
221 * Our current best estimate of the latency, based on a weighted
222 * average of at least @a latency_datapoints values.
223 */
224 struct GNUNET_TIME_Relative aged_latency;
225
226 /**
227 * When was this connection first established? (by us sending or
228 * receiving the CREATE_ACK for the first time)
229 */
230 struct GNUNET_TIME_Absolute age;
231
232 /**
233 * When was this connection last used? (by us sending or
234 * receiving a PAYLOAD message on it)
235 */
236 struct GNUNET_TIME_Absolute last_use;
237
238 /**
239 * How many packets that ought to generate an ACK did we send via
240 * this connection?
241 */
242 unsigned long long num_acked_transmissions;
243
244 /**
245 * Number of packets that were sent via this connection did actually
246 * receive an ACK? (Note: ACKs may be transmitted and lost via
247 * other connections, so this value should only be interpreted
248 * relative to @e num_acked_transmissions and in relation to other
249 * connections.)
250 */
251 unsigned long long num_successes;
252};
253
254
255/**
256 * Obtain performance @a metrics from @a cc.
257 *
258 * @param cc connection to query
259 * @return the metrics
260 */
261const struct CadetConnectionMetrics *
262GCC_get_metrics (struct CadetConnection *cc);
263
264
265/**
266 * Handle encrypted message.
267 *
268 * @param cc connection that received encrypted message
269 * @param msg the encrypted message to decrypt
270 */
271void
272GCC_handle_encrypted (struct CadetConnection *cc,
273 const struct GNUNET_CADET_TunnelEncryptedMessage *msg);
274
275
276/**
277 * We sent a message for which we expect to receive an ACK via
278 * the connection identified by @a cti.
279 *
280 * @param cid connection identifier where we expect an ACK
281 */
282void
283GCC_ack_expected (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid);
284
285
286/**
287 * We observed an ACK for a message that was originally sent via
288 * the connection identified by @a cti.
289 *
290 * @param cid connection identifier where we got an ACK for a message
291 * that was originally sent via this connection (the ACK
292 * may have gotten back to us via a different connection).
293 */
294void
295GCC_ack_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid);
296
297
298/**
299 * We observed some the given @a latency on the connection
300 * identified by @a cti. (The same connection was taken
301 * in both directions.)
302 *
303 * @param cti connection identifier where we measured latency
304 * @param latency the observed latency
305 */
306void
307GCC_latency_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti,
308 struct GNUNET_TIME_Relative latency);
309
310
311/**
312 * Return the tunnel associated with this connection.
313 *
314 * @param cc connection to query
315 * @return corresponding entry in the tunnel's connection list
316 */
317struct CadetTConnection *
318GCC_get_ct (struct CadetConnection *cc);
319
320
321/**
322 * Obtain the path used by this connection.
323 *
324 * @param cc connection
325 * @param[out] off set to offset in this path where the connection @a cc ends
326 * @return path to @a cc
327 */
328struct CadetPeerPath *
329GCC_get_path (struct CadetConnection *cc,
330 unsigned int *off);
331
332
333/**
334 * Obtain unique ID for the connection.
335 *
336 * @param cc connection.
337 * @return unique number of the connection
338 */
339const struct GNUNET_CADET_ConnectionTunnelIdentifier *
340GCC_get_id (struct CadetConnection *cc);
341
342
343/**
344 * Get a (static) string for a connection.
345 *
346 * @param cc Connection.
347 */
348const char *
349GCC_2s (const struct CadetConnection *cc);
350
351
352/**
353 * Log connection info.
354 *
355 * @param cc connection
356 * @param level Debug level to use.
357 */
358void
359GCC_debug (struct CadetConnection *cc,
360 enum GNUNET_ErrorType level);
361
362
363#endif
diff --git a/src/service/cadet/gnunet-service-cadet_core.c b/src/service/cadet/gnunet-service-cadet_core.c
new file mode 100644
index 000000000..68f7405c3
--- /dev/null
+++ b/src/service/cadet/gnunet-service-cadet_core.c
@@ -0,0 +1,1337 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2017 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file cadet/gnunet-service-cadet_core.c
23 * @brief cadet service; interaction with CORE service
24 * @author Bartlomiej Polot
25 * @author Christian Grothoff
26 *
27 * All functions in this file should use the prefix GCO (Gnunet Cadet cOre (bottom))
28 *
29 * TODO:
30 * - Optimization: given BROKEN messages, destroy paths (?)
31 */
32#include "platform.h"
33#include "gnunet-service-cadet_core.h"
34#include "gnunet-service-cadet_paths.h"
35#include "gnunet-service-cadet_peer.h"
36#include "gnunet-service-cadet_connection.h"
37#include "gnunet-service-cadet_tunnels.h"
38#include "gnunet_core_service.h"
39#include "gnunet_statistics_service.h"
40#include "cadet_protocol.h"
41
42#define LOG(level, ...) GNUNET_log_from (level, "cadet-cor", __VA_ARGS__)
43
44/**
45 * Information we keep per direction for a route.
46 */
47struct RouteDirection;
48
49/**
50 * Set of CadetRoutes that have exactly the same number of messages
51 * in their buffer. Used so we can efficiently find all of those
52 * routes that have the current maximum of messages in the buffer (in
53 * case we have to purge).
54 */
55struct Rung
56{
57 /**
58 * Rung of RouteDirections with one more buffer entry each.
59 */
60 struct Rung *next;
61
62 /**
63 * Rung of RouteDirections with one less buffer entry each.
64 */
65 struct Rung *prev;
66
67 /**
68 * DLL of route directions with a number of buffer entries matching this rung.
69 */
70 struct RouteDirection *rd_head;
71
72 /**
73 * DLL of route directions with a number of buffer entries matching this rung.
74 */
75 struct RouteDirection *rd_tail;
76
77 /**
78 * Total number of route directions in this rung.
79 */
80 unsigned int num_routes;
81
82 /**
83 * Number of messages route directions at this rung have
84 * in their buffer.
85 */
86 unsigned int rung_off;
87};
88
89
90/**
91 * Information we keep per direction for a route.
92 */
93struct RouteDirection
94{
95 /**
96 * DLL of other route directions within the same `struct Rung`.
97 */
98 struct RouteDirection *prev;
99
100 /**
101 * DLL of other route directions within the same `struct Rung`.
102 */
103 struct RouteDirection *next;
104
105 /**
106 * Rung of this route direction (matches length of the buffer DLL).
107 */
108 struct Rung *rung;
109
110 /**
111 * Head of DLL of envelopes we have in the buffer for this direction.
112 */
113 struct GNUNET_MQ_Envelope *env_head;
114
115 /**
116 * Tail of DLL of envelopes we have in the buffer for this direction.
117 */
118 struct GNUNET_MQ_Envelope *env_tail;
119
120 /**
121 * Target peer.
122 */
123 struct CadetPeer *hop;
124
125 /**
126 * Route this direction is part of.
127 */
128 struct CadetRoute *my_route;
129
130 /**
131 * Message queue manager for @e hop.
132 */
133 struct GCP_MessageQueueManager *mqm;
134
135 /**
136 * Is @e mqm currently ready for transmission?
137 */
138 int is_ready;
139};
140
141
142struct CadetRoute
143{
144 /**
145 * Information about the next hop on this route.
146 */
147 struct RouteDirection next;
148
149 /**
150 * Information about the previous hop on this route.
151 */
152 struct RouteDirection prev;
153
154 /**
155 * Unique identifier for the connection that uses this route.
156 */
157 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
158
159 /**
160 * When was this route last in use?
161 */
162 struct GNUNET_TIME_Absolute last_use;
163
164 /**
165 * Position of this route in the #route_heap.
166 */
167 struct GNUNET_CONTAINER_HeapNode *hn;
168};
169
170
171/**
172 * Handle to the CORE service.
173 */
174static struct GNUNET_CORE_Handle *core;
175
176/**
177 * Routes on which this peer is an intermediate.
178 */
179static struct GNUNET_CONTAINER_MultiShortmap *routes;
180
181/**
182 * Heap of routes, MIN-sorted by last activity.
183 */
184static struct GNUNET_CONTAINER_Heap *route_heap;
185
186/**
187 * Rung zero (always pointed to by #rung_head).
188 */
189static struct Rung rung_zero;
190
191/**
192 * DLL of rungs, with the head always point to a rung of
193 * route directions with no messages in the queue.
194 */
195static struct Rung *rung_head = &rung_zero;
196
197/**
198 * Tail of the #rung_head DLL.
199 */
200static struct Rung *rung_tail = &rung_zero;
201
202/**
203 * Maximum number of concurrent routes this peer will support.
204 */
205static unsigned long long max_routes;
206
207/**
208 * Maximum number of envelopes we will buffer at this peer.
209 */
210static unsigned long long max_buffers;
211
212/**
213 * Current number of envelopes we have buffered at this peer.
214 */
215static unsigned long long cur_buffers;
216
217/**
218 * Task to timeout routes.
219 */
220static struct GNUNET_SCHEDULER_Task *timeout_task;
221
222/**
223 * Get the route corresponding to a hash.
224 *
225 * @param cid hash generated from the connection identifier
226 */
227static struct CadetRoute *
228get_route (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
229{
230 return GNUNET_CONTAINER_multishortmap_get (routes,
231 &cid->connection_of_tunnel);
232}
233
234
235/**
236 * Lower the rung in which @a dir is by 1.
237 *
238 * @param dir direction to lower in rung.
239 */
240static void
241lower_rung (struct RouteDirection *dir)
242{
243 struct Rung *rung = dir->rung;
244 struct Rung *prev;
245
246 GNUNET_CONTAINER_DLL_remove (rung->rd_head, rung->rd_tail, dir);
247 prev = rung->prev;
248 GNUNET_assert (NULL != prev);
249 if (prev->rung_off != rung->rung_off - 1)
250 {
251 prev = GNUNET_new (struct Rung);
252 prev->rung_off = rung->rung_off - 1;
253 GNUNET_CONTAINER_DLL_insert_after (rung_head, rung_tail, rung->prev, prev);
254 }
255 GNUNET_assert (NULL != prev);
256 GNUNET_CONTAINER_DLL_insert (prev->rd_head, prev->rd_tail, dir);
257 dir->rung = prev;
258}
259
260
261/**
262 * Discard the buffer @a env from the route direction @a dir and
263 * move @a dir down a rung.
264 *
265 * @param dir direction that contains the @a env in the buffer
266 * @param env envelope to discard
267 */
268static void
269discard_buffer (struct RouteDirection *dir, struct GNUNET_MQ_Envelope *env)
270{
271 GNUNET_MQ_dll_remove (&dir->env_head, &dir->env_tail, env);
272 cur_buffers--;
273 GNUNET_MQ_discard (env);
274 lower_rung (dir);
275 GNUNET_STATISTICS_set (stats, "# buffer use", cur_buffers, GNUNET_NO);
276}
277
278
279/**
280 * Discard all messages from the highest rung, to make space.
281 */
282static void
283discard_all_from_rung_tail ()
284{
285 struct Rung *tail = rung_tail;
286 struct RouteDirection *dir;
287
288 while (NULL != (dir = tail->rd_head))
289 {
290 LOG (GNUNET_ERROR_TYPE_DEBUG,
291 "Queue full due new message on connection %s, dropping old message\n",
292 GNUNET_sh2s (&dir->my_route->cid.connection_of_tunnel));
293 GNUNET_STATISTICS_update (stats,
294 "# messages dropped due to full buffer",
295 1,
296 GNUNET_NO);
297 discard_buffer (dir, dir->env_head);
298 }
299 GNUNET_CONTAINER_DLL_remove (rung_head, rung_tail, tail);
300 GNUNET_free (tail);
301}
302
303
304/**
305 * We message @a msg from @a prev. Find its route by @a cid and
306 * forward to the next hop. Drop and signal broken route if we do not
307 * have a route.
308 *
309 * @param prev previous hop (sender)
310 * @param cid connection identifier, tells us which route to use
311 * @param msg the message to forward
312 */
313static void
314route_message (struct CadetPeer *prev,
315 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
316 const struct GNUNET_MessageHeader *msg,
317 const enum GNUNET_MQ_PriorityPreferences priority)
318{
319 struct CadetRoute *route;
320 struct RouteDirection *dir;
321 struct Rung *rung;
322 struct Rung *nxt;
323 struct GNUNET_MQ_Envelope *env;
324
325 route = get_route (cid);
326 if (NULL == route)
327 {
328 struct GNUNET_MQ_Envelope *env;
329 struct GNUNET_CADET_ConnectionBrokenMessage *bm;
330
331 LOG (GNUNET_ERROR_TYPE_DEBUG,
332 "Failed to route message of type %u from %s on connection %s: no route\n",
333 ntohs (msg->type),
334 GCP_2s (prev),
335 GNUNET_sh2s (&cid->connection_of_tunnel));
336 switch (ntohs (msg->type))
337 {
338 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY:
339 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN:
340 /* No need to respond to these! */
341 return;
342 }
343 env = GNUNET_MQ_msg (bm, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
344 bm->cid = *cid;
345 bm->peer1 = my_full_id;
346 GCP_send_ooo (prev, env);
347 return;
348 }
349 route->last_use = GNUNET_TIME_absolute_get ();
350 GNUNET_CONTAINER_heap_update_cost (route->hn, route->last_use.abs_value_us);
351 dir = (prev == route->prev.hop) ? &route->next : &route->prev;
352 if (GNUNET_YES == dir->is_ready)
353 {
354 LOG (GNUNET_ERROR_TYPE_DEBUG,
355 "Routing message of type %u from %s to %s on connection %s\n",
356 ntohs (msg->type),
357 GCP_2s (prev),
358 GNUNET_i2s (GCP_get_id (dir->hop)),
359 GNUNET_sh2s (&cid->connection_of_tunnel));
360 dir->is_ready = GNUNET_NO;
361 GCP_send (dir->mqm, GNUNET_MQ_msg_copy (msg));
362 return;
363 }
364 /* Check if low latency is required and if the previous message was
365 unreliable; if so, make sure we only queue one message per
366 direction (no buffering). */
367 if ((0 != (priority & GNUNET_MQ_PREF_LOW_LATENCY)) &&
368 (NULL != dir->env_head) &&
369 (0 ==
370 (GNUNET_MQ_env_get_options (dir->env_head) & GNUNET_MQ_PREF_UNRELIABLE)))
371 discard_buffer (dir, dir->env_head);
372 /* Check for duplicates */
373 for (const struct GNUNET_MQ_Envelope *env = dir->env_head; NULL != env;
374 env = GNUNET_MQ_env_next (env))
375 {
376 const struct GNUNET_MessageHeader *hdr = GNUNET_MQ_env_get_msg (env);
377
378 if ((hdr->size == msg->size) && (0 == memcmp (hdr, msg, ntohs (msg->size))))
379 {
380 LOG (GNUNET_ERROR_TYPE_DEBUG,
381 "Received duplicate of message already in buffer, dropping\n");
382 GNUNET_STATISTICS_update (stats,
383 "# messages dropped due to duplicate in buffer",
384 1,
385 GNUNET_NO);
386 return;
387 }
388 }
389
390 rung = dir->rung;
391 if (cur_buffers == max_buffers)
392 {
393 /* Need to make room. */
394 if (NULL != rung->next)
395 {
396 /* Easy case, drop messages from route directions in highest rung */
397 discard_all_from_rung_tail ();
398 }
399 else
400 {
401 /* We are in the highest rung, drop our own! */
402 LOG (GNUNET_ERROR_TYPE_DEBUG,
403 "Queue full due new message on connection %s, dropping old message\n",
404 GNUNET_sh2s (&dir->my_route->cid.connection_of_tunnel));
405 GNUNET_STATISTICS_update (stats,
406 "# messages dropped due to full buffer",
407 1,
408 GNUNET_NO);
409 discard_buffer (dir, dir->env_head);
410 rung = dir->rung;
411 }
412 }
413 /* remove 'dir' from current rung */
414 GNUNET_CONTAINER_DLL_remove (rung->rd_head, rung->rd_tail, dir);
415 /* make 'nxt' point to the next higher rung, create if necessary */
416 nxt = rung->next;
417 if ((NULL == nxt) || (rung->rung_off + 1 != nxt->rung_off))
418 {
419 nxt = GNUNET_new (struct Rung);
420 nxt->rung_off = rung->rung_off + 1;
421 GNUNET_CONTAINER_DLL_insert_after (rung_head, rung_tail, rung, nxt);
422 }
423 /* insert 'dir' into next higher rung */
424 GNUNET_CONTAINER_DLL_insert (nxt->rd_head, nxt->rd_tail, dir);
425 dir->rung = nxt;
426
427 /* add message into 'dir' buffer */
428 LOG (GNUNET_ERROR_TYPE_DEBUG,
429 "Queueing new message of type %u from %s to %s on connection %s\n",
430 ntohs (msg->type),
431 GCP_2s (prev),
432 GNUNET_i2s (GCP_get_id (dir->hop)),
433 GNUNET_sh2s (&cid->connection_of_tunnel));
434 env = GNUNET_MQ_msg_copy (msg);
435 GNUNET_MQ_env_set_options (env, priority);
436 if ((0 != (priority & GNUNET_MQ_PREF_LOW_LATENCY)) &&
437 (0 != (priority & GNUNET_MQ_PREF_OUT_OF_ORDER)) &&
438 (NULL != dir->env_head) &&
439 (0 == (GNUNET_MQ_env_get_options (dir->env_head)
440 & GNUNET_MQ_PREF_LOW_LATENCY)))
441 GNUNET_MQ_dll_insert_head (&dir->env_head, &dir->env_tail, env);
442 else
443 GNUNET_MQ_dll_insert_tail (&dir->env_head, &dir->env_tail, env);
444 cur_buffers++;
445 GNUNET_STATISTICS_set (stats, "# buffer use", cur_buffers, GNUNET_NO);
446 /* Clean up 'rung' if now empty (and not head) */
447 if ((NULL == rung->rd_head) && (rung != rung_head))
448 {
449 GNUNET_CONTAINER_DLL_remove (rung_head, rung_tail, rung);
450 GNUNET_free (rung);
451 }
452}
453
454
455/**
456 * Check if the create_connection message has the appropriate size.
457 *
458 * @param cls Closure (unused).
459 * @param msg Message to check.
460 *
461 * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
462 */
463static int
464check_connection_create (void *cls,
465 const struct GNUNET_CADET_ConnectionCreateMessage *msg)
466{
467 uint16_t size = ntohs (msg->header.size) - sizeof(*msg);
468
469 if (0 != (size % sizeof(struct GNUNET_PeerIdentity)))
470 {
471 GNUNET_break_op (0);
472 return GNUNET_NO;
473 }
474 return GNUNET_YES;
475}
476
477
478/**
479 * Free internal data of a route direction.
480 *
481 * @param dir direction to destroy (do NOT free memory of 'dir' itself)
482 */
483static void
484destroy_direction (struct RouteDirection *dir)
485{
486 struct GNUNET_MQ_Envelope *env;
487
488 while (NULL != (env = dir->env_head))
489 {
490 GNUNET_STATISTICS_update (stats,
491 "# messages dropped due to route destruction",
492 1,
493 GNUNET_NO);
494 discard_buffer (dir, env);
495 }
496 if (NULL != dir->mqm)
497 {
498 GCP_request_mq_cancel (dir->mqm, NULL);
499 dir->mqm = NULL;
500 }
501 GNUNET_CONTAINER_DLL_remove (rung_head->rd_head, rung_head->rd_tail, dir);
502}
503
504
505/**
506 * Destroy our state for @a route.
507 *
508 * @param route route to destroy
509 */
510static void
511destroy_route (struct CadetRoute *route)
512{
513 LOG (GNUNET_ERROR_TYPE_DEBUG,
514 "Destroying route from %s to %s of connection %s\n",
515 GNUNET_i2s (GCP_get_id (route->prev.hop)),
516 GNUNET_i2s2 (GCP_get_id (route->next.hop)),
517 GNUNET_sh2s (&route->cid.connection_of_tunnel));
518 GNUNET_assert (route == GNUNET_CONTAINER_heap_remove_node (route->hn));
519 GNUNET_assert (
520 GNUNET_YES ==
521 GNUNET_CONTAINER_multishortmap_remove (routes,
522 &route->cid.connection_of_tunnel,
523 route));
524 GNUNET_STATISTICS_set (stats,
525 "# routes",
526 GNUNET_CONTAINER_multishortmap_size (routes),
527 GNUNET_NO);
528 destroy_direction (&route->prev);
529 destroy_direction (&route->next);
530 GNUNET_free (route);
531}
532
533
534/**
535 * Send message that a route is broken between @a peer1 and @a peer2.
536 *
537 * @param target where to send the message
538 * @param cid connection identifier to use
539 * @param peer1 one of the peers where a link is broken
540 * @param peer2 another one of the peers where a link is broken
541 */
542static void
543send_broken (struct RouteDirection *target,
544 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
545 const struct GNUNET_PeerIdentity *peer1,
546 const struct GNUNET_PeerIdentity *peer2)
547{
548 struct GNUNET_MQ_Envelope *env;
549 struct GNUNET_CADET_ConnectionBrokenMessage *bm;
550
551 if (NULL == target->mqm)
552 return; /* Can't send notification, connection is down! */
553 LOG (GNUNET_ERROR_TYPE_DEBUG,
554 "Notifying %s about BROKEN route at %s-%s of connection %s\n",
555 GCP_2s (target->hop),
556 GNUNET_i2s (peer1),
557 GNUNET_i2s2 (peer2),
558 GNUNET_sh2s (&cid->connection_of_tunnel));
559
560 env = GNUNET_MQ_msg (bm, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
561 bm->cid = *cid;
562 if (NULL != peer1)
563 bm->peer1 = *peer1;
564 if (NULL != peer2)
565 bm->peer2 = *peer2;
566 GCP_request_mq_cancel (target->mqm, env);
567 target->mqm = NULL;
568}
569
570
571/**
572 * Function called to check if any routes have timed out, and if
573 * so, to clean them up. Finally, schedules itself again at the
574 * earliest time where there might be more work.
575 *
576 * @param cls NULL
577 */
578static void
579timeout_cb (void *cls)
580{
581 struct CadetRoute *r;
582 struct GNUNET_TIME_Relative linger;
583 struct GNUNET_TIME_Absolute exp;
584
585 timeout_task = NULL;
586 linger = GNUNET_TIME_relative_multiply (keepalive_period, 3);
587 while (NULL != (r = GNUNET_CONTAINER_heap_peek (route_heap)))
588 {
589 exp = GNUNET_TIME_absolute_add (r->last_use, linger);
590 if (0 != GNUNET_TIME_absolute_get_remaining (exp).rel_value_us)
591 {
592 /* Route not yet timed out, wait until it does. */
593 timeout_task = GNUNET_SCHEDULER_add_at (exp, &timeout_cb, NULL);
594 return;
595 }
596 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
597 "Sending BROKEN due to timeout (%s was last use, %s linger)\n",
598 GNUNET_STRINGS_absolute_time_to_string (r->last_use),
599 GNUNET_STRINGS_relative_time_to_string (linger, GNUNET_YES));
600 send_broken (&r->prev, &r->cid, NULL, NULL);
601 send_broken (&r->next, &r->cid, NULL, NULL);
602 destroy_route (r);
603 }
604 /* No more routes left, so no need for a #timeout_task */
605}
606
607
608/**
609 * Function called when the message queue to the previous hop
610 * becomes available/unavailable. We expect this function to
611 * be called immediately when we register, and then again
612 * later if the connection ever goes down.
613 *
614 * @param cls the `struct RouteDirection`
615 * @param ready #GNUNET_YES if sending is now possible,
616 * #GNUNET_NO if sending is no longer possible
617 * #GNUNET_SYSERR if sending is no longer possible
618 * and the last envelope was discarded
619 */
620static void
621dir_ready_cb (void *cls, int ready)
622{
623 struct RouteDirection *dir = cls;
624 struct CadetRoute *route = dir->my_route;
625 struct RouteDirection *odir;
626
627 if (GNUNET_YES == ready)
628 {
629 struct GNUNET_MQ_Envelope *env;
630
631 dir->is_ready = GNUNET_YES;
632 if (NULL != (env = dir->env_head))
633 {
634 GNUNET_MQ_dll_remove (&dir->env_head, &dir->env_tail, env);
635 cur_buffers--;
636 GNUNET_STATISTICS_set (stats, "# buffer use", cur_buffers, GNUNET_NO);
637 lower_rung (dir);
638 dir->is_ready = GNUNET_NO;
639 GCP_send (dir->mqm, env);
640 }
641 return;
642 }
643 odir = (dir == &route->next) ? &route->prev : &route->next;
644 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending BROKEN due to MQ going down\n");
645 send_broken (&route->next, &route->cid, GCP_get_id (odir->hop), &my_full_id);
646 destroy_route (route);
647}
648
649
650/**
651 * Initialize one of the directions of a route.
652 *
653 * @param route route the direction belongs to
654 * @param dir direction to initialize
655 * @param hop next hop on in the @a dir
656 */
657static void
658dir_init (struct RouteDirection *dir,
659 struct CadetRoute *route,
660 struct CadetPeer *hop)
661{
662 dir->hop = hop;
663 dir->my_route = route;
664 dir->mqm = GCP_request_mq (hop, &dir_ready_cb, dir);
665 GNUNET_CONTAINER_DLL_insert (rung_head->rd_head, rung_head->rd_tail, dir);
666 dir->rung = rung_head;
667 GNUNET_assert (GNUNET_YES == dir->is_ready);
668}
669
670
671/**
672 * We could not create the desired route. Send a
673 * #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN
674 * message to @a target.
675 *
676 * @param target who should receive the message
677 * @param cid identifier of the connection/route that failed
678 * @param failure_at neighbour with which we failed to route,
679 * or NULL.
680 */
681static void
682send_broken_without_mqm (
683 struct CadetPeer *target,
684 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
685 const struct GNUNET_PeerIdentity *failure_at)
686{
687 struct GNUNET_MQ_Envelope *env;
688 struct GNUNET_CADET_ConnectionBrokenMessage *bm;
689
690 env = GNUNET_MQ_msg (bm, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
691 bm->cid = *cid;
692 bm->peer1 = my_full_id;
693 if (NULL != failure_at)
694 bm->peer2 = *failure_at;
695 GCP_send_ooo (target, env);
696}
697
698
699/**
700 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE
701 *
702 * @param cls Closure (CadetPeer for neighbor that sent the message).
703 * @param msg Message itself.
704 */
705static void
706handle_connection_create (
707 void *cls,
708 const struct GNUNET_CADET_ConnectionCreateMessage *msg)
709{
710 struct CadetPeer *sender = cls;
711 struct CadetPeer *next;
712 const struct GNUNET_PeerIdentity *pids =
713 (const struct GNUNET_PeerIdentity *) &msg[1];
714 struct CadetRoute *route;
715 uint16_t size = ntohs (msg->header.size) - sizeof(*msg);
716 unsigned int path_length;
717 unsigned int off;
718 struct CadetTunnel *t;
719
720 path_length = size / sizeof(struct GNUNET_PeerIdentity);
721 if (0 == path_length)
722 {
723 LOG (GNUNET_ERROR_TYPE_DEBUG,
724 "Dropping CADET_CONNECTION_CREATE with empty path\n");
725 GNUNET_break_op (0);
726 return;
727 }
728 LOG (GNUNET_ERROR_TYPE_DEBUG,
729 "Handling CADET_CONNECTION_CREATE from %s for CID %s with %u hops\n",
730 GCP_2s (sender),
731 GNUNET_sh2s (&msg->cid.connection_of_tunnel),
732 path_length);
733 /* Check for loops */
734 {
735 struct GNUNET_CONTAINER_MultiPeerMap *map;
736
737 map = GNUNET_CONTAINER_multipeermap_create (path_length * 2, GNUNET_YES);
738 GNUNET_assert (NULL != map);
739 for (unsigned int i = 0; i < path_length; i++)
740 {
741 LOG (GNUNET_ERROR_TYPE_DEBUG,
742 "CADET_CONNECTION_CREATE has peer %s at offset %u\n",
743 GNUNET_i2s (&pids[i]),
744 i);
745 if (GNUNET_SYSERR == GNUNET_CONTAINER_multipeermap_put (
746 map,
747 &pids[i],
748 NULL,
749 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
750 {
751 /* bogus request */
752 GNUNET_CONTAINER_multipeermap_destroy (map);
753 LOG (GNUNET_ERROR_TYPE_DEBUG,
754 "Dropping CADET_CONNECTION_CREATE with cyclic path\n");
755 GNUNET_break_op (0);
756 return;
757 }
758 }
759 GNUNET_CONTAINER_multipeermap_destroy (map);
760 }
761 /* Initiator is at offset 0, find us */
762 for (off = 1; off < path_length; off++)
763 if (0 == GNUNET_memcmp (&my_full_id, &pids[off]))
764 break;
765 if (off == path_length)
766 {
767 LOG (GNUNET_ERROR_TYPE_DEBUG,
768 "Dropping CADET_CONNECTION_CREATE without us in the path\n");
769 GNUNET_break_op (0);
770 return;
771 }
772 /* Check previous hop */
773 if (sender != GCP_get (&pids[off - 1], GNUNET_NO))
774 {
775 LOG (GNUNET_ERROR_TYPE_DEBUG,
776 "Dropping CADET_CONNECTION_CREATE without sender at previous hop in the path\n");
777 GNUNET_break_op (0);
778 return;
779 }
780 if (NULL != (route = get_route (&msg->cid)))
781 {
782 /* Duplicate CREATE, pass it on, previous one might have been lost! */
783
784 LOG (GNUNET_ERROR_TYPE_DEBUG,
785 "Passing on duplicate CADET_CONNECTION_CREATE message on connection %s\n",
786 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
787 route_message (sender,
788 &msg->cid,
789 &msg->header,
790 GNUNET_MQ_PRIO_CRITICAL_CONTROL
791 | GNUNET_MQ_PREF_LOW_LATENCY);
792 return;
793 }
794 if (off == path_length - 1)
795 {
796 /* We are the destination, create connection */
797 struct CadetConnection *cc;
798 struct CadetPeerPath *path;
799 struct CadetPeer *origin;
800
801 cc = GCC_lookup (&msg->cid);
802 if (NULL != cc)
803 {
804 LOG (GNUNET_ERROR_TYPE_DEBUG,
805 "Received duplicate CADET_CONNECTION_CREATE message on connection %s\n",
806 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
807 GCC_handle_duplicate_create (cc);
808 return;
809 }
810
811 origin = GCP_get (&pids[0], GNUNET_YES);
812 LOG (GNUNET_ERROR_TYPE_DEBUG,
813 "I am destination for CADET_CONNECTION_CREATE message from %s for connection %s, building inverse path\n",
814 GCP_2s (origin),
815 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
816 path = GCPP_get_path_from_route (path_length - 1, pids);
817 t = GCP_get_tunnel (origin, GNUNET_YES);
818
819 // Check for CADET state in case the other side has lost the tunnel (xrs,t3ss)
820 if ((GNUNET_YES == msg->has_monotime) &&
821 (GNUNET_YES == GCP_check_and_update_monotime (origin, msg->monotime)) &&
822 (GNUNET_OK == GCP_check_monotime_sig (origin, msg)) &&
823 (CADET_TUNNEL_KEY_OK == GCT_get_estate (t)))
824 {
825 GCT_change_estate (t, CADET_TUNNEL_KEY_UNINITIALIZED);
826 }
827
828 if (GNUNET_OK !=
829 GCT_add_inbound_connection (t,
830 &msg->cid,
831 path))
832 {
833 /* Send back BROKEN: duplicate connection on the same path,
834 we will use the other one. */
835 LOG (GNUNET_ERROR_TYPE_DEBUG,
836 "Received CADET_CONNECTION_CREATE from %s for %s, but %s already has a connection. Sending BROKEN\n",
837 GCP_2s (sender),
838 GNUNET_sh2s (&msg->cid.connection_of_tunnel),
839 GCPP_2s (path));
840 send_broken_without_mqm (sender, &msg->cid, NULL);
841 return;
842 }
843 return;
844 }
845 /* We are merely a hop on the way, check if we can support the route */
846 next = GCP_get (&pids[off + 1], GNUNET_NO);
847 if ((NULL == next) || (GNUNET_NO == GCP_has_core_connection (next)))
848 {
849 /* unworkable, send back BROKEN notification */
850 LOG (GNUNET_ERROR_TYPE_DEBUG,
851 "Received CADET_CONNECTION_CREATE from %s for %s. Next hop %s:%u is down. Sending BROKEN\n",
852 GCP_2s (sender),
853 GNUNET_sh2s (&msg->cid.connection_of_tunnel),
854 GNUNET_i2s (&pids[off + 1]),
855 off + 1);
856 send_broken_without_mqm (sender, &msg->cid, &pids[off + 1]);
857 return;
858 }
859 if (max_routes <= GNUNET_CONTAINER_multishortmap_size (routes))
860 {
861 LOG (GNUNET_ERROR_TYPE_DEBUG,
862 "Received CADET_CONNECTION_CREATE from %s for %s. We have reached our route limit. Sending BROKEN\n",
863 GCP_2s (sender),
864 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
865 send_broken_without_mqm (sender, &msg->cid, &pids[off - 1]);
866 return;
867 }
868
869 /* Workable route, create routing entry */
870 LOG (GNUNET_ERROR_TYPE_DEBUG,
871 "Received CADET_CONNECTION_CREATE from %s for %s. Next hop %s:%u is up. Creating route\n",
872 GCP_2s (sender),
873 GNUNET_sh2s (&msg->cid.connection_of_tunnel),
874 GNUNET_i2s (&pids[off + 1]),
875 off + 1);
876 route = GNUNET_new (struct CadetRoute);
877 route->cid = msg->cid;
878 route->last_use = GNUNET_TIME_absolute_get ();
879 dir_init (&route->prev, route, sender);
880 dir_init (&route->next, route, next);
881 GNUNET_assert (GNUNET_OK ==
882 GNUNET_CONTAINER_multishortmap_put (
883 routes,
884 &route->cid.connection_of_tunnel,
885 route,
886 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
887 GNUNET_STATISTICS_set (stats,
888 "# routes",
889 GNUNET_CONTAINER_multishortmap_size (routes),
890 GNUNET_NO);
891 route->hn = GNUNET_CONTAINER_heap_insert (route_heap,
892 route,
893 route->last_use.abs_value_us);
894 if (NULL == timeout_task)
895 timeout_task =
896 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (
897 keepalive_period,
898 3),
899 &timeout_cb,
900 NULL);
901 /* also pass CREATE message along to next hop */
902 route_message (sender,
903 &msg->cid,
904 &msg->header,
905 GNUNET_MQ_PRIO_CRITICAL_CONTROL | GNUNET_MQ_PREF_LOW_LATENCY);
906}
907
908
909/**
910 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK
911 *
912 * @param cls Closure (CadetPeer for neighbor that sent the message).
913 * @param msg Message itself.
914 */
915static void
916handle_connection_create_ack (
917 void *cls,
918 const struct GNUNET_CADET_ConnectionCreateAckMessage *msg)
919{
920 struct CadetPeer *peer = cls;
921 struct CadetConnection *cc;
922
923 /* First, check if ACK belongs to a connection that ends here. */
924 cc = GCC_lookup (&msg->cid);
925 if (NULL != cc)
926 {
927 /* verify ACK came from the right direction */
928 unsigned int len;
929 struct CadetPeerPath *path = GCC_get_path (cc, &len);
930
931 if (peer != GCPP_get_peer_at_offset (path, 0))
932 {
933 /* received ACK from unexpected direction, ignore! */
934 GNUNET_break_op (0);
935 return;
936 }
937 LOG (GNUNET_ERROR_TYPE_DEBUG,
938 "Received CONNECTION_CREATE_ACK for connection %s.\n",
939 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
940 GCC_handle_connection_create_ack (cc);
941 return;
942 }
943
944 /* We're just an intermediary peer, route the message along its path */
945 route_message (peer,
946 &msg->cid,
947 &msg->header,
948 GNUNET_MQ_PRIO_CRITICAL_CONTROL | GNUNET_MQ_PREF_LOW_LATENCY);
949}
950
951
952/**
953 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN
954 *
955 * @param cls Closure (CadetPeer for neighbor that sent the message).
956 * @param msg Message itself.
957 * @deprecated duplicate logic with #handle_destroy(); dedup!
958 */
959static void
960handle_connection_broken (
961 void *cls,
962 const struct GNUNET_CADET_ConnectionBrokenMessage *msg)
963{
964 struct CadetPeer *peer = cls;
965 struct CadetConnection *cc;
966 struct CadetRoute *route;
967
968 /* First, check if message belongs to a connection that ends here. */
969 cc = GCC_lookup (&msg->cid);
970 if (NULL != cc)
971 {
972 /* verify message came from the right direction */
973 unsigned int len;
974 struct CadetPeerPath *path = GCC_get_path (cc, &len);
975
976 if (peer != GCPP_get_peer_at_offset (path, 0))
977 {
978 /* received message from unexpected direction, ignore! */
979 GNUNET_break_op (0);
980 return;
981 }
982 LOG (GNUNET_ERROR_TYPE_DEBUG,
983 "Received CONNECTION_BROKEN for connection %s. Destroying it.\n",
984 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
985 GCC_destroy_without_core (cc);
986
987 /* FIXME: also destroy the path up to the specified link! */
988 return;
989 }
990
991 /* We're just an intermediary peer, route the message along its path */
992 route_message (peer,
993 &msg->cid,
994 &msg->header,
995 GNUNET_MQ_PREF_LOW_LATENCY | GNUNET_MQ_PRIO_CRITICAL_CONTROL);
996 route = get_route (&msg->cid);
997 if (NULL != route)
998 destroy_route (route);
999 /* FIXME: also destroy paths we MAY have up to the specified link! */
1000}
1001
1002
1003/**
1004 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY
1005 *
1006 * @param cls Closure (CadetPeer for neighbor that sent the message).
1007 * @param msg Message itself.
1008 */
1009static void
1010handle_connection_destroy (
1011 void *cls,
1012 const struct GNUNET_CADET_ConnectionDestroyMessage *msg)
1013{
1014 struct CadetPeer *peer = cls;
1015 struct CadetConnection *cc;
1016 struct CadetRoute *route;
1017
1018 /* First, check if message belongs to a connection that ends here. */
1019 cc = GCC_lookup (&msg->cid);
1020 if (NULL != cc)
1021 {
1022 /* verify message came from the right direction */
1023 unsigned int len;
1024 struct CadetPeerPath *path = GCC_get_path (cc, &len);
1025
1026 if (peer != GCPP_get_peer_at_offset (path, 0))
1027 {
1028 /* received message from unexpected direction, ignore! */
1029 GNUNET_break_op (0);
1030 return;
1031 }
1032 LOG (GNUNET_ERROR_TYPE_DEBUG,
1033 "Received CONNECTION_DESTROY for connection %s. Destroying connection.\n",
1034 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
1035
1036 GCC_destroy_without_core (cc);
1037 return;
1038 }
1039
1040 /* We're just an intermediary peer, route the message along its path */
1041 LOG (GNUNET_ERROR_TYPE_DEBUG,
1042 "Received CONNECTION_DESTROY for connection %s. Destroying route.\n",
1043 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
1044 route_message (peer,
1045 &msg->cid,
1046 &msg->header,
1047 GNUNET_MQ_PREF_LOW_LATENCY | GNUNET_MQ_PRIO_CRITICAL_CONTROL);
1048 route = get_route (&msg->cid);
1049 if (NULL != route)
1050 destroy_route (route);
1051}
1052
1053
1054/**
1055 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX
1056 *
1057 * @param cls Closure (CadetPeer for neighbor that sent the message).
1058 * @param msg Message itself.
1059 */
1060static void
1061handle_tunnel_kx (void *cls,
1062 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
1063{
1064 struct CadetPeer *peer = cls;
1065 struct CadetConnection *cc;
1066
1067 /* First, check if message belongs to a connection that ends here. */
1068 LOG (GNUNET_ERROR_TYPE_DEBUG,
1069 "Routing KX with ephemeral %s on CID %s\n",
1070 GNUNET_e2s (&msg->ephemeral_key),
1071 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
1072
1073
1074 cc = GCC_lookup (&msg->cid);
1075 if (NULL != cc)
1076 {
1077 /* verify message came from the right direction */
1078 unsigned int len;
1079 struct CadetPeerPath *path = GCC_get_path (cc, &len);
1080
1081 if (peer != GCPP_get_peer_at_offset (path, 0))
1082 {
1083 /* received message from unexpected direction, ignore! */
1084 GNUNET_break_op (0);
1085 return;
1086 }
1087 GCC_handle_kx (cc, msg);
1088 return;
1089 }
1090
1091 /* We're just an intermediary peer, route the message along its path */
1092 route_message (peer,
1093 &msg->cid,
1094 &msg->header,
1095 GNUNET_MQ_PRIO_CRITICAL_CONTROL | GNUNET_MQ_PREF_LOW_LATENCY);
1096}
1097
1098
1099/**
1100 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX_AUTH
1101 *
1102 * @param cls Closure (CadetPeer for neighbor that sent the message).
1103 * @param msg Message itself.
1104 */
1105static void
1106handle_tunnel_kx_auth (
1107 void *cls,
1108 const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg)
1109{
1110 struct CadetPeer *peer = cls;
1111 struct CadetConnection *cc;
1112
1113 /* First, check if message belongs to a connection that ends here. */
1114 cc = GCC_lookup (&msg->kx.cid);
1115 if (NULL != cc)
1116 {
1117 /* verify message came from the right direction */
1118 unsigned int len;
1119 struct CadetPeerPath *path = GCC_get_path (cc, &len);
1120
1121 if (peer != GCPP_get_peer_at_offset (path, 0))
1122 {
1123 /* received message from unexpected direction, ignore! */
1124 GNUNET_break_op (0);
1125 return;
1126 }
1127 GCC_handle_kx_auth (cc, msg);
1128 return;
1129 }
1130
1131 /* We're just an intermediary peer, route the message along its path */
1132 route_message (peer,
1133 &msg->kx.cid,
1134 &msg->kx.header,
1135 GNUNET_MQ_PRIO_CRITICAL_CONTROL | GNUNET_MQ_PREF_LOW_LATENCY);
1136}
1137
1138
1139/**
1140 * Check if the encrypted message has the appropriate size.
1141 *
1142 * @param cls Closure (unused).
1143 * @param msg Message to check.
1144 *
1145 * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
1146 */
1147static int
1148check_tunnel_encrypted (void *cls,
1149 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
1150{
1151 return GNUNET_YES;
1152}
1153
1154
1155/**
1156 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED.
1157 *
1158 * @param cls Closure (CadetPeer for neighbor that sent the message).
1159 * @param msg Message itself.
1160 */
1161static void
1162handle_tunnel_encrypted (void *cls,
1163 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
1164{
1165 struct CadetPeer *peer = cls;
1166 struct CadetConnection *cc;
1167
1168 /* First, check if message belongs to a connection that ends here. */
1169 cc = GCC_lookup (&msg->cid);
1170 if (NULL != cc)
1171 {
1172 /* verify message came from the right direction */
1173 unsigned int len;
1174 struct CadetPeerPath *path = GCC_get_path (cc, &len);
1175
1176 if (peer != GCPP_get_peer_at_offset (path, 0))
1177 {
1178 /* received message from unexpected direction, ignore! */
1179 GNUNET_break_op (0);
1180 return;
1181 }
1182 GCC_handle_encrypted (cc, msg);
1183 return;
1184 }
1185 /* We're just an intermediary peer, route the message along its path */
1186 route_message (peer, &msg->cid, &msg->header, GNUNET_MQ_PRIO_BEST_EFFORT);
1187}
1188
1189
1190/**
1191 * Function called after #GNUNET_CORE_connect has succeeded (or failed
1192 * for good). Note that the private key of the peer is intentionally
1193 * not exposed here; if you need it, your process should try to read
1194 * the private key file directly (which should work if you are
1195 * authorized...). Implementations of this function must not call
1196 * #GNUNET_CORE_disconnect (other than by scheduling a new task to
1197 * do this later).
1198 *
1199 * @param cls closure
1200 * @param my_identity ID of this peer, NULL if we failed
1201 */
1202static void
1203core_init_cb (void *cls, const struct GNUNET_PeerIdentity *my_identity)
1204{
1205 if (NULL == my_identity)
1206 {
1207 GNUNET_break (0);
1208 return;
1209 }
1210 GNUNET_break (0 == GNUNET_memcmp (my_identity, &my_full_id));
1211}
1212
1213
1214/**
1215 * Method called whenever a given peer connects.
1216 *
1217 * @param cls closure
1218 * @param peer peer identity this notification is about
1219 */
1220static void *
1221core_connect_cb (void *cls,
1222 const struct GNUNET_PeerIdentity *peer,
1223 struct GNUNET_MQ_Handle *mq)
1224{
1225 struct CadetPeer *cp;
1226
1227 LOG (GNUNET_ERROR_TYPE_DEBUG,
1228 "CORE connection to peer %s was established.\n",
1229 GNUNET_i2s (peer));
1230 cp = GCP_get (peer, GNUNET_YES);
1231 GCP_set_mq (cp, mq);
1232 return cp;
1233}
1234
1235
1236/**
1237 * Method called whenever a peer disconnects.
1238 *
1239 * @param cls closure
1240 * @param peer peer identity this notification is about
1241 */
1242static void
1243core_disconnect_cb (void *cls,
1244 const struct GNUNET_PeerIdentity *peer,
1245 void *peer_cls)
1246{
1247 struct CadetPeer *cp = peer_cls;
1248
1249 LOG (GNUNET_ERROR_TYPE_DEBUG,
1250 "CORE connection to peer %s went down.\n",
1251 GNUNET_i2s (peer));
1252 GCP_set_mq (cp, NULL);
1253}
1254
1255
1256/**
1257 * Initialize the CORE subsystem.
1258 *
1259 * @param c Configuration.
1260 */
1261void
1262GCO_init (const struct GNUNET_CONFIGURATION_Handle *c)
1263{
1264 struct GNUNET_MQ_MessageHandler handlers[] =
1265 { GNUNET_MQ_hd_var_size (connection_create,
1266 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE,
1267 struct GNUNET_CADET_ConnectionCreateMessage,
1268 NULL),
1269 GNUNET_MQ_hd_fixed_size (connection_create_ack,
1270 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK,
1271 struct GNUNET_CADET_ConnectionCreateAckMessage,
1272 NULL),
1273 GNUNET_MQ_hd_fixed_size (connection_broken,
1274 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN,
1275 struct GNUNET_CADET_ConnectionBrokenMessage,
1276 NULL),
1277 GNUNET_MQ_hd_fixed_size (connection_destroy,
1278 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY,
1279 struct GNUNET_CADET_ConnectionDestroyMessage,
1280 NULL),
1281 GNUNET_MQ_hd_fixed_size (tunnel_kx,
1282 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX,
1283 struct GNUNET_CADET_TunnelKeyExchangeMessage,
1284 NULL),
1285 GNUNET_MQ_hd_fixed_size (tunnel_kx_auth,
1286 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX_AUTH,
1287 struct GNUNET_CADET_TunnelKeyExchangeAuthMessage,
1288 NULL),
1289 GNUNET_MQ_hd_var_size (tunnel_encrypted,
1290 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED,
1291 struct GNUNET_CADET_TunnelEncryptedMessage,
1292 NULL),
1293 GNUNET_MQ_handler_end () };
1294
1295 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (c,
1296 "CADET",
1297 "MAX_ROUTES",
1298 &max_routes))
1299 max_routes = 5000;
1300 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (c,
1301 "CADET",
1302 "MAX_MSGS_QUEUE",
1303 &max_buffers))
1304 max_buffers = 10000;
1305 routes = GNUNET_CONTAINER_multishortmap_create (1024, GNUNET_NO);
1306 route_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
1307 core = GNUNET_CORE_connect (c,
1308 NULL,
1309 &core_init_cb,
1310 &core_connect_cb,
1311 &core_disconnect_cb,
1312 handlers);
1313}
1314
1315
1316void
1317GCO_shutdown ()
1318{
1319 if (NULL != core)
1320 {
1321 GNUNET_CORE_disconnect (core);
1322 core = NULL;
1323 }
1324 GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (routes));
1325 GNUNET_CONTAINER_multishortmap_destroy (routes);
1326 routes = NULL;
1327 GNUNET_CONTAINER_heap_destroy (route_heap);
1328 route_heap = NULL;
1329 if (NULL != timeout_task)
1330 {
1331 GNUNET_SCHEDULER_cancel (timeout_task);
1332 timeout_task = NULL;
1333 }
1334}
1335
1336
1337/* end of gnunet-cadet-service_core.c */
diff --git a/src/service/cadet/gnunet-service-cadet_core.h b/src/service/cadet/gnunet-service-cadet_core.h
new file mode 100644
index 000000000..3438dcb31
--- /dev/null
+++ b/src/service/cadet/gnunet-service-cadet_core.h
@@ -0,0 +1,69 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2017 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file cadet/gnunet-service-cadet_core.h
23 * @brief cadet service; interaction with CORE service
24 * @author Bartlomiej Polot
25 * @author Christian Grothoff
26 *
27 * All functions in this file should use the prefix GCO (Gnunet Cadet cOre (bottom))
28 */
29
30#ifndef GNUNET_SERVICE_CADET_CORE_H
31#define GNUNET_SERVICE_CADET_CORE_H
32
33#ifdef __cplusplus
34extern "C"
35{
36#if 0 /* keep Emacsens' auto-indent happy */
37}
38#endif
39#endif
40
41#include "gnunet_util_lib.h"
42
43
44/**
45 * Initialize the CORE subsystem.
46 *
47 * @param c Configuration.
48 */
49void
50GCO_init (const struct GNUNET_CONFIGURATION_Handle *c);
51
52
53/**
54 * Shut down the CORE subsystem.
55 */
56void
57GCO_shutdown (void);
58
59
60#if 0 /* keep Emacsens' auto-indent happy */
61{
62#endif
63#ifdef __cplusplus
64}
65#endif
66
67/* ifndef GNUNET_CADET_SERVICE_CORE_H */
68#endif
69/* end of gnunet-cadet-service_core.h */
diff --git a/src/service/cadet/gnunet-service-cadet_dht.c b/src/service/cadet/gnunet-service-cadet_dht.c
new file mode 100644
index 000000000..dcd1efaa2
--- /dev/null
+++ b/src/service/cadet/gnunet-service-cadet_dht.c
@@ -0,0 +1,340 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2013, 2017 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file cadet/gnunet-service-cadet_dht.c
22 * @brief Information we track per peer.
23 * @author Bartlomiej Polot
24 * @author Christian Grothoff
25 */
26
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_dht_service.h"
30#include "gnunet_statistics_service.h"
31#include "gnunet-service-cadet.h"
32#include "gnunet-service-cadet_dht.h"
33#include "gnunet-service-cadet_hello.h"
34#include "gnunet-service-cadet_peer.h"
35#include "gnunet-service-cadet_paths.h"
36
37/**
38 * How long do we wait before first announcing our presence to the DHT.
39 * Used to wait for our HELLO to be available. Note that we also get
40 * notifications when our HELLO is ready, so this is just the maximum
41 * we wait for the first notification.
42 */
43#define STARTUP_DELAY GNUNET_TIME_relative_multiply ( \
44 GNUNET_TIME_UNIT_MILLISECONDS, 500)
45
46/**
47 * How long do we wait after we get an updated HELLO before publishing?
48 * Allows for the HELLO to be updated again quickly, for example in
49 * case multiple addresses changed and we got a partial update.
50 */
51#define CHANGE_DELAY GNUNET_TIME_relative_multiply ( \
52 GNUNET_TIME_UNIT_MILLISECONDS, 100)
53
54
55#define LOG(level, ...) GNUNET_log_from (level, "cadet-dht", __VA_ARGS__)
56
57
58struct GCD_search_handle
59{
60 /**
61 * DHT_GET handle.
62 */
63 struct GNUNET_DHT_GetHandle *dhtget;
64};
65
66
67/**
68 * Handle to use DHT.
69 */
70static struct GNUNET_DHT_Handle *dht_handle;
71
72/**
73 * How often to PUT own ID in the DHT.
74 */
75static struct GNUNET_TIME_Relative id_announce_time;
76
77/**
78 * DHT replication level, see DHT API: #GNUNET_DHT_get_start(), #GNUNET_DHT_put().
79 */
80static unsigned long long dht_replication_level;
81
82/**
83 * Task to periodically announce itself in the network.
84 */
85static struct GNUNET_SCHEDULER_Task *announce_id_task;
86
87/**
88 * Delay for the next ID announce.
89 */
90static struct GNUNET_TIME_Relative announce_delay;
91
92
93/**
94 * Function to process paths received for a new peer addition. The recorded
95 * paths form the initial tunnel, which can be optimized later.
96 * Called on each result obtained for the DHT search.
97 *
98 * @param cls closure
99 * @param exp when will this value expire
100 * @param key key of the result
101 * @param trunc_peer peer preceeding with invalid signature, or NULL
102 * @param get_path path of the get request
103 * @param get_path_length length of @a get_path
104 * @param put_path path of the put request
105 * @param put_path_length length of the @a put_path
106 * @param type type of the result
107 * @param size number of bytes in data
108 * @param data pointer to the result data
109 */
110static void
111dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp,
112 const struct GNUNET_HashCode *key,
113 const struct GNUNET_PeerIdentity *trunc_peer,
114 const struct GNUNET_DHT_PathElement *get_path,
115 unsigned int get_path_length,
116 const struct GNUNET_DHT_PathElement *put_path,
117 unsigned int put_path_length,
118 enum GNUNET_BLOCK_Type type,
119 size_t size,
120 const void *data)
121{
122 const struct GNUNET_MessageHeader *hello = data;
123 struct GNUNET_HELLO_Builder *builder = GNUNET_HELLO_builder_from_msg (hello);
124
125 GNUNET_assert (NULL != builder);
126 (void) trunc_peer;
127 GCPP_try_path_from_dht (get_path,
128 get_path_length,
129 put_path,
130 put_path_length);
131
132 struct CadetPeer *peer;
133
134 peer = GCP_get (&put_path[0].pred,
135 GNUNET_YES);
136 LOG (GNUNET_ERROR_TYPE_DEBUG,
137 "Got HELLO for %s\n",
138 GCP_2s (peer));
139 GCP_set_hello (peer,
140 hello);
141 GNUNET_HELLO_builder_free (builder);
142}
143
144
145/**
146 * Periodically announce self id in the DHT
147 *
148 * @param cls closure
149 */
150static void
151announce_id (void *cls)
152{
153 struct GNUNET_HashCode phash;
154 const struct GNUNET_MessageHeader *hello;
155 size_t size;
156 size_t block_size;
157 void *block;
158 struct GNUNET_TIME_Absolute expiration;
159 struct GNUNET_TIME_Relative next_put;
160
161 hello = GCH_get_mine ();
162 size = (NULL != hello) ? ntohs(hello->size) : 0;
163 if (0 == size)
164 {
165 expiration = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
166 announce_delay);
167 announce_delay = GNUNET_TIME_STD_BACKOFF (announce_delay);
168 }
169 else
170 {
171 expiration = GNUNET_HELLO_builder_get_expiration_time (hello);
172 announce_delay = GNUNET_TIME_UNIT_SECONDS;
173 }
174
175 /* Call again in id_announce_time, unless HELLO expires first,
176 * but wait at least 1s. */
177 next_put
178 = GNUNET_TIME_absolute_get_remaining (expiration);
179 next_put
180 = GNUNET_TIME_relative_min (next_put,
181 id_announce_time);
182 next_put
183 = GNUNET_TIME_relative_max (next_put,
184 GNUNET_TIME_UNIT_SECONDS);
185 announce_id_task
186 = GNUNET_SCHEDULER_add_delayed (next_put,
187 &announce_id,
188 cls);
189 GNUNET_STATISTICS_update (stats,
190 "# DHT announce",
191 1,
192 GNUNET_NO);
193 memset (&phash,
194 0,
195 sizeof(phash));
196 GNUNET_memcpy (&phash,
197 &my_full_id,
198 sizeof(my_full_id));
199 if (GNUNET_OK != GNUNET_HELLO_dht_msg_to_block (hello,
200 &my_full_id,
201 &block,
202 &block_size,
203 &expiration))
204 return;
205
206 LOG (GNUNET_ERROR_TYPE_DEBUG,
207 "Announcing my HELLO (%lu bytes) in the DHT\n",
208 (unsigned long) block_size);
209 GNUNET_DHT_put (dht_handle, /* DHT handle */
210 &phash, /* Key to use */
211 dht_replication_level, /* Replication level */
212 GNUNET_DHT_RO_RECORD_ROUTE
213 | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, /* DHT options */
214 GNUNET_BLOCK_TYPE_DHT_HELLO, /* Block type */
215 block_size, /* Size of the data */
216 (const char *) block, /* Data itself */
217 expiration, /* Data expiration */
218 NULL, /* Continuation */
219 NULL); /* Continuation closure */
220 GNUNET_free (block);
221}
222
223
224void
225GCD_hello_update ()
226{
227 if (NULL == announce_id_task)
228 return; /* too early */
229 GNUNET_SCHEDULER_cancel (announce_id_task);
230 announce_id_task
231 = GNUNET_SCHEDULER_add_delayed (CHANGE_DELAY,
232 &announce_id,
233 NULL);
234}
235
236
237void
238GCD_init (const struct GNUNET_CONFIGURATION_Handle *c)
239{
240 if (GNUNET_OK !=
241 GNUNET_CONFIGURATION_get_value_number (c,
242 "CADET",
243 "DHT_REPLICATION_LEVEL",
244 &dht_replication_level))
245 {
246 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
247 "CADET",
248 "DHT_REPLICATION_LEVEL",
249 "USING DEFAULT");
250 dht_replication_level = 3;
251 }
252
253 if (GNUNET_OK !=
254 GNUNET_CONFIGURATION_get_value_time (c,
255 "CADET",
256 "ID_ANNOUNCE_TIME",
257 &id_announce_time))
258 {
259 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
260 "CADET",
261 "ID_ANNOUNCE_TIME",
262 "MISSING");
263 GNUNET_SCHEDULER_shutdown ();
264 return;
265 }
266
267 dht_handle = GNUNET_DHT_connect (c,
268 64);
269 GNUNET_break (NULL != dht_handle);
270 announce_delay = GNUNET_TIME_UNIT_SECONDS;
271 announce_id_task = GNUNET_SCHEDULER_add_delayed (STARTUP_DELAY,
272 &announce_id,
273 NULL);
274}
275
276
277void
278GCD_shutdown (void)
279{
280 if (NULL != dht_handle)
281 {
282 GNUNET_DHT_disconnect (dht_handle);
283 dht_handle = NULL;
284 }
285 if (NULL != announce_id_task)
286 {
287 GNUNET_SCHEDULER_cancel (announce_id_task);
288 announce_id_task = NULL;
289 }
290}
291
292
293struct GCD_search_handle *
294GCD_search (const struct GNUNET_PeerIdentity *peer_id)
295{
296 struct GNUNET_HashCode phash;
297 struct GCD_search_handle *h;
298
299 GNUNET_STATISTICS_update (stats,
300 "# DHT search",
301 1,
302 GNUNET_NO);
303 memset (&phash,
304 0,
305 sizeof(phash));
306 GNUNET_memcpy (&phash,
307 peer_id,
308 sizeof(*peer_id));
309
310 h = GNUNET_new (struct GCD_search_handle);
311 h->dhtget = GNUNET_DHT_get_start (dht_handle, /* handle */
312 GNUNET_BLOCK_TYPE_DHT_HELLO, /* type */
313 &phash, /* key to search */
314 dht_replication_level, /* replication level */
315 GNUNET_DHT_RO_RECORD_ROUTE
316 | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
317 NULL, /* xquery */
318 0, /* xquery bits */
319 &dht_get_id_handler,
320 h);
321 LOG (GNUNET_ERROR_TYPE_DEBUG,
322 "Starting DHT GET for peer %s (%p)\n",
323 GNUNET_i2s (peer_id),
324 h);
325 return h;
326}
327
328
329void
330GCD_search_stop (struct GCD_search_handle *h)
331{
332 LOG (GNUNET_ERROR_TYPE_DEBUG,
333 "Stopping DHT GET %p\n",
334 h);
335 GNUNET_DHT_get_stop (h->dhtget);
336 GNUNET_free (h);
337}
338
339
340/* end of gnunet-service-cadet_dht.c */
diff --git a/src/service/cadet/gnunet-service-cadet_dht.h b/src/service/cadet/gnunet-service-cadet_dht.h
new file mode 100644
index 000000000..bcc27f5d2
--- /dev/null
+++ b/src/service/cadet/gnunet-service-cadet_dht.h
@@ -0,0 +1,100 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2013, 2017 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file cadet/gnunet-service-cadet_dht.h
23 * @brief cadet service; dealing with DHT requests and results
24 * @author Bartlomiej Polot
25 * @author Christian Grothoff
26 *
27 * All functions in this file should use the prefix GCD (Gnunet Cadet Dht)
28 */
29#ifndef GNUNET_SERVICE_CADET_DHT_H
30#define GNUNET_SERVICE_CADET_DHT_H
31
32#ifdef __cplusplus
33extern "C"
34{
35#if 0 /* keep Emacsens' auto-indent happy */
36}
37#endif
38#endif
39
40#include "platform.h"
41#include "gnunet_util_lib.h"
42
43/**
44 * Handle for DHT search operation.
45 */
46struct GCD_search_handle;
47
48
49/**
50 * Initialize the DHT subsystem.
51 *
52 * @param c Configuration.
53 */
54void
55GCD_init (const struct GNUNET_CONFIGURATION_Handle *c);
56
57
58/**
59 * Shut down the DHT subsystem.
60 */
61void
62GCD_shutdown (void);
63
64
65/**
66 * Function called by the HELLO subsystem whenever OUR hello
67 * changes. Re-triggers the DHT PUT immediately.
68 */
69void
70GCD_hello_update (void);
71
72/**
73 * Search DHT for paths to @a peeR_id
74 *
75 * @param peer_id peer to search for
76 * @return handle to abort search
77 */
78struct GCD_search_handle *
79GCD_search (const struct GNUNET_PeerIdentity *peer_id);
80
81
82/**
83 * Stop DHT search started with #GCD_search().
84 *
85 * @param h handle to search to stop
86 */
87void
88GCD_search_stop (struct GCD_search_handle *h);
89
90
91#if 0 /* keep Emacsens' auto-indent happy */
92{
93#endif
94#ifdef __cplusplus
95}
96#endif
97
98/* ifndef GNUNET_CADET_SERVICE_DHT_H */
99#endif
100/* end of gnunet-service-cadet_dht.h */
diff --git a/src/service/cadet/gnunet-service-cadet_hello.c b/src/service/cadet/gnunet-service-cadet_hello.c
new file mode 100644
index 000000000..cc28f0fde
--- /dev/null
+++ b/src/service/cadet/gnunet-service-cadet_hello.c
@@ -0,0 +1,195 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2014, 2017 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file cadet/gnunet-service-cadet_hello.c
22 * @brief spread knowledge about how to contact us (get HELLO from peerinfo),
23 * and remember HELLOs of other peers we have an interest in
24 * @author Bartlomiej Polot
25 * @author Christian Grothoff
26 */
27#include "gnunet_common.h"
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_statistics_service.h"
31#include "gnunet_peerstore_service.h"
32#include "cadet_protocol.h"
33#include "gnunet-service-cadet.h"
34#include "gnunet-service-cadet_dht.h"
35#include "gnunet-service-cadet_hello.h"
36#include "gnunet-service-cadet_peer.h"
37
38#define LOG(level, ...) GNUNET_log_from (level, "cadet-hll", __VA_ARGS__)
39
40/**
41 * Hello message of local peer.
42 */
43static struct GNUNET_MessageHeader *mine;
44
45/**
46 * Handle to the PEERSTORE service.
47 */
48static struct GNUNET_PEERSTORE_Handle *peerstore;
49
50/**
51 * Our peerstore notification context. We use notification
52 * to instantly learn about new peers as they are discovered.
53 */
54static struct GNUNET_PEERSTORE_Monitor *peerstore_notify;
55
56
57/**
58 * Process each hello message received from peerinfo.
59 *
60 * @param cls Closure (unused).
61 * @param id Identity of the peer.
62 * @param hello Hello of the peer.
63 * @param err_msg Error message.
64 */
65static void
66got_hello (void *cls,
67 const struct GNUNET_PEERSTORE_Record *record,
68 const char *err_msg)
69{
70 struct CadetPeer *peer;
71 struct GNUNET_HELLO_Builder *builder;
72 struct GNUNET_MessageHeader *hello;
73
74 if (NULL == record->value)
75 {
76 GNUNET_PEERSTORE_monitor_next (peerstore_notify, 1);
77 return;
78 }
79 hello = record->value;
80 if (0 == GNUNET_memcmp (&record->peer,
81 &my_full_id))
82 {
83 GNUNET_free (mine);
84 builder = GNUNET_HELLO_builder_from_msg (hello);
85 mine = GNUNET_HELLO_builder_to_dht_hello_msg (builder,
86 my_private_key,
87 GNUNET_TIME_UNIT_ZERO);
88 GNUNET_HELLO_builder_free (builder);
89 GCD_hello_update ();
90 GNUNET_PEERSTORE_monitor_next (peerstore_notify, 1);
91 return;
92 }
93
94 LOG (GNUNET_ERROR_TYPE_DEBUG,
95 "Hello for %s (%d bytes), expires on %s\n",
96 GNUNET_i2s (&record->peer),
97 ntohs (hello->size),
98 GNUNET_STRINGS_absolute_time_to_string (
99 GNUNET_HELLO_builder_get_expiration_time (hello)));
100 peer = GCP_get (&record->peer,
101 GNUNET_YES);
102 GCP_set_hello (peer,
103 hello);
104 GNUNET_PEERSTORE_monitor_next (peerstore_notify, 1);
105}
106
107
108static void
109error_cb (void *cls)
110{
111 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
112 "Error in PEERSTORE monitoring\n");
113}
114
115
116static void
117sync_cb (void *cls)
118{
119 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
120 "Done with initial PEERSTORE iteration during monitoring\n");
121}
122
123
124/**
125 * Initialize the hello subsystem.
126 *
127 * @param c Configuration.
128 */
129void
130GCH_init (const struct GNUNET_CONFIGURATION_Handle *c)
131{
132 GNUNET_assert (NULL == peerstore_notify);
133 peerstore = GNUNET_PEERSTORE_connect (c);
134 peerstore_notify =
135 GNUNET_PEERSTORE_monitor_start (c,
136 GNUNET_YES,
137 "peerstore",
138 NULL,
139 GNUNET_PEERSTORE_HELLO_KEY,
140 &error_cb,
141 NULL,
142 &sync_cb,
143 NULL,
144 &got_hello,
145 NULL);
146}
147
148
149/**
150 * Shut down the hello subsystem.
151 */
152void
153GCH_shutdown ()
154{
155 if (NULL != peerstore_notify)
156 {
157 GNUNET_PEERSTORE_monitor_stop (peerstore_notify);
158 peerstore_notify = NULL;
159 }
160 if (NULL != peerstore)
161 {
162 GNUNET_PEERSTORE_disconnect (peerstore);
163 peerstore = NULL;
164 }
165 if (NULL != mine)
166 {
167 GNUNET_free (mine);
168 mine = NULL;
169 }
170}
171
172
173/**
174 * Get own hello message.
175 *
176 * @return Own hello message.
177 */
178const struct GNUNET_MessageHeader *
179GCH_get_mine (void)
180{
181 struct GNUNET_HELLO_Builder *builder;
182
183 if (NULL == mine)
184 {
185 builder = GNUNET_HELLO_builder_new (&my_full_id);
186 mine = GNUNET_HELLO_builder_to_dht_hello_msg (builder,
187 my_private_key,
188 GNUNET_TIME_UNIT_ZERO);
189 GNUNET_HELLO_builder_free (builder);
190 }
191 return mine;
192}
193
194
195/* end of gnunet-service-cadet-new_hello.c */
diff --git a/src/service/cadet/gnunet-service-cadet_hello.h b/src/service/cadet/gnunet-service-cadet_hello.h
new file mode 100644
index 000000000..88c955bb9
--- /dev/null
+++ b/src/service/cadet/gnunet-service-cadet_hello.h
@@ -0,0 +1,80 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2014, 2017 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file cadet/gnunet-service-cadet_hello.h
23 * @brief cadet service; dealing with hello messages
24 * @author Bartlomiej Polot
25 * @author Christian Grothoff
26 *
27 * All functions in this file should use the prefix GCH (Gnunet Cadet Hello)
28 */
29
30#ifndef GNUNET_SERVICE_CADET_HELLO_H
31#define GNUNET_SERVICE_CADET_HELLO_H
32
33#ifdef __cplusplus
34extern "C"
35{
36#if 0 /* keep Emacsens' auto-indent happy */
37}
38#endif
39#endif
40
41#include "platform.h"
42#include "gnunet_util_lib.h"
43#include "gnunet_hello_uri_lib.h"
44
45
46/**
47 * Initialize the hello subsystem.
48 *
49 * @param c Configuration.
50 */
51void
52GCH_init (const struct GNUNET_CONFIGURATION_Handle *c);
53
54
55/**
56 * Shut down the hello subsystem.
57 */
58void
59GCH_shutdown (void);
60
61
62/**
63 * Get own hello message.
64 *
65 * @return Own hello message.
66 */
67const struct GNUNET_MessageHeader *
68GCH_get_mine (void);
69
70
71#if 0 /* keep Emacsens' auto-indent happy */
72{
73#endif
74#ifdef __cplusplus
75}
76#endif
77
78/* ifndef GNUNET_CADET_SERVICE_HELLO_H */
79#endif
80/* end of gnunet-cadet-service_hello.h */
diff --git a/src/service/cadet/gnunet-service-cadet_paths.c b/src/service/cadet/gnunet-service-cadet_paths.c
new file mode 100644
index 000000000..83b996e05
--- /dev/null
+++ b/src/service/cadet/gnunet-service-cadet_paths.c
@@ -0,0 +1,771 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2001-2017 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file cadet/gnunet-service-cadet_paths.c
22 * @brief Information we track per path.
23 * @author Bartlomiej Polot
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet-service-cadet_connection.h"
28#include "gnunet-service-cadet_tunnels.h"
29#include "gnunet-service-cadet_peer.h"
30#include "gnunet-service-cadet_paths.h"
31
32
33#define LOG(level, ...) GNUNET_log_from (level, "cadet-pat", __VA_ARGS__)
34
35
36/**
37 * Information regarding a possible path to reach a peer.
38 */
39struct CadetPeerPath
40{
41 /**
42 * Array of all the peers on the path. If @e hn is non-NULL, the
43 * last one is our owner.
44 */
45 struct CadetPeerPathEntry **entries;
46
47 /**
48 * Node of this path in the owner's heap. Used to update our position
49 * in the heap whenever our @e desirability changes.
50 */
51 struct GNUNET_CONTAINER_HeapNode *hn;
52
53 /**
54 * Desirability of the path. How unique is it for the various peers
55 * on it?
56 */
57 GNUNET_CONTAINER_HeapCostType desirability;
58
59 /**
60 * Length of the @e entries array.
61 */
62 unsigned int entries_length;
63};
64
65
66/**
67 * Calculate the path's desirability score.
68 *
69 * @param path path to calculate the score for
70 */
71static void
72recalculate_path_desirability (struct CadetPeerPath *path)
73{
74 double result = 0.0;
75
76 for (unsigned int i = 0; i < path->entries_length; i++)
77 {
78 struct CadetPeer *cp = path->entries[i]->peer;
79
80 result += GCP_get_desirability_of_path (cp,
81 i);
82 }
83 path->desirability = (GNUNET_CONTAINER_HeapCostType) result;
84}
85
86
87/**
88 * Return how much we like keeping the path. This is an aggregate
89 * score based on various factors, including the age of the path
90 * (older == better), and the value of this path to all of its adjacent
91 * peers. For example, long paths that end at a peer that we have no
92 * shorter way to reach are very desirable, while long paths that end
93 * at a peer for which we have a shorter way as well are much less
94 * desirable. Higher values indicate more valuable paths. The
95 * returned value should be used to decide which paths to remember.
96 *
97 * @param path path to return the length for
98 * @return desirability of the path, larger is more desirable
99 */
100GNUNET_CONTAINER_HeapCostType
101GCPP_get_desirability (const struct CadetPeerPath *path)
102{
103 return path->desirability;
104}
105
106
107/**
108 * Return connection to @a destination using @a path, or return
109 * NULL if no such connection exists.
110 *
111 * @param path path to traverse
112 * @param destination destination node to get to, must be on path
113 * @param off offset of @a destination on @a path
114 * @return NULL if we have no existing connection
115 * otherwise connection from us to @a destination via @a path
116 */
117struct CadetConnection *
118GCPP_get_connection (struct CadetPeerPath *path,
119 struct CadetPeer *destination,
120 unsigned int off)
121{
122 struct CadetPeerPathEntry *entry;
123
124 GNUNET_assert (off < path->entries_length);
125 entry = path->entries[off];
126 GNUNET_assert (entry->peer == destination);
127 return entry->cc;
128}
129
130
131/**
132 * Notify @a path that it is used for connection @a cc
133 * which ends at the path's offset @a off.
134 *
135 * @param path the path to remember the @a cc
136 * @param off the offset where the @a cc ends
137 * @param cc the connection to remember
138 */
139void
140GCPP_add_connection (struct CadetPeerPath *path,
141 unsigned int off,
142 struct CadetConnection *cc)
143{
144 struct CadetPeerPathEntry *entry;
145
146 LOG (GNUNET_ERROR_TYPE_DEBUG,
147 "Adding %s to path %s at offset %u\n",
148 GCC_2s (cc),
149 GCPP_2s (path),
150 off);
151 GNUNET_assert (off < path->entries_length);
152 entry = path->entries[off];
153 GNUNET_assert (NULL == entry->cc);
154 GNUNET_assert (NULL != cc);
155 entry->cc = cc;
156}
157
158
159/**
160 * Notify @a path that it is no longer used for connection @a cc which
161 * ended at the path's offset @a off.
162 *
163 * @param path the path to forget the @a cc
164 * @param off the offset where the @a cc ended
165 * @param cc the connection to forget
166 */
167void
168GCPP_del_connection (struct CadetPeerPath *path,
169 unsigned int off,
170 struct CadetConnection *cc)
171{
172 struct CadetPeerPathEntry *entry;
173
174 LOG (GNUNET_ERROR_TYPE_DEBUG,
175 "Removing connection %s to path %s at offset %u\n",
176 GCC_2s (cc),
177 GCPP_2s (path),
178 off);
179 GNUNET_assert (off < path->entries_length);
180 entry = path->entries[off];
181 GNUNET_assert (cc == entry->cc);
182 entry->cc = NULL;
183}
184
185
186/**
187 * Tries to attach @a path to a peer, working backwards from the end
188 * and stopping at @a stop_at. If path->hn is NULL on return then the
189 * path was not attached and you can assume that path->entries_length
190 * is equal to @a stop_at.
191 *
192 * @param path the path to attach
193 * @param stop_at the path length at which to stop trying
194 */
195static void
196attach_path (struct CadetPeerPath *path, unsigned int stop_at)
197{
198 GNUNET_assert (NULL == path->hn);
199
200 /* Try to attach this path to a peer, working backwards from the end. */
201 while (path->entries_length > stop_at)
202 {
203 unsigned int end = path->entries_length - 1;
204 struct CadetPeerPathEntry *entry = path->entries[end];
205 int force = GNUNET_NO;
206
207 recalculate_path_desirability (path);
208 /* If the entry already has a connection using it, force attach. */
209 if (NULL != entry->cc)
210 force = GNUNET_YES;
211 path->hn = GCP_attach_path (entry->peer,
212 path,
213 end,
214 force);
215 if (NULL != path->hn)
216 break;
217
218 /* Attach failed, trim this entry from the path. */
219 GNUNET_assert (NULL == entry->cc);
220 GCP_path_entry_remove (entry->peer,
221 entry,
222 end);
223 GNUNET_free (entry);
224 path->entries[end] = NULL;
225 path->entries_length--;
226 }
227
228 /* Shrink array to actual path length. */
229 GNUNET_array_grow (path->entries,
230 path->entries_length,
231 path->entries_length);
232}
233
234
235/**
236 * The owning peer of this path is no longer interested in maintaining
237 * it, so the path should be discarded or shortened (in case a
238 * previous peer on the path finds the path desirable).
239 *
240 * @param path the path that is being released
241 */
242void
243GCPP_release (struct CadetPeerPath *path)
244{
245 struct CadetPeerPathEntry *entry;
246
247 LOG (GNUNET_ERROR_TYPE_DEBUG,
248 "Owner releases path %s\n",
249 GCPP_2s (path));
250 path->hn = NULL;
251 entry = path->entries[path->entries_length - 1];
252 GNUNET_assert (path == entry->path);
253 GNUNET_assert (NULL == entry->cc);
254 /* cut 'off' end of path */
255 GCP_path_entry_remove (entry->peer,
256 entry,
257 path->entries_length - 1);
258 GNUNET_free (entry);
259 path->entries[path->entries_length - 1] = NULL;
260 path->entries_length--;
261 /* see if new peer at the end likes this path any better */
262 attach_path (path, 0);
263 if (NULL == path->hn)
264 {
265 /* nobody wants us, discard the path */
266 GNUNET_assert (0 == path->entries_length);
267 GNUNET_assert (NULL == path->entries);
268 GNUNET_free (path);
269 }
270}
271
272
273/**
274 * Updates the score for an entry on the path based
275 * on our experiences with using @a path.
276 *
277 * @param path the path to update
278 * @param off offset of the entry to update
279 * @param delta change in the score to apply
280 */
281void
282GCPP_update_score (struct CadetPeerPath *path,
283 unsigned int off,
284 int delta)
285{
286 struct CadetPeerPathEntry *entry;
287
288 GNUNET_assert (off < path->entries_length);
289 entry = path->entries[off];
290
291 /* Add delta, with checks for overflows */
292 if (delta >= 0)
293 {
294 if (delta + entry->score < entry->score)
295 entry->score = INT_MAX;
296 else
297 entry->score += delta;
298 }
299 else
300 {
301 if (delta + entry->score > entry->score)
302 entry->score = INT_MIN;
303 else
304 entry->score += delta;
305 }
306 recalculate_path_desirability (path);
307}
308
309
310/**
311 * Closure for #find_peer_at() and #check_match().
312 */
313struct CheckMatchContext
314{
315 /**
316 * Set to a matching path, if any.
317 */
318 struct CadetPeerPath *match;
319
320 /**
321 * Array the combined paths.
322 */
323 struct CadetPeer **cpath;
324
325 /**
326 * How long is the @e cpath array?
327 */
328 unsigned int cpath_length;
329};
330
331
332/**
333 * Check if the given path is identical on all of the
334 * hops until @a off, and not longer than @a off. If the
335 * @a path matches, store it in `match`.
336 *
337 * @param cls the `struct CheckMatchContext` to check against
338 * @param path the path to check
339 * @param off offset to check at
340 * @return #GNUNET_YES (continue to iterate), or if found #GNUNET_NO
341 */
342static int
343check_match (void *cls,
344 struct CadetPeerPath *path,
345 unsigned int off)
346{
347 struct CheckMatchContext *cm_ctx = cls;
348
349 GNUNET_assert (path->entries_length > off);
350 if ((path->entries_length != off + 1) &&
351 (off + 1 != cm_ctx->cpath_length))
352 {
353 LOG (GNUNET_ERROR_TYPE_DEBUG,
354 "check_match mismatch because path %s is too long (%u vs. %u vs. %u)\n",
355 GCPP_2s (path),
356 path->entries_length,
357 off + 1,
358 cm_ctx->cpath_length);
359 return GNUNET_YES; /* too long, goes somewhere else already, thus cannot be useful */
360 }
361 for (unsigned int i = 0; i < off; i++)
362 if (cm_ctx->cpath[i] !=
363 GCPP_get_peer_at_offset (path,
364 i))
365 {
366 LOG (GNUNET_ERROR_TYPE_DEBUG,
367 "check_match path %s mismatches at offset %u\n",
368 GCPP_2s (path),
369 i);
370 return GNUNET_YES; /* mismatch, ignore */
371 }
372 LOG (GNUNET_ERROR_TYPE_DEBUG,
373 "check_match found match with path %s\n",
374 GCPP_2s (path));
375 cm_ctx->match = path;
376 return GNUNET_NO; /* match, we are done! */
377}
378
379
380/**
381 * Extend path @a path by the @a num_peers from the @a peers
382 * array, assuming the owners past the current owner want it.
383 *
384 * @param path path to extend
385 * @param peers list of peers beyond the end of @a path
386 * @param num_peers length of the @a peers array
387 * @param force force attachment, even if we have other
388 * paths already
389 */
390static void
391extend_path (struct CadetPeerPath *path,
392 struct CadetPeer **peers,
393 unsigned int num_peers,
394 int force)
395{
396 unsigned int old_len = path->entries_length;
397 int i;
398
399 /* Expand path */
400 GNUNET_array_grow (path->entries,
401 path->entries_length,
402 old_len + num_peers);
403 for (i = num_peers - 1; i >= 0; i--)
404 {
405 struct CadetPeerPathEntry *entry = GNUNET_new (struct CadetPeerPathEntry);
406
407 path->entries[old_len + i] = entry;
408 entry->peer = peers[i];
409 entry->path = path;
410 }
411 for (i = num_peers - 1; i >= 0; i--)
412 {
413 struct CadetPeerPathEntry *entry = path->entries[old_len + i];
414
415 GCP_path_entry_add (entry->peer,
416 entry,
417 old_len + i);
418 }
419
420 /* If we extend an existing path, detach it from the
421 old owner and re-attach to the new one */
422 GCP_detach_path (path->entries[old_len - 1]->peer,
423 path,
424 path->hn);
425 path->hn = NULL;
426 path->entries_length = old_len + num_peers;
427 if (GNUNET_YES == force)
428 {
429 int end = path->entries_length - 1;
430
431 path->hn = GCP_attach_path (path->entries[end]->peer,
432 path,
433 end,
434 GNUNET_YES);
435 }
436 else
437 {
438 attach_path (path, old_len);
439 }
440 if (NULL == path->hn)
441 {
442 /* none of the peers is interested in this path;
443 re-attach. */
444 GNUNET_assert (old_len == path->entries_length);
445 path->hn = GCP_attach_path (path->entries[old_len - 1]->peer,
446 path,
447 old_len - 1,
448 GNUNET_YES);
449 GNUNET_assert (NULL != path->hn);
450 return;
451 }
452 LOG (GNUNET_ERROR_TYPE_DEBUG,
453 "Extended path %s\n",
454 GCPP_2s (path));
455}
456
457
458/**
459 * Create a peer path based on the result of a DHT lookup. If we
460 * already know this path, or one that is longer, simply return NULL.
461 * Otherwise, we try to extend an existing path, or create a new one
462 * if applicable.
463 *
464 * @param get_path path of the get request
465 * @param get_path_length length of @a get_path
466 * @param put_path path of the put request
467 * @param put_path_length length of the @a put_path
468 * @return a path through the network
469 */
470void
471GCPP_try_path_from_dht (const struct GNUNET_DHT_PathElement *get_path,
472 unsigned int get_path_length,
473 const struct GNUNET_DHT_PathElement *put_path,
474 unsigned int put_path_length)
475{
476 struct CadetPeer *cpath[get_path_length + put_path_length];
477 struct CheckMatchContext cm_ctx;
478 struct CadetPeerPath *path;
479 unsigned int skip;
480 unsigned int total_len;
481
482 /* precompute 'cpath' so we can avoid doing the lookups lots of times */
483 skip = 0;
484 memset (cpath,
485 0,
486 sizeof(cpath)); /* Just to trigger harder errors later. */
487 total_len = get_path_length + put_path_length;
488 for (unsigned int off = 0; off < total_len; off++)
489 {
490 const struct GNUNET_PeerIdentity *pid;
491
492 pid = (off < get_path_length)
493 ? &get_path[get_path_length - off - 1].pred
494 : &put_path[get_path_length + put_path_length - off - 1].pred;
495 /* Check that I am not in the path */
496 if (0 == GNUNET_memcmp (&my_full_id,
497 pid))
498 {
499 skip = off + 1;
500 continue;
501 }
502 cpath[off - skip] = GCP_get (pid,
503 GNUNET_YES);
504 /* Check that no peer is twice on the path */
505 for (unsigned int i = 0; i < off - skip; i++)
506 {
507 if (cpath[i] == cpath[off - skip])
508 {
509 skip = off - i;
510 break;
511 }
512 }
513 }
514 if (skip >= total_len)
515 {
516 LOG (GNUNET_ERROR_TYPE_DEBUG,
517 "Path discovered from DHT is one big cycle?\n");
518 return;
519 }
520 total_len -= skip;
521
522 /* First figure out if this path is a subset of an existing path, an
523 extension of an existing path, or a new path. */
524 cm_ctx.cpath_length = total_len;
525 cm_ctx.cpath = cpath;
526 cm_ctx.match = NULL;
527 for (int i = total_len - 1; i >= 0; i--)
528 {
529 GCP_iterate_paths_at (cpath[i],
530 (unsigned int) i,
531 &check_match,
532 &cm_ctx);
533 if (NULL != cm_ctx.match)
534 {
535 if (i == total_len - 1)
536 {
537 /* Existing path includes this one, nothing to do! */
538 LOG (GNUNET_ERROR_TYPE_DEBUG,
539 "Path discovered from DHT is already known\n");
540 return;
541 }
542 if (cm_ctx.match->entries_length == i + 1)
543 {
544 /* Existing path ends in the middle of new path, extend it! */
545 LOG (GNUNET_ERROR_TYPE_DEBUG,
546 "Trying to extend existing path %s by additional links discovered from DHT\n",
547 GCPP_2s (cm_ctx.match));
548 extend_path (cm_ctx.match,
549 &cpath[i + 1],
550 total_len - i - 1,
551 GNUNET_NO);
552 return;
553 }
554 }
555 }
556
557 /* No match at all, create completely new path */
558 path = GNUNET_new (struct CadetPeerPath);
559 path->entries_length = total_len;
560 path->entries = GNUNET_new_array (path->entries_length,
561 struct CadetPeerPathEntry *);
562 for (int i = path->entries_length - 1; i >= 0; i--)
563 {
564 struct CadetPeerPathEntry *entry = GNUNET_new (struct CadetPeerPathEntry);
565
566 path->entries[i] = entry;
567 entry->peer = cpath[i];
568 entry->path = path;
569 }
570 for (int i = path->entries_length - 1; i >= 0; i--)
571 {
572 struct CadetPeerPathEntry *entry = path->entries[i];
573
574 GCP_path_entry_add (entry->peer,
575 entry,
576 i);
577 }
578
579 /* Finally, try to attach it */
580 attach_path (path, 0);
581 if (NULL == path->hn)
582 {
583 /* None of the peers on the path care about it. */
584 LOG (GNUNET_ERROR_TYPE_DEBUG,
585 "Path discovered from DHT is not interesting to us\n");
586 GNUNET_assert (0 == path->entries_length);
587 GNUNET_assert (NULL == path->entries);
588 GNUNET_free (path);
589 return;
590 }
591 LOG (GNUNET_ERROR_TYPE_DEBUG,
592 "Created new path %s based on information from DHT\n",
593 GCPP_2s (path));
594}
595
596
597struct CadetPeerPath *
598GCPP_get_path_from_route (unsigned int path_length,
599 const struct GNUNET_PeerIdentity *pids)
600{
601 struct CheckMatchContext cm_ctx;
602 struct CadetPeer *cpath[path_length];
603 struct CadetPeerPath *path;
604
605 /* precompute inverted 'cpath' so we can avoid doing the lookups and
606 have the correct order */
607 for (unsigned int off = 0; off < path_length; off++)
608 cpath[off] = GCP_get (&pids[path_length - 1 - off],
609 GNUNET_YES);
610
611 /* First figure out if this path is a subset of an existing path, an
612 extension of an existing path, or a new path. */
613 cm_ctx.cpath = cpath;
614 cm_ctx.cpath_length = path_length;
615 cm_ctx.match = NULL;
616 for (int i = path_length - 1; i >= 0; i--)
617 {
618 GCP_iterate_paths_at (cpath[i],
619 (unsigned int) i,
620 &check_match,
621 &cm_ctx);
622 if (NULL != cm_ctx.match)
623 {
624 if (i == path_length - 1)
625 {
626 /* Existing path includes this one, return the match! */
627 LOG (GNUNET_ERROR_TYPE_DEBUG,
628 "Returning existing path %s as inverse for incoming connection\n",
629 GCPP_2s (cm_ctx.match));
630 return cm_ctx.match;
631 }
632 if (cm_ctx.match->entries_length == i + 1)
633 {
634 /* Existing path ends in the middle of new path, extend it! */
635 LOG (GNUNET_ERROR_TYPE_DEBUG,
636 "Extending existing path %s to create inverse for incoming connection\n",
637 GCPP_2s (cm_ctx.match));
638 extend_path (cm_ctx.match,
639 &cpath[i + 1],
640 path_length - i - 1,
641 GNUNET_YES);
642 /* Check that extension was successful */
643 GNUNET_assert (cm_ctx.match->entries_length == path_length);
644 return cm_ctx.match;
645 }
646 /* Eh, we found a match but couldn't use it? Something is wrong. */
647 GNUNET_break (0);
648 }
649 }
650
651 /* No match at all, create completely new path */
652 path = GNUNET_new (struct CadetPeerPath);
653 path->entries_length = path_length;
654 path->entries = GNUNET_new_array (path->entries_length,
655 struct CadetPeerPathEntry *);
656 for (int i = path_length - 1; i >= 0; i--)
657 {
658 struct CadetPeerPathEntry *entry = GNUNET_new (struct CadetPeerPathEntry);
659
660 path->entries[i] = entry;
661 entry->peer = cpath[i];
662 entry->path = path;
663 }
664 for (int i = path_length - 1; i >= 0; i--)
665 {
666 struct CadetPeerPathEntry *entry = path->entries[i];
667
668 GCP_path_entry_add (entry->peer,
669 entry,
670 i);
671 }
672 recalculate_path_desirability (path);
673 LOG (GNUNET_ERROR_TYPE_DEBUG,
674 "Created new path %s to create inverse for incoming connection\n",
675 GCPP_2s (path));
676 path->hn = GCP_attach_path (cpath[path_length - 1],
677 path,
678 path_length - 1,
679 GNUNET_YES);
680 return path;
681}
682
683
684/**
685 * Return the length of the path. Excludes one end of the
686 * path, so the loopback path has length 0.
687 *
688 * @param path path to return the length for
689 * @return number of peers on the path
690 */
691unsigned int
692GCPP_get_length (struct CadetPeerPath *path)
693{
694 return path->entries_length;
695}
696
697
698/**
699 * Find peer's offset on path.
700 *
701 * @param path path to search
702 * @param cp peer to look for
703 * @return offset of @a cp on @a path, or UINT_MAX if not found
704 */
705unsigned int
706GCPP_find_peer (struct CadetPeerPath *path,
707 struct CadetPeer *cp)
708{
709 for (unsigned int off = 0;
710 off < path->entries_length;
711 off++)
712 if (cp == GCPP_get_peer_at_offset (path,
713 off))
714 return off;
715 return UINT_MAX;
716}
717
718
719struct CadetPeer *
720GCPP_get_peer_at_offset (struct CadetPeerPath *path,
721 unsigned int off)
722{
723 GNUNET_assert (off < path->entries_length);
724 return path->entries[off]->peer;
725}
726
727
728/**
729 * Convert a path to a human-readable string.
730 *
731 * @param path path to convert
732 * @return string, to be freed by caller (unlike other *_2s APIs!)
733 */
734const char *
735GCPP_2s (struct CadetPeerPath *path)
736{
737 static char buf[2048];
738 size_t off;
739 const unsigned int max_plen = (sizeof(buf) - 16) / 5 - 2; /* 5 characters per entry */
740
741 off = 0;
742 for (unsigned int i = 0;
743 i < path->entries_length;
744 i++)
745 {
746 if ((path->entries_length > max_plen) &&
747 (i == max_plen / 2))
748 off += GNUNET_snprintf (&buf[off],
749 sizeof(buf) - off,
750 "...-");
751 if ((path->entries_length > max_plen) &&
752 (i > max_plen / 2) &&
753 (i < path->entries_length - max_plen / 2))
754 continue;
755 off += GNUNET_snprintf (&buf[off],
756 sizeof(buf) - off,
757 "%s%s",
758 GNUNET_i2s (GCP_get_id (GCPP_get_peer_at_offset (
759 path,
760 i))),
761 (i == path->entries_length - 1) ? "" : "-");
762 }
763 GNUNET_snprintf (&buf[off],
764 sizeof(buf) - off,
765 "(%p)",
766 path);
767 return buf;
768}
769
770
771/* end of gnunet-service-cadet-new_paths.c */
diff --git a/src/service/cadet/gnunet-service-cadet_paths.h b/src/service/cadet/gnunet-service-cadet_paths.h
new file mode 100644
index 000000000..0f3b4dd1a
--- /dev/null
+++ b/src/service/cadet/gnunet-service-cadet_paths.h
@@ -0,0 +1,183 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2001-2017 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file cadet/gnunet-service-cadet-new_paths.h
23 * @brief Information we track per path.
24 * @author Bartlomiej Polot
25 * @author Christian Grothoff
26 */
27#ifndef GNUNET_SERVICE_CADET_PATHS_H
28#define GNUNET_SERVICE_CADET_PATHS_H
29
30#include "gnunet_util_lib.h"
31#include "gnunet_dht_service.h"
32#include "gnunet-service-cadet.h"
33
34/**
35 * Create a peer path based on the result of a DHT lookup. If we
36 * already know this path, or one that is longer, simply return NULL.
37 * Otherwise, we try to extend an existing path, or create a new one
38 * if applicable.
39 *
40 * @param get_path path of the get request
41 * @param get_path_length length of @a get_path
42 * @param put_path path of the put request
43 * @param put_path_length length of the @a put_path
44 */
45void
46GCPP_try_path_from_dht (const struct GNUNET_DHT_PathElement *get_path,
47 unsigned int get_path_length,
48 const struct GNUNET_DHT_PathElement *put_path,
49 unsigned int put_path_length);
50
51
52/**
53 * We got an incoming connection, obtain the corresponding path.
54 *
55 * @param path_length number of segments on the @a path
56 * @param pids path through the network, in reverse order
57 * (we are at the end, at index @a path_length)
58 * @return corresponding path object
59 */
60struct CadetPeerPath *
61GCPP_get_path_from_route (unsigned int path_length,
62 const struct GNUNET_PeerIdentity *pids);
63
64
65/**
66 * Return the length of the path. Excludes one end of the
67 * path, so the loopback path has length 0.
68 *
69 * @param path path to return the length for
70 * @return number of peers on the path
71 */
72unsigned int
73GCPP_get_length (struct CadetPeerPath *path);
74
75
76/**
77 * Return connection to @a destination using @a path, or return
78 * NULL if no such connection exists.
79 *
80 * @param path path to traverse
81 * @param destination destination node to get to, must be on path
82 * @param off offset of @a destination on @a path
83 * @return NULL if we have no existing connection
84 * otherwise connection from us to @a destination via @a path
85 */
86struct CadetConnection *
87GCPP_get_connection (struct CadetPeerPath *path,
88 struct CadetPeer *destination,
89 unsigned int off);
90
91
92/**
93 * Notify @a path that it is used for connection @a cc
94 * which ends at the path's offset @a off.
95 *
96 * @param path the path to remember the @a cc
97 * @param off the offset where the @a cc ends
98 * @param cc the connection to remember
99 */
100void
101GCPP_add_connection (struct CadetPeerPath *path,
102 unsigned int off,
103 struct CadetConnection *cc);
104
105
106/**
107 * Notify @a path that it is no longer used for connection @a cc which
108 * ended at the path's offset @a off.
109 *
110 * @param path the path to forget the @a cc
111 * @param off the offset where the @a cc ended
112 * @param cc the connection to forget
113 */
114void
115GCPP_del_connection (struct CadetPeerPath *path,
116 unsigned int off,
117 struct CadetConnection *cc);
118
119
120/**
121 * Find peer's offset on path.
122 *
123 * @param path path to search
124 * @param cp peer to look for
125 * @return offset of @a cp on @a path, or UINT_MAX if not found
126 */
127unsigned int
128GCPP_find_peer (struct CadetPeerPath *path,
129 struct CadetPeer *cp);
130
131
132/**
133 * Return how much we like keeping the path. This is an aggregate
134 * score based on various factors, including the age of the path
135 * (older == better), and the value of this path to all of its adjacent
136 * peers. For example, long paths that end at a peer that we have no
137 * shorter way to reach are very desirable, while long paths that end
138 * at a peer for which we have a shorter way as well are much less
139 * desirable. Higher values indicate more valuable paths. The
140 * returned value should be used to decide which paths to remember.
141 *
142 * @param path path to return the length for
143 * @return desirability of the path, larger is more desirable
144 */
145GNUNET_CONTAINER_HeapCostType
146GCPP_get_desirability (const struct CadetPeerPath *path);
147
148
149/**
150 * The given peer @a cp used to own this @a path. However, it is no
151 * longer interested in maintaining it, so the path should be
152 * discarded or shortened (in case a previous peer on the path finds
153 * the path desirable).
154 *
155 * @param path the path that is being released
156 */
157void
158GCPP_release (struct CadetPeerPath *path);
159
160
161/**
162 * Obtain the peer at offset @a off in @a path.
163 *
164 * @param path peer path to inspect
165 * @param off offset to return, must be smaller than path length
166 * @return peer at offset @a off
167 */
168struct CadetPeer *
169GCPP_get_peer_at_offset (struct CadetPeerPath *path,
170 unsigned int off);
171
172
173/**
174 * Convert a path to a human-readable string.
175 *
176 * @param path path to convert
177 * @return string, statically allocated
178 */
179const char *
180GCPP_2s (struct CadetPeerPath *p);
181
182
183#endif
diff --git a/src/service/cadet/gnunet-service-cadet_peer.c b/src/service/cadet/gnunet-service-cadet_peer.c
new file mode 100644
index 000000000..03e8b8962
--- /dev/null
+++ b/src/service/cadet/gnunet-service-cadet_peer.c
@@ -0,0 +1,1554 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2001-2017 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file cadet/gnunet-service-cadet_peer.c
23 * @brief Information we track per peer.
24 * @author Bartlomiej Polot
25 * @author Christian Grothoff
26 *
27 * TODO:
28 * - optimize stopping/restarting DHT search to situations
29 * where we actually need it (i.e. not if we have a direct connection,
30 * or if we already have plenty of good short ones, or maybe even
31 * to take a break if we have some connections and have searched a lot (?))
32 */
33#include "platform.h"
34#include "gnunet_time_lib.h"
35#include "gnunet_util_lib.h"
36#include "gnunet_hello_uri_lib.h"
37#include "gnunet_signatures.h"
38#include "gnunet_transport_application_service.h"
39#include "gnunet_core_service.h"
40#include "gnunet_statistics_service.h"
41#include "gnunet-service-cadet_peer.h"
42#include "gnunet-service-cadet.h"
43#include "gnunet-service-cadet_connection.h"
44#include "gnunet-service-cadet_dht.h"
45#include "gnunet-service-cadet_paths.h"
46#include "gnunet-service-cadet_tunnels.h"
47
48
49#define LOG(level, ...) GNUNET_log_from (level, "cadet-per", __VA_ARGS__)
50
51
52/**
53 * How long do we wait until tearing down an idle peer?
54 */
55#define IDLE_PEER_TIMEOUT GNUNET_TIME_relative_multiply ( \
56 GNUNET_TIME_UNIT_MINUTES, 5)
57
58/**
59 * How long do we keep paths around if we no longer care about the peer?
60 */
61#define IDLE_PATH_TIMEOUT GNUNET_TIME_relative_multiply ( \
62 GNUNET_TIME_UNIT_MINUTES, 2)
63
64/**
65 * Queue size when we start dropping OOO messages.
66 */
67#define MAX_OOO_QUEUE_SIZE 100
68
69/**
70 * Data structure used to track whom we have to notify about changes
71 * to our message queue.
72 */
73struct GCP_MessageQueueManager
74{
75 /**
76 * Kept in a DLL.
77 */
78 struct GCP_MessageQueueManager *next;
79
80 /**
81 * Kept in a DLL.
82 */
83 struct GCP_MessageQueueManager *prev;
84
85 /**
86 * Function to call with updated message queue object.
87 */
88 GCP_MessageQueueNotificationCallback cb;
89
90 /**
91 * Closure for @e cb.
92 */
93 void *cb_cls;
94
95 /**
96 * The peer this is for.
97 */
98 struct CadetPeer *cp;
99
100 /**
101 * Envelope this manager would like to transmit once it is its turn.
102 */
103 struct GNUNET_MQ_Envelope *env;
104};
105
106
107/**
108 * Struct containing all information regarding a given peer
109 */
110struct CadetPeer
111{
112 /**
113 * ID of the peer
114 */
115 struct GNUNET_PeerIdentity pid;
116
117 /**
118 * Last time we heard from this peer (currently not used!)
119 */
120 struct GNUNET_TIME_Absolute last_connection_create;
121
122 /**
123 * Array of DLLs of paths traversing the peer, organized by the
124 * offset of the peer on the larger path.
125 */
126 struct CadetPeerPathEntry **path_heads;
127
128 /**
129 * Array of DLL of paths traversing the peer, organized by the
130 * offset of the peer on the larger path.
131 */
132 struct CadetPeerPathEntry **path_tails;
133
134 /**
135 * Notifications to call when @e core_mq changes.
136 */
137 struct GCP_MessageQueueManager *mqm_head;
138
139 /**
140 * Notifications to call when @e core_mq changes.
141 */
142 struct GCP_MessageQueueManager *mqm_tail;
143
144 /**
145 * Pointer to first "ready" entry in @e mqm_head.
146 */
147 struct GCP_MessageQueueManager *mqm_ready_ptr;
148
149 /**
150 * MIN-heap of paths owned by this peer (they also end at this
151 * peer). Ordered by desirability.
152 */
153 struct GNUNET_CONTAINER_Heap *path_heap;
154
155 /**
156 * Handle to stop the DHT search for paths to this peer
157 */
158 struct GCD_search_handle *search_h;
159
160 /**
161 * Task to clean up @e path_heap asynchronously.
162 */
163 struct GNUNET_SCHEDULER_Task *heap_cleanup_task;
164
165 /**
166 * Task to destroy this entry.
167 */
168 struct GNUNET_SCHEDULER_Task *destroy_task;
169
170 /**
171 * Tunnel to this peer, if any.
172 */
173 struct CadetTunnel *t;
174
175 /**
176 * Connections that go through this peer; indexed by tid.
177 */
178 struct GNUNET_CONTAINER_MultiShortmap *connections;
179
180 /**
181 * Handle for core transmissions.
182 */
183 struct GNUNET_MQ_Handle *core_mq;
184
185 /**
186 * Hello message of the peer.
187 */
188 struct GNUNET_MessageHeader *hello;
189
190 /**
191 * Handle to us offering the HELLO to the transport.
192 */
193 struct GNUNET_TRANSPORT_OfferHelloHandle *hello_offer;
194
195 /**
196 * Transport suggest handle.
197 */
198 struct GNUNET_TRANSPORT_ApplicationSuggestHandle *ash;
199
200 /**
201 * How many messages are in the queue to this peer.
202 */
203 unsigned int queue_n;
204
205 /**
206 * How many paths do we have to this peer (in all @e path_heads DLLs combined).
207 */
208 unsigned int num_paths;
209
210 /**
211 * Sum over all of the offsets of all of the paths in the @a path_heads DLLs.
212 * Used to speed-up #GCP_get_desirability_of_path() calculation.
213 */
214 unsigned int off_sum;
215
216 /**
217 * Number of message queue managers of this peer that have a message in waiting.
218 *
219 * Used to quickly see if we need to bother scanning the @e msm_head DLL.
220 * TODO: could be replaced by another DLL that would then allow us to avoid
221 * the O(n)-scan of the DLL for ready entries!
222 */
223 unsigned int mqm_ready_counter;
224
225 /**
226 * Current length of the @e path_heads and @e path_tails arrays.
227 * The arrays should be grown as needed.
228 */
229 unsigned int path_dll_length;
230};
231
232
233const char *
234GCP_2s (const struct CadetPeer *cp)
235{
236 static char buf[5];
237 char *ret;
238
239 if ((NULL == cp) ||
240 (GNUNET_YES == GNUNET_is_zero (&cp->pid.public_key)))
241 return "NULL";
242
243 ret = GNUNET_CRYPTO_eddsa_public_key_to_string (&cp->pid.public_key);
244 if (NULL == ret)
245 return "NULL";
246
247 GNUNET_strlcpy (buf,
248 ret,
249 sizeof(buf));
250 GNUNET_free (ret);
251 return buf;
252}
253
254
255double
256GCP_get_desirability_of_path (struct CadetPeer *cp,
257 unsigned int off)
258{
259 unsigned int num_alts = cp->num_paths;
260 unsigned int off_sum;
261 double avg_sum;
262 double path_delta;
263 double weight_alts;
264
265 GNUNET_assert (num_alts >= 1); /* 'path' should be in there! */
266 GNUNET_assert (0 != cp->path_dll_length);
267
268 /* We maintain 'off_sum' in 'peer' and thereby
269 avoid the SLOW recalculation each time. Kept here
270 just to document what is going on. */
271#if SLOW
272 off_sum = 0;
273 for (unsigned int j = 0; j < cp->path_dll_length; j++)
274 for (struct CadetPeerPathEntry *pe = cp->path_heads[j];
275 NULL != pe;
276 pe = pe->next)
277 off_sum += j;
278 GNUNET_assert (off_sum == cp->off_sum);
279#else
280 off_sum = cp->off_sum;
281#endif
282 avg_sum = off_sum * 1.0 / cp->path_dll_length;
283 path_delta = off - avg_sum;
284 /* path_delta positive: path off of peer above average (bad path for peer),
285 path_delta negative: path off of peer below average (good path for peer) */
286 if (path_delta <= -1.0)
287 weight_alts = -num_alts / path_delta; /* discount alternative paths */
288 else if (path_delta >= 1.0)
289 weight_alts = num_alts * path_delta; /* overcount alternative paths */
290 else
291 weight_alts = num_alts; /* count alternative paths normally */
292
293
294 /* off+1: long paths are generally harder to find and thus count
295 a bit more as they get longer. However, above-average paths
296 still need to count less, hence the squaring of that factor. */
297 return (off + 1.0) / (weight_alts * weight_alts);
298}
299
300
301/**
302 * This peer is no longer be needed, clean it up now.
303 *
304 * @param cls peer to clean up
305 */
306static void
307destroy_peer (void *cls)
308{
309 struct CadetPeer *cp = cls;
310
311 LOG (GNUNET_ERROR_TYPE_DEBUG,
312 "Destroying state about peer %s\n",
313 GCP_2s (cp));
314 cp->destroy_task = NULL;
315 GNUNET_assert (NULL == cp->t);
316 GNUNET_assert (NULL == cp->core_mq);
317 GNUNET_assert (0 == cp->num_paths);
318 for (unsigned int i = 0; i < cp->path_dll_length; i++)
319 GNUNET_assert (NULL == cp->path_heads[i]);
320 GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (cp->connections));
321 GNUNET_assert (GNUNET_YES ==
322 GNUNET_CONTAINER_multipeermap_remove (peers,
323 &cp->pid,
324 cp));
325 GNUNET_free (cp->path_heads);
326 GNUNET_free (cp->path_tails);
327 cp->path_dll_length = 0;
328 if (NULL != cp->search_h)
329 {
330 GCD_search_stop (cp->search_h);
331 cp->search_h = NULL;
332 }
333 /* FIXME: clean up search_delayedXXX! */
334
335
336 if (NULL != cp->ash)
337 {
338 GNUNET_TRANSPORT_application_suggest_cancel (cp->ash);
339 cp->ash = NULL;
340 }
341 GNUNET_CONTAINER_multishortmap_destroy (cp->connections);
342 if (NULL != cp->path_heap)
343 {
344 GNUNET_CONTAINER_heap_destroy (cp->path_heap);
345 cp->path_heap = NULL;
346 }
347 if (NULL != cp->heap_cleanup_task)
348 {
349 GNUNET_SCHEDULER_cancel (cp->heap_cleanup_task);
350 cp->heap_cleanup_task = NULL;
351 }
352 GNUNET_free (cp->hello);
353 /* Peer should not be freed if paths exist; if there are no paths,
354 there ought to be no connections, and without connections, no
355 notifications. Thus we can assert that mqm_head is empty at this
356 point. */
357 GNUNET_assert (NULL == cp->mqm_head);
358 GNUNET_assert (NULL == cp->mqm_ready_ptr);
359 GNUNET_free (cp);
360}
361
362
363/**
364 * This peer is now on more "active" duty, activate processes related to it.
365 *
366 * @param cp the more-active peer
367 */
368static void
369consider_peer_activate (struct CadetPeer *cp)
370{
371 struct GNUNET_BANDWIDTH_Value32NBO bw;
372
373 LOG (GNUNET_ERROR_TYPE_DEBUG,
374 "Updating peer %s activation state (%u connections)%s%s\n",
375 GCP_2s (cp),
376 GNUNET_CONTAINER_multishortmap_size (cp->connections),
377 (NULL == cp->t) ? "" : " with tunnel",
378 (NULL == cp->core_mq) ? "" : " with CORE link");
379 if (NULL != cp->destroy_task)
380 {
381 /* It's active, do not destroy! */
382 GNUNET_SCHEDULER_cancel (cp->destroy_task);
383 cp->destroy_task = NULL;
384 }
385 if ((0 == GNUNET_CONTAINER_multishortmap_size (cp->connections)) &&
386 (NULL == cp->t))
387 {
388 /* We're just on a path or directly connected; don't bother too much */
389 if (NULL != cp->ash)
390 {
391 GNUNET_TRANSPORT_application_suggest_cancel (cp->ash);
392 cp->ash = NULL;
393 }
394 if (NULL != cp->search_h)
395 {
396 GCD_search_stop (cp->search_h);
397 cp->search_h = NULL;
398 }
399 return;
400 }
401 if (NULL == cp->core_mq)
402 {
403 /* Lacks direct connection, try to create one by querying the DHT */
404 if ((NULL == cp->search_h) &&
405 (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths))
406 cp->search_h
407 = GCD_search (&cp->pid);
408 }
409 else
410 {
411 /* Have direct connection, stop DHT search if active */
412 if (NULL != cp->search_h)
413 {
414 GCD_search_stop (cp->search_h);
415 cp->search_h = NULL;
416 }
417 }
418
419 if (NULL != cp->ash)
420 GNUNET_TRANSPORT_application_suggest_cancel (cp->ash);
421 bw.value__ = 0;
422 cp->ash
423 = GNUNET_TRANSPORT_application_suggest (transport,
424 &cp->pid,
425 GNUNET_MQ_PRIO_BEST_EFFORT,
426 bw);
427}
428
429
430/**
431 * This peer may no longer be needed, consider cleaning it up.
432 *
433 * @param cp peer to clean up
434 */
435static void
436consider_peer_destroy (struct CadetPeer *cp);
437
438
439/**
440 * We really no longere care about a peer, stop hogging memory with paths to it.
441 * Afterwards, see if there is more to be cleaned up about this peer.
442 *
443 * @param cls a `struct CadetPeer`.
444 */
445static void
446drop_paths (void *cls)
447{
448 struct CadetPeer *cp = cls;
449 struct CadetPeerPath *path;
450
451 cp->destroy_task = NULL;
452 while (NULL != (path = GNUNET_CONTAINER_heap_remove_root (cp->path_heap)))
453 GCPP_release (path);
454 consider_peer_destroy (cp);
455}
456
457
458/**
459 * This peer may no longer be needed, consider cleaning it up.
460 *
461 * @param cp peer to clean up
462 */
463static void
464consider_peer_destroy (struct CadetPeer *cp)
465{
466 struct GNUNET_TIME_Relative exp;
467
468 if (NULL != cp->destroy_task)
469 {
470 GNUNET_SCHEDULER_cancel (cp->destroy_task);
471 cp->destroy_task = NULL;
472 }
473 if (NULL != cp->t)
474 return; /* still relevant! */
475 if (NULL != cp->core_mq)
476 return; /* still relevant! */
477 if (0 != GNUNET_CONTAINER_multishortmap_size (cp->connections))
478 return; /* still relevant! */
479 if ((NULL != cp->path_heap) &&
480 (0 < GNUNET_CONTAINER_heap_get_size (cp->path_heap)))
481 {
482 cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PATH_TIMEOUT,
483 &drop_paths,
484 cp);
485 return;
486 }
487 if (0 != cp->num_paths)
488 return; /* still relevant! */
489 if (NULL != cp->hello)
490 {
491 /* relevant only until HELLO expires */
492 exp = GNUNET_TIME_absolute_get_remaining (
493 GNUNET_HELLO_builder_get_expiration_time (cp
494 ->hello));
495 cp->destroy_task = GNUNET_SCHEDULER_add_delayed (exp,
496 &destroy_peer,
497 cp);
498 return;
499 }
500 cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PEER_TIMEOUT,
501 &destroy_peer,
502 cp);
503}
504
505
506/**
507 * Set the message queue to @a mq for peer @a cp and notify watchers.
508 *
509 * @param cp peer to modify
510 * @param mq message queue to set (can be NULL)
511 */
512void
513GCP_set_mq (struct CadetPeer *cp,
514 struct GNUNET_MQ_Handle *mq)
515{
516 LOG (GNUNET_ERROR_TYPE_DEBUG,
517 "Message queue for peer %s is now %p\n",
518 GCP_2s (cp),
519 mq);
520 cp->core_mq = mq;
521 for (struct GCP_MessageQueueManager *mqm = cp->mqm_head, *next;
522 NULL != mqm;
523 mqm = next)
524 {
525 /* Save next pointer in case mqm gets freed by the callback */
526 next = mqm->next;
527 if (NULL == mq)
528 {
529 if (NULL != mqm->env)
530 {
531 GNUNET_MQ_discard (mqm->env);
532 mqm->env = NULL;
533 mqm->cb (mqm->cb_cls,
534 GNUNET_SYSERR);
535 }
536 else
537 {
538 mqm->cb (mqm->cb_cls,
539 GNUNET_NO);
540 }
541 }
542 else
543 {
544 GNUNET_assert (NULL == mqm->env);
545 mqm->cb (mqm->cb_cls,
546 GNUNET_YES);
547 }
548 }
549 if ((NULL != mq) ||
550 (NULL != cp->t))
551 consider_peer_activate (cp);
552 else
553 consider_peer_destroy (cp);
554
555 if ((NULL != mq) &&
556 (NULL != cp->t))
557 {
558 /* have a new, direct path to the target, notify tunnel */
559 struct CadetPeerPath *path;
560
561 path = GCPP_get_path_from_route (1,
562 &cp->pid);
563 GCT_consider_path (cp->t,
564 path,
565 0);
566 }
567}
568
569
570/**
571 * Debug function should NEVER return true in production code, useful to
572 * simulate losses for testcases.
573 *
574 * @return #GNUNET_YES or #GNUNET_NO with the decision to drop.
575 */
576static int
577should_I_drop (void)
578{
579 if (0 == drop_percent)
580 return GNUNET_NO;
581 if (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
582 101) < drop_percent)
583 return GNUNET_YES;
584 return GNUNET_NO;
585}
586
587
588/**
589 * Function called when CORE took one of the messages from
590 * a message queue manager and transmitted it.
591 *
592 * @param cls the `struct CadetPeeer` where we made progress
593 */
594static void
595mqm_send_done (void *cls);
596
597
598/**
599 * Transmit current envelope from this @a mqm.
600 *
601 * @param mqm mqm to transmit message for now
602 */
603static void
604mqm_execute (struct GCP_MessageQueueManager *mqm)
605{
606 struct CadetPeer *cp = mqm->cp;
607
608 /* Move ready pointer to the next entry that might be ready. */
609 if ((mqm == cp->mqm_ready_ptr) &&
610 (NULL != mqm->next))
611 cp->mqm_ready_ptr = mqm->next;
612 /* Move entry to the end of the DLL, to be fair. */
613 if (mqm != cp->mqm_tail)
614 {
615 GNUNET_CONTAINER_DLL_remove (cp->mqm_head,
616 cp->mqm_tail,
617 mqm);
618 GNUNET_CONTAINER_DLL_insert_tail (cp->mqm_head,
619 cp->mqm_tail,
620 mqm);
621 }
622 cp->mqm_ready_counter--;
623 if (GNUNET_YES == should_I_drop ())
624 {
625 LOG (GNUNET_ERROR_TYPE_DEBUG,
626 "DROPPING message to peer %s from MQM %p\n",
627 GCP_2s (cp),
628 mqm);
629 GNUNET_MQ_discard (mqm->env);
630 mqm->env = NULL;
631 mqm_send_done (cp);
632 }
633 else
634 {
635 {
636 const struct GNUNET_MessageHeader *mh;
637
638 mh = GNUNET_MQ_env_get_msg (mqm->env);
639 switch (ntohs (mh->type))
640 {
641 case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX:
642 {
643 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg
644 = (const struct GNUNET_CADET_TunnelKeyExchangeMessage *) mh;
645 LOG (GNUNET_ERROR_TYPE_DEBUG,
646 "P2P forwarding KX with ephemeral %s to %s on CID %s\n",
647 GNUNET_e2s (&msg->ephemeral_key),
648 GCP_2s (cp),
649 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
650 }
651 break;
652
653 default:
654 break;
655 }
656 }
657 LOG (GNUNET_ERROR_TYPE_DEBUG,
658 "Sending to peer %s from MQM %p\n",
659 GCP_2s (cp),
660 mqm);
661 GNUNET_MQ_send (cp->core_mq,
662 mqm->env);
663 mqm->env = NULL;
664 }
665 mqm->cb (mqm->cb_cls,
666 GNUNET_YES);
667}
668
669
670/**
671 * Find the next ready message in the queue (starting
672 * the search from the `cp->mqm_ready_ptr`) and if possible
673 * execute the transmission.
674 *
675 * @param cp peer to try to send the next ready message to
676 */
677static void
678send_next_ready (struct CadetPeer *cp)
679{
680 struct GCP_MessageQueueManager *mqm;
681
682 if (0 == cp->mqm_ready_counter)
683 return;
684 while ((NULL != (mqm = cp->mqm_ready_ptr)) &&
685 (NULL == mqm->env))
686 cp->mqm_ready_ptr = mqm->next;
687 if (NULL == mqm)
688 return; /* nothing to do */
689 mqm_execute (mqm);
690}
691
692
693/**
694 * Function called when CORE took one of the messages from
695 * a message queue manager and transmitted it.
696 *
697 * @param cls the `struct CadetPeeer` where we made progress
698 */
699static void
700mqm_send_done (void *cls)
701{
702 struct CadetPeer *cp = cls;
703
704 LOG (GNUNET_ERROR_TYPE_DEBUG,
705 "Sending to peer %s completed\n",
706 GCP_2s (cp));
707 send_next_ready (cp);
708}
709
710
711/**
712 * Send the message in @a env to @a cp.
713 *
714 * @param mqm the message queue manager to use for transmission
715 * @param env envelope with the message to send; must NOT
716 * yet have a #GNUNET_MQ_notify_sent() callback attached to it
717 */
718void
719GCP_send (struct GCP_MessageQueueManager *mqm,
720 struct GNUNET_MQ_Envelope *env)
721{
722 struct CadetPeer *cp = mqm->cp;
723
724 GNUNET_assert (NULL != env);
725 LOG (GNUNET_ERROR_TYPE_DEBUG,
726 "Queueing message to peer %s in MQM %p\n",
727 GCP_2s (cp),
728 mqm);
729 GNUNET_assert (NULL != cp->core_mq);
730 GNUNET_assert (NULL == mqm->env);
731 GNUNET_MQ_notify_sent (env,
732 &mqm_send_done,
733 cp);
734 mqm->env = env;
735 cp->mqm_ready_counter++;
736 if (mqm != cp->mqm_ready_ptr)
737 cp->mqm_ready_ptr = cp->mqm_head;
738 if (1 == cp->mqm_ready_counter)
739 cp->mqm_ready_ptr = mqm;
740 if (0 != GNUNET_MQ_get_length (cp->core_mq))
741 return;
742 send_next_ready (cp);
743}
744
745
746/**
747 * Function called to destroy a peer now.
748 *
749 * @param cls NULL
750 * @param pid identity of the peer (unused)
751 * @param value the `struct CadetPeer` to clean up
752 * @return #GNUNET_OK (continue to iterate)
753 */
754static int
755destroy_iterator_cb (void *cls,
756 const struct GNUNET_PeerIdentity *pid,
757 void *value)
758{
759 struct CadetPeer *cp = value;
760
761 if (NULL != cp->destroy_task)
762 {
763 GNUNET_SCHEDULER_cancel (cp->destroy_task);
764 cp->destroy_task = NULL;
765 }
766 destroy_peer (cp);
767 return GNUNET_OK;
768}
769
770
771/**
772 * Clean up all entries about all peers.
773 * Must only be called after all tunnels, CORE-connections and
774 * connections are down.
775 */
776void
777GCP_destroy_all_peers ()
778{
779 LOG (GNUNET_ERROR_TYPE_DEBUG,
780 "Destroying all peers now\n");
781 GNUNET_CONTAINER_multipeermap_iterate (peers,
782 &destroy_iterator_cb,
783 NULL);
784}
785
786
787/**
788 * Drop all paths owned by this peer, and do not
789 * allow new ones to be added: We are shutting down.
790 *
791 * @param cp peer to drop paths to
792 */
793void
794GCP_drop_owned_paths (struct CadetPeer *cp)
795{
796 struct CadetPeerPath *path;
797
798 LOG (GNUNET_ERROR_TYPE_DEBUG,
799 "Destroying all paths to %s\n",
800 GCP_2s (cp));
801 while (NULL != (path =
802 GNUNET_CONTAINER_heap_remove_root (cp->path_heap)))
803 GCPP_release (path);
804 GNUNET_CONTAINER_heap_destroy (cp->path_heap);
805 cp->path_heap = NULL;
806}
807
808
809/**
810 * Add an entry to the DLL of all of the paths that this peer is on.
811 *
812 * @param cp peer to modify
813 * @param entry an entry on a path
814 * @param off offset of this peer on the path
815 */
816void
817GCP_path_entry_add (struct CadetPeer *cp,
818 struct CadetPeerPathEntry *entry,
819 unsigned int off)
820{
821 GNUNET_assert (cp == GCPP_get_peer_at_offset (entry->path,
822 off));
823 LOG (GNUNET_ERROR_TYPE_DEBUG,
824 "Discovered that peer %s is on path %s at offset %u\n",
825 GCP_2s (cp),
826 GCPP_2s (entry->path),
827 off);
828 if (off >= cp->path_dll_length)
829 {
830 unsigned int len = cp->path_dll_length;
831
832 GNUNET_array_grow (cp->path_heads,
833 len,
834 off + 4);
835 GNUNET_array_grow (cp->path_tails,
836 cp->path_dll_length,
837 off + 4);
838 }
839 GNUNET_CONTAINER_DLL_insert (cp->path_heads[off],
840 cp->path_tails[off],
841 entry);
842 cp->off_sum += off;
843 cp->num_paths++;
844
845 /* If we have a tunnel to this peer, tell the tunnel that there is a
846 new path available. */
847 if (NULL != cp->t)
848 GCT_consider_path (cp->t,
849 entry->path,
850 off);
851
852 if ((NULL != cp->search_h) &&
853 (DESIRED_CONNECTIONS_PER_TUNNEL <= cp->num_paths))
854 {
855 /* Now I have enough paths, stop search */
856 GCD_search_stop (cp->search_h);
857 cp->search_h = NULL;
858 }
859 if (NULL != cp->destroy_task)
860 {
861 /* paths changed, this resets the destroy timeout counter
862 and aborts a destroy task that may no longer be valid
863 to have (as we now have more paths via this peer). */
864 consider_peer_destroy (cp);
865 }
866}
867
868
869/**
870 * Remove an entry from the DLL of all of the paths that this peer is on.
871 *
872 * @param cp peer to modify
873 * @param entry an entry on a path
874 * @param off offset of this peer on the path
875 */
876void
877GCP_path_entry_remove (struct CadetPeer *cp,
878 struct CadetPeerPathEntry *entry,
879 unsigned int off)
880{
881 LOG (GNUNET_ERROR_TYPE_DEBUG,
882 "Removing knowledge about peer %s beging on path %s at offset %u\n",
883 GCP_2s (cp),
884 GCPP_2s (entry->path),
885 off);
886 GNUNET_CONTAINER_DLL_remove (cp->path_heads[off],
887 cp->path_tails[off],
888 entry);
889 GNUNET_assert (0 < cp->num_paths);
890 cp->off_sum -= off;
891 cp->num_paths--;
892 if ((NULL == cp->core_mq) &&
893 (NULL != cp->t) &&
894 (NULL == cp->search_h) &&
895 (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths))
896 cp->search_h
897 = GCD_search (&cp->pid);
898 if (NULL == cp->destroy_task)
899 {
900 /* paths changed, we might now be ready for destruction, check again */
901 consider_peer_destroy (cp);
902 }
903}
904
905
906/**
907 * Prune down the number of paths to this peer, we seem to
908 * have way too many.
909 *
910 * @param cls the `struct CadetPeer` to maintain the path heap for
911 */
912static void
913path_heap_cleanup (void *cls)
914{
915 struct CadetPeer *cp = cls;
916 struct CadetPeerPath *root;
917
918 cp->heap_cleanup_task = NULL;
919 while (GNUNET_CONTAINER_heap_get_size (cp->path_heap) >=
920 2 * DESIRED_CONNECTIONS_PER_TUNNEL)
921 {
922 /* Now we have way too many, drop least desirable UNLESS it is in use!
923 (Note that this intentionally keeps highly desirable, but currently
924 unused paths around in the hope that we might be able to switch, even
925 if the number of paths exceeds the threshold.) */
926 root = GNUNET_CONTAINER_heap_peek (cp->path_heap);
927 GNUNET_assert (NULL != root);
928 if (NULL !=
929 GCPP_get_connection (root,
930 cp,
931 GCPP_get_length (root) - 1))
932 break; /* can't fix */
933 /* Got plenty of paths to this destination, and this is a low-quality
934 one that we don't care about. Allow it to die. */
935 GNUNET_assert (root ==
936 GNUNET_CONTAINER_heap_remove_root (cp->path_heap));
937 GCPP_release (root);
938 }
939}
940
941
942struct GNUNET_CONTAINER_HeapNode *
943GCP_attach_path (struct CadetPeer *cp,
944 struct CadetPeerPath *path,
945 unsigned int off,
946 int force)
947{
948 GNUNET_CONTAINER_HeapCostType desirability;
949 struct CadetPeerPath *root;
950 GNUNET_CONTAINER_HeapCostType root_desirability;
951 struct GNUNET_CONTAINER_HeapNode *hn;
952
953 GNUNET_assert (off == GCPP_get_length (path) - 1);
954 GNUNET_assert (cp == GCPP_get_peer_at_offset (path,
955 off));
956 if (NULL == cp->path_heap)
957 {
958 /* #GCP_drop_owned_paths() was already called, we cannot take new ones! */
959 GNUNET_assert (GNUNET_NO == force);
960 return NULL;
961 }
962 desirability = GCPP_get_desirability (path);
963 if (GNUNET_NO == force)
964 {
965 /* FIXME: desirability is not yet initialized; tricky! */
966 if (GNUNET_NO ==
967 GNUNET_CONTAINER_heap_peek2 (cp->path_heap,
968 (void **) &root,
969 &root_desirability))
970 {
971 root = NULL;
972 root_desirability = 0;
973 }
974
975 if ((DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) &&
976 (desirability < root_desirability))
977 {
978 LOG (GNUNET_ERROR_TYPE_DEBUG,
979 "Decided to not attach path %s to peer %s due to undesirability\n",
980 GCPP_2s (path),
981 GCP_2s (cp));
982 return NULL;
983 }
984 }
985
986 LOG (GNUNET_ERROR_TYPE_DEBUG,
987 "Attaching path %s to peer %s (%s)\n",
988 GCPP_2s (path),
989 GCP_2s (cp),
990 (GNUNET_NO == force) ? "desirable" : "forced");
991
992 /* Yes, we'd like to add this path, add to our heap */
993 hn = GNUNET_CONTAINER_heap_insert (cp->path_heap,
994 path,
995 desirability);
996
997 /* Consider maybe dropping other paths because of the new one */
998 if ((GNUNET_CONTAINER_heap_get_size (cp->path_heap) >=
999 2 * DESIRED_CONNECTIONS_PER_TUNNEL) &&
1000 (NULL != cp->heap_cleanup_task))
1001 cp->heap_cleanup_task = GNUNET_SCHEDULER_add_now (&path_heap_cleanup,
1002 cp);
1003 return hn;
1004}
1005
1006
1007/**
1008 * This peer can no longer own @a path as the path
1009 * has been extended and a peer further down the line
1010 * is now the new owner.
1011 *
1012 * @param cp old owner of the @a path
1013 * @param path path where the ownership is lost
1014 * @param hn note in @a cp's path heap that must be deleted
1015 */
1016void
1017GCP_detach_path (struct CadetPeer *cp,
1018 struct CadetPeerPath *path,
1019 struct GNUNET_CONTAINER_HeapNode *hn)
1020{
1021 LOG (GNUNET_ERROR_TYPE_DEBUG,
1022 "Detaching path %s from peer %s\n",
1023 GCPP_2s (path),
1024 GCP_2s (cp));
1025 GNUNET_assert (path ==
1026 GNUNET_CONTAINER_heap_remove_node (hn));
1027}
1028
1029
1030/**
1031 * Add a @a connection to this @a cp.
1032 *
1033 * @param cp peer via which the @a connection goes
1034 * @param cc the connection to add
1035 */
1036void
1037GCP_add_connection (struct CadetPeer *cp,
1038 struct CadetConnection *cc)
1039{
1040 LOG (GNUNET_ERROR_TYPE_DEBUG,
1041 "Adding %s to peer %s\n",
1042 GCC_2s (cc),
1043 GCP_2s (cp));
1044 GNUNET_assert (GNUNET_OK ==
1045 GNUNET_CONTAINER_multishortmap_put (cp->connections,
1046 &GCC_get_id (
1047 cc)->connection_of_tunnel,
1048 cc,
1049 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1050 if (NULL != cp->destroy_task)
1051 {
1052 GNUNET_SCHEDULER_cancel (cp->destroy_task);
1053 cp->destroy_task = NULL;
1054 }
1055}
1056
1057
1058/**
1059 * Remove a @a connection that went via this @a cp.
1060 *
1061 * @param cp peer via which the @a connection went
1062 * @param cc the connection to remove
1063 */
1064void
1065GCP_remove_connection (struct CadetPeer *cp,
1066 struct CadetConnection *cc)
1067{
1068 LOG (GNUNET_ERROR_TYPE_DEBUG,
1069 "Removing connection %s from peer %s\n",
1070 GCC_2s (cc),
1071 GCP_2s (cp));
1072 GNUNET_assert (GNUNET_YES ==
1073 GNUNET_CONTAINER_multishortmap_remove (cp->connections,
1074 &GCC_get_id (
1075 cc)->
1076 connection_of_tunnel,
1077 cc));
1078 consider_peer_destroy (cp);
1079}
1080
1081
1082/**
1083 * Retrieve the CadetPeer structure associated with the
1084 * peer. Optionally create one and insert it in the appropriate
1085 * structures if the peer is not known yet.
1086 *
1087 * @param peer_id Full identity of the peer.
1088 * @param create #GNUNET_YES if a new peer should be created if unknown.
1089 * #GNUNET_NO to return NULL if peer is unknown.
1090 * @return Existing or newly created peer structure.
1091 * NULL if unknown and not requested @a create
1092 */
1093struct CadetPeer *
1094GCP_get (const struct GNUNET_PeerIdentity *peer_id,
1095 int create)
1096{
1097 struct CadetPeer *cp;
1098
1099 cp = GNUNET_CONTAINER_multipeermap_get (peers,
1100 peer_id);
1101 if (NULL != cp)
1102 return cp;
1103 if (GNUNET_NO == create)
1104 return NULL;
1105 cp = GNUNET_new (struct CadetPeer);
1106 cp->pid = *peer_id;
1107 cp->connections = GNUNET_CONTAINER_multishortmap_create (32,
1108 GNUNET_YES);
1109 cp->path_heap = GNUNET_CONTAINER_heap_create (
1110 GNUNET_CONTAINER_HEAP_ORDER_MIN);
1111 GNUNET_assert (GNUNET_YES ==
1112 GNUNET_CONTAINER_multipeermap_put (peers,
1113 &cp->pid,
1114 cp,
1115 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1116 LOG (GNUNET_ERROR_TYPE_DEBUG,
1117 "Creating peer %s\n",
1118 GCP_2s (cp));
1119 return cp;
1120}
1121
1122
1123/**
1124 * Obtain the peer identity for a `struct CadetPeer`.
1125 *
1126 * @param cp our peer handle
1127 * @return the peer identity
1128 */
1129const struct GNUNET_PeerIdentity *
1130GCP_get_id (struct CadetPeer *cp)
1131{
1132 return &cp->pid;
1133}
1134
1135
1136/**
1137 * Iterate over all known peers.
1138 *
1139 * @param iter Iterator.
1140 * @param cls Closure for @c iter.
1141 */
1142void
1143GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter,
1144 void *cls)
1145{
1146 GNUNET_CONTAINER_multipeermap_iterate (peers,
1147 iter,
1148 cls);
1149}
1150
1151
1152/**
1153 * Count the number of known paths toward the peer.
1154 *
1155 * @param cp Peer to get path info.
1156 * @return Number of known paths.
1157 */
1158unsigned int
1159GCP_count_paths (const struct CadetPeer *cp)
1160{
1161 return cp->num_paths;
1162}
1163
1164
1165/**
1166 * Iterate over the paths to a peer.
1167 *
1168 * @param cp Peer to get path info.
1169 * @param callback Function to call for every path.
1170 * @param callback_cls Closure for @a callback.
1171 * @return Number of iterated paths.
1172 */
1173unsigned int
1174GCP_iterate_paths (struct CadetPeer *cp,
1175 GCP_PathIterator callback,
1176 void *callback_cls)
1177{
1178 unsigned int ret = 0;
1179
1180 LOG (GNUNET_ERROR_TYPE_DEBUG,
1181 "Iterating over paths to peer %s%s\n",
1182 GCP_2s (cp),
1183 (NULL == cp->core_mq) ? "" : " including direct link");
1184 if (NULL != cp->core_mq)
1185 {
1186 /* FIXME: this branch seems to duplicate the
1187 i=0 case below (direct link). Leave out!??? -CG */
1188 struct CadetPeerPath *path;
1189
1190 path = GCPP_get_path_from_route (1,
1191 &cp->pid);
1192 ret++;
1193 if (GNUNET_NO ==
1194 callback (callback_cls,
1195 path,
1196 0))
1197 return ret;
1198 }
1199 for (unsigned int i = 0; i < cp->path_dll_length; i++)
1200 {
1201 for (struct CadetPeerPathEntry *pe = cp->path_heads[i];
1202 NULL != pe;
1203 pe = pe->next)
1204 {
1205 ret++;
1206 if (GNUNET_NO ==
1207 callback (callback_cls,
1208 pe->path,
1209 i))
1210 return ret;
1211 }
1212 }
1213 return ret;
1214}
1215
1216
1217/**
1218 * Iterate over the paths to a peer without direct link.
1219 *
1220 * @param cp Peer to get path info.
1221 * @param callback Function to call for every path.
1222 * @param callback_cls Closure for @a callback.
1223 * @return Number of iterated paths.
1224 */
1225unsigned int
1226GCP_iterate_indirect_paths (struct CadetPeer *cp,
1227 GCP_PathIterator callback,
1228 void *callback_cls)
1229{
1230 unsigned int ret = 0;
1231
1232 LOG (GNUNET_ERROR_TYPE_DEBUG,
1233 "Iterating over paths to peer %s without direct link\n",
1234 GCP_2s (cp));
1235 for (unsigned int i = 1; i < cp->path_dll_length; i++)
1236 {
1237 for (struct CadetPeerPathEntry *pe = cp->path_heads[i];
1238 NULL != pe;
1239 pe = pe->next)
1240 {
1241 ret++;
1242 if (GNUNET_NO ==
1243 callback (callback_cls,
1244 pe->path,
1245 i))
1246 return ret;
1247 }
1248 }
1249 return ret;
1250}
1251
1252
1253unsigned int
1254GCP_iterate_paths_at (struct CadetPeer *cp,
1255 unsigned int dist,
1256 GCP_PathIterator callback,
1257 void *callback_cls)
1258{
1259 unsigned int ret = 0;
1260
1261 if (dist >= cp->path_dll_length)
1262 {
1263 LOG (GNUNET_ERROR_TYPE_DEBUG,
1264 "Asked to look for paths at distance %u, but maximum for me is < %u\n",
1265 dist,
1266 cp->path_dll_length);
1267 return 0;
1268 }
1269 for (struct CadetPeerPathEntry *pe = cp->path_heads[dist];
1270 NULL != pe;
1271 pe = pe->next)
1272 {
1273 if (GNUNET_NO ==
1274 callback (callback_cls,
1275 pe->path,
1276 dist))
1277 return ret;
1278 ret++;
1279 }
1280 return ret;
1281}
1282
1283
1284/**
1285 * Get the tunnel towards a peer.
1286 *
1287 * @param cp Peer to get from.
1288 * @param create #GNUNET_YES to create a tunnel if we do not have one
1289 * @return Tunnel towards peer.
1290 */
1291struct CadetTunnel *
1292GCP_get_tunnel (struct CadetPeer *cp,
1293 int create)
1294{
1295 if (NULL == cp)
1296 return NULL;
1297 if ((NULL != cp->t) ||
1298 (GNUNET_NO == create))
1299 return cp->t;
1300 cp->t = GCT_create_tunnel (cp);
1301 consider_peer_activate (cp);
1302 return cp->t;
1303}
1304
1305
1306void
1307GCP_set_hello (struct CadetPeer *cp,
1308 const struct GNUNET_MessageHeader *hello)
1309{
1310 struct GNUNET_BANDWIDTH_Value32NBO bw;
1311 uint16_t size = ntohs (hello->size);
1312
1313 LOG (GNUNET_ERROR_TYPE_DEBUG,
1314 "Got %u byte HELLO for peer %s\n",
1315 (unsigned int) size,
1316 GCP_2s (cp));
1317 if (NULL != cp->hello)
1318 {
1319 struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
1320
1321 struct GNUNET_TIME_Absolute new_hello_exp =
1322 GNUNET_HELLO_builder_get_expiration_time (hello);
1323 struct GNUNET_TIME_Absolute old_hello_exp =
1324 GNUNET_HELLO_builder_get_expiration_time (cp
1325 ->hello);
1326
1327 if (GNUNET_TIME_absolute_cmp (new_hello_exp, >, now) &&
1328 GNUNET_TIME_absolute_cmp (new_hello_exp, >, old_hello_exp))
1329 {
1330 GNUNET_free (cp->hello);
1331 cp->hello = GNUNET_malloc (size);
1332 GNUNET_memcpy (cp->hello, hello, size);
1333 }
1334 else
1335 {
1336 return;
1337 }
1338 }
1339 else
1340 {
1341 cp->hello = GNUNET_memdup (hello,
1342 size);
1343 }
1344 if (NULL != cp->ash)
1345 GNUNET_TRANSPORT_application_suggest_cancel (cp->ash);
1346 bw.value__ = 0;
1347 cp->ash
1348 = GNUNET_TRANSPORT_application_suggest (transport,
1349 &cp->pid,
1350 GNUNET_MQ_PRIO_BEST_EFFORT,
1351 bw);
1352 /* New HELLO means cp's destruction time may change... */
1353 consider_peer_destroy (cp);
1354}
1355
1356
1357/**
1358 * The tunnel to the given peer no longer exists, remove it from our
1359 * data structures, and possibly clean up the peer itself.
1360 *
1361 * @param cp the peer affected
1362 * @param t the dead tunnel
1363 */
1364void
1365GCP_drop_tunnel (struct CadetPeer *cp,
1366 struct CadetTunnel *t)
1367{
1368 LOG (GNUNET_ERROR_TYPE_DEBUG,
1369 "Dropping tunnel %s to peer %s\n",
1370 GCT_2s (t),
1371 GCP_2s (cp));
1372 GNUNET_assert (cp->t == t);
1373 cp->t = NULL;
1374 consider_peer_destroy (cp);
1375}
1376
1377
1378/**
1379 * Test if @a cp has a core-level connection
1380 *
1381 * @param cp peer to test
1382 * @return #GNUNET_YES if @a cp has a core-level connection
1383 */
1384int
1385GCP_has_core_connection (struct CadetPeer *cp)
1386{
1387 return (NULL != cp->core_mq) ? GNUNET_YES : GNUNET_NO;
1388}
1389
1390
1391/**
1392 * Start message queue change notifications.
1393 *
1394 * @param cp peer to notify for
1395 * @param cb function to call if mq becomes available or unavailable
1396 * @param cb_cls closure for @a cb
1397 * @return handle to cancel request
1398 */
1399struct GCP_MessageQueueManager *
1400GCP_request_mq (struct CadetPeer *cp,
1401 GCP_MessageQueueNotificationCallback cb,
1402 void *cb_cls)
1403{
1404 struct GCP_MessageQueueManager *mqm;
1405
1406 mqm = GNUNET_new (struct GCP_MessageQueueManager);
1407 mqm->cb = cb;
1408 mqm->cb_cls = cb_cls;
1409 mqm->cp = cp;
1410 GNUNET_CONTAINER_DLL_insert (cp->mqm_head,
1411 cp->mqm_tail,
1412 mqm);
1413 LOG (GNUNET_ERROR_TYPE_DEBUG,
1414 "Creating MQM %p for peer %s\n",
1415 mqm,
1416 GCP_2s (cp));
1417 if (NULL != cp->core_mq)
1418 cb (cb_cls,
1419 GNUNET_YES);
1420 return mqm;
1421}
1422
1423
1424/**
1425 * Stops message queue change notifications.
1426 *
1427 * @param mqm handle matching request to cancel
1428 * @param last_env final message to transmit, or NULL
1429 */
1430void
1431GCP_request_mq_cancel (struct GCP_MessageQueueManager *mqm,
1432 struct GNUNET_MQ_Envelope *last_env)
1433{
1434 struct CadetPeer *cp = mqm->cp;
1435
1436 LOG (GNUNET_ERROR_TYPE_DEBUG,
1437 "Destroying MQM %p for peer %s%s\n",
1438 mqm,
1439 GCP_2s (cp),
1440 (NULL == last_env) ? "" : " with last ditch transmission");
1441 if (NULL != mqm->env)
1442 GNUNET_MQ_discard (mqm->env);
1443 if (NULL != last_env)
1444 {
1445 if (NULL != cp->core_mq)
1446 {
1447 GNUNET_MQ_notify_sent (last_env,
1448 &mqm_send_done,
1449 cp);
1450 GNUNET_MQ_send (cp->core_mq,
1451 last_env);
1452 }
1453 else
1454 {
1455 GNUNET_MQ_discard (last_env);
1456 }
1457 }
1458 if (cp->mqm_ready_ptr == mqm)
1459 cp->mqm_ready_ptr = mqm->next;
1460 GNUNET_CONTAINER_DLL_remove (cp->mqm_head,
1461 cp->mqm_tail,
1462 mqm);
1463 GNUNET_free (mqm);
1464}
1465
1466
1467/**
1468 * Send the message in @a env to @a cp, overriding queueing logic.
1469 * This function should only be used to send error messages outside
1470 * of flow and congestion control, similar to ICMP. Note that
1471 * the envelope may be silently discarded as well.
1472 *
1473 * @param cp peer to send the message to
1474 * @param env envelope with the message to send
1475 */
1476void
1477GCP_send_ooo (struct CadetPeer *cp,
1478 struct GNUNET_MQ_Envelope *env)
1479{
1480 LOG (GNUNET_ERROR_TYPE_DEBUG,
1481 "Sending message to %s out of management\n",
1482 GCP_2s (cp));
1483 if (NULL == cp->core_mq)
1484 {
1485 GNUNET_MQ_discard (env);
1486 return;
1487 }
1488 if (GNUNET_MQ_get_length (cp->core_mq) > MAX_OOO_QUEUE_SIZE)
1489 {
1490 GNUNET_MQ_discard (env);
1491 return;
1492 }
1493 GNUNET_MQ_notify_sent (env,
1494 &mqm_send_done,
1495 cp);
1496 GNUNET_MQ_send (cp->core_mq,
1497 env);
1498}
1499
1500
1501/**
1502 * Checking if a monotime value is newer than the last monotime value received from a peer. If the time value is newer it will be stored at the peer.
1503 *
1504 * @param peer The peer we received a new time value from.
1505 * @param monotime Time value we check against the last time value we received from a peer.
1506 * @return GNUNET_YES if monotime is newer than the last received time value, GNUNET_NO if monotime is not newer.
1507 */
1508int
1509GCP_check_and_update_monotime (struct CadetPeer *peer,
1510 struct GNUNET_TIME_AbsoluteNBO monotime)
1511{
1512
1513 struct GNUNET_TIME_Absolute mt = GNUNET_TIME_absolute_ntoh (monotime);
1514
1515 if (mt.abs_value_us > *(&peer->last_connection_create.abs_value_us))
1516 {
1517 peer->last_connection_create = mt;
1518 return GNUNET_YES;
1519 }
1520 return GNUNET_NO;
1521}
1522
1523
1524/**
1525 * Checking the signature for a monotime of a GNUNET_CADET_ConnectionCreateMessage.
1526 *
1527 * @param peer The peer that signed the monotime value.
1528 * @param msg The GNUNET_CADET_ConnectionCreateMessage with the monotime value.
1529 * @return GNUNET_OK if the signature is good, GNUNET_SYSERR if not.
1530 */
1531int
1532GCP_check_monotime_sig (struct CadetPeer *peer,
1533 const struct GNUNET_CADET_ConnectionCreateMessage *msg)
1534{
1535 struct CadetConnectionCreatePS cp = { .purpose.purpose = htonl (
1536 GNUNET_SIGNATURE_PURPOSE_CADET_CONNECTION_INITIATOR),
1537 .purpose.size = htonl (sizeof(cp)),
1538 .monotonic_time = msg->monotime};
1539
1540 if (GNUNET_OK !=
1541 GNUNET_CRYPTO_eddsa_verify (
1542 GNUNET_SIGNATURE_PURPOSE_CADET_CONNECTION_INITIATOR,
1543 &cp,
1544 &msg->monotime_sig,
1545 &peer->pid.public_key))
1546 {
1547 GNUNET_break_op (0);
1548 return GNUNET_SYSERR;
1549 }
1550 return GNUNET_OK;
1551}
1552
1553
1554/* end of gnunet-service-cadet-new_peer.c */
diff --git a/src/service/cadet/gnunet-service-cadet_peer.h b/src/service/cadet/gnunet-service-cadet_peer.h
new file mode 100644
index 000000000..4c5ad4252
--- /dev/null
+++ b/src/service/cadet/gnunet-service-cadet_peer.h
@@ -0,0 +1,433 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2001-2017 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file cadet/gnunet-service-cadet_peer.h
23 * @brief Information we track per peer.
24 * @author Bartlomiej Polot
25 * @author Christian Grothoff
26 */
27#ifndef GNUNET_SERVICE_CADET_PEER_H
28#define GNUNET_SERVICE_CADET_PEER_H
29
30#include "gnunet-service-cadet.h"
31#include "gnunet_util_lib.h"
32
33
34/**
35 * Get the static string for a peer ID.
36 *
37 * @param peer Peer.
38 *
39 * @return Static string for it's ID.
40 */
41const char *
42GCP_2s (const struct CadetPeer *peer);
43
44
45/**
46 * Retrieve the CadetPeer structure associated with the
47 * peer. Optionally create one and insert it in the appropriate
48 * structures if the peer is not known yet.
49 *
50 * @param peer_id Full identity of the peer.
51 * @param create #GNUNET_YES if a new peer should be created if unknown.
52 * #GNUNET_NO to return NULL if peer is unknown.
53 * @return Existing or newly created peer structure.
54 * NULL if unknown and not requested @a create
55 */
56struct CadetPeer *
57GCP_get (const struct GNUNET_PeerIdentity *peer_id,
58 int create);
59
60
61/**
62 * Calculate how desirable a path is for @a cp if
63 * @a cp is at offset @a off in the path.
64 *
65 * The 'desirability_table.c' program can be used to compute a list of
66 * sample outputs for different scenarios. Basically, we score paths
67 * lower if there are many alternatives, and higher if they are
68 * shorter than average, and very high if they are much shorter than
69 * average and without many alternatives.
70 *
71 * @param cp a peer reachable via a path
72 * @param off offset of @a cp in a path
73 * @return score how useful a path is to reach @a cp,
74 * positive scores mean path is more desirable
75 */
76double
77GCP_get_desirability_of_path (struct CadetPeer *cp,
78 unsigned int off);
79
80
81/**
82 * Obtain the peer identity for a `struct CadetPeer`.
83 *
84 * @param cp our peer handle
85 * @return the peer identity
86 */
87const struct GNUNET_PeerIdentity *
88GCP_get_id (struct CadetPeer *cp);
89
90
91/**
92 * Iterate over all known peers.
93 *
94 * @param iter Iterator.
95 * @param cls Closure for @c iter.
96 */
97void
98GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter,
99 void *cls);
100
101
102/**
103 * Count the number of known paths toward the peer.
104 *
105 * @param cp Peer to get path info.
106 * @return Number of known paths.
107 */
108unsigned int
109GCP_count_paths (const struct CadetPeer *cp);
110
111
112/**
113 * Drop all paths owned by this peer, and do not
114 * allow new ones to be added: We are shutting down.
115 *
116 * @param cp peer to drop paths to
117 */
118void
119GCP_drop_owned_paths (struct CadetPeer *cp);
120
121
122/**
123 * Peer path iterator.
124 *
125 * @param cls Closure.
126 * @param path Path itself
127 * @param off offset of the target peer in @a path
128 * @return #GNUNET_YES if should keep iterating.
129 * #GNUNET_NO otherwise.
130 */
131typedef int
132(*GCP_PathIterator) (void *cls,
133 struct CadetPeerPath *path,
134 unsigned int off);
135
136
137/**
138 * Iterate over the paths to a peer.
139 *
140 * @param cp Peer to get path info.
141 * @param callback Function to call for every path.
142 * @param callback_cls Closure for @a callback.
143 * @return Number of iterated paths.
144 */
145unsigned int
146GCP_iterate_paths (struct CadetPeer *cp,
147 GCP_PathIterator callback,
148 void *callback_cls);
149
150/**
151 * Iterate over the paths to a peer without direct link.
152 *
153 * @param cp Peer to get path info.
154 * @param callback Function to call for every path.
155 * @param callback_cls Closure for @a callback.
156 * @return Number of iterated paths.
157 */
158unsigned int
159GCP_iterate_indirect_paths (struct CadetPeer *cp,
160 GCP_PathIterator callback,
161 void *callback_cls);
162
163
164/**
165 * Iterate over the paths to @a peer where
166 * @a peer is at distance @a dist from us.
167 *
168 * @param cp Peer to get path info.
169 * @param dist desired distance of @a peer to us on the path
170 * @param callback Function to call for every path.
171 * @param callback_cls Closure for @a callback.
172 * @return Number of iterated paths.
173 */
174unsigned int
175GCP_iterate_paths_at (struct CadetPeer *cp,
176 unsigned int dist,
177 GCP_PathIterator callback,
178 void *callback_cls);
179
180
181/**
182 * Remove an entry from the DLL of all of the paths that this peer is on.
183 *
184 * @param cp peer to modify
185 * @param entry an entry on a path
186 * @param off offset of this peer on the path
187 */
188void
189GCP_path_entry_remove (struct CadetPeer *cp,
190 struct CadetPeerPathEntry *entry,
191 unsigned int off);
192
193
194/**
195 * Add an entry to the DLL of all of the paths that this peer is on.
196 *
197 * @param cp peer to modify
198 * @param entry an entry on a path
199 * @param off offset of this peer on the path
200 */
201void
202GCP_path_entry_add (struct CadetPeer *cp,
203 struct CadetPeerPathEntry *entry,
204 unsigned int off);
205
206
207/**
208 * Get the tunnel towards a peer.
209 *
210 * @param cp Peer to get from.
211 * @param create #GNUNET_YES to create a tunnel if we do not have one
212 * @return Tunnel towards peer.
213 */
214struct CadetTunnel *
215GCP_get_tunnel (struct CadetPeer *cp,
216 int create);
217
218
219/**
220 * The tunnel to the given peer no longer exists, remove it from our
221 * data structures, and possibly clean up the peer itself.
222 *
223 * @param cp the peer affected
224 * @param t the dead tunnel
225 */
226void
227GCP_drop_tunnel (struct CadetPeer *cp,
228 struct CadetTunnel *t);
229
230
231/**
232 * Try adding a @a path to this @a cp. If the peer already
233 * has plenty of paths, return NULL.
234 *
235 * @param cp peer to which the @a path leads to
236 * @param path a path looking for an owner; may not be fully initialized yet!
237 * @param off offset of @a cp in @a path
238 * @param force force attaching the path
239 * @return NULL if this peer does not care to become a new owner,
240 * otherwise the node in the peer's path heap for the @a path.
241 */
242struct GNUNET_CONTAINER_HeapNode *
243GCP_attach_path (struct CadetPeer *cp,
244 struct CadetPeerPath *path,
245 unsigned int off,
246 int force);
247
248
249/**
250 * This peer can no longer own @a path as the path
251 * has been extended and a peer further down the line
252 * is now the new owner.
253 *
254 * @param cp old owner of the @a path
255 * @param path path where the ownership is lost
256 * @param hn note in @a cp's path heap that must be deleted
257 */
258void
259GCP_detach_path (struct CadetPeer *cp,
260 struct CadetPeerPath *path,
261 struct GNUNET_CONTAINER_HeapNode *hn);
262
263
264/**
265 * Add a @a connection to this @a cp.
266 *
267 * @param cp peer via which the @a connection goes
268 * @param cc the connection to add
269 */
270void
271GCP_add_connection (struct CadetPeer *cp,
272 struct CadetConnection *cc);
273
274
275/**
276 * Remove a @a connection that went via this @a cp.
277 *
278 * @param cp peer via which the @a connection went
279 * @param cc the connection to remove
280 */
281void
282GCP_remove_connection (struct CadetPeer *cp,
283 struct CadetConnection *cc);
284
285
286/**
287 * We got a HELLO for a @a cp, remember it, and possibly
288 * trigger adequate actions (like trying to connect).
289 *
290 * @param cp the peer we got a HELLO for
291 * @param hello the HELLO to remember
292 */
293void
294GCP_set_hello (struct CadetPeer *cp,
295 const struct GNUNET_MessageHeader *hello);
296
297
298/**
299 * Clean up all entries about all peers.
300 * Must only be called after all tunnels, CORE-connections and
301 * connections are down.
302 */
303void
304GCP_destroy_all_peers (void);
305
306
307/**
308 * Data structure used to track whom we have to notify about changes
309 * in our ability to transmit to a given peer.
310 *
311 * All queue managers will be given equal chance for sending messages
312 * to @a cp. This construct this guarantees fairness for access to @a
313 * cp among the different message queues. Each connection or route
314 * will have its respective message queue managers for each direction.
315 */
316struct GCP_MessageQueueManager;
317
318
319/**
320 * Function to call with updated message queue object.
321 *
322 * @param cls closure
323 * @param available #GNUNET_YES if sending is now possible,
324 * #GNUNET_NO if sending is no longer possible
325 * #GNUNET_SYSERR if sending is no longer possible
326 * and the last envelope was discarded
327 */
328typedef void
329(*GCP_MessageQueueNotificationCallback)(void *cls,
330 int available);
331
332
333/**
334 * Start message queue change notifications. Will create a new slot
335 * to manage the message queue to the given @a cp.
336 *
337 * @param cp peer to notify for
338 * @param cb function to call if mq becomes available or unavailable
339 * @param cb_cls closure for @a cb
340 * @return handle to cancel request
341 */
342struct GCP_MessageQueueManager *
343GCP_request_mq (struct CadetPeer *cp,
344 GCP_MessageQueueNotificationCallback cb,
345 void *cb_cls);
346
347
348/**
349 * Test if @a cp has a core-level connection
350 *
351 * @param cp peer to test
352 * @return #GNUNET_YES if @a cp has a core-level connection
353 */
354int
355GCP_has_core_connection (struct CadetPeer *cp);
356
357
358/**
359 * Send the message in @a env via a @a mqm. Must only be called at
360 * most once after the respective
361 * #GCP_MessageQueueNotificationCallback was called with `available`
362 * set to #GNUNET_YES, and not after the callback was called with
363 * `available` set to #GNUNET_NO or #GNUNET_SYSERR.
364 *
365 * @param mqm message queue manager for the transmission
366 * @param env envelope with the message to send; must NOT
367 * yet have a #GNUNET_MQ_notify_sent() callback attached to it
368 */
369void
370GCP_send (struct GCP_MessageQueueManager *mqm,
371 struct GNUNET_MQ_Envelope *env);
372
373
374/**
375 * Send the message in @a env to @a cp, overriding queueing logic.
376 * This function should only be used to send error messages outside
377 * of flow and congestion control, similar to ICMP. Note that
378 * the envelope may be silently discarded as well.
379 *
380 * @param cp peer to send the message to
381 * @param env envelope with the message to send
382 */
383void
384GCP_send_ooo (struct CadetPeer *cp,
385 struct GNUNET_MQ_Envelope *env);
386
387
388/**
389 * Stops message queue change notifications and sends a last message.
390 * In practice, this is implemented by sending that @a last_env
391 * message immediately (if any), ignoring queue order.
392 *
393 * @param mqm handle matching request to cancel
394 * @param last_env final message to transmit, or NULL
395 */
396void
397GCP_request_mq_cancel (struct GCP_MessageQueueManager *mqm,
398 struct GNUNET_MQ_Envelope *last_env);
399
400
401/**
402 * Set the message queue to @a mq for peer @a cp and notify watchers.
403 *
404 * @param cp peer to modify
405 * @param mq message queue to set (can be NULL)
406 */
407void
408GCP_set_mq (struct CadetPeer *cp,
409 struct GNUNET_MQ_Handle *mq);
410
411/**
412 * Checking the signature for a monotime of a GNUNET_CADET_ConnectionCreateMessage.
413 *
414 * @param peer The peer that signed the monotime value.
415 * @param msg The GNUNET_CADET_ConnectionCreateMessage with the monotime value.
416 * @return GNUNET_OK if the signature is good, GNUNET_SYSERR if not.
417 */
418int
419GCP_check_monotime_sig (struct CadetPeer *peer, const struct
420 GNUNET_CADET_ConnectionCreateMessage *msg);
421
422/**
423 * Checking if a monotime value is newer than the last monotime value received from a peer. If the time value is newer it will be stored at the peer.
424 *
425 * @param peer The peer we received a new time value from.
426 * @param monotime Time value we check against the last time value we received from a peer.
427 * @return GNUNET_YES if monotime is newer than the last received time value, GNUNET_NO if monotime is not newer.
428 */
429int
430GCP_check_and_update_monotime (struct CadetPeer *peer,
431 struct GNUNET_TIME_AbsoluteNBO monotime);
432
433#endif
diff --git a/src/service/cadet/gnunet-service-cadet_tunnels.c b/src/service/cadet/gnunet-service-cadet_tunnels.c
new file mode 100644
index 000000000..c7e422926
--- /dev/null
+++ b/src/service/cadet/gnunet-service-cadet_tunnels.c
@@ -0,0 +1,3668 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2013, 2017, 2018 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file cadet/gnunet-service-cadet_tunnels.c
22 * @brief Information we track per tunnel.
23 * @author Bartlomiej Polot
24 * @author Christian Grothoff
25 *
26 * FIXME:
27 * - proper connection evaluation during connection management:
28 * + consider quality (or quality spread?) of current connection set
29 * when deciding how often to do maintenance
30 * + interact with PEER to drive DHT GET/PUT operations based
31 * on how much we like our connections
32 */
33#include "platform.h"
34#include "gnunet_util_lib.h"
35#include "gnunet_statistics_service.h"
36#include "gnunet_signatures.h"
37#include "cadet_protocol.h"
38#include "gnunet-service-cadet_channel.h"
39#include "gnunet-service-cadet_connection.h"
40#include "gnunet-service-cadet_tunnels.h"
41#include "gnunet-service-cadet_peer.h"
42#include "gnunet-service-cadet_paths.h"
43
44
45#define LOG(level, ...) GNUNET_log_from (level, "cadet-tun", __VA_ARGS__)
46
47/**
48 * How often do we try to decrypt payload with unverified key
49 * material? Used to limit CPU increase upon receiving bogus
50 * KX.
51 */
52#define MAX_UNVERIFIED_ATTEMPTS 16
53
54/**
55 * How long do we wait until tearing down an idle tunnel?
56 */
57#define IDLE_DESTROY_DELAY GNUNET_TIME_relative_multiply ( \
58 GNUNET_TIME_UNIT_SECONDS, 90)
59
60/**
61 * How long do we wait initially before retransmitting the KX?
62 * TODO: replace by 2 RTT if/once we have connection-level RTT data!
63 */
64#define INITIAL_KX_RETRY_DELAY GNUNET_TIME_relative_multiply ( \
65 GNUNET_TIME_UNIT_MILLISECONDS, 250)
66
67/**
68 * Maximum number of skipped keys we keep in memory per tunnel.
69 */
70#define MAX_SKIPPED_KEYS 64
71
72/**
73 * Maximum number of keys (and thus ratchet steps) we are willing to
74 * skip before we decide this is either a bogus packet or a DoS-attempt.
75 */
76#define MAX_KEY_GAP 256
77
78
79/**
80 * Struct to old keys for skipped messages while advancing the Axolotl ratchet.
81 */
82struct CadetTunnelSkippedKey
83{
84 /**
85 * DLL next.
86 */
87 struct CadetTunnelSkippedKey *next;
88
89 /**
90 * DLL prev.
91 */
92 struct CadetTunnelSkippedKey *prev;
93
94 /**
95 * When was this key stored (for timeout).
96 */
97 struct GNUNET_TIME_Absolute timestamp;
98
99 /**
100 * Header key.
101 */
102 struct GNUNET_CRYPTO_SymmetricSessionKey HK;
103
104 /**
105 * Message key.
106 */
107 struct GNUNET_CRYPTO_SymmetricSessionKey MK;
108
109 /**
110 * Key number for a given HK.
111 */
112 unsigned int Kn;
113};
114
115
116/**
117 * Axolotl data, according to https://github.com/trevp/axolotl/wiki .
118 */
119struct CadetTunnelAxolotl
120{
121 /**
122 * A (double linked) list of stored message keys and associated header keys
123 * for "skipped" messages, i.e. messages that have not been
124 * received despite the reception of more recent messages, (head).
125 */
126 struct CadetTunnelSkippedKey *skipped_head;
127
128 /**
129 * Skipped messages' keys DLL, tail.
130 */
131 struct CadetTunnelSkippedKey *skipped_tail;
132
133 /**
134 * 32-byte root key which gets updated by DH ratchet.
135 */
136 struct GNUNET_CRYPTO_SymmetricSessionKey RK;
137
138 /**
139 * 32-byte header key (currently used for sending).
140 */
141 struct GNUNET_CRYPTO_SymmetricSessionKey HKs;
142
143 /**
144 * 32-byte header key (currently used for receiving)
145 */
146 struct GNUNET_CRYPTO_SymmetricSessionKey HKr;
147
148 /**
149 * 32-byte next header key (for sending), used once the
150 * ratchet advances. We are sure that the sender has this
151 * key as well only after @e ratchet_allowed is #GNUNET_YES.
152 */
153 struct GNUNET_CRYPTO_SymmetricSessionKey NHKs;
154
155 /**
156 * 32-byte next header key (for receiving). To be tried
157 * when decrypting with @e HKr fails and thus the sender
158 * may have advanced the ratchet.
159 */
160 struct GNUNET_CRYPTO_SymmetricSessionKey NHKr;
161
162 /**
163 * 32-byte chain keys (used for forward-secrecy) for
164 * sending messages. Updated for every message.
165 */
166 struct GNUNET_CRYPTO_SymmetricSessionKey CKs;
167
168 /**
169 * 32-byte chain keys (used for forward-secrecy) for
170 * receiving messages. Updated for every message. If
171 * messages are skipped, the respective derived MKs
172 * (and the current @e HKr) are kept in the @e skipped_head DLL.
173 */
174 struct GNUNET_CRYPTO_SymmetricSessionKey CKr;
175
176 /**
177 * ECDH for key exchange (A0 / B0).
178 */
179 struct GNUNET_CRYPTO_EcdhePrivateKey kx_0;
180
181 /**
182 * ECDH Ratchet key (our private key in the current DH).
183 */
184 struct GNUNET_CRYPTO_EcdhePrivateKey DHRs;
185
186 /**
187 * ECDH Ratchet key (other peer's public key in the current DH).
188 */
189 struct GNUNET_CRYPTO_EcdhePublicKey DHRr;
190
191 /**
192 * Last ephemeral public key received from the other peer,
193 * for duplicate detection.
194 */
195 struct GNUNET_CRYPTO_EcdhePublicKey last_ephemeral;
196
197 /**
198 * Time when the current ratchet expires and a new one is triggered
199 * (if @e ratchet_allowed is #GNUNET_YES).
200 */
201 struct GNUNET_TIME_Absolute ratchet_expiration;
202
203 /**
204 * Number of elements in @a skipped_head <-> @a skipped_tail.
205 */
206 unsigned int skipped;
207
208 /**
209 * Message number (reset to 0 with each new ratchet, next message to send).
210 */
211 uint32_t Ns;
212
213 /**
214 * Message number (reset to 0 with each new ratchet, next message to recv).
215 */
216 uint32_t Nr;
217
218 /**
219 * Previous message numbers (# of msgs sent under prev ratchet)
220 */
221 uint32_t PNs;
222
223 /**
224 * True (#GNUNET_YES) if we have to send a new ratchet key in next msg.
225 */
226 int ratchet_flag;
227
228 /**
229 * True (#GNUNET_YES) if we have received a message from the
230 * other peer that uses the keys from our last ratchet step.
231 * This implies that we are again allowed to advance the ratchet,
232 * otherwise we have to wait until the other peer sees our current
233 * ephemeral key and advances first.
234 *
235 * #GNUNET_NO if we have advanced the ratched but lack any evidence
236 * that the other peer has noticed this.
237 */
238 int ratchet_allowed;
239
240 /**
241 * Number of messages received since our last ratchet advance.
242 *
243 * If this counter = 0, we cannot send a new ratchet key in the next
244 * message.
245 *
246 * If this counter > 0, we could (but don't have to) send a new key.
247 *
248 * Once the @e ratchet_counter is larger than
249 * #ratchet_messages (or @e ratchet_expiration time has past), and
250 * @e ratchet_allowed is #GNUNET_YES, we advance the ratchet.
251 */
252 unsigned int ratchet_counter;
253};
254
255
256/**
257 * Struct used to save messages in a non-ready tunnel to send once connected.
258 */
259struct CadetTunnelQueueEntry
260{
261 /**
262 * We are entries in a DLL
263 */
264 struct CadetTunnelQueueEntry *next;
265
266 /**
267 * We are entries in a DLL
268 */
269 struct CadetTunnelQueueEntry *prev;
270
271 /**
272 * Tunnel these messages belong in.
273 */
274 struct CadetTunnel *t;
275
276 /**
277 * Continuation to call once sent (on the channel layer).
278 */
279 GCT_SendContinuation cont;
280
281 /**
282 * Closure for @c cont.
283 */
284 void *cont_cls;
285
286 /**
287 * Envelope of message to send follows.
288 */
289 struct GNUNET_MQ_Envelope *env;
290
291 /**
292 * Where to put the connection identifier into the payload
293 * of the message in @e env once we have it?
294 */
295 struct GNUNET_CADET_ConnectionTunnelIdentifier *cid;
296};
297
298
299/**
300 * Struct containing all information regarding a tunnel to a peer.
301 */
302struct CadetTunnel
303{
304 /**
305 * Destination of the tunnel.
306 */
307 struct CadetPeer *destination;
308
309 /**
310 * Peer's ephemeral key, to recreate @c e_key and @c d_key when own
311 * ephemeral key changes.
312 */
313 struct GNUNET_CRYPTO_EcdhePublicKey peers_ephemeral_key;
314
315 /**
316 * Encryption ("our") key. It is only "confirmed" if kx_ctx is NULL.
317 */
318 struct GNUNET_CRYPTO_SymmetricSessionKey e_key;
319
320 /**
321 * Decryption ("their") key. It is only "confirmed" if kx_ctx is NULL.
322 */
323 struct GNUNET_CRYPTO_SymmetricSessionKey d_key;
324
325 /**
326 * Axolotl info.
327 */
328 struct CadetTunnelAxolotl ax;
329
330 /**
331 * Unverified Axolotl info, used only if we got a fresh KX (not a
332 * KX_AUTH) while our end of the tunnel was still up. In this case,
333 * we keep the fresh KX around but do not put it into action until
334 * we got encrypted payload that assures us of the authenticity of
335 * the KX.
336 */
337 struct CadetTunnelAxolotl *unverified_ax;
338
339 /**
340 * Task scheduled if there are no more channels using the tunnel.
341 */
342 struct GNUNET_SCHEDULER_Task *destroy_task;
343
344 /**
345 * Task to trim connections if too many are present.
346 */
347 struct GNUNET_SCHEDULER_Task *maintain_connections_task;
348
349 /**
350 * Task to send messages from queue (if possible).
351 */
352 struct GNUNET_SCHEDULER_Task *send_task;
353
354 /**
355 * Task to trigger KX.
356 */
357 struct GNUNET_SCHEDULER_Task *kx_task;
358
359 /**
360 * Tokenizer for decrypted messages.
361 */
362 struct GNUNET_MessageStreamTokenizer *mst;
363
364 /**
365 * Dispatcher for decrypted messages only (do NOT use for sending!).
366 */
367 struct GNUNET_MQ_Handle *mq;
368
369 /**
370 * DLL of ready connections that are actively used to reach the destination peer.
371 */
372 struct CadetTConnection *connection_ready_head;
373
374 /**
375 * DLL of ready connections that are actively used to reach the destination peer.
376 */
377 struct CadetTConnection *connection_ready_tail;
378
379 /**
380 * DLL of connections that we maintain that might be used to reach the destination peer.
381 */
382 struct CadetTConnection *connection_busy_head;
383
384 /**
385 * DLL of connections that we maintain that might be used to reach the destination peer.
386 */
387 struct CadetTConnection *connection_busy_tail;
388
389 /**
390 * Channels inside this tunnel. Maps
391 * `struct GNUNET_CADET_ChannelTunnelNumber` to a `struct CadetChannel`.
392 */
393 struct GNUNET_CONTAINER_MultiHashMap32 *channels;
394
395 /**
396 * Channel ID for the next created channel in this tunnel.
397 */
398 struct GNUNET_CADET_ChannelTunnelNumber next_ctn;
399
400 /**
401 * Queued messages, to transmit once tunnel gets connected.
402 */
403 struct CadetTunnelQueueEntry *tq_head;
404
405 /**
406 * Queued messages, to transmit once tunnel gets connected.
407 */
408 struct CadetTunnelQueueEntry *tq_tail;
409
410 /**
411 * Identification of the connection from which we are currently processing
412 * a message. Only valid (non-NULL) during #handle_decrypted() and the
413 * handle-*()-functions called from our @e mq during that function.
414 */
415 struct CadetTConnection *current_ct;
416
417 /**
418 * How long do we wait until we retry the KX?
419 */
420 struct GNUNET_TIME_Relative kx_retry_delay;
421
422 /**
423 * When do we try the next KX?
424 */
425 struct GNUNET_TIME_Absolute next_kx_attempt;
426
427 /**
428 * Number of connections in the @e connection_ready_head DLL.
429 */
430 unsigned int num_ready_connections;
431
432 /**
433 * Number of connections in the @e connection_busy_head DLL.
434 */
435 unsigned int num_busy_connections;
436
437 /**
438 * How often have we tried and failed to decrypt a message using
439 * the unverified KX material from @e unverified_ax? Used to
440 * stop trying after #MAX_UNVERIFIED_ATTEMPTS.
441 */
442 unsigned int unverified_attempts;
443
444 /**
445 * Number of entries in the @e tq_head DLL.
446 */
447 unsigned int tq_len;
448
449 /**
450 * State of the tunnel encryption.
451 */
452 enum CadetTunnelEState estate;
453
454 /**
455 * Force triggering KX_AUTH independent of @e estate.
456 */
457 int kx_auth_requested;
458};
459
460
461/**
462 * Am I Alice or Betty (some call her Bob), or talking to myself?
463 *
464 * @param other the other peer
465 * @return #GNUNET_YES for Alice, #GNUNET_NO for Betty, #GNUNET_SYSERR if talking to myself
466 */
467int
468GCT_alice_or_betty (const struct GNUNET_PeerIdentity *other)
469{
470 if (0 > GNUNET_memcmp (&my_full_id,
471 other))
472 return GNUNET_YES;
473 else if (0 < GNUNET_memcmp (&my_full_id,
474 other))
475 return GNUNET_NO;
476 else
477 {
478 GNUNET_break_op (0);
479 return GNUNET_SYSERR;
480 }
481}
482
483
484/**
485 * Connection @a ct is now unready, clear it's ready flag
486 * and move it from the ready DLL to the busy DLL.
487 *
488 * @param ct connection to move to unready status
489 */
490static void
491mark_connection_unready (struct CadetTConnection *ct)
492{
493 struct CadetTunnel *t = ct->t;
494
495 GNUNET_assert (GNUNET_YES == ct->is_ready);
496 GNUNET_CONTAINER_DLL_remove (t->connection_ready_head,
497 t->connection_ready_tail,
498 ct);
499 GNUNET_assert (0 < t->num_ready_connections);
500 t->num_ready_connections--;
501 ct->is_ready = GNUNET_NO;
502 GNUNET_CONTAINER_DLL_insert (t->connection_busy_head,
503 t->connection_busy_tail,
504 ct);
505 t->num_busy_connections++;
506}
507
508
509/**
510 * Get the static string for the peer this tunnel is directed.
511 *
512 * @param t Tunnel.
513 *
514 * @return Static string the destination peer's ID.
515 */
516const char *
517GCT_2s (const struct CadetTunnel *t)
518{
519 static char buf[64];
520
521 if (NULL == t)
522 return "Tunnel(NULL)";
523 GNUNET_snprintf (buf,
524 sizeof(buf),
525 "Tunnel %s",
526 GNUNET_i2s (GCP_get_id (t->destination)));
527 return buf;
528}
529
530
531/**
532 * Get string description for tunnel encryption state.
533 *
534 * @param es Tunnel state.
535 *
536 * @return String representation.
537 */
538static const char *
539estate2s (enum CadetTunnelEState es)
540{
541 static char buf[32];
542
543 switch (es)
544 {
545 case CADET_TUNNEL_KEY_UNINITIALIZED:
546 return "CADET_TUNNEL_KEY_UNINITIALIZED";
547 case CADET_TUNNEL_KEY_AX_RECV:
548 return "CADET_TUNNEL_KEY_AX_RECV";
549 case CADET_TUNNEL_KEY_AX_SENT:
550 return "CADET_TUNNEL_KEY_AX_SENT";
551 case CADET_TUNNEL_KEY_AX_SENT_AND_RECV:
552 return "CADET_TUNNEL_KEY_AX_SENT_AND_RECV";
553 case CADET_TUNNEL_KEY_AX_AUTH_SENT:
554 return "CADET_TUNNEL_KEY_AX_AUTH_SENT";
555 case CADET_TUNNEL_KEY_OK:
556 return "CADET_TUNNEL_KEY_OK";
557 }
558 GNUNET_snprintf (buf,
559 sizeof(buf),
560 "%u (UNKNOWN STATE)",
561 es);
562 return buf;
563}
564
565
566/**
567 * Return the peer to which this tunnel goes.
568 *
569 * @param t a tunnel
570 * @return the destination of the tunnel
571 */
572struct CadetPeer *
573GCT_get_destination (struct CadetTunnel *t)
574{
575 return t->destination;
576}
577
578
579unsigned int
580GCT_count_channels (struct CadetTunnel *t)
581{
582 return GNUNET_CONTAINER_multihashmap32_size (t->channels);
583}
584
585
586/**
587 * Lookup a channel by its @a ctn.
588 *
589 * @param t tunnel to look in
590 * @param ctn number of channel to find
591 * @return NULL if channel does not exist
592 */
593struct CadetChannel *
594lookup_channel (struct CadetTunnel *t,
595 struct GNUNET_CADET_ChannelTunnelNumber ctn)
596{
597 return GNUNET_CONTAINER_multihashmap32_get (t->channels,
598 ntohl (ctn.cn));
599}
600
601
602unsigned int
603GCT_count_any_connections (const struct CadetTunnel *t)
604{
605 return t->num_ready_connections + t->num_busy_connections;
606}
607
608
609/**
610 * Find first connection that is ready in the list of
611 * our connections. Picks ready connections round-robin.
612 *
613 * @param t tunnel to search
614 * @return NULL if we have no connection that is ready
615 */
616static struct CadetTConnection *
617get_ready_connection (struct CadetTunnel *t)
618{
619 struct CadetTConnection *hd = t->connection_ready_head;
620
621 GNUNET_assert ((NULL == hd) ||
622 (GNUNET_YES == hd->is_ready));
623 return hd;
624}
625
626
627/**
628 * Get the encryption state of a tunnel.
629 *
630 * @param t Tunnel.
631 *
632 * @return Tunnel's encryption state.
633 */
634enum CadetTunnelEState
635GCT_get_estate (struct CadetTunnel *t)
636{
637 return t->estate;
638}
639
640
641/**
642 * Called when either we have a new connection, or a new message in the
643 * queue, or some existing connection has transmission capacity. Looks
644 * at our message queue and if there is a message, picks a connection
645 * to send it on.
646 *
647 * @param cls the `struct CadetTunnel` to process messages on
648 */
649static void
650trigger_transmissions (void *cls);
651
652
653/* ************************************** start core crypto ***************************** */
654
655
656/**
657 * Create a new Axolotl ephemeral (ratchet) key.
658 *
659 * @param ax key material to update
660 */
661static void
662new_ephemeral (struct CadetTunnelAxolotl *ax)
663{
664 LOG (GNUNET_ERROR_TYPE_DEBUG,
665 "Creating new ephemeral ratchet key (DHRs)\n");
666 GNUNET_CRYPTO_ecdhe_key_create (&ax->DHRs);
667}
668
669
670/**
671 * Calculate HMAC.
672 *
673 * @param plaintext Content to HMAC.
674 * @param size Size of @c plaintext.
675 * @param iv Initialization vector for the message.
676 * @param key Key to use.
677 * @param[out] hmac Destination to store the HMAC.
678 */
679static void
680t_hmac (const void *plaintext,
681 size_t size,
682 uint32_t iv,
683 const struct GNUNET_CRYPTO_SymmetricSessionKey *key,
684 struct GNUNET_ShortHashCode *hmac)
685{
686 static const char ctx[] = "cadet authentication key";
687 struct GNUNET_CRYPTO_AuthKey auth_key;
688 struct GNUNET_HashCode hash;
689
690 GNUNET_CRYPTO_hmac_derive_key (&auth_key,
691 key,
692 &iv, sizeof(iv),
693 key, sizeof(*key),
694 ctx, sizeof(ctx),
695 NULL);
696 /* Two step: GNUNET_ShortHash is only 256 bits,
697 GNUNET_HashCode is 512, so we truncate. */
698 GNUNET_CRYPTO_hmac (&auth_key,
699 plaintext,
700 size,
701 &hash);
702 GNUNET_memcpy (hmac,
703 &hash,
704 sizeof(*hmac));
705}
706
707
708/**
709 * Perform a HMAC.
710 *
711 * @param key Key to use.
712 * @param[out] hash Resulting HMAC.
713 * @param source Source key material (data to HMAC).
714 * @param len Length of @a source.
715 */
716static void
717t_ax_hmac_hash (const struct GNUNET_CRYPTO_SymmetricSessionKey *key,
718 struct GNUNET_HashCode *hash,
719 const void *source,
720 unsigned int len)
721{
722 static const char ctx[] = "axolotl HMAC-HASH";
723 struct GNUNET_CRYPTO_AuthKey auth_key;
724
725 GNUNET_CRYPTO_hmac_derive_key (&auth_key,
726 key,
727 ctx, sizeof(ctx),
728 NULL);
729 GNUNET_CRYPTO_hmac (&auth_key,
730 source,
731 len,
732 hash);
733}
734
735
736/**
737 * Derive a symmetric encryption key from an HMAC-HASH.
738 *
739 * @param key Key to use for the HMAC.
740 * @param[out] out Key to generate.
741 * @param source Source key material (data to HMAC).
742 * @param len Length of @a source.
743 */
744static void
745t_hmac_derive_key (const struct GNUNET_CRYPTO_SymmetricSessionKey *key,
746 struct GNUNET_CRYPTO_SymmetricSessionKey *out,
747 const void *source,
748 unsigned int len)
749{
750 static const char ctx[] = "axolotl derive key";
751 struct GNUNET_HashCode h;
752
753 t_ax_hmac_hash (key,
754 &h,
755 source,
756 len);
757 GNUNET_CRYPTO_kdf (out, sizeof(*out),
758 ctx, sizeof(ctx),
759 &h, sizeof(h),
760 NULL);
761}
762
763
764/**
765 * Encrypt data with the axolotl tunnel key.
766 *
767 * @param ax key material to use.
768 * @param dst Destination with @a size bytes for the encrypted data.
769 * @param src Source of the plaintext. Can overlap with @c dst, must contain @a size bytes
770 * @param size Size of the buffers at @a src and @a dst
771 */
772static void
773t_ax_encrypt (struct CadetTunnelAxolotl *ax,
774 void *dst,
775 const void *src,
776 size_t size)
777{
778 struct GNUNET_CRYPTO_SymmetricSessionKey MK;
779 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
780 size_t out_size;
781
782 ax->ratchet_counter++;
783 if ((GNUNET_YES == ax->ratchet_allowed) &&
784 ((ratchet_messages <= ax->ratchet_counter) ||
785 (0 == GNUNET_TIME_absolute_get_remaining (
786 ax->ratchet_expiration).rel_value_us)))
787 {
788 ax->ratchet_flag = GNUNET_YES;
789 }
790 if (GNUNET_YES == ax->ratchet_flag)
791 {
792 /* Advance ratchet */
793 struct GNUNET_CRYPTO_SymmetricSessionKey keys[3];
794 struct GNUNET_HashCode dh;
795 struct GNUNET_HashCode hmac;
796 static const char ctx[] = "axolotl ratchet";
797
798 new_ephemeral (ax);
799 ax->HKs = ax->NHKs;
800
801 /* RK, NHKs, CKs = KDF( HMAC-HASH(RK, DH(DHRs, DHRr)) ) */
802 GNUNET_CRYPTO_ecc_ecdh (&ax->DHRs,
803 &ax->DHRr,
804 &dh);
805 t_ax_hmac_hash (&ax->RK,
806 &hmac,
807 &dh,
808 sizeof(dh));
809 GNUNET_CRYPTO_kdf (keys, sizeof(keys),
810 ctx, sizeof(ctx),
811 &hmac, sizeof(hmac),
812 NULL);
813 ax->RK = keys[0];
814 ax->NHKs = keys[1];
815 ax->CKs = keys[2];
816
817 ax->PNs = ax->Ns;
818 ax->Ns = 0;
819 ax->ratchet_flag = GNUNET_NO;
820 ax->ratchet_allowed = GNUNET_NO;
821 ax->ratchet_counter = 0;
822 ax->ratchet_expiration
823 = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
824 ratchet_time);
825 }
826
827 t_hmac_derive_key (&ax->CKs,
828 &MK,
829 "0",
830 1);
831 GNUNET_CRYPTO_symmetric_derive_iv (&iv,
832 &MK,
833 NULL, 0,
834 NULL);
835
836 out_size = GNUNET_CRYPTO_symmetric_encrypt (src,
837 size,
838 &MK,
839 &iv,
840 dst);
841 GNUNET_assert (size == out_size);
842 t_hmac_derive_key (&ax->CKs,
843 &ax->CKs,
844 "1",
845 1);
846}
847
848
849/**
850 * Decrypt data with the axolotl tunnel key.
851 *
852 * @param ax key material to use.
853 * @param dst Destination for the decrypted data, must contain @a size bytes.
854 * @param src Source of the ciphertext. Can overlap with @c dst, must contain @a size bytes.
855 * @param size Size of the @a src and @a dst buffers
856 */
857static void
858t_ax_decrypt (struct CadetTunnelAxolotl *ax,
859 void *dst,
860 const void *src,
861 size_t size)
862{
863 struct GNUNET_CRYPTO_SymmetricSessionKey MK;
864 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
865 size_t out_size;
866
867 t_hmac_derive_key (&ax->CKr,
868 &MK,
869 "0",
870 1);
871 GNUNET_CRYPTO_symmetric_derive_iv (&iv,
872 &MK,
873 NULL, 0,
874 NULL);
875 GNUNET_assert (size >= sizeof(struct GNUNET_MessageHeader));
876 out_size = GNUNET_CRYPTO_symmetric_decrypt (src,
877 size,
878 &MK,
879 &iv,
880 dst);
881 GNUNET_assert (out_size == size);
882 t_hmac_derive_key (&ax->CKr,
883 &ax->CKr,
884 "1",
885 1);
886}
887
888
889/**
890 * Encrypt header with the axolotl header key.
891 *
892 * @param ax key material to use.
893 * @param[in,out] msg Message whose header to encrypt.
894 */
895static void
896t_h_encrypt (struct CadetTunnelAxolotl *ax,
897 struct GNUNET_CADET_TunnelEncryptedMessage *msg)
898{
899 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
900 size_t out_size;
901
902 GNUNET_CRYPTO_symmetric_derive_iv (&iv,
903 &ax->HKs,
904 NULL, 0,
905 NULL);
906 out_size = GNUNET_CRYPTO_symmetric_encrypt (&msg->ax_header,
907 sizeof(struct
908 GNUNET_CADET_AxHeader),
909 &ax->HKs,
910 &iv,
911 &msg->ax_header);
912 GNUNET_assert (sizeof(struct GNUNET_CADET_AxHeader) == out_size);
913}
914
915
916/**
917 * Decrypt header with the current axolotl header key.
918 *
919 * @param ax key material to use.
920 * @param src Message whose header to decrypt.
921 * @param dst Where to decrypt header to.
922 */
923static void
924t_h_decrypt (struct CadetTunnelAxolotl *ax,
925 const struct GNUNET_CADET_TunnelEncryptedMessage *src,
926 struct GNUNET_CADET_TunnelEncryptedMessage *dst)
927{
928 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
929 size_t out_size;
930
931 GNUNET_CRYPTO_symmetric_derive_iv (&iv,
932 &ax->HKr,
933 NULL, 0,
934 NULL);
935 out_size = GNUNET_CRYPTO_symmetric_decrypt (&src->ax_header.Ns,
936 sizeof(struct
937 GNUNET_CADET_AxHeader),
938 &ax->HKr,
939 &iv,
940 &dst->ax_header.Ns);
941 GNUNET_assert (sizeof(struct GNUNET_CADET_AxHeader) == out_size);
942}
943
944
945/**
946 * Delete a key from the list of skipped keys.
947 *
948 * @param ax key material to delete @a key from.
949 * @param key Key to delete.
950 */
951static void
952delete_skipped_key (struct CadetTunnelAxolotl *ax,
953 struct CadetTunnelSkippedKey *key)
954{
955 GNUNET_CONTAINER_DLL_remove (ax->skipped_head,
956 ax->skipped_tail,
957 key);
958 GNUNET_free (key);
959 ax->skipped--;
960}
961
962
963/**
964 * Decrypt and verify data with the appropriate tunnel key and verify that the
965 * data has not been altered since it was sent by the remote peer.
966 *
967 * @param ax key material to use.
968 * @param dst Destination for the plaintext.
969 * @param src Source of the message. Can overlap with @c dst.
970 * @param size Size of the message.
971 * @return Size of the decrypted data, -1 if an error was encountered.
972 */
973static ssize_t
974try_old_ax_keys (struct CadetTunnelAxolotl *ax,
975 void *dst,
976 const struct GNUNET_CADET_TunnelEncryptedMessage *src,
977 size_t size)
978{
979 struct CadetTunnelSkippedKey *key;
980 struct GNUNET_ShortHashCode *hmac;
981 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
982 struct GNUNET_CADET_TunnelEncryptedMessage plaintext_header;
983 struct GNUNET_CRYPTO_SymmetricSessionKey *valid_HK;
984 size_t esize;
985 size_t res;
986 size_t len;
987 unsigned int N;
988
989 LOG (GNUNET_ERROR_TYPE_DEBUG,
990 "Trying skipped keys\n");
991 hmac = &plaintext_header.hmac;
992 esize = size - sizeof(struct GNUNET_CADET_TunnelEncryptedMessage);
993
994 /* Find a correct Header Key */
995 valid_HK = NULL;
996 for (key = ax->skipped_head; NULL != key; key = key->next)
997 {
998 t_hmac (&src->ax_header,
999 sizeof(struct GNUNET_CADET_AxHeader) + esize,
1000 0,
1001 &key->HK,
1002 hmac);
1003 if (0 == GNUNET_memcmp (hmac,
1004 &src->hmac))
1005 {
1006 valid_HK = &key->HK;
1007 break;
1008 }
1009 }
1010 if (NULL == key)
1011 return -1;
1012
1013 /* Should've been checked in -cadet_connection.c handle_cadet_encrypted. */
1014 GNUNET_assert (size > sizeof(struct GNUNET_CADET_TunnelEncryptedMessage));
1015 len = size - sizeof(struct GNUNET_CADET_TunnelEncryptedMessage);
1016 GNUNET_assert (len >= sizeof(struct GNUNET_MessageHeader));
1017
1018 /* Decrypt header */
1019 GNUNET_CRYPTO_symmetric_derive_iv (&iv,
1020 &key->HK,
1021 NULL, 0,
1022 NULL);
1023 res = GNUNET_CRYPTO_symmetric_decrypt (&src->ax_header.Ns,
1024 sizeof(struct GNUNET_CADET_AxHeader),
1025 &key->HK,
1026 &iv,
1027 &plaintext_header.ax_header.Ns);
1028 GNUNET_assert (sizeof(struct GNUNET_CADET_AxHeader) == res);
1029
1030 /* Find the correct message key */
1031 N = ntohl (plaintext_header.ax_header.Ns);
1032 while ((NULL != key) &&
1033 (N != key->Kn))
1034 key = key->next;
1035 if ((NULL == key) ||
1036 (0 != GNUNET_memcmp (&key->HK,
1037 valid_HK)))
1038 return -1;
1039
1040 /* Decrypt payload */
1041 GNUNET_CRYPTO_symmetric_derive_iv (&iv,
1042 &key->MK,
1043 NULL,
1044 0,
1045 NULL);
1046 res = GNUNET_CRYPTO_symmetric_decrypt (&src[1],
1047 len,
1048 &key->MK,
1049 &iv,
1050 dst);
1051 delete_skipped_key (ax,
1052 key);
1053 return res;
1054}
1055
1056
1057/**
1058 * Delete a key from the list of skipped keys.
1059 *
1060 * @param ax key material to delete from.
1061 * @param HKr Header Key to use.
1062 */
1063static void
1064store_skipped_key (struct CadetTunnelAxolotl *ax,
1065 const struct GNUNET_CRYPTO_SymmetricSessionKey *HKr)
1066{
1067 struct CadetTunnelSkippedKey *key;
1068
1069 key = GNUNET_new (struct CadetTunnelSkippedKey);
1070 key->timestamp = GNUNET_TIME_absolute_get ();
1071 key->Kn = ax->Nr;
1072 key->HK = ax->HKr;
1073 t_hmac_derive_key (&ax->CKr,
1074 &key->MK,
1075 "0",
1076 1);
1077 t_hmac_derive_key (&ax->CKr,
1078 &ax->CKr,
1079 "1",
1080 1);
1081 GNUNET_CONTAINER_DLL_insert (ax->skipped_head,
1082 ax->skipped_tail,
1083 key);
1084 ax->skipped++;
1085 ax->Nr++;
1086}
1087
1088
1089/**
1090 * Stage skipped AX keys and calculate the message key.
1091 * Stores each HK and MK for skipped messages.
1092 *
1093 * @param ax key material to use
1094 * @param HKr Header key.
1095 * @param Np Received meesage number.
1096 * @return #GNUNET_OK if keys were stored.
1097 * #GNUNET_SYSERR if an error occurred (@a Np not expected).
1098 */
1099static int
1100store_ax_keys (struct CadetTunnelAxolotl *ax,
1101 const struct GNUNET_CRYPTO_SymmetricSessionKey *HKr,
1102 uint32_t Np)
1103{
1104 int gap;
1105
1106 gap = Np - ax->Nr;
1107 LOG (GNUNET_ERROR_TYPE_DEBUG,
1108 "Storing skipped keys [%u, %u)\n",
1109 ax->Nr,
1110 Np);
1111 if (MAX_KEY_GAP < gap)
1112 {
1113 /* Avoid DoS (forcing peer to do more than #MAX_KEY_GAP HMAC operations) */
1114 /* TODO: start new key exchange on return */
1115 GNUNET_break_op (0);
1116 LOG (GNUNET_ERROR_TYPE_WARNING,
1117 "Got message %u, expected %u+\n",
1118 Np,
1119 ax->Nr);
1120 return GNUNET_SYSERR;
1121 }
1122 if (0 > gap)
1123 {
1124 /* Delayed message: don't store keys, flag to try old keys. */
1125 return GNUNET_SYSERR;
1126 }
1127
1128 while (ax->Nr < Np)
1129 store_skipped_key (ax,
1130 HKr);
1131
1132 while (ax->skipped > MAX_SKIPPED_KEYS)
1133 delete_skipped_key (ax,
1134 ax->skipped_tail);
1135 return GNUNET_OK;
1136}
1137
1138
1139/**
1140 * Decrypt and verify data with the appropriate tunnel key and verify that the
1141 * data has not been altered since it was sent by the remote peer.
1142 *
1143 * @param ax key material to use
1144 * @param dst Destination for the plaintext.
1145 * @param src Source of the message. Can overlap with @c dst.
1146 * @param size Size of the message.
1147 * @return Size of the decrypted data, -1 if an error was encountered.
1148 */
1149static ssize_t
1150t_ax_decrypt_and_validate (struct CadetTunnelAxolotl *ax,
1151 void *dst,
1152 const struct
1153 GNUNET_CADET_TunnelEncryptedMessage *src,
1154 size_t size)
1155{
1156 struct GNUNET_ShortHashCode msg_hmac;
1157 struct GNUNET_HashCode hmac;
1158 struct GNUNET_CADET_TunnelEncryptedMessage plaintext_header;
1159 uint32_t Np;
1160 uint32_t PNp;
1161 size_t esize; /* Size of encryped payload */
1162
1163 esize = size - sizeof(struct GNUNET_CADET_TunnelEncryptedMessage);
1164
1165 /* Try current HK */
1166 t_hmac (&src->ax_header,
1167 sizeof(struct GNUNET_CADET_AxHeader) + esize,
1168 0, &ax->HKr,
1169 &msg_hmac);
1170 if (0 != GNUNET_memcmp (&msg_hmac,
1171 &src->hmac))
1172 {
1173 static const char ctx[] = "axolotl ratchet";
1174 struct GNUNET_CRYPTO_SymmetricSessionKey keys[3]; /* RKp, NHKp, CKp */
1175 struct GNUNET_CRYPTO_SymmetricSessionKey HK;
1176 struct GNUNET_HashCode dh;
1177 struct GNUNET_CRYPTO_EcdhePublicKey *DHRp;
1178
1179 /* Try Next HK */
1180 t_hmac (&src->ax_header,
1181 sizeof(struct GNUNET_CADET_AxHeader) + esize,
1182 0,
1183 &ax->NHKr,
1184 &msg_hmac);
1185 if (0 != GNUNET_memcmp (&msg_hmac,
1186 &src->hmac))
1187 {
1188 /* Try the skipped keys, if that fails, we're out of luck. */
1189 return try_old_ax_keys (ax,
1190 dst,
1191 src,
1192 size);
1193 }
1194 HK = ax->HKr;
1195 ax->HKr = ax->NHKr;
1196 t_h_decrypt (ax,
1197 src,
1198 &plaintext_header);
1199 Np = ntohl (plaintext_header.ax_header.Ns);
1200 PNp = ntohl (plaintext_header.ax_header.PNs);
1201 DHRp = &plaintext_header.ax_header.DHRs;
1202 store_ax_keys (ax,
1203 &HK,
1204 PNp);
1205
1206 /* RKp, NHKp, CKp = KDF (HMAC-HASH (RK, DH (DHRp, DHRs))) */
1207 GNUNET_CRYPTO_ecc_ecdh (&ax->DHRs,
1208 DHRp,
1209 &dh);
1210 t_ax_hmac_hash (&ax->RK,
1211 &hmac,
1212 &dh, sizeof(dh));
1213 GNUNET_CRYPTO_kdf (keys, sizeof(keys),
1214 ctx, sizeof(ctx),
1215 &hmac, sizeof(hmac),
1216 NULL);
1217
1218 /* Commit "purported" keys */
1219 ax->RK = keys[0];
1220 ax->NHKr = keys[1];
1221 ax->CKr = keys[2];
1222 ax->DHRr = *DHRp;
1223 ax->Nr = 0;
1224 ax->ratchet_allowed = GNUNET_YES;
1225 }
1226 else
1227 {
1228 t_h_decrypt (ax,
1229 src,
1230 &plaintext_header);
1231 Np = ntohl (plaintext_header.ax_header.Ns);
1232 PNp = ntohl (plaintext_header.ax_header.PNs);
1233 }
1234 if ((Np != ax->Nr) &&
1235 (GNUNET_OK != store_ax_keys (ax,
1236 &ax->HKr,
1237 Np)))
1238 {
1239 /* Try the skipped keys, if that fails, we're out of luck. */
1240 return try_old_ax_keys (ax,
1241 dst,
1242 src,
1243 size);
1244 }
1245
1246 t_ax_decrypt (ax,
1247 dst,
1248 &src[1],
1249 esize);
1250 ax->Nr = Np + 1;
1251 return esize;
1252}
1253
1254
1255/**
1256 * Our tunnel became ready for the first time, notify channels
1257 * that have been waiting.
1258 *
1259 * @param cls our tunnel, not used
1260 * @param key unique ID of the channel, not used
1261 * @param value the `struct CadetChannel` to notify
1262 * @return #GNUNET_OK (continue to iterate)
1263 */
1264static int
1265notify_tunnel_up_cb (void *cls,
1266 uint32_t key,
1267 void *value)
1268{
1269 struct CadetChannel *ch = value;
1270
1271 GCCH_tunnel_up (ch);
1272 return GNUNET_OK;
1273}
1274
1275
1276/**
1277 * Change the tunnel encryption state.
1278 * If the encryption state changes to OK, stop the rekey task.
1279 *
1280 * @param t Tunnel whose encryption state to change, or NULL.
1281 * @param state New encryption state.
1282 */
1283void
1284GCT_change_estate (struct CadetTunnel *t,
1285 enum CadetTunnelEState state)
1286{
1287 enum CadetTunnelEState old = t->estate;
1288
1289 t->estate = state;
1290 LOG (GNUNET_ERROR_TYPE_DEBUG,
1291 "%s estate changed from %s to %s\n",
1292 GCT_2s (t),
1293 estate2s (old),
1294 estate2s (state));
1295
1296 if ((CADET_TUNNEL_KEY_OK != old) &&
1297 (CADET_TUNNEL_KEY_OK == t->estate))
1298 {
1299 if (NULL != t->kx_task)
1300 {
1301 GNUNET_SCHEDULER_cancel (t->kx_task);
1302 t->kx_task = NULL;
1303 }
1304 /* notify all channels that have been waiting */
1305 GNUNET_CONTAINER_multihashmap32_iterate (t->channels,
1306 &notify_tunnel_up_cb,
1307 t);
1308 if (NULL != t->send_task)
1309 GNUNET_SCHEDULER_cancel (t->send_task);
1310 t->send_task = GNUNET_SCHEDULER_add_now (&trigger_transmissions,
1311 t);
1312 }
1313}
1314
1315
1316/**
1317 * Send a KX message.
1318 *
1319 * @param t tunnel on which to send the KX_AUTH
1320 * @param ct Tunnel and connection on which to send the KX_AUTH, NULL if
1321 * we are to find one that is ready.
1322 * @param ax axolotl key context to use
1323 */
1324static void
1325send_kx (struct CadetTunnel *t,
1326 struct CadetTConnection *ct,
1327 struct CadetTunnelAxolotl *ax)
1328{
1329 struct CadetConnection *cc;
1330 struct GNUNET_MQ_Envelope *env;
1331 struct GNUNET_CADET_TunnelKeyExchangeMessage *msg;
1332 enum GNUNET_CADET_KX_Flags flags;
1333
1334 if (GNUNET_YES != GCT_alice_or_betty (GCP_get_id (t->destination)))
1335 return; /* only Alice may send KX */
1336 if ((NULL == ct) ||
1337 (GNUNET_NO == ct->is_ready))
1338 ct = get_ready_connection (t);
1339 if (NULL == ct)
1340 {
1341 LOG (GNUNET_ERROR_TYPE_DEBUG,
1342 "Wanted to send %s in state %s, but no connection is ready, deferring\n",
1343 GCT_2s (t),
1344 estate2s (t->estate));
1345 t->next_kx_attempt = GNUNET_TIME_absolute_get ();
1346 return;
1347 }
1348 cc = ct->cc;
1349 env = GNUNET_MQ_msg (msg,
1350 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX);
1351 flags = GNUNET_CADET_KX_FLAG_FORCE_REPLY; /* always for KX */
1352 msg->flags = htonl (flags);
1353 msg->cid = *GCC_get_id (cc);
1354 GNUNET_CRYPTO_ecdhe_key_get_public (&ax->kx_0,
1355 &msg->ephemeral_key);
1356#if DEBUG_KX
1357 msg->ephemeral_key_XXX = ax->kx_0;
1358 msg->private_key_XXX = *my_private_key;
1359#endif
1360 LOG (GNUNET_ERROR_TYPE_DEBUG,
1361 "Sending KX message to %s with ephemeral %s on CID %s\n",
1362 GCT_2s (t),
1363 GNUNET_e2s (&msg->ephemeral_key),
1364 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
1365 GNUNET_CRYPTO_ecdhe_key_get_public (&ax->DHRs,
1366 &msg->ratchet_key);
1367 mark_connection_unready (ct);
1368 t->kx_retry_delay = GNUNET_TIME_STD_BACKOFF (t->kx_retry_delay);
1369 t->next_kx_attempt = GNUNET_TIME_relative_to_absolute (t->kx_retry_delay);
1370 if (CADET_TUNNEL_KEY_UNINITIALIZED == t->estate)
1371 GCT_change_estate (t,
1372 CADET_TUNNEL_KEY_AX_SENT);
1373 else if (CADET_TUNNEL_KEY_AX_RECV == t->estate)
1374 GCT_change_estate (t,
1375 CADET_TUNNEL_KEY_AX_SENT_AND_RECV);
1376 GCC_transmit (cc,
1377 env);
1378 GNUNET_STATISTICS_update (stats,
1379 "# KX transmitted",
1380 1,
1381 GNUNET_NO);
1382}
1383
1384
1385/**
1386 * Send a KX_AUTH message.
1387 *
1388 * @param t tunnel on which to send the KX_AUTH
1389 * @param ct Tunnel and connection on which to send the KX_AUTH, NULL if
1390 * we are to find one that is ready.
1391 * @param ax axolotl key context to use
1392 * @param force_reply Force the other peer to reply with a KX_AUTH message
1393 * (set if we would like to transmit right now, but cannot)
1394 */
1395static void
1396send_kx_auth (struct CadetTunnel *t,
1397 struct CadetTConnection *ct,
1398 struct CadetTunnelAxolotl *ax,
1399 int force_reply)
1400{
1401 struct CadetConnection *cc;
1402 struct GNUNET_MQ_Envelope *env;
1403 struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg;
1404 enum GNUNET_CADET_KX_Flags flags;
1405
1406 if ((NULL == ct) ||
1407 (GNUNET_NO == ct->is_ready))
1408 ct = get_ready_connection (t);
1409 if (NULL == ct)
1410 {
1411 LOG (GNUNET_ERROR_TYPE_DEBUG,
1412 "Wanted to send KX_AUTH on %s, but no connection is ready, deferring\n",
1413 GCT_2s (t));
1414 t->next_kx_attempt = GNUNET_TIME_absolute_get ();
1415 t->kx_auth_requested = GNUNET_YES; /* queue KX_AUTH independent of estate */
1416 return;
1417 }
1418 t->kx_auth_requested = GNUNET_NO; /* clear flag */
1419 cc = ct->cc;
1420 env = GNUNET_MQ_msg (msg,
1421 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX_AUTH);
1422 flags = GNUNET_CADET_KX_FLAG_NONE;
1423 if (GNUNET_YES == force_reply)
1424 flags |= GNUNET_CADET_KX_FLAG_FORCE_REPLY;
1425 msg->kx.flags = htonl (flags);
1426 msg->kx.cid = *GCC_get_id (cc);
1427 GNUNET_CRYPTO_ecdhe_key_get_public (&ax->kx_0,
1428 &msg->kx.ephemeral_key);
1429 GNUNET_CRYPTO_ecdhe_key_get_public (&ax->DHRs,
1430 &msg->kx.ratchet_key);
1431#if DEBUG_KX
1432 msg->kx.ephemeral_key_XXX = ax->kx_0;
1433 msg->kx.private_key_XXX = *my_private_key;
1434 msg->r_ephemeral_key_XXX = ax->last_ephemeral;
1435#endif
1436 LOG (GNUNET_ERROR_TYPE_DEBUG,
1437 "Sending KX_AUTH message to %s with ephemeral %s on CID %s\n",
1438 GCT_2s (t),
1439 GNUNET_e2s (&msg->kx.ephemeral_key),
1440 GNUNET_sh2s (&msg->kx.cid.connection_of_tunnel));
1441
1442 /* Compute authenticator (this is the main difference to #send_kx()) */
1443 GNUNET_CRYPTO_hash (&ax->RK,
1444 sizeof(ax->RK),
1445 &msg->auth);
1446 /* Compute when to be triggered again; actual job will
1447 be scheduled via #connection_ready_cb() */
1448 t->kx_retry_delay
1449 = GNUNET_TIME_STD_BACKOFF (t->kx_retry_delay);
1450 t->next_kx_attempt
1451 = GNUNET_TIME_relative_to_absolute (t->kx_retry_delay);
1452
1453 /* Send via cc, mark it as unready */
1454 mark_connection_unready (ct);
1455
1456 /* Update state machine, unless we are already OK */
1457 if (CADET_TUNNEL_KEY_OK != t->estate)
1458 GCT_change_estate (t,
1459 CADET_TUNNEL_KEY_AX_AUTH_SENT);
1460 GCC_transmit (cc,
1461 env);
1462 GNUNET_STATISTICS_update (stats,
1463 "# KX_AUTH transmitted",
1464 1,
1465 GNUNET_NO);
1466}
1467
1468
1469/**
1470 * Cleanup state used by @a ax.
1471 *
1472 * @param ax state to free, but not memory of @a ax itself
1473 */
1474static void
1475cleanup_ax (struct CadetTunnelAxolotl *ax)
1476{
1477 while (NULL != ax->skipped_head)
1478 delete_skipped_key (ax,
1479 ax->skipped_head);
1480 GNUNET_assert (0 == ax->skipped);
1481 GNUNET_CRYPTO_ecdhe_key_clear (&ax->kx_0);
1482 GNUNET_CRYPTO_ecdhe_key_clear (&ax->DHRs);
1483}
1484
1485
1486/**
1487 * Update our Axolotl key state based on the KX data we received.
1488 * Computes the new chain keys, and root keys, etc, and also checks
1489 * whether this is a replay of the current chain.
1490 *
1491 * @param[in,out] ax chain key state to recompute
1492 * @param pid peer identity of the other peer
1493 * @param ephemeral_key ephemeral public key of the other peer
1494 * @param ratchet_key senders next ephemeral public key
1495 * @return #GNUNET_OK on success, #GNUNET_NO if the resulting
1496 * root key is already in @a ax and thus the KX is useless;
1497 * #GNUNET_SYSERR on hard errors (i.e. @a pid is #my_full_id)
1498 */
1499static int
1500update_ax_by_kx (struct CadetTunnelAxolotl *ax,
1501 const struct GNUNET_PeerIdentity *pid,
1502 const struct GNUNET_CRYPTO_EcdhePublicKey *ephemeral_key,
1503 const struct GNUNET_CRYPTO_EcdhePublicKey *ratchet_key)
1504{
1505 struct GNUNET_HashCode key_material[3];
1506 struct GNUNET_CRYPTO_SymmetricSessionKey keys[5];
1507 const char salt[] = "CADET Axolotl salt";
1508 int am_I_alice;
1509
1510 if (GNUNET_SYSERR == (am_I_alice = GCT_alice_or_betty (pid)))
1511 {
1512 GNUNET_break_op (0);
1513 return GNUNET_SYSERR;
1514 }
1515 if (0 == GNUNET_memcmp (&ax->DHRr,
1516 ratchet_key))
1517 {
1518 GNUNET_STATISTICS_update (stats,
1519 "# Ratchet key already known",
1520 1,
1521 GNUNET_NO);
1522 LOG (GNUNET_ERROR_TYPE_DEBUG,
1523 "Ratchet key already known. Ignoring KX.\n");
1524 return GNUNET_NO;
1525 }
1526
1527 ax->DHRr = *ratchet_key;
1528 ax->last_ephemeral = *ephemeral_key;
1529 /* ECDH A B0 */
1530 if (GNUNET_YES == am_I_alice)
1531 {
1532 GNUNET_CRYPTO_eddsa_ecdh (my_private_key, /* a */
1533 ephemeral_key, /* B0 */
1534 &key_material[0]);
1535 }
1536 else
1537 {
1538 GNUNET_CRYPTO_ecdh_eddsa (&ax->kx_0, /* b0 */
1539 &pid->public_key, /* A */
1540 &key_material[0]);
1541 }
1542 /* ECDH A0 B */
1543 if (GNUNET_YES == am_I_alice)
1544 {
1545 GNUNET_CRYPTO_ecdh_eddsa (&ax->kx_0, /* a0 */
1546 &pid->public_key, /* B */
1547 &key_material[1]);
1548 }
1549 else
1550 {
1551 GNUNET_CRYPTO_eddsa_ecdh (my_private_key, /* b */
1552 ephemeral_key, /* A0 */
1553 &key_material[1]);
1554 }
1555
1556 /* ECDH A0 B0 */
1557 GNUNET_CRYPTO_ecc_ecdh (&ax->kx_0, /* a0 or b0 */
1558 ephemeral_key, /* B0 or A0 */
1559 &key_material[2]);
1560 /* KDF */
1561 GNUNET_CRYPTO_kdf (keys, sizeof(keys),
1562 salt, sizeof(salt),
1563 &key_material, sizeof(key_material),
1564 NULL);
1565
1566 if (0 == memcmp (&ax->RK,
1567 &keys[0],
1568 sizeof(ax->RK)))
1569 {
1570 LOG (GNUNET_ERROR_TYPE_DEBUG,
1571 "Root key already known. Ignoring KX.\n");
1572 GNUNET_STATISTICS_update (stats,
1573 "# Root key already known",
1574 1,
1575 GNUNET_NO);
1576 return GNUNET_NO;
1577 }
1578
1579 ax->RK = keys[0];
1580 if (GNUNET_YES == am_I_alice)
1581 {
1582 ax->HKr = keys[1];
1583 ax->NHKs = keys[2];
1584 ax->NHKr = keys[3];
1585 ax->CKr = keys[4];
1586 ax->ratchet_flag = GNUNET_YES;
1587 }
1588 else
1589 {
1590 ax->HKs = keys[1];
1591 ax->NHKr = keys[2];
1592 ax->NHKs = keys[3];
1593 ax->CKs = keys[4];
1594 ax->ratchet_flag = GNUNET_NO;
1595 ax->ratchet_expiration
1596 = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
1597 ratchet_time);
1598 }
1599 return GNUNET_OK;
1600}
1601
1602
1603/**
1604 * Try to redo the KX or KX_AUTH handshake, if we can.
1605 *
1606 * @param cls the `struct CadetTunnel` to do KX for.
1607 */
1608static void
1609retry_kx (void *cls)
1610{
1611 struct CadetTunnel *t = cls;
1612 struct CadetTunnelAxolotl *ax;
1613
1614 t->kx_task = NULL;
1615 LOG (GNUNET_ERROR_TYPE_DEBUG,
1616 "Trying to make KX progress on %s in state %s\n",
1617 GCT_2s (t),
1618 estate2s (t->estate));
1619 switch (t->estate)
1620 {
1621 case CADET_TUNNEL_KEY_UNINITIALIZED: /* first attempt */
1622 case CADET_TUNNEL_KEY_AX_SENT: /* trying again */
1623 send_kx (t,
1624 NULL,
1625 &t->ax);
1626 break;
1627
1628 case CADET_TUNNEL_KEY_AX_RECV:
1629 case CADET_TUNNEL_KEY_AX_SENT_AND_RECV:
1630 /* We are responding, so only require reply
1631 if WE have a channel waiting. */
1632 if (NULL != t->unverified_ax)
1633 {
1634 /* Send AX_AUTH so we might get this one verified */
1635 ax = t->unverified_ax;
1636 }
1637 else
1638 {
1639 /* How can this be? */
1640 GNUNET_break (0);
1641 ax = &t->ax;
1642 }
1643 send_kx_auth (t,
1644 NULL,
1645 ax,
1646 (0 == GCT_count_channels (t))
1647 ? GNUNET_NO
1648 : GNUNET_YES);
1649 break;
1650
1651 case CADET_TUNNEL_KEY_AX_AUTH_SENT:
1652 /* We are responding, so only require reply
1653 if WE have a channel waiting. */
1654 if (NULL != t->unverified_ax)
1655 {
1656 /* Send AX_AUTH so we might get this one verified */
1657 ax = t->unverified_ax;
1658 }
1659 else
1660 {
1661 /* How can this be? */
1662 GNUNET_break (0);
1663 ax = &t->ax;
1664 }
1665 send_kx_auth (t,
1666 NULL,
1667 ax,
1668 (0 == GCT_count_channels (t))
1669 ? GNUNET_NO
1670 : GNUNET_YES);
1671 break;
1672
1673 case CADET_TUNNEL_KEY_OK:
1674 /* Must have been the *other* peer asking us to
1675 respond with a KX_AUTH. */
1676 if (NULL != t->unverified_ax)
1677 {
1678 /* Sending AX_AUTH in response to AX so we might get this one verified */
1679 ax = t->unverified_ax;
1680 }
1681 else
1682 {
1683 /* Sending AX_AUTH in response to AX_AUTH */
1684 ax = &t->ax;
1685 }
1686 send_kx_auth (t,
1687 NULL,
1688 ax,
1689 GNUNET_NO);
1690 break;
1691 }
1692}
1693
1694
1695void
1696GCT_handle_kx (struct CadetTConnection *ct,
1697 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
1698{
1699 struct CadetTunnel *t = ct->t;
1700 int ret;
1701
1702 GNUNET_STATISTICS_update (stats,
1703 "# KX received",
1704 1,
1705 GNUNET_NO);
1706 if (GNUNET_YES ==
1707 GCT_alice_or_betty (GCP_get_id (t->destination)))
1708 {
1709 /* Betty/Bob is not allowed to send KX! */
1710 GNUNET_break_op (0);
1711 return;
1712 }
1713 LOG (GNUNET_ERROR_TYPE_DEBUG,
1714 "Received KX message from %s with ephemeral %s from %s on connection %s\n",
1715 GCT_2s (t),
1716 GNUNET_e2s (&msg->ephemeral_key),
1717 GNUNET_i2s (GCP_get_id (t->destination)),
1718 GCC_2s (ct->cc));
1719#if 1
1720 if ((0 ==
1721 memcmp (&t->ax.DHRr,
1722 &msg->ratchet_key,
1723 sizeof(msg->ratchet_key))) &&
1724 (0 ==
1725 memcmp (&t->ax.last_ephemeral,
1726 &msg->ephemeral_key,
1727 sizeof(msg->ephemeral_key))))
1728
1729 {
1730 GNUNET_STATISTICS_update (stats,
1731 "# Duplicate KX received",
1732 1,
1733 GNUNET_NO);
1734 send_kx_auth (t,
1735 ct,
1736 &t->ax,
1737 GNUNET_NO);
1738 return;
1739 }
1740#endif
1741 /* We only keep ONE unverified KX around, so if there is an existing one,
1742 clean it up. */
1743 if (NULL != t->unverified_ax)
1744 {
1745 if ((0 ==
1746 memcmp (&t->unverified_ax->DHRr,
1747 &msg->ratchet_key,
1748 sizeof(msg->ratchet_key))) &&
1749 (0 ==
1750 memcmp (&t->unverified_ax->last_ephemeral,
1751 &msg->ephemeral_key,
1752 sizeof(msg->ephemeral_key))))
1753 {
1754 GNUNET_STATISTICS_update (stats,
1755 "# Duplicate unverified KX received",
1756 1,
1757 GNUNET_NO);
1758#if 1
1759 send_kx_auth (t,
1760 ct,
1761 t->unverified_ax,
1762 GNUNET_NO);
1763 return;
1764#endif
1765 }
1766 LOG (GNUNET_ERROR_TYPE_DEBUG,
1767 "Dropping old unverified KX state.\n");
1768 GNUNET_STATISTICS_update (stats,
1769 "# Unverified KX dropped for fresh KX",
1770 1,
1771 GNUNET_NO);
1772 GNUNET_break (NULL == t->unverified_ax->skipped_head);
1773 memset (t->unverified_ax,
1774 0,
1775 sizeof(struct CadetTunnelAxolotl));
1776 }
1777 else
1778 {
1779 LOG (GNUNET_ERROR_TYPE_DEBUG,
1780 "Creating fresh unverified KX for %s\n",
1781 GCT_2s (t));
1782 GNUNET_STATISTICS_update (stats,
1783 "# Fresh KX setup",
1784 1,
1785 GNUNET_NO);
1786 t->unverified_ax = GNUNET_new (struct CadetTunnelAxolotl);
1787 }
1788 /* Set as the 'current' RK/DHRr the one we are currently using,
1789 so that the duplicate-detection logic of
1790 #update_ax_by_kx can work. */
1791 t->unverified_ax->RK = t->ax.RK;
1792 t->unverified_ax->DHRr = t->ax.DHRr;
1793 t->unverified_ax->DHRs = t->ax.DHRs;
1794 t->unverified_ax->kx_0 = t->ax.kx_0;
1795 t->unverified_attempts = 0;
1796
1797 /* Update 'ax' by the new key material */
1798 ret = update_ax_by_kx (t->unverified_ax,
1799 GCP_get_id (t->destination),
1800 &msg->ephemeral_key,
1801 &msg->ratchet_key);
1802 GNUNET_break (GNUNET_SYSERR != ret);
1803 if (GNUNET_OK != ret)
1804 {
1805 GNUNET_STATISTICS_update (stats,
1806 "# Useless KX",
1807 1,
1808 GNUNET_NO);
1809 return; /* duplicate KX, nothing to do */
1810 }
1811 /* move ahead in our state machine */
1812 if (CADET_TUNNEL_KEY_UNINITIALIZED == t->estate)
1813 GCT_change_estate (t,
1814 CADET_TUNNEL_KEY_AX_RECV);
1815 else if (CADET_TUNNEL_KEY_AX_SENT == t->estate)
1816 GCT_change_estate (t,
1817 CADET_TUNNEL_KEY_AX_SENT_AND_RECV);
1818
1819 /* KX is still not done, try again our end. */
1820 if (CADET_TUNNEL_KEY_OK != t->estate)
1821 {
1822 if (NULL != t->kx_task)
1823 GNUNET_SCHEDULER_cancel (t->kx_task);
1824 t->kx_task
1825 = GNUNET_SCHEDULER_add_now (&retry_kx,
1826 t);
1827 }
1828}
1829
1830
1831#if DEBUG_KX
1832static void
1833check_ee (const struct GNUNET_CRYPTO_EcdhePrivateKey *e1,
1834 const struct GNUNET_CRYPTO_EcdhePrivateKey *e2)
1835{
1836 struct GNUNET_CRYPTO_EcdhePublicKey p1;
1837 struct GNUNET_CRYPTO_EcdhePublicKey p2;
1838 struct GNUNET_HashCode hc1;
1839 struct GNUNET_HashCode hc2;
1840
1841 GNUNET_CRYPTO_ecdhe_key_get_public (e1,
1842 &p1);
1843 GNUNET_CRYPTO_ecdhe_key_get_public (e2,
1844 &p2);
1845 GNUNET_assert (GNUNET_OK ==
1846 GNUNET_CRYPTO_ecc_ecdh (e1,
1847 &p2,
1848 &hc1));
1849 GNUNET_assert (GNUNET_OK ==
1850 GNUNET_CRYPTO_ecc_ecdh (e2,
1851 &p1,
1852 &hc2));
1853 GNUNET_break (0 == GNUNET_memcmp (&hc1,
1854 &hc2));
1855}
1856
1857
1858static void
1859check_ed (const struct GNUNET_CRYPTO_EcdhePrivateKey *e1,
1860 const struct GNUNET_CRYPTO_EddsaPrivateKey *e2)
1861{
1862 struct GNUNET_CRYPTO_EcdhePublicKey p1;
1863 struct GNUNET_CRYPTO_EddsaPublicKey p2;
1864 struct GNUNET_HashCode hc1;
1865 struct GNUNET_HashCode hc2;
1866
1867 GNUNET_CRYPTO_ecdhe_key_get_public (e1,
1868 &p1);
1869 GNUNET_CRYPTO_eddsa_key_get_public (e2,
1870 &p2);
1871 GNUNET_assert (GNUNET_OK ==
1872 GNUNET_CRYPTO_ecdh_eddsa (e1,
1873 &p2,
1874 &hc1));
1875 GNUNET_assert (GNUNET_OK ==
1876 GNUNET_CRYPTO_eddsa_ecdh (e2,
1877 &p1,
1878 &hc2));
1879 GNUNET_break (0 == GNUNET_memcmp (&hc1,
1880 &hc2));
1881}
1882
1883
1884static void
1885test_crypto_bug (const struct GNUNET_CRYPTO_EcdhePrivateKey *e1,
1886 const struct GNUNET_CRYPTO_EcdhePrivateKey *e2,
1887 const struct GNUNET_CRYPTO_EddsaPrivateKey *d1,
1888 const struct GNUNET_CRYPTO_EddsaPrivateKey *d2)
1889{
1890 check_ee (e1, e2);
1891 check_ed (e1, d2);
1892 check_ed (e2, d1);
1893}
1894
1895
1896#endif
1897
1898
1899/**
1900 * Handle KX_AUTH message.
1901 *
1902 * @param ct connection/tunnel combo that received encrypted message
1903 * @param msg the key exchange message
1904 */
1905void
1906GCT_handle_kx_auth (struct CadetTConnection *ct,
1907 const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg)
1908{
1909 struct CadetTunnel *t = ct->t;
1910 struct CadetTunnelAxolotl ax_tmp;
1911 struct GNUNET_HashCode kx_auth;
1912 int ret;
1913
1914 GNUNET_STATISTICS_update (stats,
1915 "# KX_AUTH received",
1916 1,
1917 GNUNET_NO);
1918 if ((CADET_TUNNEL_KEY_UNINITIALIZED == t->estate) ||
1919 (CADET_TUNNEL_KEY_AX_RECV == t->estate))
1920 {
1921 /* Confusing, we got a KX_AUTH before we even send our own
1922 KX. This should not happen. We'll send our own KX ASAP anyway,
1923 so let's ignore this here. */
1924 GNUNET_break_op (0);
1925 return;
1926 }
1927 LOG (GNUNET_ERROR_TYPE_DEBUG,
1928 "Handling KX_AUTH message from %s with ephemeral %s\n",
1929 GCT_2s (t),
1930 GNUNET_e2s (&msg->kx.ephemeral_key));
1931 /* We do everything in ax_tmp until we've checked the authentication
1932 so we don't clobber anything we care about by accident. */
1933 ax_tmp = t->ax;
1934
1935 /* Update 'ax' by the new key material */
1936 ret = update_ax_by_kx (&ax_tmp,
1937 GCP_get_id (t->destination),
1938 &msg->kx.ephemeral_key,
1939 &msg->kx.ratchet_key);
1940 if (GNUNET_OK != ret)
1941 {
1942 if (GNUNET_NO == ret)
1943 GNUNET_STATISTICS_update (stats,
1944 "# redundant KX_AUTH received",
1945 1,
1946 GNUNET_NO);
1947 else
1948 GNUNET_break (0); /* connect to self!? */
1949 return;
1950 }
1951 GNUNET_CRYPTO_hash (&ax_tmp.RK,
1952 sizeof(ax_tmp.RK),
1953 &kx_auth);
1954 if (0 != GNUNET_memcmp (&kx_auth,
1955 &msg->auth))
1956 {
1957 /* This KX_AUTH is not using the latest KX/KX_AUTH data
1958 we transmitted to the sender, refuse it, try KX again. */
1959 GNUNET_STATISTICS_update (stats,
1960 "# KX_AUTH not using our last KX received (auth failure)",
1961 1,
1962 GNUNET_NO);
1963 LOG (GNUNET_ERROR_TYPE_WARNING,
1964 "KX AUTH mismatch!\n");
1965#if DEBUG_KX
1966 {
1967 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
1968
1969 GNUNET_CRYPTO_ecdhe_key_get_public (&ax_tmp.kx_0,
1970 &ephemeral_key);
1971 if (0 != GNUNET_memcmp (&ephemeral_key,
1972 &msg->r_ephemeral_key_XXX))
1973 {
1974 LOG (GNUNET_ERROR_TYPE_WARNING,
1975 "My ephemeral is %s!\n",
1976 GNUNET_e2s (&ephemeral_key));
1977 LOG (GNUNET_ERROR_TYPE_WARNING,
1978 "Response is for ephemeral %s!\n",
1979 GNUNET_e2s (&msg->r_ephemeral_key_XXX));
1980 }
1981 else
1982 {
1983 test_crypto_bug (&ax_tmp.kx_0,
1984 &msg->kx.ephemeral_key_XXX,
1985 my_private_key,
1986 &msg->kx.private_key_XXX);
1987 }
1988 }
1989#endif
1990 if (NULL == t->kx_task)
1991 t->kx_task
1992 = GNUNET_SCHEDULER_add_at (t->next_kx_attempt,
1993 &retry_kx,
1994 t);
1995 return;
1996 }
1997 /* Yep, we're good. */
1998 t->ax = ax_tmp;
1999 if (NULL != t->unverified_ax)
2000 {
2001 /* We got some "stale" KX before, drop that. */
2002 cleanup_ax (t->unverified_ax);
2003 GNUNET_free (t->unverified_ax);
2004 t->unverified_ax = NULL;
2005 }
2006
2007 /* move ahead in our state machine */
2008 switch (t->estate)
2009 {
2010 case CADET_TUNNEL_KEY_UNINITIALIZED:
2011 case CADET_TUNNEL_KEY_AX_RECV:
2012 /* Checked above, this is impossible. */
2013 GNUNET_assert (0);
2014 break;
2015
2016 case CADET_TUNNEL_KEY_AX_SENT: /* This is the normal case */
2017 case CADET_TUNNEL_KEY_AX_SENT_AND_RECV: /* both peers started KX */
2018 case CADET_TUNNEL_KEY_AX_AUTH_SENT: /* both peers now did KX_AUTH */
2019 GCT_change_estate (t,
2020 CADET_TUNNEL_KEY_OK);
2021 break;
2022
2023 case CADET_TUNNEL_KEY_OK:
2024 /* Did not expect another KX_AUTH, but so what, still acceptable.
2025 Nothing to do here. */
2026 break;
2027 }
2028 if (0 != (GNUNET_CADET_KX_FLAG_FORCE_REPLY & ntohl (msg->kx.flags)))
2029 {
2030 send_kx_auth (t,
2031 NULL,
2032 &t->ax,
2033 GNUNET_NO);
2034 }
2035}
2036
2037
2038/* ************************************** end core crypto ***************************** */
2039
2040
2041/**
2042 * Compute the next free channel tunnel number for this tunnel.
2043 *
2044 * @param t the tunnel
2045 * @return unused number that can uniquely identify a channel in the tunnel
2046 */
2047static struct GNUNET_CADET_ChannelTunnelNumber
2048get_next_free_ctn (struct CadetTunnel *t)
2049{
2050#define HIGH_BIT 0x8000000
2051 struct GNUNET_CADET_ChannelTunnelNumber ret;
2052 uint32_t ctn;
2053 int cmp;
2054 uint32_t highbit;
2055
2056 cmp = GNUNET_memcmp (&my_full_id,
2057 GCP_get_id (GCT_get_destination (t)));
2058 if (0 < cmp)
2059 highbit = HIGH_BIT;
2060 else if (0 > cmp)
2061 highbit = 0;
2062 else
2063 GNUNET_assert (0); // loopback must never go here!
2064 ctn = ntohl (t->next_ctn.cn);
2065 while (NULL !=
2066 GNUNET_CONTAINER_multihashmap32_get (t->channels,
2067 ctn | highbit))
2068 {
2069 ctn = ((ctn + 1) & (~HIGH_BIT));
2070 }
2071 t->next_ctn.cn = htonl ((ctn + 1) & (~HIGH_BIT));
2072 ret.cn = htonl (ctn | highbit);
2073 return ret;
2074}
2075
2076
2077/**
2078 * Add a channel to a tunnel, and notify channel that we are ready
2079 * for transmission if we are already up. Otherwise that notification
2080 * will be done later in #notify_tunnel_up_cb().
2081 *
2082 * @param t Tunnel.
2083 * @param ch Channel
2084 * @return unique number identifying @a ch within @a t
2085 */
2086struct GNUNET_CADET_ChannelTunnelNumber
2087GCT_add_channel (struct CadetTunnel *t,
2088 struct CadetChannel *ch)
2089{
2090 struct GNUNET_CADET_ChannelTunnelNumber ctn;
2091
2092 ctn = get_next_free_ctn (t);
2093 if (NULL != t->destroy_task)
2094 {
2095 GNUNET_SCHEDULER_cancel (t->destroy_task);
2096 t->destroy_task = NULL;
2097 }
2098 GNUNET_assert (GNUNET_YES ==
2099 GNUNET_CONTAINER_multihashmap32_put (t->channels,
2100 ntohl (ctn.cn),
2101 ch,
2102 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
2103 LOG (GNUNET_ERROR_TYPE_DEBUG,
2104 "Adding %s to %s with state %d\n",
2105 GCCH_2s (ch),
2106 GCT_2s (t),
2107 t->estate);
2108 switch (t->estate)
2109 {
2110 case CADET_TUNNEL_KEY_UNINITIALIZED:
2111 /* waiting for connection to start KX */
2112 break;
2113
2114 case CADET_TUNNEL_KEY_AX_RECV:
2115 case CADET_TUNNEL_KEY_AX_SENT:
2116 case CADET_TUNNEL_KEY_AX_SENT_AND_RECV:
2117 /* we're currently waiting for KX to complete */
2118 break;
2119
2120 case CADET_TUNNEL_KEY_AX_AUTH_SENT:
2121 /* waiting for OTHER peer to send us data,
2122 we might need to prompt more aggressively! */
2123 if (NULL == t->kx_task)
2124 t->kx_task
2125 = GNUNET_SCHEDULER_add_at (t->next_kx_attempt,
2126 &retry_kx,
2127 t);
2128 break;
2129
2130 case CADET_TUNNEL_KEY_OK:
2131 /* We are ready. Tell the new channel that we are up. */
2132 GCCH_tunnel_up (ch);
2133 break;
2134 }
2135 return ctn;
2136}
2137
2138
2139/**
2140 * We lost a connection, remove it from our list and clean up
2141 * the connection object itself.
2142 *
2143 * @param ct binding of connection to tunnel of the connection that was lost.
2144 */
2145void
2146GCT_connection_lost (struct CadetTConnection *ct)
2147{
2148 struct CadetTunnel *t = ct->t;
2149
2150 if (GNUNET_YES == ct->is_ready)
2151 {
2152 GNUNET_CONTAINER_DLL_remove (t->connection_ready_head,
2153 t->connection_ready_tail,
2154 ct);
2155 t->num_ready_connections--;
2156 }
2157 else
2158 {
2159 GNUNET_CONTAINER_DLL_remove (t->connection_busy_head,
2160 t->connection_busy_tail,
2161 ct);
2162 t->num_busy_connections--;
2163 }
2164 GNUNET_free (ct);
2165}
2166
2167
2168/**
2169 * Clean up connection @a ct of a tunnel.
2170 *
2171 * @param cls the `struct CadetTunnel`
2172 * @param ct connection to clean up
2173 */
2174static void
2175destroy_t_connection (void *cls,
2176 struct CadetTConnection *ct)
2177{
2178 struct CadetTunnel *t = cls;
2179 struct CadetConnection *cc = ct->cc;
2180
2181 GNUNET_assert (ct->t == t);
2182 GCT_connection_lost (ct);
2183 GCC_destroy_without_tunnel (cc);
2184}
2185
2186
2187/**
2188 * This tunnel is no longer used, destroy it.
2189 *
2190 * @param cls the idle tunnel
2191 */
2192static void
2193destroy_tunnel (void *cls)
2194{
2195 struct CadetTunnel *t = cls;
2196 struct CadetTunnelQueueEntry *tq;
2197
2198 t->destroy_task = NULL;
2199 LOG (GNUNET_ERROR_TYPE_DEBUG,
2200 "Destroying idle %s\n",
2201 GCT_2s (t));
2202 GNUNET_assert (0 == GCT_count_channels (t));
2203 GCT_iterate_connections (t,
2204 &destroy_t_connection,
2205 t);
2206 GNUNET_assert (NULL == t->connection_ready_head);
2207 GNUNET_assert (NULL == t->connection_busy_head);
2208 while (NULL != (tq = t->tq_head))
2209 {
2210 if (NULL != tq->cont)
2211 tq->cont (tq->cont_cls,
2212 NULL);
2213 GCT_send_cancel (tq);
2214 }
2215 GCP_drop_tunnel (t->destination,
2216 t);
2217 GNUNET_CONTAINER_multihashmap32_destroy (t->channels);
2218 if (NULL != t->maintain_connections_task)
2219 {
2220 GNUNET_SCHEDULER_cancel (t->maintain_connections_task);
2221 t->maintain_connections_task = NULL;
2222 }
2223 if (NULL != t->send_task)
2224 {
2225 GNUNET_SCHEDULER_cancel (t->send_task);
2226 t->send_task = NULL;
2227 }
2228 if (NULL != t->kx_task)
2229 {
2230 GNUNET_SCHEDULER_cancel (t->kx_task);
2231 t->kx_task = NULL;
2232 }
2233 GNUNET_MST_destroy (t->mst);
2234 GNUNET_MQ_destroy (t->mq);
2235 if (NULL != t->unverified_ax)
2236 {
2237 cleanup_ax (t->unverified_ax);
2238 GNUNET_free (t->unverified_ax);
2239 }
2240 cleanup_ax (&t->ax);
2241 GNUNET_assert (NULL == t->destroy_task);
2242 GNUNET_free (t);
2243}
2244
2245
2246/**
2247 * Remove a channel from a tunnel.
2248 *
2249 * @param t Tunnel.
2250 * @param ch Channel
2251 * @param ctn unique number identifying @a ch within @a t
2252 */
2253void
2254GCT_remove_channel (struct CadetTunnel *t,
2255 struct CadetChannel *ch,
2256 struct GNUNET_CADET_ChannelTunnelNumber ctn)
2257{
2258 LOG (GNUNET_ERROR_TYPE_DEBUG,
2259 "Removing %s from %s\n",
2260 GCCH_2s (ch),
2261 GCT_2s (t));
2262 GNUNET_assert (GNUNET_YES ==
2263 GNUNET_CONTAINER_multihashmap32_remove (t->channels,
2264 ntohl (ctn.cn),
2265 ch));
2266 if ((0 ==
2267 GCT_count_channels (t)) &&
2268 (NULL == t->destroy_task))
2269 {
2270 t->destroy_task
2271 = GNUNET_SCHEDULER_add_delayed (IDLE_DESTROY_DELAY,
2272 &destroy_tunnel,
2273 t);
2274 }
2275}
2276
2277
2278/**
2279 * Destroy remaining channels during shutdown.
2280 *
2281 * @param cls the `struct CadetTunnel` of the channel
2282 * @param key key of the channel
2283 * @param value the `struct CadetChannel`
2284 * @return #GNUNET_OK (continue to iterate)
2285 */
2286static int
2287destroy_remaining_channels (void *cls,
2288 uint32_t key,
2289 void *value)
2290{
2291 struct CadetChannel *ch = value;
2292
2293 GCCH_handle_remote_destroy (ch,
2294 NULL);
2295 return GNUNET_OK;
2296}
2297
2298
2299/**
2300 * Destroys the tunnel @a t now, without delay. Used during shutdown.
2301 *
2302 * @param t tunnel to destroy
2303 */
2304void
2305GCT_destroy_tunnel_now (struct CadetTunnel *t)
2306{
2307 GNUNET_assert (GNUNET_YES == shutting_down);
2308 GNUNET_CONTAINER_multihashmap32_iterate (t->channels,
2309 &destroy_remaining_channels,
2310 t);
2311 GNUNET_assert (0 ==
2312 GCT_count_channels (t));
2313 if (NULL != t->destroy_task)
2314 {
2315 GNUNET_SCHEDULER_cancel (t->destroy_task);
2316 t->destroy_task = NULL;
2317 }
2318 destroy_tunnel (t);
2319}
2320
2321
2322/**
2323 * Send normal payload from queue in @a t via connection @a ct.
2324 * Does nothing if our payload queue is empty.
2325 *
2326 * @param t tunnel to send data from
2327 * @param ct connection to use for transmission (is ready)
2328 */
2329static void
2330try_send_normal_payload (struct CadetTunnel *t,
2331 struct CadetTConnection *ct)
2332{
2333 struct CadetTunnelQueueEntry *tq;
2334
2335 GNUNET_assert (GNUNET_YES == ct->is_ready);
2336 tq = t->tq_head;
2337 if (NULL == tq)
2338 {
2339 /* no messages pending right now */
2340 LOG (GNUNET_ERROR_TYPE_DEBUG,
2341 "Not sending payload of %s on ready %s (nothing pending)\n",
2342 GCT_2s (t),
2343 GCC_2s (ct->cc));
2344 return;
2345 }
2346 /* ready to send message 'tq' on tunnel 'ct' */
2347 GNUNET_assert (t == tq->t);
2348 GNUNET_CONTAINER_DLL_remove (t->tq_head,
2349 t->tq_tail,
2350 tq);
2351 if (NULL != tq->cid)
2352 *tq->cid = *GCC_get_id (ct->cc);
2353 mark_connection_unready (ct);
2354 LOG (GNUNET_ERROR_TYPE_DEBUG,
2355 "Sending payload of %s on %s\n",
2356 GCT_2s (t),
2357 GCC_2s (ct->cc));
2358 GCC_transmit (ct->cc,
2359 tq->env);
2360 if (NULL != tq->cont)
2361 tq->cont (tq->cont_cls,
2362 GCC_get_id (ct->cc));
2363 GNUNET_free (tq);
2364}
2365
2366
2367/**
2368 * A connection is @a is_ready for transmission. Looks at our message
2369 * queue and if there is a message, sends it out via the connection.
2370 *
2371 * @param cls the `struct CadetTConnection` that is @a is_ready
2372 * @param is_ready #GNUNET_YES if connection are now ready,
2373 * #GNUNET_NO if connection are no longer ready
2374 */
2375static void
2376connection_ready_cb (void *cls,
2377 int is_ready)
2378{
2379 struct CadetTConnection *ct = cls;
2380 struct CadetTunnel *t = ct->t;
2381
2382 if (GNUNET_NO == is_ready)
2383 {
2384 LOG (GNUNET_ERROR_TYPE_DEBUG,
2385 "%s no longer ready for %s\n",
2386 GCC_2s (ct->cc),
2387 GCT_2s (t));
2388 mark_connection_unready (ct);
2389 return;
2390 }
2391 GNUNET_assert (GNUNET_NO == ct->is_ready);
2392 GNUNET_CONTAINER_DLL_remove (t->connection_busy_head,
2393 t->connection_busy_tail,
2394 ct);
2395 GNUNET_assert (0 < t->num_busy_connections);
2396 t->num_busy_connections--;
2397 ct->is_ready = GNUNET_YES;
2398 GNUNET_CONTAINER_DLL_insert_tail (t->connection_ready_head,
2399 t->connection_ready_tail,
2400 ct);
2401 t->num_ready_connections++;
2402
2403 LOG (GNUNET_ERROR_TYPE_DEBUG,
2404 "%s now ready for %s in state %s\n",
2405 GCC_2s (ct->cc),
2406 GCT_2s (t),
2407 estate2s (t->estate));
2408 switch (t->estate)
2409 {
2410 case CADET_TUNNEL_KEY_UNINITIALIZED:
2411 LOG (GNUNET_ERROR_TYPE_DEBUG,
2412 "Do not begin KX for %s if WE have no channels waiting. Retrying after %llu\n",
2413 GCT_2s (t),
2414 (unsigned long long) GNUNET_TIME_absolute_get_remaining (
2415 t->next_kx_attempt).rel_value_us);
2416 /* Do not begin KX if WE have no channels waiting! */
2417 if (0 != GNUNET_TIME_absolute_get_remaining (
2418 t->next_kx_attempt).rel_value_us)
2419 return; /* wait for timeout before retrying */
2420 /* We are uninitialized, just transmit immediately,
2421 without undue delay. */
2422
2423 LOG (GNUNET_ERROR_TYPE_DEBUG,
2424 "Why for %s \n",
2425 GCT_2s (t));
2426
2427 if (NULL != t->kx_task)
2428 {
2429 GNUNET_SCHEDULER_cancel (t->kx_task);
2430 t->kx_task = NULL;
2431 }
2432 send_kx (t,
2433 ct,
2434 &t->ax);
2435 if ((0 ==
2436 GCT_count_channels (t)) &&
2437 (NULL == t->destroy_task))
2438 {
2439 t->destroy_task
2440 = GNUNET_SCHEDULER_add_delayed (IDLE_DESTROY_DELAY,
2441 &destroy_tunnel,
2442 t);
2443 }
2444 break;
2445
2446 case CADET_TUNNEL_KEY_AX_RECV:
2447 case CADET_TUNNEL_KEY_AX_SENT:
2448 case CADET_TUNNEL_KEY_AX_SENT_AND_RECV:
2449 case CADET_TUNNEL_KEY_AX_AUTH_SENT:
2450 /* we're currently waiting for KX to complete, schedule job */
2451 if (NULL == t->kx_task)
2452 t->kx_task
2453 = GNUNET_SCHEDULER_add_at (t->next_kx_attempt,
2454 &retry_kx,
2455 t);
2456 break;
2457
2458 case CADET_TUNNEL_KEY_OK:
2459 if (GNUNET_YES == t->kx_auth_requested)
2460 {
2461 if (0 != GNUNET_TIME_absolute_get_remaining (
2462 t->next_kx_attempt).rel_value_us)
2463 return; /* wait for timeout */
2464 if (NULL != t->kx_task)
2465 {
2466 GNUNET_SCHEDULER_cancel (t->kx_task);
2467 t->kx_task = NULL;
2468 }
2469 send_kx_auth (t,
2470 ct,
2471 &t->ax,
2472 GNUNET_NO);
2473 return;
2474 }
2475 try_send_normal_payload (t,
2476 ct);
2477 break;
2478 }
2479}
2480
2481
2482/**
2483 * Called when either we have a new connection, or a new message in the
2484 * queue, or some existing connection has transmission capacity. Looks
2485 * at our message queue and if there is a message, picks a connection
2486 * to send it on.
2487 *
2488 * @param cls the `struct CadetTunnel` to process messages on
2489 */
2490static void
2491trigger_transmissions (void *cls)
2492{
2493 struct CadetTunnel *t = cls;
2494 struct CadetTConnection *ct;
2495
2496 t->send_task = NULL;
2497 if (NULL == t->tq_head)
2498 return; /* no messages pending right now */
2499 ct = get_ready_connection (t);
2500 if (NULL == ct)
2501 return; /* no connections ready */
2502 try_send_normal_payload (t,
2503 ct);
2504}
2505
2506
2507/**
2508 * Closure for #evaluate_connection. Used to assemble summary information
2509 * about the existing connections so we can evaluate a new path.
2510 */
2511struct EvaluationSummary
2512{
2513 /**
2514 * Minimum length of any of our connections, `UINT_MAX` if we have none.
2515 */
2516 unsigned int min_length;
2517
2518 /**
2519 * Maximum length of any of our connections, 0 if we have none.
2520 */
2521 unsigned int max_length;
2522
2523 /**
2524 * Minimum desirability of any of our connections, UINT64_MAX if we have none.
2525 */
2526 GNUNET_CONTAINER_HeapCostType min_desire;
2527
2528 /**
2529 * Maximum desirability of any of our connections, 0 if we have none.
2530 */
2531 GNUNET_CONTAINER_HeapCostType max_desire;
2532
2533 /**
2534 * Path we are comparing against for #evaluate_connection, can be NULL.
2535 */
2536 struct CadetPeerPath *path;
2537
2538 /**
2539 * Connection deemed the "worst" so far encountered by #evaluate_connection,
2540 * NULL if we did not yet encounter any connections.
2541 */
2542 struct CadetTConnection *worst;
2543
2544 /**
2545 * Numeric score of @e worst, only set if @e worst is non-NULL.
2546 */
2547 double worst_score;
2548
2549 /**
2550 * Set to #GNUNET_YES if we have a connection over @e path already.
2551 */
2552 int duplicate;
2553};
2554
2555
2556/**
2557 * Evaluate a connection, updating our summary information in @a cls about
2558 * what kinds of connections we have.
2559 *
2560 * @param cls the `struct EvaluationSummary *` to update
2561 * @param ct a connection to include in the summary
2562 */
2563static void
2564evaluate_connection (void *cls,
2565 struct CadetTConnection *ct)
2566{
2567 struct EvaluationSummary *es = cls;
2568 struct CadetConnection *cc = ct->cc;
2569 unsigned int ct_length;
2570 struct CadetPeerPath *ps;
2571 const struct CadetConnectionMetrics *metrics;
2572 GNUNET_CONTAINER_HeapCostType ct_desirability;
2573 struct GNUNET_TIME_Relative uptime;
2574 struct GNUNET_TIME_Relative last_use;
2575 double score;
2576 double success_rate;
2577
2578 ps = GCC_get_path (cc,
2579 &ct_length);
2580 LOG (GNUNET_ERROR_TYPE_DEBUG,
2581 "Evaluating path %s of existing %s\n",
2582 GCPP_2s (ps),
2583 GCC_2s (cc));
2584 if (ps == es->path)
2585 {
2586 LOG (GNUNET_ERROR_TYPE_DEBUG,
2587 "Ignoring duplicate path %s.\n",
2588 GCPP_2s (es->path));
2589 es->duplicate = GNUNET_YES;
2590 return;
2591 }
2592 if (NULL != es->path)
2593 {
2594 int duplicate = GNUNET_YES;
2595
2596 for (unsigned int i = 0; i < ct_length; i++)
2597 {
2598 GNUNET_assert (GCPP_get_length (es->path) > i);
2599 if (GCPP_get_peer_at_offset (es->path,
2600 i) !=
2601 GCPP_get_peer_at_offset (ps,
2602 i))
2603 {
2604 duplicate = GNUNET_NO;
2605 break;
2606 }
2607 }
2608 if (GNUNET_YES == duplicate)
2609 {
2610 LOG (GNUNET_ERROR_TYPE_DEBUG,
2611 "Ignoring overlapping path %s.\n",
2612 GCPP_2s (es->path));
2613 es->duplicate = GNUNET_YES;
2614 return;
2615 }
2616 else
2617 {
2618 LOG (GNUNET_ERROR_TYPE_DEBUG,
2619 "Known path %s differs from proposed path\n",
2620 GCPP_2s (ps));
2621 }
2622 }
2623
2624 ct_desirability = GCPP_get_desirability (ps);
2625 metrics = GCC_get_metrics (cc);
2626 uptime = GNUNET_TIME_absolute_get_duration (metrics->age);
2627 last_use = GNUNET_TIME_absolute_get_duration (metrics->last_use);
2628 /* We add 1.0 here to avoid division by zero. */
2629 success_rate = (metrics->num_acked_transmissions + 1.0)
2630 / (metrics->num_successes + 1.0);
2631 score
2632 = ct_desirability
2633 + 100.0 / (1.0 + ct_length) /* longer paths = better */
2634 + sqrt (uptime.rel_value_us / 60000000LL) /* larger uptime = better */
2635 - last_use.rel_value_us / 1000L; /* longer idle = worse */
2636 score *= success_rate; /* weigh overall by success rate */
2637
2638 if ((NULL == es->worst) ||
2639 (score < es->worst_score))
2640 {
2641 es->worst = ct;
2642 es->worst_score = score;
2643 }
2644 es->min_length = GNUNET_MIN (es->min_length,
2645 ct_length);
2646 es->max_length = GNUNET_MAX (es->max_length,
2647 ct_length);
2648 es->min_desire = GNUNET_MIN (es->min_desire,
2649 ct_desirability);
2650 es->max_desire = GNUNET_MAX (es->max_desire,
2651 ct_desirability);
2652}
2653
2654
2655/**
2656 * Consider using the path @a p for the tunnel @a t.
2657 * The tunnel destination is at offset @a off in path @a p.
2658 *
2659 * @param cls our tunnel
2660 * @param path a path to our destination
2661 * @param off offset of the destination on path @a path
2662 * @return #GNUNET_YES (should keep iterating)
2663 */
2664static int
2665consider_path_cb (void *cls,
2666 struct CadetPeerPath *path,
2667 unsigned int off)
2668{
2669 struct CadetTunnel *t = cls;
2670 struct EvaluationSummary es;
2671 struct CadetTConnection *ct;
2672
2673 GNUNET_assert (off < GCPP_get_length (path));
2674 GNUNET_assert (GCPP_get_peer_at_offset (path,
2675 off) == t->destination);
2676 es.min_length = UINT_MAX;
2677 es.max_length = 0;
2678 es.max_desire = 0;
2679 es.min_desire = UINT64_MAX;
2680 es.path = path;
2681 es.duplicate = GNUNET_NO;
2682 es.worst = NULL;
2683
2684 /* Compute evaluation summary over existing connections. */
2685 LOG (GNUNET_ERROR_TYPE_DEBUG,
2686 "Evaluating proposed path %s for target %s\n",
2687 GCPP_2s (path),
2688 GCT_2s (t));
2689 /* FIXME: suspect this does not ACTUALLY iterate
2690 over all existing paths, otherwise dup detection
2691 should work!!! */
2692 GCT_iterate_connections (t,
2693 &evaluate_connection,
2694 &es);
2695 if (GNUNET_YES == es.duplicate)
2696 return GNUNET_YES;
2697
2698 /* FIXME: not sure we should really just count
2699 'num_connections' here, as they may all have
2700 consistently failed to connect. */
2701
2702 /* We iterate by increasing path length; if we have enough paths and
2703 this one is more than twice as long than what we are currently
2704 using, then ignore all of these super-long ones! */
2705 if ((GCT_count_any_connections (t) > DESIRED_CONNECTIONS_PER_TUNNEL) &&
2706 (es.min_length * 2 < off) &&
2707 (es.max_length < off))
2708 {
2709 LOG (GNUNET_ERROR_TYPE_DEBUG,
2710 "Ignoring paths of length %u, they are way too long.\n",
2711 es.min_length * 2);
2712 return GNUNET_NO;
2713 }
2714 /* If we have enough paths and this one looks no better, ignore it. */
2715 if ((GCT_count_any_connections (t) >= DESIRED_CONNECTIONS_PER_TUNNEL) &&
2716 (es.min_length < GCPP_get_length (path)) &&
2717 (es.min_desire > GCPP_get_desirability (path)) &&
2718 (es.max_length < off))
2719 {
2720 LOG (GNUNET_ERROR_TYPE_DEBUG,
2721 "Ignoring path (%u/%llu) to %s, got something better already.\n",
2722 GCPP_get_length (path),
2723 (unsigned long long) GCPP_get_desirability (path),
2724 GCP_2s (t->destination));
2725 return GNUNET_YES;
2726 }
2727
2728 /* Path is interesting (better by some metric, or we don't have
2729 enough paths yet). */
2730 ct = GNUNET_new (struct CadetTConnection);
2731 ct->created = GNUNET_TIME_absolute_get ();
2732 ct->t = t;
2733 ct->cc = GCC_create (t->destination,
2734 path,
2735 off,
2736 ct,
2737 &connection_ready_cb,
2738 ct);
2739
2740 /* FIXME: schedule job to kill connection (and path?) if it takes
2741 too long to get ready! (And track performance data on how long
2742 other connections took with the tunnel!)
2743 => Note: to be done within 'connection'-logic! */
2744 GNUNET_CONTAINER_DLL_insert (t->connection_busy_head,
2745 t->connection_busy_tail,
2746 ct);
2747 t->num_busy_connections++;
2748 LOG (GNUNET_ERROR_TYPE_DEBUG,
2749 "Found interesting path %s for %s, created %s\n",
2750 GCPP_2s (path),
2751 GCT_2s (t),
2752 GCC_2s (ct->cc));
2753 return GNUNET_YES;
2754}
2755
2756
2757/**
2758 * Function called to maintain the connections underlying our tunnel.
2759 * Tries to maintain (incl. tear down) connections for the tunnel, and
2760 * if there is a significant change, may trigger transmissions.
2761 *
2762 * Basically, needs to check if there are connections that perform
2763 * badly, and if so eventually kill them and trigger a replacement.
2764 * The strategy is to open one more connection than
2765 * #DESIRED_CONNECTIONS_PER_TUNNEL, and then periodically kick out the
2766 * least-performing one, and then inquire for new ones.
2767 *
2768 * @param cls the `struct CadetTunnel`
2769 */
2770static void
2771maintain_connections_cb (void *cls)
2772{
2773 struct CadetTunnel *t = cls;
2774 struct GNUNET_TIME_Relative delay;
2775 struct EvaluationSummary es;
2776
2777 t->maintain_connections_task = NULL;
2778 LOG (GNUNET_ERROR_TYPE_DEBUG,
2779 "Performing connection maintenance for %s.\n",
2780 GCT_2s (t));
2781
2782 es.min_length = UINT_MAX;
2783 es.max_length = 0;
2784 es.max_desire = 0;
2785 es.min_desire = UINT64_MAX;
2786 es.path = NULL;
2787 es.worst = NULL;
2788 es.duplicate = GNUNET_NO;
2789 GCT_iterate_connections (t,
2790 &evaluate_connection,
2791 &es);
2792 if ((NULL != es.worst) &&
2793 (GCT_count_any_connections (t) > DESIRED_CONNECTIONS_PER_TUNNEL))
2794 {
2795 /* Clear out worst-performing connection 'es.worst'. */
2796 destroy_t_connection (t,
2797 es.worst);
2798 }
2799
2800 /* Consider additional paths */
2801 (void) GCP_iterate_paths (t->destination,
2802 &consider_path_cb,
2803 t);
2804
2805 /* FIXME: calculate when to try again based on how well we are doing;
2806 in particular, if we have to few connections, we might be able
2807 to do without this (as PATHS should tell us whenever a new path
2808 is available instantly; however, need to make sure this job is
2809 restarted after that happens).
2810 Furthermore, if the paths we do know are in a reasonably narrow
2811 quality band and are plentyful, we might also consider us stabilized
2812 and then reduce the frequency accordingly. */delay = GNUNET_TIME_UNIT_MINUTES;
2813 t->maintain_connections_task
2814 = GNUNET_SCHEDULER_add_delayed (delay,
2815 &maintain_connections_cb,
2816 t);
2817}
2818
2819
2820void
2821GCT_consider_path (struct CadetTunnel *t,
2822 struct CadetPeerPath *p,
2823 unsigned int off)
2824{
2825 LOG (GNUNET_ERROR_TYPE_DEBUG,
2826 "Considering %s for %s (offset %u)\n",
2827 GCPP_2s (p),
2828 GCT_2s (t),
2829 off);
2830 (void) consider_path_cb (t,
2831 p,
2832 off);
2833}
2834
2835
2836/**
2837 * We got a keepalive. Track in statistics.
2838 *
2839 * @param cls the `struct CadetTunnel` for which we decrypted the message
2840 * @param msg the message we received on the tunnel
2841 */
2842static void
2843handle_plaintext_keepalive (void *cls,
2844 const struct GNUNET_MessageHeader *msg)
2845{
2846 struct CadetTunnel *t = cls;
2847
2848 LOG (GNUNET_ERROR_TYPE_DEBUG,
2849 "Received KEEPALIVE on %s\n",
2850 GCT_2s (t));
2851 GNUNET_STATISTICS_update (stats,
2852 "# keepalives received",
2853 1,
2854 GNUNET_NO);
2855}
2856
2857
2858/**
2859 * Check that @a msg is well-formed.
2860 *
2861 * @param cls the `struct CadetTunnel` for which we decrypted the message
2862 * @param msg the message we received on the tunnel
2863 * @return #GNUNET_OK (any variable-size payload goes)
2864 */
2865static int
2866check_plaintext_data (void *cls,
2867 const struct GNUNET_CADET_ChannelAppDataMessage *msg)
2868{
2869 return GNUNET_OK;
2870}
2871
2872
2873/**
2874 * We received payload data for a channel. Locate the channel
2875 * and process the data, or return an error if the channel is unknown.
2876 *
2877 * @param cls the `struct CadetTunnel` for which we decrypted the message
2878 * @param msg the message we received on the tunnel
2879 */
2880static void
2881handle_plaintext_data (void *cls,
2882 const struct GNUNET_CADET_ChannelAppDataMessage *msg)
2883{
2884 struct CadetTunnel *t = cls;
2885 struct CadetChannel *ch;
2886
2887 ch = lookup_channel (t,
2888 msg->ctn);
2889 if (NULL == ch)
2890 {
2891 /* We don't know about such a channel, might have been destroyed on our
2892 end in the meantime, or never existed. Send back a DESTROY. */
2893 LOG (GNUNET_ERROR_TYPE_DEBUG,
2894 "Received %u bytes of application data for unknown channel %u, sending DESTROY\n",
2895 (unsigned int) (ntohs (msg->header.size) - sizeof(*msg)),
2896 ntohl (msg->ctn.cn));
2897 GCT_send_channel_destroy (t,
2898 msg->ctn);
2899 return;
2900 }
2901 GCCH_handle_channel_plaintext_data (ch,
2902 GCC_get_id (t->current_ct->cc),
2903 msg);
2904}
2905
2906
2907/**
2908 * We received an acknowledgement for data we sent on a channel.
2909 * Locate the channel and process it, or return an error if the
2910 * channel is unknown.
2911 *
2912 * @param cls the `struct CadetTunnel` for which we decrypted the message
2913 * @param ack the message we received on the tunnel
2914 */
2915static void
2916handle_plaintext_data_ack (void *cls,
2917 const struct GNUNET_CADET_ChannelDataAckMessage *ack)
2918{
2919 struct CadetTunnel *t = cls;
2920 struct CadetChannel *ch;
2921
2922 ch = lookup_channel (t,
2923 ack->ctn);
2924 if (NULL == ch)
2925 {
2926 /* We don't know about such a channel, might have been destroyed on our
2927 end in the meantime, or never existed. Send back a DESTROY. */
2928 LOG (GNUNET_ERROR_TYPE_DEBUG,
2929 "Received DATA_ACK for unknown channel %u, sending DESTROY\n",
2930 ntohl (ack->ctn.cn));
2931 GCT_send_channel_destroy (t,
2932 ack->ctn);
2933 return;
2934 }
2935 GCCH_handle_channel_plaintext_data_ack (ch,
2936 GCC_get_id (t->current_ct->cc),
2937 ack);
2938}
2939
2940
2941/**
2942 * We have received a request to open a channel to a port from
2943 * another peer. Creates the incoming channel.
2944 *
2945 * @param cls the `struct CadetTunnel` for which we decrypted the message
2946 * @param copen the message we received on the tunnel
2947 */
2948static void
2949handle_plaintext_channel_open (void *cls,
2950 const struct
2951 GNUNET_CADET_ChannelOpenMessage *copen)
2952{
2953 struct CadetTunnel *t = cls;
2954 struct CadetChannel *ch;
2955
2956 ch = GNUNET_CONTAINER_multihashmap32_get (t->channels,
2957 ntohl (copen->ctn.cn));
2958 if (NULL != ch)
2959 {
2960 LOG (GNUNET_ERROR_TYPE_DEBUG,
2961 "Received duplicate channel CHANNEL_OPEN on h_port %s from %s (%s), resending ACK\n",
2962 GNUNET_h2s (&copen->h_port),
2963 GCT_2s (t),
2964 GCCH_2s (ch));
2965 GCCH_handle_duplicate_open (ch,
2966 GCC_get_id (t->current_ct->cc));
2967 return;
2968 }
2969 LOG (GNUNET_ERROR_TYPE_DEBUG,
2970 "Received CHANNEL_OPEN on h_port %s from %s\n",
2971 GNUNET_h2s (&copen->h_port),
2972 GCT_2s (t));
2973 ch = GCCH_channel_incoming_new (t,
2974 copen->ctn,
2975 &copen->h_port,
2976 ntohl (copen->opt));
2977 if (NULL != t->destroy_task)
2978 {
2979 GNUNET_SCHEDULER_cancel (t->destroy_task);
2980 t->destroy_task = NULL;
2981 }
2982 GNUNET_assert (GNUNET_OK ==
2983 GNUNET_CONTAINER_multihashmap32_put (t->channels,
2984 ntohl (copen->ctn.cn),
2985 ch,
2986 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
2987}
2988
2989
2990/**
2991 * Send a DESTROY message via the tunnel.
2992 *
2993 * @param t the tunnel to transmit over
2994 * @param ctn ID of the channel to destroy
2995 */
2996void
2997GCT_send_channel_destroy (struct CadetTunnel *t,
2998 struct GNUNET_CADET_ChannelTunnelNumber ctn)
2999{
3000 struct GNUNET_CADET_ChannelDestroyMessage msg;
3001
3002 LOG (GNUNET_ERROR_TYPE_DEBUG,
3003 "Sending DESTROY message for channel ID %u\n",
3004 ntohl (ctn.cn));
3005 msg.header.size = htons (sizeof(msg));
3006 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY);
3007 msg.reserved = htonl (0);
3008 msg.ctn = ctn;
3009 GCT_send (t,
3010 &msg.header,
3011 NULL,
3012 NULL,
3013 &ctn);
3014}
3015
3016
3017/**
3018 * We have received confirmation from the target peer that the
3019 * given channel could be established (the port is open).
3020 * Tell the client.
3021 *
3022 * @param cls the `struct CadetTunnel` for which we decrypted the message
3023 * @param cm the message we received on the tunnel
3024 */
3025static void
3026handle_plaintext_channel_open_ack (void *cls,
3027 const struct
3028 GNUNET_CADET_ChannelOpenAckMessage *cm)
3029{
3030 struct CadetTunnel *t = cls;
3031 struct CadetChannel *ch;
3032
3033 ch = lookup_channel (t,
3034 cm->ctn);
3035 if (NULL == ch)
3036 {
3037 /* We don't know about such a channel, might have been destroyed on our
3038 end in the meantime, or never existed. Send back a DESTROY. */
3039 LOG (GNUNET_ERROR_TYPE_DEBUG,
3040 "Received channel OPEN_ACK for unknown channel %u, sending DESTROY\n",
3041 ntohl (cm->ctn.cn));
3042 GCT_send_channel_destroy (t,
3043 cm->ctn);
3044 return;
3045 }
3046 LOG (GNUNET_ERROR_TYPE_DEBUG,
3047 "Received channel OPEN_ACK on channel %s from %s\n",
3048 GCCH_2s (ch),
3049 GCT_2s (t));
3050 GCCH_handle_channel_open_ack (ch,
3051 GCC_get_id (t->current_ct->cc),
3052 &cm->port);
3053}
3054
3055
3056/**
3057 * We received a message saying that a channel should be destroyed.
3058 * Pass it on to the correct channel.
3059 *
3060 * @param cls the `struct CadetTunnel` for which we decrypted the message
3061 * @param cm the message we received on the tunnel
3062 */
3063static void
3064handle_plaintext_channel_destroy (void *cls,
3065 const struct
3066 GNUNET_CADET_ChannelDestroyMessage *cm)
3067{
3068 struct CadetTunnel *t = cls;
3069 struct CadetChannel *ch;
3070
3071 ch = lookup_channel (t,
3072 cm->ctn);
3073 if (NULL == ch)
3074 {
3075 /* We don't know about such a channel, might have been destroyed on our
3076 end in the meantime, or never existed. */
3077 LOG (GNUNET_ERROR_TYPE_DEBUG,
3078 "Received channel DESTROY for unknown channel %u. Ignoring.\n",
3079 ntohl (cm->ctn.cn));
3080 return;
3081 }
3082 LOG (GNUNET_ERROR_TYPE_DEBUG,
3083 "Received channel DESTROY on %s from %s\n",
3084 GCCH_2s (ch),
3085 GCT_2s (t));
3086 GCCH_handle_remote_destroy (ch,
3087 GCC_get_id (t->current_ct->cc));
3088}
3089
3090
3091/**
3092 * Handles a message we decrypted, by injecting it into
3093 * our message queue (which will do the dispatching).
3094 *
3095 * @param cls the `struct CadetTunnel` that got the message
3096 * @param msg the message
3097 * @return #GNUNET_OK on success (always)
3098 * #GNUNET_NO to stop further processing (no error)
3099 * #GNUNET_SYSERR to stop further processing with error
3100 */
3101static int
3102handle_decrypted (void *cls,
3103 const struct GNUNET_MessageHeader *msg)
3104{
3105 struct CadetTunnel *t = cls;
3106
3107 GNUNET_assert (NULL != t->current_ct);
3108 GNUNET_MQ_inject_message (t->mq,
3109 msg);
3110 return GNUNET_OK;
3111}
3112
3113
3114/**
3115 * Function called if we had an error processing
3116 * an incoming decrypted message.
3117 *
3118 * @param cls the `struct CadetTunnel`
3119 * @param error error code
3120 */
3121static void
3122decrypted_error_cb (void *cls,
3123 enum GNUNET_MQ_Error error)
3124{
3125 GNUNET_break_op (0);
3126}
3127
3128
3129/**
3130 * Create a tunnel to @a destination. Must only be called
3131 * from within #GCP_get_tunnel().
3132 *
3133 * @param destination where to create the tunnel to
3134 * @return new tunnel to @a destination
3135 */
3136struct CadetTunnel *
3137GCT_create_tunnel (struct CadetPeer *destination)
3138{
3139 struct CadetTunnel *t = GNUNET_new (struct CadetTunnel);
3140 struct GNUNET_MQ_MessageHandler handlers[] = {
3141 GNUNET_MQ_hd_fixed_size (plaintext_keepalive,
3142 GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE,
3143 struct GNUNET_MessageHeader,
3144 t),
3145 GNUNET_MQ_hd_var_size (plaintext_data,
3146 GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA,
3147 struct GNUNET_CADET_ChannelAppDataMessage,
3148 t),
3149 GNUNET_MQ_hd_fixed_size (plaintext_data_ack,
3150 GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK,
3151 struct GNUNET_CADET_ChannelDataAckMessage,
3152 t),
3153 GNUNET_MQ_hd_fixed_size (plaintext_channel_open,
3154 GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN,
3155 struct GNUNET_CADET_ChannelOpenMessage,
3156 t),
3157 GNUNET_MQ_hd_fixed_size (plaintext_channel_open_ack,
3158 GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK,
3159 struct GNUNET_CADET_ChannelOpenAckMessage,
3160 t),
3161 GNUNET_MQ_hd_fixed_size (plaintext_channel_destroy,
3162 GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY,
3163 struct GNUNET_CADET_ChannelDestroyMessage,
3164 t),
3165 GNUNET_MQ_handler_end ()
3166 };
3167
3168 t->kx_retry_delay = INITIAL_KX_RETRY_DELAY;
3169 new_ephemeral (&t->ax);
3170 GNUNET_CRYPTO_ecdhe_key_create (&t->ax.kx_0);
3171 t->destination = destination;
3172 t->channels = GNUNET_CONTAINER_multihashmap32_create (8);
3173 t->maintain_connections_task
3174 = GNUNET_SCHEDULER_add_now (&maintain_connections_cb,
3175 t);
3176 t->mq = GNUNET_MQ_queue_for_callbacks (NULL,
3177 NULL,
3178 NULL,
3179 NULL,
3180 handlers,
3181 &decrypted_error_cb,
3182 t);
3183 t->mst = GNUNET_MST_create (&handle_decrypted,
3184 t);
3185 return t;
3186}
3187
3188
3189int
3190GCT_add_inbound_connection (struct CadetTunnel *t,
3191 const struct
3192 GNUNET_CADET_ConnectionTunnelIdentifier *cid,
3193 struct CadetPeerPath *path)
3194{
3195 struct CadetTConnection *ct;
3196
3197 ct = GNUNET_new (struct CadetTConnection);
3198 ct->created = GNUNET_TIME_absolute_get ();
3199 ct->t = t;
3200 ct->cc = GCC_create_inbound (t->destination,
3201 path,
3202 ct,
3203 cid,
3204 &connection_ready_cb,
3205 ct);
3206 if (NULL == ct->cc)
3207 {
3208 LOG (GNUNET_ERROR_TYPE_DEBUG,
3209 "%s refused inbound %s (duplicate)\n",
3210 GCT_2s (t),
3211 GCC_2s (ct->cc));
3212 GNUNET_free (ct);
3213 return GNUNET_SYSERR;
3214 }
3215 /* FIXME: schedule job to kill connection (and path?) if it takes
3216 too long to get ready! (And track performance data on how long
3217 other connections took with the tunnel!)
3218 => Note: to be done within 'connection'-logic! */
3219 GNUNET_CONTAINER_DLL_insert (t->connection_busy_head,
3220 t->connection_busy_tail,
3221 ct);
3222 t->num_busy_connections++;
3223 LOG (GNUNET_ERROR_TYPE_DEBUG,
3224 "%s has new %s\n",
3225 GCT_2s (t),
3226 GCC_2s (ct->cc));
3227 return GNUNET_OK;
3228}
3229
3230
3231/**
3232 * Handle encrypted message.
3233 *
3234 * @param ct connection/tunnel combo that received encrypted message
3235 * @param msg the encrypted message to decrypt
3236 */
3237void
3238GCT_handle_encrypted (struct CadetTConnection *ct,
3239 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
3240{
3241 struct CadetTunnel *t = ct->t;
3242 uint16_t size = ntohs (msg->header.size);
3243 char cbuf[size] GNUNET_ALIGN;
3244 ssize_t decrypted_size;
3245
3246 LOG (GNUNET_ERROR_TYPE_DEBUG,
3247 "%s received %u bytes of encrypted data in state %d\n",
3248 GCT_2s (t),
3249 (unsigned int) size,
3250 t->estate);
3251
3252 switch (t->estate)
3253 {
3254 case CADET_TUNNEL_KEY_UNINITIALIZED:
3255 case CADET_TUNNEL_KEY_AX_RECV:
3256 /* We did not even SEND our KX, how can the other peer
3257 send us encrypted data? Must have been that we went
3258 down and the other peer still things we are up.
3259 Let's send it KX back. */
3260 GNUNET_STATISTICS_update (stats,
3261 "# received encrypted without any KX",
3262 1,
3263 GNUNET_NO);
3264 if (NULL != t->kx_task)
3265 {
3266 GNUNET_SCHEDULER_cancel (t->kx_task);
3267 t->kx_task = NULL;
3268 }
3269 send_kx (t,
3270 ct,
3271 &t->ax);
3272 return;
3273
3274 case CADET_TUNNEL_KEY_AX_SENT_AND_RECV:
3275 /* We send KX, and other peer send KX to us at the same time.
3276 Neither KX is AUTH'ed, so let's try KX_AUTH this time. */
3277 GNUNET_STATISTICS_update (stats,
3278 "# received encrypted without KX_AUTH",
3279 1,
3280 GNUNET_NO);
3281 if (NULL != t->kx_task)
3282 {
3283 GNUNET_SCHEDULER_cancel (t->kx_task);
3284 t->kx_task = NULL;
3285 }
3286 send_kx_auth (t,
3287 ct,
3288 &t->ax,
3289 GNUNET_YES);
3290 return;
3291
3292 case CADET_TUNNEL_KEY_AX_SENT:
3293 /* We did not get the KX of the other peer, but that
3294 might have been lost. Send our KX again immediately. */
3295 GNUNET_STATISTICS_update (stats,
3296 "# received encrypted without KX",
3297 1,
3298 GNUNET_NO);
3299 if (NULL != t->kx_task)
3300 {
3301 GNUNET_SCHEDULER_cancel (t->kx_task);
3302 t->kx_task = NULL;
3303 }
3304 send_kx (t,
3305 ct,
3306 &t->ax);
3307 return;
3308
3309 case CADET_TUNNEL_KEY_AX_AUTH_SENT:
3310 /* Great, first payload, we might graduate to OK! */
3311 case CADET_TUNNEL_KEY_OK:
3312 /* We are up and running, all good. */
3313 break;
3314 }
3315
3316 decrypted_size = -1;
3317 if (CADET_TUNNEL_KEY_OK == t->estate)
3318 {
3319 /* We have well-established key material available,
3320 try that. (This is the common case.) */
3321 decrypted_size = t_ax_decrypt_and_validate (&t->ax,
3322 cbuf,
3323 msg,
3324 size);
3325 }
3326
3327 if ((-1 == decrypted_size) &&
3328 (NULL != t->unverified_ax))
3329 {
3330 /* We have un-authenticated KX material available. We should try
3331 this as a back-up option, in case the sender crashed and
3332 switched keys. */
3333 decrypted_size = t_ax_decrypt_and_validate (t->unverified_ax,
3334 cbuf,
3335 msg,
3336 size);
3337 if (-1 != decrypted_size)
3338 {
3339 /* It worked! Treat this as authentication of the AX data! */
3340 cleanup_ax (&t->ax);
3341 t->ax = *t->unverified_ax;
3342 GNUNET_free (t->unverified_ax);
3343 t->unverified_ax = NULL;
3344 }
3345 if (CADET_TUNNEL_KEY_AX_AUTH_SENT == t->estate)
3346 {
3347 /* First time it worked, move tunnel into production! */
3348 GCT_change_estate (t,
3349 CADET_TUNNEL_KEY_OK);
3350 if (NULL != t->send_task)
3351 GNUNET_SCHEDULER_cancel (t->send_task);
3352 t->send_task = GNUNET_SCHEDULER_add_now (&trigger_transmissions,
3353 t);
3354 }
3355 }
3356 if (NULL != t->unverified_ax)
3357 {
3358 /* We had unverified KX material that was useless; so increment
3359 counter and eventually move to ignore it. Note that we even do
3360 this increment if we successfully decrypted with the old KX
3361 material and thus didn't even both with the new one. This is
3362 the ideal case, as a malicious injection of bogus KX data
3363 basically only causes us to increment a counter a few times. */t->unverified_attempts++;
3364 LOG (GNUNET_ERROR_TYPE_DEBUG,
3365 "Failed to decrypt message with unverified KX data %u times\n",
3366 t->unverified_attempts);
3367 if (t->unverified_attempts > MAX_UNVERIFIED_ATTEMPTS)
3368 {
3369 cleanup_ax (t->unverified_ax);
3370 GNUNET_free (t->unverified_ax);
3371 t->unverified_ax = NULL;
3372 }
3373 }
3374
3375 if (-1 == decrypted_size)
3376 {
3377 /* Decryption failed for good, complain. */
3378 LOG (GNUNET_ERROR_TYPE_WARNING,
3379 "%s failed to decrypt and validate encrypted data, retrying KX\n",
3380 GCT_2s (t));
3381 GNUNET_STATISTICS_update (stats,
3382 "# unable to decrypt",
3383 1,
3384 GNUNET_NO);
3385 if (NULL != t->kx_task)
3386 {
3387 GNUNET_SCHEDULER_cancel (t->kx_task);
3388 t->kx_task = NULL;
3389 }
3390 send_kx (t,
3391 ct,
3392 &t->ax);
3393 return;
3394 }
3395 GNUNET_STATISTICS_update (stats,
3396 "# decrypted bytes",
3397 decrypted_size,
3398 GNUNET_NO);
3399
3400 /* The MST will ultimately call #handle_decrypted() on each message. */
3401 t->current_ct = ct;
3402 GNUNET_break_op (GNUNET_OK ==
3403 GNUNET_MST_from_buffer (t->mst,
3404 cbuf,
3405 decrypted_size,
3406 GNUNET_YES,
3407 GNUNET_NO));
3408 t->current_ct = NULL;
3409}
3410
3411
3412struct CadetTunnelQueueEntry *
3413GCT_send (struct CadetTunnel *t,
3414 const struct GNUNET_MessageHeader *message,
3415 GCT_SendContinuation cont,
3416 void *cont_cls,
3417 struct GNUNET_CADET_ChannelTunnelNumber *ctn)
3418{
3419 struct CadetTunnelQueueEntry *tq;
3420 uint16_t payload_size;
3421 struct GNUNET_MQ_Envelope *env;
3422 struct GNUNET_CADET_TunnelEncryptedMessage *ax_msg;
3423 struct CadetChannel *ch;
3424
3425 if (NULL != ctn)
3426 {
3427 ch = lookup_channel (t,
3428 *ctn);
3429 if ((NULL != ch) && GCCH_is_type_to_drop (ch, message))
3430 {
3431 GNUNET_break (0);
3432 return NULL;
3433 }
3434 }
3435
3436 if (CADET_TUNNEL_KEY_OK != t->estate)
3437 {
3438 GNUNET_break (0);
3439 return NULL;
3440 }
3441 payload_size = ntohs (message->size);
3442 LOG (GNUNET_ERROR_TYPE_DEBUG,
3443 "Encrypting %u bytes for %s\n",
3444 (unsigned int) payload_size,
3445 GCT_2s (t));
3446 env = GNUNET_MQ_msg_extra (ax_msg,
3447 payload_size,
3448 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED);
3449 t_ax_encrypt (&t->ax,
3450 &ax_msg[1],
3451 message,
3452 payload_size);
3453 GNUNET_STATISTICS_update (stats,
3454 "# encrypted bytes",
3455 payload_size,
3456 GNUNET_NO);
3457 ax_msg->ax_header.Ns = htonl (t->ax.Ns++);
3458 ax_msg->ax_header.PNs = htonl (t->ax.PNs);
3459 /* FIXME: we should do this once, not once per message;
3460 this is a point multiplication, and DHRs does not
3461 change all the time. */
3462 GNUNET_CRYPTO_ecdhe_key_get_public (&t->ax.DHRs,
3463 &ax_msg->ax_header.DHRs);
3464 t_h_encrypt (&t->ax,
3465 ax_msg);
3466 t_hmac (&ax_msg->ax_header,
3467 sizeof(struct GNUNET_CADET_AxHeader) + payload_size,
3468 0,
3469 &t->ax.HKs,
3470 &ax_msg->hmac);
3471
3472 tq = GNUNET_malloc (sizeof(*tq));
3473 tq->t = t;
3474 tq->env = env;
3475 tq->cid = &ax_msg->cid; /* will initialize 'ax_msg->cid' once we know the connection */
3476 tq->cont = cont;
3477 tq->cont_cls = cont_cls;
3478 GNUNET_CONTAINER_DLL_insert_tail (t->tq_head,
3479 t->tq_tail,
3480 tq);
3481 if (NULL != t->send_task)
3482 GNUNET_SCHEDULER_cancel (t->send_task);
3483 t->send_task
3484 = GNUNET_SCHEDULER_add_now (&trigger_transmissions,
3485 t);
3486 return tq;
3487}
3488
3489
3490void
3491GCT_send_cancel (struct CadetTunnelQueueEntry *tq)
3492{
3493 struct CadetTunnel *t = tq->t;
3494
3495 GNUNET_CONTAINER_DLL_remove (t->tq_head,
3496 t->tq_tail,
3497 tq);
3498 GNUNET_MQ_discard (tq->env);
3499 GNUNET_free (tq);
3500}
3501
3502
3503/**
3504 * Iterate over all connections of a tunnel.
3505 *
3506 * @param t Tunnel whose connections to iterate.
3507 * @param iter Iterator.
3508 * @param iter_cls Closure for @c iter.
3509 */
3510void
3511GCT_iterate_connections (struct CadetTunnel *t,
3512 GCT_ConnectionIterator iter,
3513 void *iter_cls)
3514{
3515 struct CadetTConnection *n;
3516
3517 for (struct CadetTConnection *ct = t->connection_ready_head;
3518 NULL != ct;
3519 ct = n)
3520 {
3521 n = ct->next;
3522 iter (iter_cls,
3523 ct);
3524 }
3525 for (struct CadetTConnection *ct = t->connection_busy_head;
3526 NULL != ct;
3527 ct = n)
3528 {
3529 n = ct->next;
3530 iter (iter_cls,
3531 ct);
3532 }
3533}
3534
3535
3536/**
3537 * Closure for #iterate_channels_cb.
3538 */
3539struct ChanIterCls
3540{
3541 /**
3542 * Function to call.
3543 */
3544 GCT_ChannelIterator iter;
3545
3546 /**
3547 * Closure for @e iter.
3548 */
3549 void *iter_cls;
3550};
3551
3552
3553/**
3554 * Helper function for #GCT_iterate_channels.
3555 *
3556 * @param cls the `struct ChanIterCls`
3557 * @param key unused
3558 * @param value a `struct CadetChannel`
3559 * @return #GNUNET_OK
3560 */
3561static int
3562iterate_channels_cb (void *cls,
3563 uint32_t key,
3564 void *value)
3565{
3566 struct ChanIterCls *ctx = cls;
3567 struct CadetChannel *ch = value;
3568
3569 ctx->iter (ctx->iter_cls,
3570 ch);
3571 return GNUNET_OK;
3572}
3573
3574
3575/**
3576 * Iterate over all channels of a tunnel.
3577 *
3578 * @param t Tunnel whose channels to iterate.
3579 * @param iter Iterator.
3580 * @param iter_cls Closure for @c iter.
3581 */
3582void
3583GCT_iterate_channels (struct CadetTunnel *t,
3584 GCT_ChannelIterator iter,
3585 void *iter_cls)
3586{
3587 struct ChanIterCls ctx;
3588
3589 ctx.iter = iter;
3590 ctx.iter_cls = iter_cls;
3591 GNUNET_CONTAINER_multihashmap32_iterate (t->channels,
3592 &iterate_channels_cb,
3593 &ctx);
3594}
3595
3596
3597/**
3598 * Call #GCCH_debug() on a channel.
3599 *
3600 * @param cls points to the log level to use
3601 * @param key unused
3602 * @param value the `struct CadetChannel` to dump
3603 * @return #GNUNET_OK (continue iteration)
3604 */
3605static int
3606debug_channel (void *cls,
3607 uint32_t key,
3608 void *value)
3609{
3610 const enum GNUNET_ErrorType *level = cls;
3611 struct CadetChannel *ch = value;
3612
3613 GCCH_debug (ch, *level);
3614 return GNUNET_OK;
3615}
3616
3617
3618#define LOG2(level, ...) GNUNET_log_from_nocheck (level, "cadet-tun", \
3619 __VA_ARGS__)
3620
3621
3622/**
3623 * Log all possible info about the tunnel state.
3624 *
3625 * @param t Tunnel to debug.
3626 * @param level Debug level to use.
3627 */
3628void
3629GCT_debug (const struct CadetTunnel *t,
3630 enum GNUNET_ErrorType level)
3631{
3632#if ! defined(GNUNET_CULL_LOGGING)
3633 struct CadetTConnection *iter_c;
3634 int do_log;
3635
3636 do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
3637 "cadet-tun",
3638 __FILE__, __FUNCTION__, __LINE__);
3639 if (0 == do_log)
3640 return;
3641
3642 LOG2 (level,
3643 "TTT TUNNEL TOWARDS %s in estate %s tq_len: %u #cons: %u\n",
3644 GCT_2s (t),
3645 estate2s (t->estate),
3646 t->tq_len,
3647 GCT_count_any_connections (t));
3648 LOG2 (level,
3649 "TTT channels:\n");
3650 GNUNET_CONTAINER_multihashmap32_iterate (t->channels,
3651 &debug_channel,
3652 &level);
3653 LOG2 (level,
3654 "TTT connections:\n");
3655 for (iter_c = t->connection_ready_head; NULL != iter_c; iter_c = iter_c->next)
3656 GCC_debug (iter_c->cc,
3657 level);
3658 for (iter_c = t->connection_busy_head; NULL != iter_c; iter_c = iter_c->next)
3659 GCC_debug (iter_c->cc,
3660 level);
3661
3662 LOG2 (level,
3663 "TTT TUNNEL END\n");
3664#endif
3665}
3666
3667
3668/* end of gnunet-service-cadet_tunnels.c */
diff --git a/src/service/cadet/gnunet-service-cadet_tunnels.h b/src/service/cadet/gnunet-service-cadet_tunnels.h
new file mode 100644
index 000000000..e893955a0
--- /dev/null
+++ b/src/service/cadet/gnunet-service-cadet_tunnels.h
@@ -0,0 +1,391 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2001-2017 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file cadet/gnunet-service-cadet_tunnels.h
23 * @brief Information we track per tunnel.
24 * @author Bartlomiej Polot
25 * @author Christian Grothoff
26 */
27#ifndef GNUNET_SERVICE_CADET_TUNNELS_H
28#define GNUNET_SERVICE_CADET_TUNNELS_H
29
30#include "gnunet-service-cadet.h"
31#include "cadet_protocol.h"
32
33
34/**
35 * How many connections would we like to have per tunnel?
36 */
37#define DESIRED_CONNECTIONS_PER_TUNNEL 3
38
39
40/**
41 * All the encryption states a tunnel can be in.
42 */
43enum CadetTunnelEState
44{
45 /**
46 * Uninitialized status, we need to send KX. We will stay
47 * in this state until the first connection is up.
48 */
49 CADET_TUNNEL_KEY_UNINITIALIZED,
50
51 /**
52 * KX message sent, waiting for other peer's KX_AUTH.
53 */
54 CADET_TUNNEL_KEY_AX_SENT,
55
56 /**
57 * KX message received, trying to send back KX_AUTH.
58 */
59 CADET_TUNNEL_KEY_AX_RECV,
60
61 /**
62 * KX message sent and received, trying to send back KX_AUTH.
63 */
64 CADET_TUNNEL_KEY_AX_SENT_AND_RECV,
65
66 /**
67 * KX received and we sent KX_AUTH back, but we got no traffic yet,
68 * so we're waiting for either KX_AUTH or ENCRYPED traffic from
69 * the other peer.
70 *
71 * We will not yet send traffic, as this might have been a replay.
72 * The other (initiating) peer should send a CHANNEL_OPEN next
73 * anyway, and then we are in business!
74 */
75 CADET_TUNNEL_KEY_AX_AUTH_SENT,
76
77 /**
78 * Handshake completed: session key available.
79 */
80 CADET_TUNNEL_KEY_OK
81};
82
83/**
84 * Am I Alice or Betty (some call her Bob), or talking to myself?
85 *
86 * @param other the other peer
87 * @return #GNUNET_YES for Alice, #GNUNET_NO for Betty, #GNUNET_SYSERR if talking to myself
88 */
89int
90GCT_alice_or_betty (const struct GNUNET_PeerIdentity *other);
91
92/**
93 * Get the static string for the peer this tunnel is directed.
94 *
95 * @param t Tunnel.
96 *
97 * @return Static string the destination peer's ID.
98 */
99const char *
100GCT_2s (const struct CadetTunnel *t);
101
102
103/**
104 * Create a tunnel to @a destination. Must only be called
105 * from within #GCP_get_tunnel().
106 *
107 * @param destination where to create the tunnel to
108 * @return new tunnel to @a destination
109 */
110struct CadetTunnel *
111GCT_create_tunnel (struct CadetPeer *destination);
112
113
114/**
115 * Destroys the tunnel @a t now, without delay. Used during shutdown.
116 *
117 * @param t tunnel to destroy
118 */
119void
120GCT_destroy_tunnel_now (struct CadetTunnel *t);
121
122
123/**
124 * Add a @a connection to the @a tunnel.
125 *
126 * @param t a tunnel
127 * @param cid connection identifier to use for the connection
128 * @param path path to use for the connection
129 * @return #GNUNET_OK on success,
130 * #GNUNET_SYSERR on failure (duplicate connection)
131 */
132int
133GCT_add_inbound_connection (struct CadetTunnel *t,
134 const struct
135 GNUNET_CADET_ConnectionTunnelIdentifier *cid,
136 struct CadetPeerPath *path);
137
138
139/**
140 * We lost a connection, remove it from our list and clean up
141 * the connection object itself.
142 *
143 * @param ct binding of connection to tunnel of the connection that was lost.
144 */
145void
146GCT_connection_lost (struct CadetTConnection *ct);
147
148
149/**
150 * Return the peer to which this tunnel goes.
151 *
152 * @param t a tunnel
153 * @return the destination of the tunnel
154 */
155struct CadetPeer *
156GCT_get_destination (struct CadetTunnel *t);
157
158
159/**
160 * Consider using the path @a p for the tunnel @a t.
161 * The tunnel destination is at offset @a off in path @a p.
162 *
163 * @param t our tunnel
164 * @param p a path to our destination
165 * @param off offset of the destination on path @a path
166 */
167void
168GCT_consider_path (struct CadetTunnel *t,
169 struct CadetPeerPath *p,
170 unsigned int off);
171
172
173/**
174 * Add a channel to a tunnel.
175 *
176 * @param t Tunnel.
177 * @param ch Channel
178 * @return unique number identifying @a ch within @a t
179 */
180struct GNUNET_CADET_ChannelTunnelNumber
181GCT_add_channel (struct CadetTunnel *t,
182 struct CadetChannel *ch);
183
184
185/**
186 * Remove a channel from a tunnel.
187 *
188 * @param t Tunnel.
189 * @param ch Channel
190 * @param ctn unique number identifying @a ch within @a t
191 */
192void
193GCT_remove_channel (struct CadetTunnel *t,
194 struct CadetChannel *ch,
195 struct GNUNET_CADET_ChannelTunnelNumber ctn);
196
197
198/**
199 * Send a DESTROY message via the tunnel.
200 *
201 * @param t the tunnel to transmit over
202 * @param ctn ID of the channel to destroy
203 */
204void
205GCT_send_channel_destroy (struct CadetTunnel *t,
206 struct GNUNET_CADET_ChannelTunnelNumber ctn);
207
208
209/**
210 * Function called when a transmission requested using #GCT_send is done.
211 *
212 * @param cls closure
213 * @param ctn identifier of the connection used for transmission, NULL if
214 * the transmission failed (to be used to match ACKs to the
215 * respective connection for connection performance evaluation)
216 */
217typedef void
218(*GCT_SendContinuation)(void *cls,
219 const struct
220 GNUNET_CADET_ConnectionTunnelIdentifier *cid);
221
222
223/**
224 * Sends an already built message on a tunnel, encrypting it and
225 * choosing the best connection if not provided.
226 *
227 * @param message Message to send. Function modifies it.
228 * @param t Tunnel on which this message is transmitted.
229 * @param cont Continuation to call once message is really sent.
230 * @param cont_cls Closure for @c cont.
231 * @return Handle to cancel message.
232 */
233struct CadetTunnelQueueEntry *
234GCT_send (struct CadetTunnel *t,
235 const struct GNUNET_MessageHeader *message,
236 GCT_SendContinuation cont,
237 void *cont_cls,
238 struct GNUNET_CADET_ChannelTunnelNumber *ctn);
239
240
241/**
242 * Cancel a previously sent message while it's in the queue.
243 *
244 * ONLY can be called before the continuation given to the send
245 * function is called. Once the continuation is called, the message is
246 * no longer in the queue!
247 *
248 * @param q Handle to the queue entry to cancel.
249 */
250void
251GCT_send_cancel (struct CadetTunnelQueueEntry *q);
252
253
254/**
255 * Returns the number of channels using a tunnel.
256 *
257 * @param t Tunnel in question.
258 * @return Number of channels using the tunnel.
259 */
260unsigned int
261GCT_count_channels (struct CadetTunnel *t);
262
263
264/**
265 * Counts the number of connections created for a tunnel,
266 * including busy connections.
267 *
268 * @param t Tunnel to be counted.
269 * @return Number of connections created for the tunnel.
270 */
271unsigned int
272GCT_count_any_connections (const struct CadetTunnel *t);
273
274
275/**
276 * Iterator over connections.
277 *
278 * @param cls closure
279 * @param ct one of the connections
280 */
281typedef void
282(*GCT_ConnectionIterator) (void *cls,
283 struct CadetTConnection *ct);
284
285
286/**
287 * Iterate over all connections of a tunnel.
288 *
289 * @param t Tunnel whose connections to iterate.
290 * @param iter Iterator.
291 * @param iter_cls Closure for @c iter.
292 */
293void
294GCT_iterate_connections (struct CadetTunnel *t,
295 GCT_ConnectionIterator iter,
296 void *iter_cls);
297
298
299/**
300 * Iterator over channels.
301 *
302 * @param cls closure
303 * @param ch one of the channels
304 */
305typedef void
306(*GCT_ChannelIterator) (void *cls,
307 struct CadetChannel *ch);
308
309
310/**
311 * Iterate over all channels of a tunnel.
312 *
313 * @param t Tunnel whose channels to iterate.
314 * @param iter Iterator.
315 * @param iter_cls Closure for @c iter.
316 */
317void
318GCT_iterate_channels (struct CadetTunnel *t,
319 GCT_ChannelIterator iter,
320 void *iter_cls);
321
322
323/**
324 * Get the encryption state of a tunnel.
325 *
326 * @param t Tunnel.
327 *
328 * @return Tunnel's encryption state.
329 */
330enum CadetTunnelEState
331GCT_get_estate (struct CadetTunnel *t);
332
333/**
334 * Change the tunnel encryption state.
335 * If the encryption state changes to OK, stop the rekey task.
336 *
337 * @param t Tunnel whose encryption state to change, or NULL.
338 * @param state New encryption state.
339 */
340void
341GCT_change_estate (struct CadetTunnel *t,
342 enum CadetTunnelEState state);
343
344/**
345 * Handle KX message that lacks authentication (and which will thus
346 * only be considered authenticated after we respond with our own
347 * KX_AUTH and finally successfully decrypt the payload).
348 *
349 * @param ct connection/tunnel combo that received encrypted message
350 * @param msg the key exchange message
351 */
352void
353GCT_handle_kx (struct CadetTConnection *ct,
354 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg);
355
356
357/**
358 * Handle KX_AUTH message.
359 *
360 * @param ct connection/tunnel combo that received encrypted message
361 * @param msg the key exchange message
362 */
363void
364GCT_handle_kx_auth (struct CadetTConnection *ct,
365 const struct
366 GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg);
367
368
369/**
370 * Handle encrypted message.
371 *
372 * @param ct connection/tunnel combo that received encrypted message
373 * @param msg the encrypted message to decrypt
374 */
375void
376GCT_handle_encrypted (struct CadetTConnection *ct,
377 const struct GNUNET_CADET_TunnelEncryptedMessage *msg);
378
379
380/**
381 * Log all possible info about the tunnel state.
382 *
383 * @param t Tunnel to debug.
384 * @param level Debug level to use.
385 */
386void
387GCT_debug (const struct CadetTunnel *t,
388 enum GNUNET_ErrorType level);
389
390
391#endif
diff --git a/src/service/cadet/loopcheck.sh b/src/service/cadet/loopcheck.sh
new file mode 100755
index 000000000..9b867e95b
--- /dev/null
+++ b/src/service/cadet/loopcheck.sh
@@ -0,0 +1,57 @@
1#!/usr/bin/env bash
2# This script is in the public domain
3# POSIX shell solution for named pipes and pipestatus,
4# http://shell.cfajohnson.com/cus-faq-2.html#Q11
5# run() {
6# j=1
7# while eval "\${pipestatus_$j+:} false"; do
8# unset pipestatus_$j
9# j=$(($j+1))
10# done
11# j=1 com= k=1 l=
12# for a; do
13# if [ "x$a" = 'x|' ]; then
14# com="$com { $l "'3>&-
15# echo "pipestatus_'$j'=$?" >&3
16# } 4>&- |'
17# j=$(($j+1)) l=
18# else
19# l="$l \"\$$k\""
20# fi
21# k=$(($k+1))
22# done
23# com="$com $l"' 3>&- >&4 4>&-
24# echo "pipestatus_'$j'=$?"'
25# exec 4>&1
26# eval "$(exec 3>&1; eval "$com")"
27# exec 4>&-
28# j=1
29# while eval "\${pipestatus_$j+:} false"; do
30# eval "[ \$pipestatus_$j -eq 0 ]" || return 1
31# j=$(($j+1))
32# done
33# return 0
34# }
35
36# # https://mywiki.wooledge.org/Bashism has another solution:
37# # mkfifo fifo; command2 <fifo & command1 >fifo; echo "$?"
38
39while true; do
40 if [ "$1" = "" ]; then
41 echo All
42 taskset 1 make check || break;
43 else
44 echo One
45 LOGFILE="test_`date "+%m.%d-%H:%M:%S"`.log"
46 taskset 01 $1 2>&1 | tee $LOGFILE | grep -v DEBUG;
47 # TODO: Replace $PIPESTATUS with more portable code
48 if [ "${PIPESTATUS[0]}" != "0" ]; then
49 echo "Failed";
50 date;
51 break;
52 fi
53 fi
54 grep cadet test_*.log | grep -B 10 ERROR && break
55 grep cadet test_*.log | grep -B 10 Assert && break
56 ls core* > /dev/null 2>&1 && break
57done
diff --git a/src/service/cadet/meson.build b/src/service/cadet/meson.build
new file mode 100644
index 000000000..0f465e0e2
--- /dev/null
+++ b/src/service/cadet/meson.build
@@ -0,0 +1,72 @@
1libgnunetcadet_src = ['cadet_api.c',
2 'cadet_api_drop_message.c',
3 'cadet_api_get_channel.c',
4 'cadet_api_get_path.c',
5 'cadet_api_list_peers.c',
6 'cadet_api_list_tunnels.c',
7 'cadet_api_helper.c']
8
9gnunetcadet_src = ['gnunet-cadet.c']
10gnunetservicecadet_src = ['gnunet-service-cadet.c',
11 'gnunet-service-cadet_channel.c',
12 'gnunet-service-cadet_connection.c',
13 'gnunet-service-cadet_core.c',
14 'gnunet-service-cadet_dht.c',
15 'gnunet-service-cadet_hello.c',
16 'gnunet-service-cadet_tunnels.c',
17 'gnunet-service-cadet_paths.c',
18 'gnunet-service-cadet_peer.c']
19
20configure_file(input : 'cadet.conf.in',
21 output : 'cadet.conf',
22 configuration : cdata,
23 install: true,
24 install_dir: pkgcfgdir)
25
26if get_option('monolith')
27 foreach p : libgnunetcadet_src + gnunetservicecadet_src
28 gnunet_src += 'cadet/' + p
29 endforeach
30endif
31
32libgnunetcadet = library('gnunetcadet',
33 libgnunetcadet_src,
34 dependencies: libgnunetutil_dep,
35 include_directories: [incdir, configuration_inc],
36 install: true,
37 soversion: '7',
38 version: '7.0.0',
39 install_dir: get_option('libdir'))
40libgnunetcadet_dep = declare_dependency(link_with : libgnunetcadet)
41pkg.generate(libgnunetcadet, url: 'https://www.gnunet.org',
42 description : 'API for multicast and multi-hop routing between GNUnet peers')
43
44executable ('gnunet-service-cadet',
45 gnunetservicecadet_src,
46 dependencies: [libgnunetcadet_dep,
47 libgnunetutil_dep,
48 m_dep,
49 libgnunetcore_dep,
50 libgnunetdht_dep,
51 libgnunetstatistics_dep,
52 libgnunettransportapplication_dep,
53 libgnunetpeerstore_dep,
54 libgnunethello_dep,
55 libgnunetblock_dep],
56 include_directories: [incdir, configuration_inc],
57 install: true,
58 install_dir: get_option('libdir') / 'gnunet' / 'libexec')
59
60testcadetlocalmq = executable ('test_cadet_local_mq',
61 ['test_cadet_local_mq.c'],
62 dependencies: [libgnunetcadet_dep,
63 libgnunettesting_dep,
64 libgnunetutil_dep],
65 include_directories: [incdir, configuration_inc],
66 install: false)
67configure_file(input : 'test_cadet.conf',
68 output : 'test_cadet.conf',
69 configuration : cdata,
70 install: false)
71test('test_cadet_local_mq', testcadetlocalmq, workdir: meson.current_build_dir(), suite: 'cadet')
72
diff --git a/src/service/cadet/profiler.conf b/src/service/cadet/profiler.conf
new file mode 100644
index 000000000..7ce283870
--- /dev/null
+++ b/src/service/cadet/profiler.conf
@@ -0,0 +1,19 @@
1@INLINE@ test_cadet.conf
2
3[testbed]
4OVERLAY_TOPOLOGY = RANDOM
5OVERLAY_RANDOM_LINKS = %LINKS%
6MAX_PARALLEL_SERVICE_CONNECTIONS=4000
7SETUP_TIMEOUT = 60 m
8
9[transport]
10#MANIPULATE_DELAY_IN = 50 ms
11MANIPULATE_DELAY_OUT = 10 ms
12
13[cadet]
14REFRESH_CONNECTION_TIME = 1 h
15DISABLE_TRY_CONNECT = YES
16ID_ANNOUNCE_TIME = 5 s
17
18[dht]
19FORCE_NSE = %NSE%
diff --git a/src/service/cadet/run_profiler.sh b/src/service/cadet/run_profiler.sh
new file mode 100755
index 000000000..4273dcd27
--- /dev/null
+++ b/src/service/cadet/run_profiler.sh
@@ -0,0 +1,25 @@
1#!/bin/sh
2
3if [ "$#" -lt "3" ]; then
4 echo "usage: $0 ROUND_TIME PEERS PINGING_PEERS";
5 echo "example: $0 30s 16 1";
6 exit 1;
7fi
8
9ROUNDTIME=$1
10PEERS=$2
11PINGS=$3
12
13if [ $PEERS -eq 1 ]; then
14 echo "cannot run 1 peer";
15 exit 1;
16fi
17
18LINKS=`echo "l($PEERS) * l($PEERS) * $PEERS / 2" | bc -l`
19LINKS=`printf "%.0f" $LINKS`
20NSE=`echo "l($PEERS)/l(2)" | bc -l`
21echo "using $PEERS peers, $LINKS links";
22
23sed -e "s/%LINKS%/$LINKS/;s/%NSE%/$NSE/" profiler.conf > .profiler.conf
24
25./gnunet-cadet-profiler $ROUNDTIME $PEERS $PINGS $4 2>&1 | tee log | grep -v DEBUG
diff --git a/src/service/cadet/small.dat b/src/service/cadet/small.dat
new file mode 100644
index 000000000..c3805ee80
--- /dev/null
+++ b/src/service/cadet/small.dat
@@ -0,0 +1,21 @@
116
21:2
31:9
42:3
53:4
63:11
74:5
85:6
95:13
106:7
117:8
127:15
138:9
149:10
1510:11
1611:12
1712:13
1813:14
1914:15
2015:16
2116:1
diff --git a/src/service/cadet/test_cadet.conf b/src/service/cadet/test_cadet.conf
new file mode 100644
index 000000000..79c86bb59
--- /dev/null
+++ b/src/service/cadet/test_cadet.conf
@@ -0,0 +1,109 @@
1[testbed]
2HOSTNAME = localhost
3OVERLAY_TOPOLOGY = LINE
4#PREFIX = xterm -geometry 100x85 -T peer1 -e libtool --mode=execute gdb --args
5
6[cadet]
7#BINARY = gnunet-service-cadet-enc
8#PREFIX = valgrind --leak-check=full
9#PREFIX = xterm -geometry 100x85 -T peer1 -e gdb --args
10REFRESH_CONNECTION_TIME = 1 s
11ID_ANNOUNCE_TIME = 5 s
12CONNECT_TIMEOUT = 30 s
13DEFAULT_TTL = 16
14DHT_REPLICATION_LEVEL = 10
15MAX_TUNNELS = 10
16MAX_CONNECTIONS = 10
17MAX_MSGS_QUEUE = 20
18DISABLE_TRY_CONNECT = YES
19REKEY_PERIOD = 2 s
20
21[dht]
22DISABLE_TRY_CONNECT = YES
23FORCE_NSE = 3
24
25[dhtcache]
26QUOTA = 1 MB
27DATABASE = heap
28
29[transport]
30#PLUGINS = udp
31PLUGINS = tcp
32NEIGHBOUR_LIMIT = 50
33#MANIPULATE_DELAY_IN = 10 ms
34#MANIPULATE_DELAY_OUT = 10 ms
35
36[nat]
37ENABLE_UPNP = NO
38
39[ats]
40# Network specific inbound/outbound quotas
41UNSPECIFIED_QUOTA_IN = unlimited
42UNSPECIFIED_QUOTA_OUT = unlimited
43# LOOPBACK
44LOOPBACK_QUOTA_IN = unlimited
45LOOPBACK_QUOTA_OUT = unlimited
46# LAN
47LAN_QUOTA_IN = unlimited
48LAN_QUOTA_OUT = unlimited
49#WAN
50WAN_QUOTA_OUT = unlimited
51WAN_QUOTA_IN = unlimited
52# WLAN
53WLAN_QUOTA_IN = unlimited
54WLAN_QUOTA_OUT = unlimited
55# BLUETOOTH
56BLUETOOTH_QUOTA_IN = unlimited
57BLUETOOTH_QUOTA_OUT = unlimited
58
59[core]
60USE_EPHEMERAL_KEYS = NO
61
62[PATHS]
63GNUNET_TEST_HOME = $GNUNET_TMP/test-cadet/
64
65[peerinfo]
66NO_IO = YES
67
68[nse]
69WORKBITS = 2
70
71[hostlist]
72IMMEDIATE_START = NO
73START_ON_DEMAND = NO
74
75[fs]
76IMMEDIATE_START = NO
77START_ON_DEMAND = NO
78
79[vpn]
80IMMEDIATE_START = NO
81START_ON_DEMAND = NO
82
83[revocation]
84IMMEDIATE_START = NO
85START_ON_DEMAND = NO
86
87[gns]
88IMMEDIATE_START = NO
89START_ON_DEMAND = NO
90
91[namestore]
92IMMEDIATE_START = NO
93START_ON_DEMAND = NO
94
95[namecache]
96IMMEDIATE_START = NO
97START_ON_DEMAND = NO
98
99[topology]
100IMMEDIATE_START = NO
101START_ON_DEMAND = NO
102
103[rps]
104IMMEDIATE_START = NO
105START_ON_DEMAND = NO
106
107[rest]
108IMMEDIATE_START = NO
109START_ON_DEMAND = NO
diff --git a/src/service/cadet/test_cadet_local_mq.c b/src/service/cadet/test_cadet_local_mq.c
new file mode 100644
index 000000000..6f75dfd1f
--- /dev/null
+++ b/src/service/cadet/test_cadet_local_mq.c
@@ -0,0 +1,338 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2017 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file cadet/test_cadet_local_mq.c
23 * @brief test cadet local: test of cadet channels with just one peer
24 * @author Bartlomiej Polot
25 */
26
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_dht_service.h"
30#include "gnunet_testing_lib.h"
31#include "gnunet_cadet_service.h"
32
33#define TEST_MESSAGE_TYPE 1
34#define TEST_PORT_ID 1
35
36/**
37 * Test message structure.
38 */
39struct GNUNET_CADET_TestMsg
40{
41 /**
42 * Type: #TEST_MESSAGE_TYPE
43 *
44 * Size: sizeof(struct GNUNET_CADET_TestMsg)
45 */
46 struct GNUNET_MessageHeader header;
47
48 /**
49 * Test payload.
50 */
51 uint64_t payload;
52};
53
54struct GNUNET_TESTING_Peer *me;
55
56static struct GNUNET_CADET_Handle *cadet_peer_1;
57
58static struct GNUNET_CADET_Handle *cadet_peer_2;
59
60static struct GNUNET_CADET_Channel *ch;
61
62static int result = GNUNET_OK;
63
64static int got_data = GNUNET_NO;
65
66static struct GNUNET_SCHEDULER_Task *abort_task;
67
68static struct GNUNET_SCHEDULER_Task *connect_task;
69
70
71/**
72 * Connect to other client and send data
73 *
74 * @param cls Closue (unused).
75 */
76static void
77do_connect (void *cls);
78
79
80/**
81 * Shutdown nicely
82 */
83static void
84do_shutdown (void *cls)
85{
86 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
87 "shutdown\n");
88 if (NULL != abort_task)
89 {
90 GNUNET_SCHEDULER_cancel (abort_task);
91 abort_task = NULL;
92 }
93 if (NULL != ch)
94 {
95 GNUNET_CADET_channel_destroy (ch);
96 ch = NULL;
97 }
98 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
99 "Disconnect client 1\n");
100 if (NULL != cadet_peer_1)
101 {
102 GNUNET_CADET_disconnect (cadet_peer_1);
103 cadet_peer_1 = NULL;
104 }
105 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
106 "Disconnect client 2\n");
107 if (NULL != cadet_peer_2)
108 {
109 GNUNET_CADET_disconnect (cadet_peer_2);
110 cadet_peer_2 = NULL;
111 }
112 if (NULL != connect_task)
113 {
114 GNUNET_SCHEDULER_cancel (connect_task);
115 connect_task = NULL;
116 }
117}
118
119
120/**
121 * Something went wrong and timed out. Kill everything and set error flag
122 */
123static void
124do_abort (void *cls)
125{
126 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
127 "ABORT from line %ld\n",
128 (long) cls);
129 result = GNUNET_SYSERR;
130 abort_task = NULL;
131 GNUNET_SCHEDULER_shutdown ();
132}
133
134
135/**
136 * Method called whenever a peer connects to a port in MQ-based CADET.
137 *
138 * @param cls Closure from #GNUNET_CADET_open_port.
139 * @param channel New handle to the channel.
140 * @param source Peer that started this channel.
141 * @return Closure for the incoming @a channel. It's given to:
142 * - The #GNUNET_CADET_DisconnectEventHandler (given to
143 * #GNUNET_CADET_open_port) when the channel dies.
144 * - Each the #GNUNET_MQ_MessageCallback handlers for each message
145 * received on the @a channel.
146 */
147static void *
148connected (void *cls,
149 struct GNUNET_CADET_Channel *channel,
150 const struct GNUNET_PeerIdentity *source)
151{
152 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
153 "connected %s, cls: %p\n",
154 GNUNET_i2s (source),
155 cls);
156 return channel;
157}
158
159
160/**
161 * Function called whenever an MQ-channel is destroyed, even if the destruction
162 * was requested by #GNUNET_CADET_channel_destroy.
163 * It must NOT call #GNUNET_CADET_channel_destroy on the channel.
164 *
165 * It should clean up any associated state, including cancelling any pending
166 * transmission on this channel.
167 *
168 * @param cls Channel closure.
169 * @param channel Connection to the other end (henceforth invalid).
170 */
171static void
172disconnected (void *cls,
173 const struct GNUNET_CADET_Channel *channel)
174{
175 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
176 "disconnected channel %p, cls: %p\n",
177 channel, cls);
178 if (channel == ch)
179 ch = NULL;
180}
181
182
183/**
184 * Handle test data
185 *
186 * @param h The cadet handle
187 * @param msg A message with the details of the new incoming channel
188 */
189static void
190handle_data_received (void *cls,
191 const struct GNUNET_CADET_TestMsg *msg)
192{
193 uint64_t payload;
194
195 payload = GNUNET_ntohll (msg->payload);
196 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
197 "Data callback payload %llu with cls: %p! Shutting down.\n",
198 (unsigned long long) payload,
199 cls);
200 GNUNET_assert (42 == payload);
201 got_data = GNUNET_YES;
202 GNUNET_SCHEDULER_shutdown ();
203}
204
205
206/**
207 * Signature of the main function of a task.
208 *
209 * @param cls Closure (unused).
210 */
211static void
212message_sent (void *cls)
213{
214 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
215 "message sent\n");
216}
217
218
219/**
220 * Connect to other client and send data
221 *
222 * @param cls Closure (unused).
223 */
224static void
225do_connect (void *cls)
226{
227 struct GNUNET_PeerIdentity id;
228 struct GNUNET_MQ_Handle *mq;
229 struct GNUNET_MQ_Envelope *env;
230 struct GNUNET_CADET_TestMsg *msg;
231
232 struct GNUNET_MQ_MessageHandler handlers[] = {
233 GNUNET_MQ_hd_fixed_size (data_received,
234 TEST_MESSAGE_TYPE,
235 struct GNUNET_CADET_TestMsg,
236 cadet_peer_1),
237 GNUNET_MQ_handler_end ()
238 };
239
240 connect_task = NULL;
241 GNUNET_TESTING_peer_get_identity (me, &id);
242 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
243 "creating channel\n");
244 ch = GNUNET_CADET_channel_create (cadet_peer_1, /* cadet handle */
245 NULL, /* channel cls */
246 &id, /* destination */
247 GC_u2h (TEST_MESSAGE_TYPE), /* port */
248 NULL, /* window change */
249 &disconnected, /* disconnect handler */
250 handlers /* traffic handlers */
251 );
252 env = GNUNET_MQ_msg (msg, TEST_MESSAGE_TYPE);
253 msg->payload = GNUNET_htonll (42);
254 mq = GNUNET_CADET_get_mq (ch);
255 GNUNET_MQ_notify_sent (env, &message_sent, NULL);
256 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
257 "sending message\n");
258 GNUNET_MQ_send (mq, env);
259}
260
261
262/**
263 * Initialize framework and start test
264 *
265 * @param cls Closure (unused).
266 * @param cfg Configuration handle.
267 * @param peer Testing peer handle.
268 */
269static void
270run (void *cls,
271 const struct GNUNET_CONFIGURATION_Handle *cfg,
272 struct GNUNET_TESTING_Peer *peer)
273{
274 struct GNUNET_MQ_MessageHandler handlers[] = {
275 GNUNET_MQ_hd_fixed_size (data_received,
276 TEST_MESSAGE_TYPE,
277 struct GNUNET_CADET_TestMsg,
278 cadet_peer_2),
279 GNUNET_MQ_handler_end ()
280 };
281 struct GNUNET_TIME_Relative delay;
282
283 me = peer;
284 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
285 NULL);
286 delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15);
287 abort_task = GNUNET_SCHEDULER_add_delayed (delay,
288 &do_abort,
289 (void *) (long) __LINE__);
290 cadet_peer_1 = GNUNET_CADET_connect (cfg);
291 cadet_peer_2 = GNUNET_CADET_connect (cfg);
292
293 if ((NULL == cadet_peer_1) ||
294 (NULL == cadet_peer_2))
295 {
296 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
297 "Couldn't connect to cadet\n");
298 result = GNUNET_SYSERR;
299 GNUNET_SCHEDULER_shutdown ();
300 return;
301 }
302 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CADET 1: %p\n", cadet_peer_1);
303 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CADET 2: %p\n", cadet_peer_2);
304 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "handlers 2: %p\n", handlers);
305 GNUNET_CADET_open_port (cadet_peer_2, /* cadet handle */
306 GC_u2h (TEST_PORT_ID), /* port id */
307 &connected, /* connect handler */
308 (void *) 2L, /* handle for #connected */
309 NULL, /* window size handler */
310 &disconnected, /* disconnect handler */
311 handlers); /* traffic handlers */
312 delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2);
313 if (NULL == connect_task)
314 connect_task = GNUNET_SCHEDULER_add_delayed (delay,
315 &do_connect,
316 NULL);
317}
318
319
320/**
321 * Main
322 */
323int
324main (int argc, char *argv[])
325{
326 if (0 != GNUNET_TESTING_peer_run ("test-cadet-local",
327 "test_cadet.conf",
328 &run, NULL))
329 {
330 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "run failed\n");
331 return 2;
332 }
333 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Final result: %d\n", result);
334 return (result == GNUNET_OK) ? 0 : 1;
335}
336
337
338/* end of test_cadet_local_1.c */
diff --git a/src/service/cadet/valgrind-cadet.supp b/src/service/cadet/valgrind-cadet.supp
new file mode 100644
index 000000000..fecd5185b
--- /dev/null
+++ b/src/service/cadet/valgrind-cadet.supp
@@ -0,0 +1,116 @@
1{
2 logsetup_addr
3 Memcheck:Addr8
4 obj:/lib/libc-2.14.1.so
5 ...
6 fun:get_type
7 fun:GNUNET_log_setup
8 fun:GNUNET_SERVICE_run
9 fun:main
10}
11
12{
13 scanf_addr
14 Memcheck:Addr8
15 obj:/lib/libc-2.14.1.so
16 ...
17 fun:vsscanf
18 fun:sscanf
19 fun:GNUNET_CONFIGURATION_get_value_number
20 fun:GNUNET_SERVICE_get_server_addresses
21 fun:setup_service
22 fun:GNUNET_SERVICE_run
23 fun:main
24}
25
26{
27 mylog_addr
28 Memcheck:Addr8
29 obj:/lib/libc-2.14.1.so
30 ...
31 fun:service_task
32 fun:GNUNET_SCHEDULER_run
33 fun:GNUNET_SERVICE_run
34 fun:main
35}
36
37{
38 mylog_uninit
39 Memcheck:Value8
40 obj:/lib/libc-2.14.1.so
41 ...
42 fun:mylog
43 fun:GNUNET_log_from_nocheck
44 fun:service_task
45 ...
46 fun:GNUNET_SCHEDULER_run
47 fun:GNUNET_SERVICE_run
48 fun:main
49}
50
51{
52 mylog_from_cond
53 Memcheck:Cond
54 obj:/lib/libc-2.14.1.so
55 ...
56 fun:mylog
57 fun:GNUNET_log_from_nocheck
58 ...
59 fun:service_task
60 fun:GNUNET_SCHEDULER_run
61 fun:GNUNET_SERVICE_run
62 fun:main
63}
64
65{
66 mylog_cond
67 Memcheck:Cond
68 obj:/lib/libc-2.14.1.so
69 ...
70 fun:mylog
71 fun:GNUNET_log_nocheck
72 ...
73 fun:service_task
74 fun:GNUNET_SCHEDULER_run
75 fun:GNUNET_SERVICE_run
76 fun:main
77}
78
79{
80 inet_ntop_cond
81 Memcheck:Cond
82 obj:/lib/libc-2.14.1.so
83 ...
84 fun:inet_ntop
85 fun:GNUNET_a2s
86 ...
87 fun:service_task
88 fun:GNUNET_SCHEDULER_run
89 fun:GNUNET_SERVICE_run
90 fun:main
91}
92
93{
94 create_key_from_file
95 Memcheck:Addr8
96 obj:/lib/libc-2.14.1.so
97 ...
98 fun:GNUNET_CRYPTO_rsa_key_create_from_file
99 fun:run
100 fun:service_task
101 fun:GNUNET_SCHEDULER_run
102 fun:GNUNET_SERVICE_run
103 fun:main
104}
105
106{
107 main_notify_handler
108 Memcheck:Addr8
109 obj:/lib/libc-2.14.1.so
110 ...
111 fun:main_notify_handler
112 fun:receive_ready
113 fun:GNUNET_SCHEDULER_run
114 fun:GNUNET_SERVICE_run
115 fun:main
116} \ No newline at end of file