aboutsummaryrefslogtreecommitdiff
path: root/src/cadet
diff options
context:
space:
mode:
Diffstat (limited to 'src/cadet')
-rw-r--r--src/cadet/.gitignore26
-rw-r--r--src/cadet/Makefile.am225
-rw-r--r--src/cadet/TODO36
-rw-r--r--src/cadet/cadet.conf.in53
-rw-r--r--src/cadet/cadet.h579
-rw-r--r--src/cadet/cadet_api.c1088
-rw-r--r--src/cadet/cadet_api_drop_message.c59
-rw-r--r--src/cadet/cadet_api_get_channel.c260
-rw-r--r--src/cadet/cadet_api_get_path.c276
-rw-r--r--src/cadet/cadet_api_helper.c54
-rw-r--r--src/cadet/cadet_api_list_peers.c238
-rw-r--r--src/cadet/cadet_api_list_tunnels.c239
-rw-r--r--src/cadet/cadet_protocol.h541
-rw-r--r--src/cadet/cadet_test_lib.c376
-rw-r--r--src/cadet/cadet_test_lib.h106
-rw-r--r--src/cadet/desirability_table.c33
-rw-r--r--src/cadet/gnunet-cadet-profiler.c1159
-rw-r--r--src/cadet/gnunet-cadet.c851
-rw-r--r--src/cadet/gnunet-service-cadet.c1381
-rw-r--r--src/cadet/gnunet-service-cadet.h328
-rw-r--r--src/cadet/gnunet-service-cadet_channel.c2074
-rw-r--r--src/cadet/gnunet-service-cadet_channel.h304
-rw-r--r--src/cadet/gnunet-service-cadet_connection.c1106
-rw-r--r--src/cadet/gnunet-service-cadet_connection.h361
-rw-r--r--src/cadet/gnunet-service-cadet_core.c1348
-rw-r--r--src/cadet/gnunet-service-cadet_core.h69
-rw-r--r--src/cadet/gnunet-service-cadet_dht.c353
-rw-r--r--src/cadet/gnunet-service-cadet_dht.h100
-rw-r--r--src/cadet/gnunet-service-cadet_hello.c150
-rw-r--r--src/cadet/gnunet-service-cadet_hello.h80
-rw-r--r--src/cadet/gnunet-service-cadet_paths.c785
-rw-r--r--src/cadet/gnunet-service-cadet_paths.h181
-rw-r--r--src/cadet/gnunet-service-cadet_peer.c1609
-rw-r--r--src/cadet/gnunet-service-cadet_peer.h427
-rw-r--r--src/cadet/gnunet-service-cadet_tunnels.c3728
-rw-r--r--src/cadet/gnunet-service-cadet_tunnels.h388
-rwxr-xr-xsrc/cadet/loopcheck.sh57
-rw-r--r--src/cadet/profiler.conf19
-rwxr-xr-xsrc/cadet/run_profiler.sh25
-rw-r--r--src/cadet/small.dat21
-rw-r--r--src/cadet/test_cadet.c1605
-rw-r--r--src/cadet/test_cadet.conf109
-rw-r--r--src/cadet/test_cadet_drop.conf4
-rw-r--r--src/cadet/test_cadet_flow.c891
-rw-r--r--src/cadet/test_cadet_local_mq.c338
-rw-r--r--src/cadet/valgrind-cadet.supp116
46 files changed, 0 insertions, 24156 deletions
diff --git a/src/cadet/.gitignore b/src/cadet/.gitignore
deleted file mode 100644
index b556fa4c8..000000000
--- a/src/cadet/.gitignore
+++ /dev/null
@@ -1,26 +0,0 @@
1gnunet-service-cadet
2gnunet-cadet
3gnunet-cadet-profiler
4test_cadet_2_forward
5test_cadet_2_keepalive
6test_cadet_2_signal
7test_cadet_2_speed
8test_cadet_2_speed_ack
9test_cadet_2_speed_backwards
10test_cadet_2_speed_reliable
11test_cadet_2_speed_reliable_backwards
12test_cadet_5_forward
13test_cadet_5_keepalive
14test_cadet_5_signal
15test_cadet_5_speed
16test_cadet_5_speed_ack
17test_cadet_5_speed_backwards
18test_cadet_5_speed_reliable
19test_cadet_5_speed_reliable_backwards
20test_cadet_local
21test_cadet_single
22gnunet-service-cadet-new
23test_cadet_local_mq
24test_cadet_*_newtest_cadet_2_reopen
25test_cadet_5_reopen
26test_cadet_2_reopen
diff --git a/src/cadet/Makefile.am b/src/cadet/Makefile.am
deleted file mode 100644
index d942c6495..000000000
--- a/src/cadet/Makefile.am
+++ /dev/null
@@ -1,225 +0,0 @@
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 $(EXP_LIBEXEC)
23
24bin_PROGRAMS = \
25 gnunet-cadet
26
27lib_LTLIBRARIES = \
28 libgnunetcadet.la \
29 $(EXP_LIB)
30
31libgnunetcadet_la_SOURCES = \
32 cadet_api.c \
33 cadet_api_drop_message.c \
34 cadet_api_get_channel.c \
35 cadet_api_get_path.c \
36 cadet_api_list_peers.c \
37 cadet_api_list_tunnels.c \
38 cadet_api_helper.c
39libgnunetcadet_la_LIBADD = \
40 $(top_builddir)/src/util/libgnunetutil.la \
41 $(XLIB) \
42 $(LTLIBINTL)
43libgnunetcadet_la_LDFLAGS = \
44 $(GN_LIB_LDFLAGS) \
45 -version-info 7:0:0
46
47gnunet_cadet_SOURCES = \
48 gnunet-cadet.c
49gnunet_cadet_LDADD = \
50 libgnunetcadet.la \
51 $(top_builddir)/src/util/libgnunetutil.la
52gnunet_cadet_LDFLAGS = \
53 $(GN_LIBINTL)
54
55gnunet_service_cadet_SOURCES = \
56 gnunet-service-cadet.c gnunet-service-cadet.h \
57 gnunet-service-cadet_channel.c gnunet-service-cadet_channel.h \
58 gnunet-service-cadet_connection.c gnunet-service-cadet_connection.h \
59 gnunet-service-cadet_core.c gnunet-service-cadet_core.h \
60 gnunet-service-cadet_dht.c gnunet-service-cadet_dht.h \
61 gnunet-service-cadet_hello.c gnunet-service-cadet_hello.h \
62 gnunet-service-cadet_tunnels.c gnunet-service-cadet_tunnels.h \
63 gnunet-service-cadet_paths.c gnunet-service-cadet_paths.h \
64 gnunet-service-cadet_peer.c gnunet-service-cadet_peer.h
65gnunet_service_cadet_LDADD = \
66 $(top_builddir)/src/util/libgnunetutil.la \
67 $(top_builddir)/src/ats/libgnunetats.la \
68 $(top_builddir)/src/core/libgnunetcore.la \
69 $(top_builddir)/src/dht/libgnunetdht.la \
70 $(top_builddir)/src/statistics/libgnunetstatistics.la \
71 $(top_builddir)/src/transport/libgnunettransport.la \
72 $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
73 $(top_builddir)/src/hello/libgnunethello.la \
74 $(top_builddir)/src/block/libgnunetblock.la
75if LINUX
76 gnunet_service_cadet_LDFLAGS = -lrt \
77 $(GN_LIBINTL)
78endif
79
80
81 noinst_LTLIBRARIES = libgnunetcadettest.la $(noinst_LIB_EXP)
82# noinst_PROGRAMS = gnunet-cadet-profiler
83
84check_PROGRAMS = \
85 test_cadet_local_mq \
86 test_cadet_2_forward \
87 test_cadet_2_forward \
88 test_cadet_2_signal \
89 test_cadet_2_keepalive \
90 test_cadet_2_speed \
91 test_cadet_2_speed_ack \
92 test_cadet_2_speed_backwards \
93 test_cadet_2_speed_reliable \
94 test_cadet_2_speed_reliable_backwards \
95 test_cadet_2_reopen \
96 test_cadet_2_destroy \
97 test_cadet_5_forward \
98 test_cadet_5_signal \
99 test_cadet_5_keepalive \
100 test_cadet_5_speed \
101 test_cadet_5_speed_ack \
102 test_cadet_5_speed_reliable \
103 test_cadet_5_speed_reliable_backwards \
104 test_cadet_5_speed_backwards \
105 test_cadet_5_reopen
106
107
108#gnunet_cadet_profiler_SOURCES = \
109# gnunet-cadet-profiler.c
110#gnunet_cadet_profiler_LDADD = $(ld_cadet_test_lib)
111
112
113test_cadet_local_mq_SOURCES = \
114 test_cadet_local_mq.c
115test_cadet_local_mq_LDADD = \
116 libgnunetcadet.la \
117 $(top_builddir)/src/testing/libgnunettesting.la \
118 $(top_builddir)/src/util/libgnunetutil.la
119
120
121libgnunetcadettest_la_SOURCES = \
122 cadet_test_lib.c cadet_test_lib.h
123libgnunetcadettest_la_LIBADD = \
124 $(top_builddir)/src/util/libgnunetutil.la \
125 $(top_builddir)/src/testbed/libgnunettestbed.la \
126 libgnunetcadet.la
127
128ld_cadet_test_lib = \
129 $(top_builddir)/src/util/libgnunetutil.la \
130 $(top_builddir)/src/testing/libgnunettesting.la \
131 libgnunetcadet.la \
132 libgnunetcadettest.la \
133 $(top_builddir)/src/testbed/libgnunettestbed.la \
134 $(top_builddir)/src/statistics/libgnunetstatistics.la
135dep_cadet_test_lib = \
136 libgnunetcadet.la \
137 libgnunetcadettest.la \
138 $(top_builddir)/src/statistics/libgnunetstatistics.la
139
140test_cadet_2_forward_SOURCES = \
141 test_cadet.c
142test_cadet_2_forward_LDADD = $(ld_cadet_test_lib)
143
144test_cadet_2_signal_SOURCES = \
145 test_cadet.c
146test_cadet_2_signal_LDADD = $(ld_cadet_test_lib)
147
148test_cadet_2_keepalive_SOURCES = \
149 test_cadet.c
150test_cadet_2_keepalive_LDADD = $(ld_cadet_test_lib)
151
152test_cadet_2_speed_SOURCES = \
153 test_cadet.c
154test_cadet_2_speed_LDADD = $(ld_cadet_test_lib)
155
156test_cadet_2_speed_ack_SOURCES = \
157 test_cadet.c
158test_cadet_2_speed_ack_LDADD = $(ld_cadet_test_lib)
159
160test_cadet_2_speed_backwards_SOURCES = \
161 test_cadet.c
162test_cadet_2_speed_backwards_LDADD = $(ld_cadet_test_lib)
163
164test_cadet_2_speed_reliable_SOURCES = \
165 test_cadet.c
166test_cadet_2_speed_reliable_LDADD = $(ld_cadet_test_lib)
167
168test_cadet_2_speed_reliable_backwards_SOURCES = \
169 test_cadet.c
170test_cadet_2_speed_reliable_backwards_LDADD = $(ld_cadet_test_lib)
171
172test_cadet_5_forward_SOURCES = \
173 test_cadet.c
174test_cadet_5_forward_LDADD = $(ld_cadet_test_lib)
175
176test_cadet_5_signal_SOURCES = \
177 test_cadet.c
178test_cadet_5_signal_LDADD = $(ld_cadet_test_lib)
179
180test_cadet_5_keepalive_SOURCES = \
181 test_cadet.c
182test_cadet_5_keepalive_LDADD = $(ld_cadet_test_lib)
183
184test_cadet_5_speed_SOURCES = \
185 test_cadet.c
186test_cadet_5_speed_LDADD = $(ld_cadet_test_lib)
187
188test_cadet_5_speed_ack_SOURCES = \
189 test_cadet.c
190test_cadet_5_speed_ack_LDADD = $(ld_cadet_test_lib)
191
192test_cadet_5_speed_backwards_SOURCES = \
193 test_cadet.c
194test_cadet_5_speed_backwards_LDADD = $(ld_cadet_test_lib)
195
196test_cadet_5_speed_reliable_SOURCES = \
197 test_cadet.c
198test_cadet_5_speed_reliable_LDADD = $(ld_cadet_test_lib)
199
200test_cadet_5_speed_reliable_backwards_SOURCES = \
201 test_cadet.c
202test_cadet_5_speed_reliable_backwards_LDADD = $(ld_cadet_test_lib)
203
204test_cadet_2_reopen_SOURCES = \
205 test_cadet.c
206test_cadet_2_reopen_LDADD = $(ld_cadet_test_lib)
207
208test_cadet_5_reopen_SOURCES = \
209 test_cadet.c
210test_cadet_5_reopen_LDADD = $(ld_cadet_test_lib)
211
212test_cadet_2_destroy_SOURCES = \
213 test_cadet.c
214test_cadet_2_destroy_LDADD = $(ld_cadet_test_lib)
215
216if ENABLE_TEST_RUN
217AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
218TESTS = \
219 $(check_PROGRAMS)
220endif
221
222EXTRA_DIST = \
223 cadet.h cadet_protocol.h \
224 test_cadet.conf \
225 test_cadet_drop.conf
diff --git a/src/cadet/TODO b/src/cadet/TODO
deleted file mode 100644
index 06567b0ad..000000000
--- a/src/cadet/TODO
+++ /dev/null
@@ -1,36 +0,0 @@
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/cadet/cadet.conf.in b/src/cadet/cadet.conf.in
deleted file mode 100644
index 8f700951c..000000000
--- a/src/cadet/cadet.conf.in
+++ /dev/null
@@ -1,53 +0,0 @@
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/cadet/cadet.h b/src/cadet/cadet.h
deleted file mode 100644
index 31dad4117..000000000
--- a/src/cadet/cadet.h
+++ /dev/null
@@ -1,579 +0,0 @@
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_peer_lib.h"
59#include "gnunet_core_service.h"
60#include "gnunet_cadet_service.h"
61#include "gnunet_protocols.h"
62#include "gnunet_cadet_service.h"
63
64/******************************************************************************/
65/************************** CONSTANTS ******************************/
66/******************************************************************************/
67
68/**
69 * Minimum value for channel IDs of local clients.
70 */
71#define GNUNET_CADET_LOCAL_CHANNEL_ID_CLI 0x80000000U
72
73/**
74 * FIXME.
75 */
76#define HIGH_PID 0xFF000000
77
78/**
79 * FIXME.
80 */
81#define LOW_PID 0x00FFFFFF
82
83
84/**
85 * Test if the two PIDs (of type `uint32_t`) are in the range where we
86 * have to worry about overflows. This is the case when @a pid is
87 * large and @a max is small, useful when comparing @a pid smaller
88 * than @a max.
89 */
90#define PID_OVERFLOW(pid, max) (((pid) > HIGH_PID) && ((max) < LOW_PID))
91
92/******************************************************************************/
93/************************** MESSAGES ******************************/
94/******************************************************************************/
95
96GNUNET_NETWORK_STRUCT_BEGIN
97
98/**
99 * Number uniquely identifying a channel of a client.
100 */
101struct GNUNET_CADET_ClientChannelNumber
102{
103 /**
104 * Values for channel numbering.
105 * Local channel numbers given by the service (incoming) are
106 * smaller than #GNUNET_CADET_LOCAL_CHANNEL_ID_CLI.
107 * Local channel numbers given by the client (created) are
108 * larger than #GNUNET_CADET_LOCAL_CHANNEL_ID_CLI.
109 */
110 uint32_t channel_of_client GNUNET_PACKED;
111};
112
113/**
114 * Opaque handle to a channel.
115 */
116struct GNUNET_CADET_Channel
117{
118
119 /**
120 * Other end of the channel.
121 */
122 struct GNUNET_PeerIdentity peer;
123
124 /**
125 * Handle to the cadet this channel belongs to
126 */
127 struct GNUNET_CADET_Handle *cadet;
128
129 /**
130 * Channel's port, if incoming.
131 */
132 struct GNUNET_CADET_Port *incoming_port;
133
134 /**
135 * Any data the caller wants to put in here, used for the
136 * various callbacks (@e disconnects, @e window_changes, handlers).
137 */
138 void *ctx;
139
140 /**
141 * Message Queue for the channel (which we are implementing).
142 */
143 struct GNUNET_MQ_Handle *mq;
144
145 /**
146 * Task to allow mq to send more traffic.
147 */
148 struct GNUNET_SCHEDULER_Task *mq_cont;
149
150 /**
151 * Pending envelope with a message to be transmitted to the
152 * service as soon as we are allowed to. Should only be
153 * non-NULL if @e allow_send is 0.
154 */
155 struct GNUNET_MQ_Envelope *pending_env;
156
157 /**
158 * Window change handler.
159 */
160 GNUNET_CADET_WindowSizeEventHandler window_changes;
161
162 /**
163 * Disconnect handler.
164 */
165 GNUNET_CADET_DisconnectEventHandler disconnects;
166
167 /**
168 * Local ID of the channel, #GNUNET_CADET_LOCAL_CHANNEL_ID_CLI bit is set if outbound.
169 */
170 struct GNUNET_CADET_ClientChannelNumber ccn;
171
172 /**
173 * How many messages are we allowed to send to the service right now?
174 */
175 unsigned int allow_send;
176};
177
178/**
179 * Message for a client to create and destroy channels.
180 */
181struct GNUNET_CADET_PortMessage
182{
183 /**
184 * Type: #GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN
185 * or #GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE
186 *
187 * Size: sizeof(struct GNUNET_CADET_ChannelMessage)
188 */
189 struct GNUNET_MessageHeader header;
190
191 /**
192 * Port to open/close.
193 */
194 struct GNUNET_HashCode port GNUNET_PACKED;
195};
196
197
198/**
199 * Message for a client to create channels.
200 */
201struct GNUNET_CADET_LocalChannelCreateMessage
202{
203 /**
204 * Type: #GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE
205 *
206 * Size: sizeof(struct GNUNET_CADET_ChannelOpenMessageMessage)
207 */
208 struct GNUNET_MessageHeader header;
209
210 /**
211 * ID of a channel controlled by this client.
212 */
213 struct GNUNET_CADET_ClientChannelNumber ccn;
214
215 /**
216 * Channel's peer
217 */
218 struct GNUNET_PeerIdentity peer;
219
220 /**
221 * Port of the channel.
222 */
223 struct GNUNET_HashCode port;
224
225 /**
226 * Options.
227 */
228 uint32_t opt GNUNET_PACKED;
229};
230
231
232/**
233 * Message for or to a client to destroy tunnel.
234 */
235struct GNUNET_CADET_LocalChannelDestroyMessage
236{
237 /**
238 * Type: #GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY
239 */
240 struct GNUNET_MessageHeader header;
241
242 /**
243 * ID of a channel controlled by this client.
244 */
245 struct GNUNET_CADET_ClientChannelNumber ccn;
246};
247
248
249/**
250 * Message for cadet data traffic.
251 */
252struct GNUNET_CADET_LocalData
253{
254 /**
255 * Type: #GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA
256 */
257 struct GNUNET_MessageHeader header;
258
259 /**
260 * ID of the channel
261 */
262 struct GNUNET_CADET_ClientChannelNumber ccn;
263
264 /**
265 * Priority and preferences (an enum GNUNET_MQ_PriorityPreferences)
266 * of the message in NBO.
267 */
268 uint32_t pp GNUNET_PACKED;
269
270 /**
271 * Payload follows
272 */
273};
274
275
276/**
277 * Message to allow the client send more data to the service
278 * (always service -> client).
279 */
280struct GNUNET_CADET_LocalAck
281{
282 /**
283 * Type: #GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK
284 */
285 struct GNUNET_MessageHeader header;
286
287 /**
288 * ID of the channel allowed to send more data.
289 */
290 struct GNUNET_CADET_ClientChannelNumber ccn;
291};
292
293
294/**
295 * Message to inform the client about channels in the service.
296 *
297 * TODO: split into two messages!
298 */
299struct GNUNET_CADET_LocalInfo
300{
301 /**
302 * Type: #GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL or
303 * #GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER
304 */
305 struct GNUNET_MessageHeader header;
306
307 /**
308 * ID of the channel allowed to send more data.
309 */
310 struct GNUNET_CADET_ClientChannelNumber ccn;
311
312 /**
313 * ID of the destination of the channel (can be local peer).
314 */
315 struct GNUNET_PeerIdentity peer;
316};
317
318/**
319 * Message to drop another message of specific type. Used in test context
320 */
321struct GNUNET_CADET_RequestDropCadetMessage
322{
323
324 /**
325 * Type: #GNUNET_MESSAGE_TYPE_CADET_DROP_CADET_MESSAGE
326 */
327 struct GNUNET_MessageHeader header;
328
329 /**
330 * Type of the message this handler covers, in host byte order.
331 */
332 uint16_t type;
333
334 /**
335 * ID of the channel we want to drop a message for.
336 */
337 struct GNUNET_CADET_ClientChannelNumber ccn;
338
339};
340
341/**
342 * Message to inform the client about channels in the service.
343 */
344struct GNUNET_CADET_RequestPathInfoMessage
345{
346 /**
347 * Type: #GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_PATH
348 */
349 struct GNUNET_MessageHeader header;
350
351 /**
352 * Always zero.
353 */
354 uint32_t resered GNUNET_PACKED;
355
356 /**
357 * ID of the destination of the channel (can be local peer).
358 */
359 struct GNUNET_PeerIdentity peer;
360};
361
362
363/**
364 * Message to inform the client about channels in the service.
365 */
366struct GNUNET_CADET_ChannelInfoMessage
367{
368 /**
369 * Type: #GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNEL.
370 */
371 struct GNUNET_MessageHeader header;
372
373 /**
374 * Root of the channel
375 */
376 struct GNUNET_PeerIdentity root;
377
378 /**
379 * Destination of the channel
380 */
381 struct GNUNET_PeerIdentity dest;
382
383 /* FIXME: expand! */
384};
385
386
387/**
388 * Message to as the service about information on a channel.
389 */
390struct GNUNET_CADET_RequestChannelInfoMessage
391{
392 /**
393 * Type: #GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_CHANNEL.
394 */
395 struct GNUNET_MessageHeader header;
396
397 /**
398 * Target of the channel.
399 */
400 struct GNUNET_PeerIdentity target;
401};
402
403
404/**
405 * Message to inform the client about one of the paths known to the service.
406 */
407struct GNUNET_CADET_LocalInfoPath
408{
409 /**
410 * Type: #GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PATH.
411 */
412 struct GNUNET_MessageHeader header;
413
414 /**
415 * Offset of the peer that was requested.
416 */
417 uint32_t off GNUNET_PACKED;
418};
419
420
421/**
422 * Message to inform the client about one of the peers in the service.
423 */
424struct GNUNET_CADET_LocalInfoPeers
425{
426 /**
427 * Type: #GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS
428 */
429 struct GNUNET_MessageHeader header;
430
431 /**
432 * Number of paths.
433 */
434 uint16_t paths GNUNET_PACKED;
435
436 /**
437 * Do we have a tunnel toward this peer?
438 */
439 int16_t tunnel GNUNET_PACKED;
440
441 /**
442 * Shortest known path.
443 */
444 uint32_t best_path_length GNUNET_PACKED;
445
446 /**
447 * ID of the peer (can be local peer).
448 */
449 struct GNUNET_PeerIdentity destination;
450};
451
452
453/**
454 * Message to inform the client about one of the tunnels in the service.
455 *
456 * TODO: split into two messages!
457 */
458struct GNUNET_CADET_LocalInfoTunnel
459{
460 /**
461 * Type: #GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL
462 * or #GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS
463 */
464 struct GNUNET_MessageHeader header;
465
466 /**
467 * Number of channels.
468 */
469 uint32_t channels GNUNET_PACKED;
470
471 /**
472 * ID of the destination of the tunnel (can be local peer).
473 */
474 struct GNUNET_PeerIdentity destination;
475
476 /**
477 * Number of connections.
478 */
479 uint32_t connections GNUNET_PACKED;
480
481 /**
482 * Encryption state.
483 */
484 uint16_t estate GNUNET_PACKED;
485
486 /**
487 * Connection state.
488 */
489 uint16_t cstate GNUNET_PACKED;
490
491 /* If TUNNEL (no 'S'): struct GNUNET_CADET_ConnectionTunnelIdentifier connection_ids[connections] */
492 /* If TUNNEL (no 'S'): uint32_t channel_ids[channels] */
493};
494
495
496GNUNET_NETWORK_STRUCT_END
497
498
499/**
500 * @brief Translate a fwd variable into a string representation, for logging.
501 *
502 * @param fwd Is FWD? (#GNUNET_YES or #GNUNET_NO)
503 *
504 * @return String representing FWD or BCK.
505 */
506char *
507GC_f2s (int fwd);
508
509
510/**
511 * Check if one pid is bigger than other, accounting for overflow.
512 *
513 * @param bigger Argument that should be bigger.
514 * @param smaller Argument that should be smaller.
515 *
516 * @return True if bigger (arg1) has a higher value than smaller (arg 2).
517 */
518int
519GC_is_pid_bigger (uint32_t bigger, uint32_t smaller);
520
521
522/**
523 * Get the higher ACK value out of two values, taking in account overflow.
524 *
525 * @param a First ACK value.
526 * @param b Second ACK value.
527 *
528 * @return Highest ACK value from the two.
529 */
530uint32_t
531GC_max_pid (uint32_t a, uint32_t b);
532
533
534/**
535 * Get the lower ACK value out of two values, taking in account overflow.
536 *
537 * @param a First ACK value.
538 * @param b Second ACK value.
539 *
540 * @return Lowest ACK value from the two.
541 */
542uint32_t
543GC_min_pid (uint32_t a, uint32_t b);
544
545
546/**
547 * Allocate a string with a hexdump of any binary data.
548 *
549 * @param bin Arbitrary binary data.
550 * @param len Length of @a bin in bytes.
551 * @param output Where to write the output (if *output be NULL it's allocated).
552 *
553 * @return The size of the output.
554 */
555size_t
556GC_bin2s (void *bin, unsigned int len, char **output);
557
558
559/**
560 * Convert a message type into a string to help debug
561 * Generated with:
562 * FIND: "#define ([^ ]+)[ ]*([0-9]+)"
563 * REPLACE: " case \2: return "\1"; break;"
564 *
565 * @param m Message type.
566 *
567 * @return Human readable string description.
568 */
569const char *
570GC_m2s (uint16_t m);
571
572#if 0 /* keep Emacsens' auto-indent happy */
573{
574#endif
575#ifdef __cplusplus
576}
577#endif
578
579#endif
diff --git a/src/cadet/cadet_api.c b/src/cadet/cadet_api.c
deleted file mode 100644
index c9f0722d5..000000000
--- a/src/cadet/cadet_api.c
+++ /dev/null
@@ -1,1088 +0,0 @@
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 * @param call_cleaner Whether to call the cleaner handler.
202 */
203static void
204destroy_channel (struct GNUNET_CADET_Channel *ch)
205{
206 struct GNUNET_CADET_Handle *h = ch->cadet;
207
208 LOG (GNUNET_ERROR_TYPE_DEBUG,
209 "Destroying channel %X of %p\n",
210 htonl (ch->ccn.channel_of_client),
211 h);
212 GNUNET_assert (
213 GNUNET_YES ==
214 GNUNET_CONTAINER_multihashmap32_remove (h->channels,
215 ntohl (ch->ccn.channel_of_client),
216 ch));
217 if (NULL != ch->mq_cont)
218 {
219 GNUNET_SCHEDULER_cancel (ch->mq_cont);
220 ch->mq_cont = NULL;
221 }
222 /* signal channel destruction */
223 if (NULL != ch->disconnects)
224 ch->disconnects (ch->ctx, ch);
225 if (NULL != ch->pending_env)
226 GNUNET_MQ_discard (ch->pending_env);
227 GNUNET_MQ_destroy (ch->mq);
228 GNUNET_free (ch);
229}
230
231
232/**
233 * Reconnect to the service, retransmit all information to try to restore the
234 * original state.
235 *
236 * @param h handle to the cadet
237 */
238static void
239reconnect (struct GNUNET_CADET_Handle *h);
240
241
242/**
243 * Function called during #reconnect_cbk() to (re)open
244 * all ports that are still open.
245 *
246 * @param cls the `struct GNUNET_CADET_Handle`
247 * @param id port ID
248 * @param value a `struct GNUNET_CADET_Channel` to open
249 * @return #GNUNET_OK (continue to iterate)
250 */
251static int
252open_port_cb (void *cls, const struct GNUNET_HashCode *id, void *value)
253{
254 struct GNUNET_CADET_Handle *h = cls;
255 struct GNUNET_CADET_Port *port = value;
256 struct GNUNET_CADET_PortMessage *msg;
257 struct GNUNET_MQ_Envelope *env;
258
259 (void) id;
260 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN);
261 msg->port = port->id;
262 GNUNET_MQ_send (h->mq, env);
263 return GNUNET_OK;
264}
265
266
267/**
268 * Reconnect callback: tries to reconnect again after a failed previous
269 * connection
270 *
271 * @param cls closure (cadet handle)
272 */
273static void
274reconnect_cbk (void *cls)
275{
276 struct GNUNET_CADET_Handle *h = cls;
277
278 h->reconnect_task = NULL;
279 h->reconnect_time = GNUNET_TIME_STD_BACKOFF (h->reconnect_time);
280 reconnect (h);
281 GNUNET_CONTAINER_multihashmap_iterate (h->ports, &open_port_cb, h);
282}
283
284
285/**
286 * Notify the application about a change in the window size (if needed).
287 *
288 * @param ch Channel to notify about.
289 */
290static void
291notify_window_size (struct GNUNET_CADET_Channel *ch)
292{
293 if (NULL != ch->window_changes)
294 ch->window_changes (ch->ctx,
295 ch, /* FIXME: remove 'ch'? */
296 ch->allow_send);
297}
298
299
300/**
301 * Transmit the next message from our queue.
302 *
303 * @param cls Closure (channel whose mq to activate).
304 */
305static void
306cadet_mq_send_now (void *cls)
307{
308 struct GNUNET_CADET_Channel *ch = cls;
309 struct GNUNET_MQ_Envelope *env = ch->pending_env;
310
311 ch->mq_cont = NULL;
312 if (0 == ch->allow_send)
313 {
314 /* how did we get here? */
315 GNUNET_break (0);
316 return;
317 }
318 if (NULL == env)
319 {
320 /* how did we get here? */
321 GNUNET_break (0);
322 return;
323 }
324 ch->allow_send--;
325 ch->pending_env = NULL;
326 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
327 "Sending message on channel %s to CADET, new window size is %u\n",
328 GNUNET_i2s (&ch->peer),
329 ch->allow_send);
330 GNUNET_MQ_send (ch->cadet->mq, env);
331 GNUNET_MQ_impl_send_continue (ch->mq);
332}
333
334
335/**
336 * Implement sending functionality of a message queue for
337 * us sending messages to a peer.
338 *
339 * Encapsulates the payload message in a #GNUNET_CADET_LocalData message
340 * in order to label the message with the channel ID and send the
341 * encapsulated message to the service.
342 *
343 * @param mq the message queue
344 * @param msg the message to send
345 * @param impl_state state of the implementation
346 */
347static void
348cadet_mq_send_impl (struct GNUNET_MQ_Handle *mq,
349 const struct GNUNET_MessageHeader *msg,
350 void *impl_state)
351{
352 struct GNUNET_CADET_Channel *ch = impl_state;
353 struct GNUNET_CADET_Handle *h = ch->cadet;
354 uint16_t msize;
355 struct GNUNET_MQ_Envelope *orig_env;
356 struct GNUNET_MQ_Envelope *env;
357 struct GNUNET_CADET_LocalData *cadet_msg;
358 enum GNUNET_MQ_PriorityPreferences pp;
359
360 if (NULL == h->mq)
361 {
362 /* We're currently reconnecting, pretend this worked */
363 GNUNET_MQ_impl_send_continue (mq);
364 return;
365 }
366 orig_env = GNUNET_MQ_get_current_envelope (mq);
367 pp = GNUNET_MQ_env_get_options (orig_env);
368
369 /* check message size for sanity */
370 msize = ntohs (msg->size);
371 if (msize > GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE)
372 {
373 GNUNET_break (0);
374 GNUNET_MQ_impl_send_continue (mq);
375 return;
376 }
377 env = GNUNET_MQ_msg_nested_mh (cadet_msg,
378 GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA,
379 msg);
380 cadet_msg->ccn = ch->ccn;
381 cadet_msg->pp = htonl ((uint32_t) pp);
382 GNUNET_assert (NULL == ch->pending_env);
383 ch->pending_env = env;
384 if (0 < ch->allow_send)
385 ch->mq_cont = GNUNET_SCHEDULER_add_now (&cadet_mq_send_now, ch);
386}
387
388
389/**
390 * Handle destruction of a message queue. Implementations must not
391 * free @a mq, but should take care of @a impl_state.
392 *
393 * @param mq the message queue to destroy
394 * @param impl_state state of the implementation
395 */
396static void
397cadet_mq_destroy_impl (struct GNUNET_MQ_Handle *mq, void *impl_state)
398{
399 struct GNUNET_CADET_Channel *ch = impl_state;
400
401 GNUNET_assert (mq == ch->mq);
402 ch->mq = NULL;
403}
404
405
406/**
407 * We had an error processing a message we forwarded from a peer to
408 * the CADET service. We should just complain about it but otherwise
409 * continue processing.
410 *
411 * @param cls closure with our `struct GNUNET_CADET_Channel`
412 * @param error error code
413 */
414static void
415cadet_mq_error_handler (void *cls, enum GNUNET_MQ_Error error)
416{
417 struct GNUNET_CADET_Channel *ch = cls;
418
419 if (GNUNET_MQ_ERROR_NO_MATCH == error)
420 {
421 /* Got a message we did not understand, still try to continue! */
422 GNUNET_break_op (0);
423 GNUNET_CADET_receive_done (ch);
424 }
425 else
426 {
427 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
428 "MQ error in communication with CADET: %d\n",
429 error);
430 if (NULL != ch->disconnects)
431 ch->disconnects (ch->ctx, ch);
432 GNUNET_CADET_channel_destroy (ch);
433 }
434}
435
436
437/**
438 * Implementation function that cancels the currently sent message.
439 * Should basically undo whatever #mq_send_impl() did.
440 *
441 * @param mq message queue
442 * @param impl_state state specific to the implementation
443 */
444static void
445cadet_mq_cancel_impl (struct GNUNET_MQ_Handle *mq, void *impl_state)
446{
447 struct GNUNET_CADET_Channel *ch = impl_state;
448
449 (void) mq;
450 GNUNET_assert (NULL != ch->pending_env);
451 GNUNET_MQ_discard (ch->pending_env);
452 ch->pending_env = NULL;
453 if (NULL != ch->mq_cont)
454 {
455 GNUNET_SCHEDULER_cancel (ch->mq_cont);
456 ch->mq_cont = NULL;
457 }
458}
459
460
461/**
462 * Process the new channel notification and add it to the channels in the handle
463 *
464 * @param h The cadet handle
465 * @param msg A message with the details of the new incoming channel
466 */
467static void
468handle_channel_created (
469 void *cls,
470 const struct GNUNET_CADET_LocalChannelCreateMessage *msg)
471{
472 struct GNUNET_CADET_Handle *h = cls;
473 struct GNUNET_CADET_Channel *ch;
474 struct GNUNET_CADET_Port *port;
475 const struct GNUNET_HashCode *port_number;
476 struct GNUNET_CADET_ClientChannelNumber ccn;
477
478 ccn = msg->ccn;
479 port_number = &msg->port;
480 if (ntohl (ccn.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
481 {
482 GNUNET_break (0);
483 return;
484 }
485 port = find_port (h, port_number);
486 if (NULL == port)
487 {
488 /* We could have closed the port but the service didn't know about it yet
489 * This is not an error.
490 */
491 struct GNUNET_CADET_LocalChannelDestroyMessage *d_msg;
492 struct GNUNET_MQ_Envelope *env;
493
494 LOG (GNUNET_ERROR_TYPE_DEBUG,
495 "No handler for incoming channel %X (on port %s, recently closed?)\n",
496 ntohl (ccn.channel_of_client),
497 GNUNET_h2s (port_number));
498 env =
499 GNUNET_MQ_msg (d_msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY);
500 d_msg->ccn = msg->ccn;
501 GNUNET_MQ_send (h->mq, env);
502 return;
503 }
504
505 ch = create_channel (h, &ccn);
506 ch->peer = msg->peer;
507 ch->incoming_port = port;
508 LOG (GNUNET_ERROR_TYPE_DEBUG,
509 "Creating incoming channel %X [%s] %p\n",
510 ntohl (ccn.channel_of_client),
511 GNUNET_h2s (port_number),
512 ch);
513
514 GNUNET_assert (NULL != port->connects);
515 ch->window_changes = port->window_changes;
516 ch->disconnects = port->disconnects;
517 ch->mq = GNUNET_MQ_queue_for_callbacks (&cadet_mq_send_impl,
518 &cadet_mq_destroy_impl,
519 &cadet_mq_cancel_impl,
520 ch,
521 port->handlers,
522 &cadet_mq_error_handler,
523 ch);
524 ch->ctx = port->connects (port->cls, ch, &msg->peer);
525 GNUNET_MQ_set_handlers_closure (ch->mq, ch->ctx);
526}
527
528
529/**
530 * Process the channel destroy notification and free associated resources
531 *
532 * @param h The cadet handle
533 * @param msg A message with the details of the channel being destroyed
534 */
535static void
536handle_channel_destroy (
537 void *cls,
538 const struct GNUNET_CADET_LocalChannelDestroyMessage *msg)
539{
540 struct GNUNET_CADET_Handle *h = cls;
541 struct GNUNET_CADET_Channel *ch;
542
543 ch = find_channel (h, msg->ccn);
544 if (NULL == ch)
545 {
546 LOG (GNUNET_ERROR_TYPE_DEBUG,
547 "Received channel destroy for unknown channel %X from CADET service (recently close?)\n",
548 ntohl (msg->ccn.channel_of_client));
549 return;
550 }
551 LOG (GNUNET_ERROR_TYPE_DEBUG,
552 "Received channel destroy for channel %X from CADET service\n",
553 ntohl (msg->ccn.channel_of_client));
554 destroy_channel (ch);
555}
556
557
558/**
559 * Check that message received from CADET service is well-formed.
560 *
561 * @param cls the `struct GNUNET_CADET_Handle`
562 * @param message the message we got
563 * @return #GNUNET_OK if the message is well-formed,
564 * #GNUNET_SYSERR otherwise
565 */
566static int
567check_local_data (void *cls, const struct GNUNET_CADET_LocalData *message)
568{
569 uint16_t size;
570
571 (void) cls;
572 size = ntohs (message->header.size);
573 if (sizeof(*message) + sizeof(struct GNUNET_MessageHeader) > size)
574 {
575 GNUNET_break (0);
576 return GNUNET_SYSERR;
577 }
578 return GNUNET_OK;
579}
580
581
582/**
583 * Process the incoming data packets, call appropriate handlers.
584 *
585 * @param h The cadet handle
586 * @param message A message encapsulating the data
587 */
588static void
589handle_local_data (void *cls, const struct GNUNET_CADET_LocalData *message)
590{
591 struct GNUNET_CADET_Handle *h = cls;
592 const struct GNUNET_MessageHeader *payload;
593 struct GNUNET_CADET_Channel *ch;
594 uint16_t type;
595 int fwd;
596
597 ch = find_channel (h, message->ccn);
598 if (NULL == ch)
599 {
600 LOG (GNUNET_ERROR_TYPE_DEBUG,
601 "Unknown channel %X for incoming data (recently closed?)\n",
602 ntohl (message->ccn.channel_of_client));
603 return;
604 }
605
606 payload = (const struct GNUNET_MessageHeader *) &message[1];
607 type = ntohs (payload->type);
608 fwd = ntohl (ch->ccn.channel_of_client) <= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI;
609 LOG (GNUNET_ERROR_TYPE_DEBUG,
610 "Got a %s data on channel %s [%X] of type %u\n",
611 fwd ? "FWD" : "BWD",
612 GNUNET_i2s (&ch->peer),
613 ntohl (message->ccn.channel_of_client),
614 type);
615 GNUNET_MQ_inject_message (ch->mq, payload);
616}
617
618
619/**
620 * Process a local ACK message, enabling the client to send
621 * more data to the service.
622 *
623 * @param h Cadet handle.
624 * @param message Message itself.
625 */
626static void
627handle_local_ack (void *cls, const struct GNUNET_CADET_LocalAck *message)
628{
629 struct GNUNET_CADET_Handle *h = cls;
630 struct GNUNET_CADET_Channel *ch;
631
632 ch = find_channel (h, message->ccn);
633 if (NULL == ch)
634 {
635 LOG (GNUNET_ERROR_TYPE_DEBUG,
636 "ACK on unknown channel %X\n",
637 ntohl (message->ccn.channel_of_client));
638 return;
639 }
640 ch->allow_send++;
641 LOG (GNUNET_ERROR_TYPE_DEBUG,
642 "Got an ACK on mq channel %X (peer %s); new window size is %u!\n",
643 ntohl (ch->ccn.channel_of_client),
644 GNUNET_i2s (&ch->peer),
645 ch->allow_send);
646 if (NULL == ch->pending_env)
647 {
648 LOG (GNUNET_ERROR_TYPE_DEBUG,
649 "Got an ACK on mq channel %X, allow send now %u!\n",
650 ntohl (ch->ccn.channel_of_client),
651 ch->allow_send);
652 notify_window_size (ch);
653 return;
654 }
655 if (NULL != ch->mq_cont)
656 return; /* already working on it! */
657 ch->mq_cont = GNUNET_SCHEDULER_add_now (&cadet_mq_send_now, ch);
658}
659
660
661/**
662 * Function called during #GNUNET_CADET_disconnect() to destroy
663 * all channels that are still open.
664 *
665 * @param cls the `struct GNUNET_CADET_Handle`
666 * @param cid chanenl ID
667 * @param value a `struct GNUNET_CADET_Channel` to destroy
668 * @return #GNUNET_OK (continue to iterate)
669 */
670static int
671destroy_channel_cb (void *cls, uint32_t cid, void *value)
672{
673 /* struct GNUNET_CADET_Handle *handle = cls; */
674 struct GNUNET_CADET_Channel *ch = value;
675
676 (void) cls;
677 (void) cid;
678 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
679 "Destroying channel due to GNUNET_CADET_disconnect()\n");
680 destroy_channel (ch);
681 return GNUNET_OK;
682}
683
684
685/**
686 * Generic error handler, called with the appropriate error code and
687 * the same closure specified at the creation of the message queue.
688 * Not every message queue implementation supports an error handler.
689 *
690 * @param cls closure, a `struct GNUNET_CORE_Handle *`
691 * @param error error code
692 */
693static void
694handle_mq_error (void *cls, enum GNUNET_MQ_Error error)
695{
696 struct GNUNET_CADET_Handle *h = cls;
697
698 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MQ ERROR: %u\n", error);
699 GNUNET_CONTAINER_multihashmap32_iterate (h->channels, &destroy_channel_cb, h);
700 GNUNET_MQ_destroy (h->mq);
701 h->mq = NULL;
702 GNUNET_assert (NULL == h->reconnect_task);
703 h->reconnect_task =
704 GNUNET_SCHEDULER_add_delayed (h->reconnect_time, &reconnect_cbk, h);
705}
706
707
708/**
709 * Reconnect to the service, retransmit all information to try to restore the
710 * original state.
711 *
712 * @param h handle to the cadet
713 */
714static void
715reconnect (struct GNUNET_CADET_Handle *h)
716{
717 struct GNUNET_MQ_MessageHandler handlers[] =
718 { GNUNET_MQ_hd_fixed_size (channel_created,
719 GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE,
720 struct GNUNET_CADET_LocalChannelCreateMessage,
721 h),
722 GNUNET_MQ_hd_fixed_size (channel_destroy,
723 GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY,
724 struct GNUNET_CADET_LocalChannelDestroyMessage,
725 h),
726 GNUNET_MQ_hd_var_size (local_data,
727 GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA,
728 struct GNUNET_CADET_LocalData,
729 h),
730 GNUNET_MQ_hd_fixed_size (local_ack,
731 GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK,
732 struct GNUNET_CADET_LocalAck,
733 h),
734 GNUNET_MQ_handler_end () };
735
736 GNUNET_assert (NULL == h->mq);
737 h->mq =
738 GNUNET_CLIENT_connect (h->cfg, "cadet", handlers, &handle_mq_error, h);
739}
740
741
742/**
743 * Function called during #GNUNET_CADET_disconnect() to destroy
744 * all ports that are still open.
745 *
746 * @param cls the `struct GNUNET_CADET_Handle`
747 * @param id port ID
748 * @param value a `struct GNUNET_CADET_Channel` to destroy
749 * @return #GNUNET_OK (continue to iterate)
750 */
751static int
752destroy_port_cb (void *cls, const struct GNUNET_HashCode *id, void *value)
753{
754 /* struct GNUNET_CADET_Handle *handle = cls; */
755 struct GNUNET_CADET_Port *port = value;
756
757 (void) cls;
758 (void) id;
759 /* This is a warning, the app should have cleanly closed all open ports */
760 GNUNET_break (0);
761 GNUNET_CADET_close_port (port);
762 return GNUNET_OK;
763}
764
765
766/**
767 * Disconnect from the cadet service. All channels will be destroyed. All channel
768 * disconnect callbacks will be called on any still connected peers, notifying
769 * about their disconnection. The registered inbound channel cleaner will be
770 * called should any inbound channels still exist.
771 *
772 * @param handle connection to cadet to disconnect
773 */
774void
775GNUNET_CADET_disconnect (struct GNUNET_CADET_Handle *handle)
776{
777 GNUNET_CONTAINER_multihashmap_iterate (handle->ports,
778 &destroy_port_cb,
779 handle);
780 GNUNET_CONTAINER_multihashmap_destroy (handle->ports);
781 handle->ports = NULL;
782 GNUNET_CONTAINER_multihashmap32_iterate (handle->channels,
783 &destroy_channel_cb,
784 handle);
785 GNUNET_CONTAINER_multihashmap32_destroy (handle->channels);
786 handle->channels = NULL;
787 if (NULL != handle->mq)
788 {
789 GNUNET_MQ_destroy (handle->mq);
790 handle->mq = NULL;
791 }
792 if (NULL != handle->reconnect_task)
793 {
794 GNUNET_SCHEDULER_cancel (handle->reconnect_task);
795 handle->reconnect_task = NULL;
796 }
797 GNUNET_free (handle);
798}
799
800
801/**
802 * Close a port opened with @a GNUNET_CADET_open_port().
803 * The @a new_channel callback will no longer be called.
804 *
805 * @param p Port handle.
806 */
807void
808GNUNET_CADET_close_port (struct GNUNET_CADET_Port *p)
809{
810 GNUNET_assert (
811 GNUNET_YES ==
812 GNUNET_CONTAINER_multihashmap_remove (p->cadet->ports, &p->id, p));
813 if (NULL != p->cadet->mq)
814 {
815 struct GNUNET_CADET_PortMessage *msg;
816 struct GNUNET_MQ_Envelope *env;
817
818 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE);
819 msg->port = p->id;
820 GNUNET_MQ_send (p->cadet->mq, env);
821 }
822 GNUNET_free (p->handlers);
823 GNUNET_free (p);
824}
825
826
827/**
828 * Destroy an existing channel.
829 *
830 * The existing end callback for the channel will NOT be called.
831 * Any pending outgoing messages will be sent but no incoming messages will be
832 * accepted and no data callbacks will be called.
833 *
834 * @param channel Channel handle, becomes invalid after this call.
835 */
836void
837GNUNET_CADET_channel_destroy (struct GNUNET_CADET_Channel *channel)
838{
839 struct GNUNET_CADET_Handle *h = channel->cadet;
840 struct GNUNET_CADET_LocalChannelDestroyMessage *msg;
841 struct GNUNET_MQ_Envelope *env;
842
843 if (NULL != h->mq)
844 {
845 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY);
846 msg->ccn = channel->ccn;
847 GNUNET_MQ_send (h->mq, env);
848 }
849 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
850 "Destroying channel due to GNUNET_CADET_channel_destroy()\n");
851 channel->disconnects = NULL;
852 destroy_channel (channel);
853}
854
855
856/**
857 * Get information about a channel.
858 *
859 * @param channel Channel handle.
860 * @param option Query (GNUNET_CADET_OPTION_*).
861 * @param ... dependent on option, currently not used
862 *
863 * @return Union with an answer to the query.
864 */
865const union GNUNET_CADET_ChannelInfo *
866GNUNET_CADET_channel_get_info (struct GNUNET_CADET_Channel *channel,
867 enum GNUNET_CADET_ChannelInfoOption option,
868 ...)
869{
870 switch (option)
871 {
872 case GNUNET_CADET_OPTION_PEER:
873 return (const union GNUNET_CADET_ChannelInfo *) &channel->peer;
874
875 default:
876 GNUNET_break (0);
877 return NULL;
878 }
879}
880
881
882/**
883 * Send an ack on the channel to confirm the processing of a message.
884 *
885 * @param ch Channel on which to send the ACK.
886 */
887void
888GNUNET_CADET_receive_done (struct GNUNET_CADET_Channel *channel)
889{
890 struct GNUNET_CADET_LocalAck *msg;
891 struct GNUNET_MQ_Envelope *env;
892
893 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK);
894 LOG (GNUNET_ERROR_TYPE_DEBUG,
895 "Sending ACK on channel %X\n",
896 ntohl (channel->ccn.channel_of_client));
897 msg->ccn = channel->ccn;
898 GNUNET_MQ_send (channel->cadet->mq, env);
899}
900
901
902/**
903 * Connect to the MQ-based cadet service.
904 *
905 * @param cfg Configuration to use.
906 *
907 * @return Handle to the cadet service NULL on error.
908 */
909struct GNUNET_CADET_Handle *
910GNUNET_CADET_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
911{
912 struct GNUNET_CADET_Handle *h;
913
914 LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_CADET_connect()\n");
915 h = GNUNET_new (struct GNUNET_CADET_Handle);
916 h->cfg = cfg;
917 h->ports = GNUNET_CONTAINER_multihashmap_create (4, GNUNET_YES);
918 h->channels = GNUNET_CONTAINER_multihashmap32_create (4);
919 reconnect (h);
920 if (NULL == h->mq)
921 {
922 GNUNET_break (0);
923 GNUNET_CADET_disconnect (h);
924 return NULL;
925 }
926 h->next_ccn.channel_of_client = htonl (GNUNET_CADET_LOCAL_CHANNEL_ID_CLI);
927 return h;
928}
929
930
931/**
932 * Function to return link to AGPL source upon request.
933 *
934 * @param cls closure with the identification of the client
935 * @param msg AGPL request
936 */
937static void
938return_agpl (void *cls, const struct GNUNET_MessageHeader *msg)
939{
940 struct GNUNET_SERVICE_Client *client = cls;
941 struct GNUNET_MQ_Handle *mq;
942 struct GNUNET_MQ_Envelope *env;
943 struct GNUNET_MessageHeader *res;
944 size_t slen;
945 const struct GNUNET_OS_ProjectData *pd = GNUNET_OS_project_data_get ();
946
947 (void) msg;
948 slen = strlen (pd->agpl_url) + 1;
949 env = GNUNET_MQ_msg_extra (res, GNUNET_MESSAGE_TYPE_RESPONSE_AGPL, slen);
950 memcpy (&res[1], GNUNET_AGPL_URL, slen);
951 mq = GNUNET_SERVICE_client_get_mq (client);
952 GNUNET_MQ_send (mq, env);
953 GNUNET_SERVICE_client_continue (client);
954}
955
956
957/**
958 * Open a port to receive incoming MQ-based channels.
959 *
960 * @param h CADET handle.
961 * @param port Hash identifying the port.
962 * @param connects Function called when an incoming channel is connected.
963 * @param connects_cls Closure for the @a connects handler.
964 * @param window_changes Function called when the transmit window size changes.
965 * @param disconnects Function called when a channel is disconnected.
966 * @param handlers Callbacks for messages we care about, NULL-terminated.
967 * @return Port handle, NULL if port is in use
968 */
969struct GNUNET_CADET_Port *
970GNUNET_CADET_open_port (struct GNUNET_CADET_Handle *h,
971 const struct GNUNET_HashCode *port,
972 GNUNET_CADET_ConnectEventHandler connects,
973 void *connects_cls,
974 GNUNET_CADET_WindowSizeEventHandler window_changes,
975 GNUNET_CADET_DisconnectEventHandler disconnects,
976 const struct GNUNET_MQ_MessageHandler *handlers)
977{
978 struct GNUNET_CADET_Port *p;
979 const struct GNUNET_OS_ProjectData *pd = GNUNET_OS_project_data_get ();
980
981 GNUNET_assert (NULL != connects);
982 GNUNET_assert (NULL != disconnects);
983 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
984 "Listening to CADET port %s\n",
985 GNUNET_h2s (port));
986
987 p = GNUNET_new (struct GNUNET_CADET_Port);
988 p->cadet = h;
989 p->id = *port;
990 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (
991 h->ports,
992 &p->id,
993 p,
994 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
995 {
996 GNUNET_free (p);
997 return NULL;
998 }
999 p->connects = connects;
1000 p->cls = connects_cls;
1001 p->window_changes = window_changes;
1002 p->disconnects = disconnects;
1003 p->handlers = (NULL == pd->agpl_url)
1004 ? GNUNET_MQ_copy_handlers (handlers)
1005 : GNUNET_MQ_copy_handlers2 (handlers, &return_agpl, NULL);
1006
1007 GNUNET_assert (GNUNET_OK == open_port_cb (h, &p->id, p));
1008 return p;
1009}
1010
1011
1012/**
1013 * Create a new channel towards a remote peer.
1014 *
1015 * If the destination peer closes the channel after accepting it,
1016 * @a disconnects will be called for this channel (unless
1017 * #GNUNET_CADET_channel_destroy() was called on this end first).
1018 *
1019 * @param h CADET handle.
1020 * @param channel_cls Closure for the channel. It's given to:
1021 * - The disconnect handler @a disconnects
1022 * - Each message type callback in @a handlers
1023 * @param destination Peer identity the channel should go to.
1024 * @param port Identification of the destination port.
1025 * @param window_changes Function called when the transmit window size changes.
1026 * @param disconnects Function called when the channel is disconnected.
1027 * @param handlers Callbacks for messages we care about, NULL-terminated.
1028 * @return Handle to the channel.
1029 */
1030struct GNUNET_CADET_Channel *
1031GNUNET_CADET_channel_create (struct GNUNET_CADET_Handle *h,
1032 void *channel_cls,
1033 const struct GNUNET_PeerIdentity *destination,
1034 const struct GNUNET_HashCode *port,
1035 GNUNET_CADET_WindowSizeEventHandler window_changes,
1036 GNUNET_CADET_DisconnectEventHandler disconnects,
1037 const struct GNUNET_MQ_MessageHandler *handlers)
1038{
1039 struct GNUNET_CADET_Channel *ch;
1040 struct GNUNET_CADET_LocalChannelCreateMessage *msg;
1041 struct GNUNET_MQ_Envelope *env;
1042
1043 GNUNET_assert (NULL != disconnects);
1044 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1045 "Creating channel to peer %s at port %s\n",
1046 GNUNET_i2s (destination),
1047 GNUNET_h2s (port));
1048 ch = create_channel (h, NULL);
1049 ch->ctx = channel_cls;
1050 ch->peer = *destination;
1051 ch->window_changes = window_changes;
1052 ch->disconnects = disconnects;
1053
1054 /* Create MQ for channel */
1055 ch->mq = GNUNET_MQ_queue_for_callbacks (&cadet_mq_send_impl,
1056 &cadet_mq_destroy_impl,
1057 &cadet_mq_cancel_impl,
1058 ch,
1059 handlers,
1060 &cadet_mq_error_handler,
1061 ch);
1062 GNUNET_MQ_set_handlers_closure (ch->mq, channel_cls);
1063
1064 /* Request channel creation to service */
1065 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE);
1066 msg->ccn = ch->ccn;
1067 msg->port = *port;
1068 msg->peer = *destination;
1069 GNUNET_MQ_send (h->mq, env);
1070 return ch;
1071}
1072
1073
1074/**
1075 * Obtain the message queue for a connected peer.
1076 *
1077 * @param channel The channel handle from which to get the MQ.
1078 *
1079 * @return NULL if @a channel is not yet connected.
1080 */
1081struct GNUNET_MQ_Handle *
1082GNUNET_CADET_get_mq (const struct GNUNET_CADET_Channel *channel)
1083{
1084 return channel->mq;
1085}
1086
1087
1088/* end of cadet_api.c */
diff --git a/src/cadet/cadet_api_drop_message.c b/src/cadet/cadet_api_drop_message.c
deleted file mode 100644
index 2b031b5c0..000000000
--- a/src/cadet/cadet_api_drop_message.c
+++ /dev/null
@@ -1,59 +0,0 @@
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/cadet/cadet_api_get_channel.c b/src/cadet/cadet_api_get_channel.c
deleted file mode 100644
index 05e2a8383..000000000
--- a/src/cadet/cadet_api_get_channel.c
+++ /dev/null
@@ -1,260 +0,0 @@
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/cadet/cadet_api_get_path.c b/src/cadet/cadet_api_get_path.c
deleted file mode 100644
index 68070eab2..000000000
--- a/src/cadet/cadet_api_get_path.c
+++ /dev/null
@@ -1,276 +0,0 @@
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
219/**
220 * Request information about paths known to the running cadet peer.
221 *
222 * @param cfg configuration to use
223 * @param id Peer whose paths to examine.
224 * @param callback Function to call with the requested data.
225 * @param callback_cls Closure for @c callback.
226 * @return NULL on error
227 */
228struct GNUNET_CADET_GetPath *
229GNUNET_CADET_get_path (const struct GNUNET_CONFIGURATION_Handle *cfg,
230 const struct GNUNET_PeerIdentity *id,
231 GNUNET_CADET_PathCB callback,
232 void *callback_cls)
233{
234 struct GNUNET_CADET_GetPath *gp;
235
236 if (NULL == callback)
237 {
238 GNUNET_break (0);
239 return NULL;
240 }
241 gp = GNUNET_new (struct GNUNET_CADET_GetPath);
242 gp->path_cb = callback;
243 gp->path_cb_cls = callback_cls;
244 gp->cfg = cfg;
245 gp->id = *id;
246 reconnect (gp);
247 if (NULL == gp->mq)
248 {
249 GNUNET_free (gp);
250 return NULL;
251 }
252 return gp;
253}
254
255
256/**
257 * Cancel @a gp operation.
258 *
259 * @param gp operation to cancel
260 * @return closure from #GNUNET_CADET_get_path().
261 */
262void *
263GNUNET_CADET_get_path_cancel (struct GNUNET_CADET_GetPath *gp)
264{
265 void *ret = gp->path_cb_cls;
266
267 if (NULL != gp->mq)
268 GNUNET_MQ_destroy (gp->mq);
269 if (NULL != gp->reconnect_task)
270 GNUNET_SCHEDULER_cancel (gp->reconnect_task);
271 GNUNET_free (gp);
272 return ret;
273}
274
275
276/* end of cadet_api_get_path.c */
diff --git a/src/cadet/cadet_api_helper.c b/src/cadet/cadet_api_helper.c
deleted file mode 100644
index 52aec6cc9..000000000
--- a/src/cadet/cadet_api_helper.c
+++ /dev/null
@@ -1,54 +0,0 @@
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/cadet/cadet_api_list_peers.c b/src/cadet/cadet_api_list_peers.c
deleted file mode 100644
index 52f59cc74..000000000
--- a/src/cadet/cadet_api_list_peers.c
+++ /dev/null
@@ -1,238 +0,0 @@
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/cadet/cadet_api_list_tunnels.c b/src/cadet/cadet_api_list_tunnels.c
deleted file mode 100644
index e9ae069bb..000000000
--- a/src/cadet/cadet_api_list_tunnels.c
+++ /dev/null
@@ -1,239 +0,0 @@
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 message 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/cadet/cadet_protocol.h b/src/cadet/cadet_protocol.h
deleted file mode 100644
index 117a7922e..000000000
--- a/src/cadet/cadet_protocol.h
+++ /dev/null
@@ -1,541 +0,0 @@
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/cadet/cadet_test_lib.c b/src/cadet/cadet_test_lib.c
deleted file mode 100644
index 9c7b9063d..000000000
--- a/src/cadet/cadet_test_lib.c
+++ /dev/null
@@ -1,376 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012, 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_test_lib.c
22 * @author Bartlomiej Polot
23 * @brief library for writing CADET tests
24 */
25#include "platform.h"
26#include "gnunet_util_lib.h"
27#include "cadet_test_lib.h"
28#include "gnunet_cadet_service.h"
29
30
31/**
32 * Test context for a CADET Test.
33 */
34struct GNUNET_CADET_TEST_Context
35{
36 /**
37 * Array of running peers.
38 */
39 struct GNUNET_TESTBED_Peer **peers;
40
41 /**
42 * Array of handles to the CADET for each peer.
43 */
44 struct GNUNET_CADET_Handle **cadets;
45
46 /**
47 * Operation associated with the connection to the CADET.
48 */
49 struct GNUNET_TESTBED_Operation **ops;
50
51 /**
52 * Number of peers running, size of the arrays above.
53 */
54 unsigned int num_peers;
55
56 /**
57 * Main function of the test to run once all CADETs are available.
58 */
59 GNUNET_CADET_TEST_AppMain app_main;
60
61 /**
62 * Closure for 'app_main'.
63 */
64 void *app_main_cls;
65
66 /**
67 * Handler for incoming tunnels.
68 */
69 GNUNET_CADET_ConnectEventHandler connects;
70
71 /**
72 * Function called when the transmit window size changes.
73 */
74 GNUNET_CADET_WindowSizeEventHandler window_changes;
75
76 /**
77 * Cleaner for destroyed incoming tunnels.
78 */
79 GNUNET_CADET_DisconnectEventHandler disconnects;
80
81 /**
82 * Message handlers.
83 */
84 struct GNUNET_MQ_MessageHandler *handlers;
85
86 /**
87 * Application ports.
88 */
89 const struct GNUNET_HashCode **ports;
90
91 /**
92 * Number of ports in #ports.
93 */
94 unsigned int port_count;
95};
96
97
98/**
99 * Context for a cadet adapter callback.
100 */
101struct GNUNET_CADET_TEST_AdapterContext
102{
103 /**
104 * Peer number for the particular peer.
105 */
106 unsigned int peer;
107
108 /**
109 * Port handlers for open ports.
110 */
111 struct GNUNET_CADET_Port **ports;
112
113 /**
114 * General context.
115 */
116 struct GNUNET_CADET_TEST_Context *ctx;
117};
118
119
120/**
121 * Adapter function called to establish a connection to
122 * the CADET service.
123 *
124 * @param cls closure
125 * @param cfg configuration of the peer to connect to; will be available until
126 * GNUNET_TESTBED_operation_done() is called on the operation returned
127 * from GNUNET_TESTBED_service_connect()
128 * @return service handle to return in 'op_result', NULL on error
129 */
130static void *
131cadet_connect_adapter (void *cls,
132 const struct GNUNET_CONFIGURATION_Handle *cfg)
133{
134 struct GNUNET_CADET_TEST_AdapterContext *actx = cls;
135 struct GNUNET_CADET_TEST_Context *ctx = actx->ctx;
136 struct GNUNET_CADET_Handle *h;
137
138 h = GNUNET_CADET_connect (cfg);
139 if (NULL == h)
140 {
141 GNUNET_break (0);
142 return NULL;
143 }
144 if (NULL == ctx->ports)
145 return h;
146 actx->ports = GNUNET_new_array (ctx->port_count,
147 struct GNUNET_CADET_Port *);
148 for (unsigned int i = 0; i < ctx->port_count; i++)
149 {
150 actx->ports[i] = GNUNET_CADET_open_port (h,
151 ctx->ports[i],
152 ctx->connects,
153 (void *) (long) actx->peer,
154 ctx->window_changes,
155 ctx->disconnects,
156 ctx->handlers);
157 }
158 return h;
159}
160
161
162/**
163 * Adapter function called to destroy a connection to
164 * the CADET service.
165 *
166 * @param cls closure
167 * @param op_result service handle returned from the connect adapter
168 */
169static void
170cadet_disconnect_adapter (void *cls,
171 void *op_result)
172{
173 struct GNUNET_CADET_Handle *cadet = op_result;
174 struct GNUNET_CADET_TEST_AdapterContext *actx = cls;
175
176 if (NULL != actx->ports)
177 {
178 for (unsigned int i = 0; i < actx->ctx->port_count; i++)
179 {
180 GNUNET_CADET_close_port (actx->ports[i]);
181 actx->ports[i] = NULL;
182 }
183 GNUNET_free (actx->ports);
184 }
185 GNUNET_free (actx);
186 GNUNET_CADET_disconnect (cadet);
187}
188
189
190/**
191 * Callback to be called when a service connect operation is completed.
192 *
193 * @param cls The callback closure from functions generating an operation.
194 * @param op The operation that has been finished.
195 * @param ca_result The service handle returned from
196 * GNUNET_TESTBED_ConnectAdapter() (cadet handle).
197 * @param emsg Error message in case the operation has failed.
198 * NULL if operation has executed successfully.
199 */
200static void
201cadet_connect_cb (void *cls,
202 struct GNUNET_TESTBED_Operation *op,
203 void *ca_result,
204 const char *emsg)
205{
206 struct GNUNET_CADET_TEST_Context *ctx = cls;
207
208 if (NULL != emsg)
209 {
210 fprintf (stderr,
211 "Failed to connect to CADET service: %s\n",
212 emsg);
213 GNUNET_SCHEDULER_shutdown ();
214 return;
215 }
216 for (unsigned int i = 0; i < ctx->num_peers; i++)
217 if (op == ctx->ops[i])
218 {
219 ctx->cadets[i] = ca_result;
220 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
221 "...cadet %u connected\n",
222 i);
223 }
224 for (unsigned int i = 0; i < ctx->num_peers; i++)
225 if (NULL == ctx->cadets[i])
226 return;
227 /* still some CADET connections missing */
228 /* all CADET connections ready! */
229 ctx->app_main (ctx->app_main_cls,
230 ctx,
231 ctx->num_peers,
232 ctx->peers,
233 ctx->cadets);
234}
235
236
237void
238GNUNET_CADET_TEST_cleanup (struct GNUNET_CADET_TEST_Context *ctx)
239{
240 for (unsigned int i = 0; i < ctx->num_peers; i++)
241 {
242 GNUNET_assert (NULL != ctx->ops[i]);
243 GNUNET_TESTBED_operation_done (ctx->ops[i]);
244 ctx->ops[i] = NULL;
245 }
246 GNUNET_free (ctx->ops);
247 GNUNET_free (ctx->cadets);
248 GNUNET_free (ctx->handlers);
249 GNUNET_free (ctx);
250 GNUNET_SCHEDULER_shutdown ();
251}
252
253
254/**
255 * Callback run when the testbed is ready (peers running and connected to
256 * each other)
257 *
258 * @param cls Closure (context).
259 * @param h the run handle
260 * @param num_peers Number of peers that are running.
261 * @param peers Handles to each one of the @c num_peers peers.
262 * @param links_succeeded the number of overlay link connection attempts that
263 * succeeded
264 * @param links_failed the number of overlay link connection attempts that
265 * failed
266 */
267static void
268cadet_test_run (void *cls,
269 struct GNUNET_TESTBED_RunHandle *h,
270 unsigned int num_peers,
271 struct GNUNET_TESTBED_Peer **peers,
272 unsigned int links_succeeded,
273 unsigned int links_failed)
274{
275 struct GNUNET_CADET_TEST_Context *ctx = cls;
276
277 if (0 != links_failed)
278 {
279 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
280 "Some links failed (%u), ending\n",
281 links_failed);
282 exit (77);
283 }
284 if (num_peers != ctx->num_peers)
285 {
286 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
287 "Peers started %u/%u, ending\n",
288 num_peers,
289 ctx->num_peers);
290 exit (1);
291 }
292 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
293 "Testbed up, %u peers and %u links\n",
294 num_peers,
295 links_succeeded);
296 ctx->peers = peers;
297 for (unsigned int i = 0; i < num_peers; i++)
298 {
299 struct GNUNET_CADET_TEST_AdapterContext *newctx;
300
301 newctx = GNUNET_new (struct GNUNET_CADET_TEST_AdapterContext);
302 newctx->peer = i;
303 newctx->ctx = ctx;
304 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
305 "Connecting to cadet %u\n",
306 i);
307 ctx->ops[i] = GNUNET_TESTBED_service_connect (ctx,
308 peers[i],
309 "cadet",
310 &cadet_connect_cb,
311 ctx,
312 &cadet_connect_adapter,
313 &cadet_disconnect_adapter,
314 newctx);
315 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
316 "op handle %p\n",
317 ctx->ops[i]);
318 }
319}
320
321
322/**
323 * Run a test using the given name, configuration file and number of peers.
324 * All cadet callbacks will receive the peer number (long) as the closure.
325 *
326 * @param testname Name of the test (for logging).
327 * @param cfgfile Name of the configuration file.
328 * @param num_peers Number of peers to start.
329 * @param tmain Main function to run once the testbed is ready.
330 * @param tmain_cls Closure for @a tmain.
331 * @param connects Handler for incoming channels.
332 * @param window_changes Handler for the window size change notification.
333 * @param disconnects Cleaner for destroyed incoming channels.
334 * @param handlers Message handlers.
335 * @param ports Ports the peers offer, NULL-terminated.
336 */
337void
338GNUNET_CADET_TEST_ruN (const char *testname,
339 const char *cfgfile,
340 unsigned int num_peers,
341 GNUNET_CADET_TEST_AppMain tmain,
342 void *tmain_cls,
343 GNUNET_CADET_ConnectEventHandler connects,
344 GNUNET_CADET_WindowSizeEventHandler window_changes,
345 GNUNET_CADET_DisconnectEventHandler disconnects,
346 struct GNUNET_MQ_MessageHandler *handlers,
347 const struct GNUNET_HashCode **ports)
348{
349 struct GNUNET_CADET_TEST_Context *ctx;
350
351 ctx = GNUNET_new (struct GNUNET_CADET_TEST_Context);
352 ctx->num_peers = num_peers;
353 ctx->ops = GNUNET_new_array (num_peers,
354 struct GNUNET_TESTBED_Operation *);
355 ctx->cadets = GNUNET_new_array (num_peers,
356 struct GNUNET_CADET_Handle *);
357 ctx->app_main = tmain;
358 ctx->app_main_cls = tmain_cls;
359 ctx->connects = connects;
360 ctx->window_changes = window_changes;
361 ctx->disconnects = disconnects;
362 ctx->handlers = GNUNET_MQ_copy_handlers (handlers);
363 ctx->ports = ports;
364 ctx->port_count = 0;
365 while (NULL != ctx->ports[ctx->port_count])
366 ctx->port_count++;
367 GNUNET_TESTBED_test_run (testname,
368 cfgfile,
369 num_peers,
370 0LL, NULL, NULL,
371 &cadet_test_run,
372 ctx);
373}
374
375
376/* end of cadet_test_lib.c */
diff --git a/src/cadet/cadet_test_lib.h b/src/cadet/cadet_test_lib.h
deleted file mode 100644
index 7d446801a..000000000
--- a/src/cadet/cadet_test_lib.h
+++ /dev/null
@@ -1,106 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012,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_test_lib.h
22 * @author Bartlomiej Polot
23 * @brief library for writing CADET tests
24 */
25#ifndef CADET_TEST_LIB_H
26#define CADET_TEST_LIB_H
27
28#ifdef __cplusplus
29extern "C"
30{
31#if 0 /* keep Emacsens' auto-indent happy */
32}
33#endif
34#endif
35
36#include "gnunet_testbed_service.h"
37#include "gnunet_cadet_service.h"
38
39/**
40 * Test context for a CADET Test.
41 */
42struct GNUNET_CADET_TEST_Context;
43
44
45/**
46 * Main function of a CADET test.
47 *
48 * @param cls Closure.
49 * @param ctx Argument to give to GNUNET_CADET_TEST_cleanup on test end.
50 * @param num_peers Number of peers that are running.
51 * @param peers Array of peers.
52 * @param cadets Handle to each of the CADETs of the peers.
53 */
54typedef void (*GNUNET_CADET_TEST_AppMain) (void *cls,
55 struct GNUNET_CADET_TEST_Context *ctx,
56 unsigned int num_peers,
57 struct GNUNET_TESTBED_Peer **peers,
58 struct GNUNET_CADET_Handle **cadets);
59
60
61/**
62 * Run a test using the given name, configuration file and number of peers.
63 * All cadet callbacks will receive the peer number (long) as the closure.
64 *
65 * @param testname Name of the test (for logging).
66 * @param cfgfile Name of the configuration file.
67 * @param num_peers Number of peers to start.
68 * @param tmain Main function to run once the testbed is ready.
69 * @param tmain_cls Closure for @a tmain.
70 * @param connects Handler for incoming channels.
71 * @param window_changes Handler for the window size change notification.
72 * @param disconnects Cleaner for destroyed incoming channels.
73 * @param handlers Message handlers.
74 * @param ports Ports the peers offer, NULL-terminated.
75 */
76void
77GNUNET_CADET_TEST_ruN (const char *testname,
78 const char *cfgfile,
79 unsigned int num_peers,
80 GNUNET_CADET_TEST_AppMain tmain,
81 void *tmain_cls,
82 GNUNET_CADET_ConnectEventHandler connects,
83 GNUNET_CADET_WindowSizeEventHandler window_changes,
84 GNUNET_CADET_DisconnectEventHandler disconnects,
85 struct GNUNET_MQ_MessageHandler *handlers,
86 const struct GNUNET_HashCode **ports);
87
88/**
89 * Clean up the testbed.
90 *
91 * @param ctx handle for the testbed
92 */
93void
94GNUNET_CADET_TEST_cleanup (struct GNUNET_CADET_TEST_Context *ctx);
95
96
97#if 0 /* keep Emacsens' auto-indent happy */
98{
99#endif
100#ifdef __cplusplus
101}
102#endif
103
104
105/* ifndef CADET_TEST_LIB_H */
106#endif
diff --git a/src/cadet/desirability_table.c b/src/cadet/desirability_table.c
deleted file mode 100644
index 829c618af..000000000
--- a/src/cadet/desirability_table.c
+++ /dev/null
@@ -1,33 +0,0 @@
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 <stdio.h>
9
10int
11main ()
12{
13 for (unsigned int num_alts = 1; num_alts < 10; num_alts++)
14 for (unsigned int off = 0; off < 10; off++)
15 for (double delta = -(int) off; delta <= 5; delta += 0.25)
16 {
17 double weight_alts;
18
19 if (delta <= -1.0)
20 weight_alts = -1.0 * num_alts / delta; /* discount alternative paths */
21 else if (delta >= 1.0)
22 weight_alts = 1.0 * num_alts * delta; /* overcount alternative paths */
23 else
24 weight_alts = 1.0 * num_alts; /* count alternative paths normally */
25
26 fprintf (stderr,
27 "Paths: %u Offset: %u Delta: %5.2f SCORE: %f\n",
28 num_alts,
29 off,
30 delta,
31 ((off + 1.0) / (weight_alts * weight_alts)));
32 }
33}
diff --git a/src/cadet/gnunet-cadet-profiler.c b/src/cadet/gnunet-cadet-profiler.c
deleted file mode 100644
index e61053f94..000000000
--- a/src/cadet/gnunet-cadet-profiler.c
+++ /dev/null
@@ -1,1159 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 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 * @file cadet/gnunet-cadet-profiler.c
22 *
23 * @brief Profiler for cadet experiments.
24 */
25#include <stdio.h>
26#include "platform.h"
27#include "cadet_test_lib.h"
28#include "gnunet_cadet_service.h"
29#include "gnunet_statistics_service.h"
30
31
32#define PING 1
33#define PONG 2
34
35
36/**
37 * Paximum ping period in milliseconds. Real period = rand (0, PING_PERIOD)
38 */
39#define PING_PERIOD 500
40
41/**
42 * How long until we give up on connecting the peers?
43 */
44#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120)
45
46/**
47 * Time to wait for stuff that should be rather fast
48 */
49#define SHORT_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300)
50
51/**
52 * Total number of rounds.
53 */
54#define number_rounds sizeof(rounds) / sizeof(rounds[0])
55
56/**
57 * Ratio of peers active. First round always is 1.0.
58 */
59static float rounds[] = { 0.8, 0.6, 0.8, 0.5, 0.3, 0.8, 0.0 };
60
61/**
62 * Message type for pings.
63 */
64struct CadetPingMessage
65{
66 /**
67 * Header. Type PING/PONG.
68 */
69 struct GNUNET_MessageHeader header;
70
71 /**
72 * Message number.
73 */
74 uint32_t counter;
75
76 /**
77 * Time the message was sent.
78 */
79 struct GNUNET_TIME_AbsoluteNBO timestamp;
80
81 /**
82 * Round number.
83 */
84 uint32_t round_number;
85};
86
87/**
88 * Peer description.
89 */
90struct CadetPeer
91{
92 /**
93 * Testbed Operation (to get peer id, etc).
94 */
95 struct GNUNET_TESTBED_Operation *op;
96
97 /**
98 * Peer ID.
99 */
100 struct GNUNET_PeerIdentity id;
101
102 /**
103 * Cadet handle for the root peer
104 */
105 struct GNUNET_CADET_Handle *cadet;
106
107 /**
108 * Channel handle for the root peer
109 */
110 struct GNUNET_CADET_Channel *ch;
111
112 /**
113 * Channel handle for the dest peer
114 */
115 struct GNUNET_CADET_Channel *incoming_ch;
116
117 /**
118 * Channel handle for a warmup channel.
119 */
120 struct GNUNET_CADET_Channel *warmup_ch;
121
122 /**
123 * Number of payload packes sent
124 */
125 int data_sent;
126
127 /**
128 * Number of payload packets received
129 */
130 int data_received;
131
132 /**
133 * Is peer up?
134 */
135 int up;
136
137 /**
138 * Destinaton to ping.
139 */
140 struct CadetPeer *dest;
141
142 /**
143 * Incoming channel for pings.
144 */
145 struct CadetPeer *incoming;
146
147 /**
148 * Task to do the next ping.
149 */
150 struct GNUNET_SCHEDULER_Task *ping_task;
151
152 /**
153 * NTR operation for the next ping.
154 */
155 struct GNUNET_CADET_TransmitHandle *ping_ntr;
156
157 float mean[number_rounds];
158 float var[number_rounds];
159 unsigned int pongs[number_rounds];
160 unsigned int pings[number_rounds];
161};
162
163/**
164 * Duration of each round.
165 */
166static struct GNUNET_TIME_Relative round_time;
167
168/**
169 * GNUNET_PeerIdentity -> CadetPeer
170 */
171static struct GNUNET_CONTAINER_MultiPeerMap *ids;
172
173/**
174 * Testbed peer handles.
175 */
176static struct GNUNET_TESTBED_Peer **testbed_handles;
177
178/**
179 * Testbed Operation (to get stats).
180 */
181static struct GNUNET_TESTBED_Operation *stats_op;
182
183/**
184 * Operation to get peer ids.
185 */
186static struct CadetPeer *peers;
187
188/**
189 * Peer ids counter.
190 */
191static unsigned int p_ids;
192
193/**
194 * Total number of peers.
195 */
196static unsigned long long peers_total;
197
198/**
199 * Number of currently running peers.
200 */
201static unsigned long long peers_running;
202
203/**
204 * Number of peers doing pings.
205 */
206static unsigned long long peers_pinging;
207
208/**
209 * Test context (to shut down).
210 */
211static struct GNUNET_CADET_TEST_Context *test_ctx;
212
213/**
214 * Task called to disconnect peers, before shutdown.
215 */
216static struct GNUNET_SCHEDULER_Task *disconnect_task;
217
218/**
219 * Task to perform tests
220 */
221static struct GNUNET_SCHEDULER_Task *test_task;
222
223/**
224 * Round number.
225 */
226static unsigned int current_round;
227
228/**
229 * Do preconnect? (Each peer creates a tunnel to one other peer).
230 */
231static int do_warmup;
232
233/**
234 * Warmup progress.
235 */
236static unsigned int peers_warmup;
237
238/**
239 * Flag to notify callbacks not to generate any new traffic anymore.
240 */
241static int test_finished;
242
243/**
244 * Task running each round of the benchmark.
245 */
246static struct GNUNET_SCHEDULER_Task *round_task;
247
248
249/**
250 * START THE TEST ITSELF, AS WE ARE CONNECTED TO THE CADET SERVICES.
251 *
252 * Testcase continues when the root receives confirmation of connected peers,
253 * on callback function ch.
254 *
255 * @param cls Closure (unused).
256 */
257static void
258start_test (void *cls);
259
260
261/**
262 * Calculate a random delay.
263 *
264 * @param max Exclusive maximum, in ms.
265 *
266 * @return A time between 0 a max-1 ms.
267 */
268static struct GNUNET_TIME_Relative
269delay_ms_rnd (unsigned int max)
270{
271 unsigned int rnd;
272
273 rnd = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, max);
274 return GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, rnd);
275}
276
277
278/**
279 * Get the index of a peer in the peers array.
280 *
281 * @param peer Peer whose index to get.
282 *
283 * @return Index of peer in peers.
284 */
285static unsigned int
286get_index (struct CadetPeer *peer)
287{
288 return peer - peers;
289}
290
291
292/**
293 * Show the results of the test (banwidth achieved) and log them to GAUGER
294 */
295static void
296show_end_data (void)
297{
298 struct CadetPeer *peer;
299 unsigned int i;
300 unsigned int j;
301
302 for (i = 0; i < number_rounds; i++)
303 {
304 for (j = 0; j < peers_pinging; j++)
305 {
306 peer = &peers[j];
307 fprintf (stdout,
308 "ROUND %3u PEER %3u: %10.2f / %10.2f, PINGS: %3u, PONGS: %3u\n",
309 i, j, peer->mean[i], sqrt (peer->var[i] / (peer->pongs[i] - 1)),
310 peer->pings[i], peer->pongs[i]);
311 }
312 }
313}
314
315
316/**
317 * Disconnect from cadet services af all peers, call shutdown.
318 *
319 * @param cls Closure (unused).
320 */
321static void
322disconnect_cadet_peers (void *cls)
323{
324 long line = (long) cls;
325 unsigned int i;
326
327 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
328 "disconnecting cadet service, called from line %ld\n",
329 line);
330 disconnect_task = NULL;
331 for (i = 0; i < peers_total; i++)
332 {
333 if (NULL != peers[i].op)
334 GNUNET_TESTBED_operation_done (peers[i].op);
335
336 if (peers[i].up != GNUNET_YES)
337 continue;
338
339 if (NULL != peers[i].ch)
340 {
341 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
342 "%u: channel %p\n", i, peers[i].ch);
343 GNUNET_CADET_channel_destroy (peers[i].ch);
344 }
345 if (NULL != peers[i].warmup_ch)
346 {
347 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
348 "%u: warmup channel %p\n",
349 i, peers[i].warmup_ch);
350 GNUNET_CADET_channel_destroy (peers[i].warmup_ch);
351 }
352 if (NULL != peers[i].incoming_ch)
353 {
354 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
355 "%u: incoming channel %p\n",
356 i, peers[i].incoming_ch);
357 GNUNET_CADET_channel_destroy (peers[i].incoming_ch);
358 }
359 }
360 GNUNET_CADET_TEST_cleanup (test_ctx);
361 GNUNET_SCHEDULER_shutdown ();
362}
363
364
365/**
366 * Shut down peergroup, clean up.
367 *
368 * @param cls Closure (unused).
369 */
370static void
371shutdown_task (void *cls)
372{
373 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
374 "Ending test.\n");
375 if (NULL != disconnect_task)
376 {
377 GNUNET_SCHEDULER_cancel (disconnect_task);
378 disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers,
379 (void *) __LINE__);
380 }
381 if (NULL != round_task)
382 {
383 GNUNET_SCHEDULER_cancel (round_task);
384 round_task = NULL;
385 }
386 if (NULL != test_task)
387 {
388 GNUNET_SCHEDULER_cancel (test_task);
389 test_task = NULL;
390 }
391}
392
393
394/**
395 * Finish test normally: schedule disconnect and shutdown
396 *
397 * @param line Line in the code the abort is requested from (__LINE__).
398 */
399static void
400abort_test (long line)
401{
402 if (disconnect_task != NULL)
403 {
404 GNUNET_SCHEDULER_cancel (disconnect_task);
405 disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers,
406 (void *) line);
407 }
408}
409
410
411/**
412 * Stats callback. Finish the stats testbed operation and when all stats have
413 * been iterated, shutdown the test.
414 *
415 * @param cls closure
416 * @param op the operation that has been finished
417 * @param emsg error message in case the operation has failed; will be NULL if
418 * operation has executed successfully.
419 */
420static void
421stats_cont (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg)
422{
423 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "... collecting statistics done.\n");
424 GNUNET_TESTBED_operation_done (stats_op);
425
426 if (NULL != disconnect_task)
427 GNUNET_SCHEDULER_cancel (disconnect_task);
428 disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers,
429 (void *) __LINE__);
430}
431
432
433/**
434 * Process statistic values.
435 *
436 * @param cls closure
437 * @param peer the peer the statistic belong to
438 * @param subsystem name of subsystem that created the statistic
439 * @param name the name of the datum
440 * @param value the current value
441 * @param is_persistent #GNUNET_YES if the value is persistent, #GNUNET_NO if not
442 * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
443 */
444static int
445stats_iterator (void *cls,
446 const struct GNUNET_TESTBED_Peer *peer,
447 const char *subsystem,
448 const char *name,
449 uint64_t value,
450 int is_persistent)
451{
452 uint32_t i;
453
454 i = GNUNET_TESTBED_get_index (peer);
455 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
456 " STATS %u - %s [%s]: %llu\n",
457 i, subsystem, name,
458 (unsigned long long) value);
459
460 return GNUNET_OK;
461}
462
463
464/**
465 * Task check that keepalives were sent and received.
466 *
467 * @param cls Closure (NULL).
468 */
469static void
470collect_stats (void *cls)
471{
472 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
473 "Start collecting statistics...\n");
474 stats_op = GNUNET_TESTBED_get_statistics (peers_total,
475 testbed_handles,
476 NULL, NULL,
477 &stats_iterator,
478 &stats_cont, NULL);
479}
480
481
482/**
483 * @brief Finish profiler normally. Signal finish and start collecting stats.
484 *
485 * @param cls Closure (unused).
486 */
487static void
488finish_profiler (void *cls)
489{
490 test_finished = GNUNET_YES;
491 show_end_data ();
492 GNUNET_SCHEDULER_add_now (&collect_stats, NULL);
493}
494
495
496/**
497 * Set the total number of running peers.
498 *
499 * @param target Desired number of running peers.
500 */
501static void
502adjust_running_peers (unsigned int target)
503{
504 struct GNUNET_TESTBED_Operation *op;
505 unsigned int delta;
506 unsigned int run;
507 unsigned int i;
508 unsigned int r;
509
510 GNUNET_assert (target <= peers_total);
511
512 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "adjust peers to %u\n", target);
513 if (target > peers_running)
514 {
515 delta = target - peers_running;
516 run = GNUNET_YES;
517 }
518 else
519 {
520 delta = peers_running - target;
521 run = GNUNET_NO;
522 }
523
524 for (i = 0; i < delta; i++)
525 {
526 do
527 {
528 r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
529 peers_total - peers_pinging);
530 r += peers_pinging;
531 }
532 while (peers[r].up == run || NULL != peers[r].incoming);
533 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "St%s peer %u: %s\n",
534 run ? "arting" : "opping", r, GNUNET_i2s (&peers[r].id));
535
536 if (NULL != peers[r].ping_task)
537 {
538 GNUNET_SCHEDULER_cancel (peers[r].ping_task);
539 peers[r].ping_task = NULL;
540 }
541 if (NULL != peers[r].ping_ntr)
542 {
543 GNUNET_CADET_notify_transmit_ready_cancel (peers[r].ping_ntr);
544 peers[r].ping_ntr = NULL;
545 }
546 peers[r].up = run;
547
548 if (NULL != peers[r].ch)
549 GNUNET_CADET_channel_destroy (peers[r].ch);
550 peers[r].ch = NULL;
551 if (NULL != peers[r].dest)
552 {
553 if (NULL != peers[r].dest->incoming_ch)
554 GNUNET_CADET_channel_destroy (peers[r].dest->incoming_ch);
555 peers[r].dest->incoming_ch = NULL;
556 }
557
558 op = GNUNET_TESTBED_peer_manage_service (&peers[r], testbed_handles[r],
559 "cadet", NULL, NULL, run);
560 GNUNET_break (NULL != op);
561 peers_running += run ? 1 : -1;
562 GNUNET_assert (peers_running > 0);
563 }
564}
565
566
567/**
568 * @brief Move to next round.
569 *
570 * @param cls Closure (round #).
571 */
572static void
573next_rnd (void *cls)
574{
575 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
576 "ROUND %u\n",
577 current_round);
578 if (0.0 == rounds[current_round])
579 {
580 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Finishing\n");
581 GNUNET_SCHEDULER_add_now (&finish_profiler, NULL);
582 return;
583 }
584 adjust_running_peers (rounds[current_round] * peers_total);
585 current_round++;
586
587 round_task = GNUNET_SCHEDULER_add_delayed (round_time,
588 &next_rnd,
589 NULL);
590}
591
592
593/**
594 * Transmit ping callback.
595 *
596 * @param cls Closure (peer for PING, NULL for PONG).
597 * @param size Size of the transmit buffer.
598 * @param buf Pointer to the beginning of the buffer.
599 *
600 * @return Number of bytes written to buf.
601 */
602static size_t
603tmt_rdy_ping (void *cls, size_t size, void *buf);
604
605
606/**
607 * Transmit pong callback.
608 *
609 * @param cls Closure (copy of PING message, to be freed).
610 * @param size Size of the buffer we have.
611 * @param buf Buffer to copy data to.
612 */
613static size_t
614tmt_rdy_pong (void *cls, size_t size, void *buf)
615{
616 struct CadetPingMessage *ping = cls;
617 struct CadetPingMessage *pong;
618
619 if ((0 == size) || (NULL == buf))
620 {
621 GNUNET_free (ping);
622 return 0;
623 }
624 pong = (struct CadetPingMessage *) buf;
625 GNUNET_memcpy (pong, ping, sizeof(*ping));
626 pong->header.type = htons (PONG);
627
628 GNUNET_free (ping);
629 return sizeof(*ping);
630}
631
632
633/**
634 * @brief Send a ping to destination
635 *
636 * @param cls Closure (peer).
637 */
638static void
639ping (void *cls)
640{
641 struct CadetPeer *peer = cls;
642
643 peer->ping_task = NULL;
644 if (GNUNET_YES == test_finished)
645 return;
646 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
647 "%u -> %u (%u)\n",
648 get_index (peer),
649 get_index (peer->dest),
650 peer->data_sent);
651 peer->ping_ntr = GNUNET_CADET_notify_transmit_ready (peer->ch, GNUNET_NO,
652 GNUNET_TIME_UNIT_FOREVER_REL,
653 sizeof(struct
654 CadetPingMessage),
655 &tmt_rdy_ping, peer);
656}
657
658
659/**
660 * @brief Reply with a pong to origin.
661 *
662 * @param cls Closure (peer).
663 * @param tc Task context.
664 */
665static void
666pong (struct GNUNET_CADET_Channel *channel,
667 const struct CadetPingMessage *ping)
668{
669 struct CadetPingMessage *copy;
670
671 copy = GNUNET_new (struct CadetPingMessage);
672 *copy = *ping;
673 GNUNET_CADET_notify_transmit_ready (channel, GNUNET_NO,
674 GNUNET_TIME_UNIT_FOREVER_REL,
675 sizeof(struct CadetPingMessage),
676 &tmt_rdy_pong, copy);
677}
678
679
680/**
681 * Transmit ping callback
682 *
683 * @param cls Closure (peer).
684 * @param size Size of the buffer we have.
685 * @param buf Buffer to copy data to.
686 */
687static size_t
688tmt_rdy_ping (void *cls, size_t size, void *buf)
689{
690 struct CadetPeer *peer = cls;
691 struct CadetPingMessage *msg = buf;
692
693 peer->ping_ntr = NULL;
694 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
695 "tmt_rdy called, filling buffer\n");
696 if ((size < sizeof(struct CadetPingMessage)) || (NULL == buf))
697 {
698 GNUNET_break (GNUNET_YES == test_finished);
699 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
700 "size %u, buf %p, data_sent %u, data_received %u\n",
701 (unsigned int) size,
702 buf,
703 peer->data_sent,
704 peer->data_received);
705
706 return 0;
707 }
708 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
709 "Sending: msg %d\n",
710 peer->data_sent);
711 msg->header.size = htons (size);
712 msg->header.type = htons (PING);
713 msg->counter = htonl (peer->data_sent++);
714 msg->round_number = htonl (current_round);
715 msg->timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
716 peer->pings[current_round]++;
717 peer->ping_task = GNUNET_SCHEDULER_add_delayed (delay_ms_rnd (PING_PERIOD),
718 &ping, peer);
719
720 return sizeof(struct CadetPingMessage);
721}
722
723
724/**
725 * Function is called whenever a PING message is received.
726 *
727 * @param cls closure (peer #, set from GNUNET_CADET_connect)
728 * @param channel connection to the other end
729 * @param channel_ctx place to store local state associated with the channel
730 * @param message the actual message
731 * @return GNUNET_OK to keep the connection open,
732 * GNUNET_SYSERR to close it (signal serious error)
733 */
734int
735ping_handler (void *cls, struct GNUNET_CADET_Channel *channel,
736 void **channel_ctx,
737 const struct GNUNET_MessageHeader *message)
738{
739 long n = (long) cls;
740
741 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
742 "%u got PING\n",
743 (unsigned int) n);
744 GNUNET_CADET_receive_done (channel);
745 if (GNUNET_NO == test_finished)
746 pong (channel, (struct CadetPingMessage *) message);
747
748 return GNUNET_OK;
749}
750
751
752/**
753 * Function is called whenever a PONG message is received.
754 *
755 * @param cls closure (peer #, set from GNUNET_CADET_connect)
756 * @param channel connection to the other end
757 * @param channel_ctx place to store local state associated with the channel
758 * @param message the actual message
759 * @return GNUNET_OK to keep the connection open,
760 * GNUNET_SYSERR to close it (signal serious error)
761 */
762int
763pong_handler (void *cls, struct GNUNET_CADET_Channel *channel,
764 void **channel_ctx,
765 const struct GNUNET_MessageHeader *message)
766{
767 long n = (long) cls;
768 struct CadetPeer *peer;
769 struct CadetPingMessage *msg;
770 struct GNUNET_TIME_Absolute send_time;
771 struct GNUNET_TIME_Relative latency;
772 unsigned int r /* Ping round */;
773 float delta;
774
775 GNUNET_CADET_receive_done (channel);
776 peer = &peers[n];
777
778 msg = (struct CadetPingMessage *) message;
779
780 send_time = GNUNET_TIME_absolute_ntoh (msg->timestamp);
781 latency = GNUNET_TIME_absolute_get_duration (send_time);
782 r = ntohl (msg->round_number);
783 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%u <- %u (%u) latency: %s\n",
784 get_index (peer),
785 get_index (peer->dest),
786 (uint32_t) ntohl (msg->counter),
787 GNUNET_STRINGS_relative_time_to_string (latency, GNUNET_NO));
788
789 /* Online variance calculation */
790 peer->pongs[r]++;
791 delta = latency.rel_value_us - peer->mean[r];
792 peer->mean[r] = peer->mean[r] + delta / peer->pongs[r];
793 peer->var[r] += delta * (latency.rel_value_us - peer->mean[r]);
794
795 return GNUNET_OK;
796}
797
798
799/**
800 * Handlers, for diverse services
801 */
802static struct GNUNET_CADET_MessageHandler handlers[] = {
803 { &ping_handler, PING, sizeof(struct CadetPingMessage) },
804 { &pong_handler, PONG, sizeof(struct CadetPingMessage) },
805 { NULL, 0, 0 }
806};
807
808
809/**
810 * Method called whenever another peer has added us to a channel
811 * the other peer initiated.
812 *
813 * @param cls Closure.
814 * @param channel New handle to the channel.
815 * @param initiator Peer that started the channel.
816 * @param port Port this channel is connected to.
817 * @param options channel option flags
818 * @return Initial channel context for the channel
819 * (can be NULL -- that's not an error).
820 */
821static void *
822incoming_channel (void *cls, struct GNUNET_CADET_Channel *channel,
823 const struct GNUNET_PeerIdentity *initiator,
824 const struct GNUNET_HashCode *port,
825 enum GNUNET_CADET_ChannelOption options)
826{
827 long n = (long) cls;
828 struct CadetPeer *peer;
829
830 peer = GNUNET_CONTAINER_multipeermap_get (ids, initiator);
831 GNUNET_assert (NULL != peer);
832 if (NULL == peers[n].incoming)
833 {
834 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
835 "WARMUP %3u: %u <= %u\n",
836 peers_warmup,
837 (unsigned int) n,
838 get_index (peer));
839 peers_warmup++;
840 if (peers_warmup < peers_total)
841 return NULL;
842 if (NULL != test_task)
843 {
844 GNUNET_SCHEDULER_cancel (test_task);
845 test_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
846 &start_test, NULL);
847 }
848 return NULL;
849 }
850 GNUNET_assert (peer == peers[n].incoming);
851 GNUNET_assert (peer->dest == &peers[n]);
852 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
853 "%u <= %u %p\n",
854 (unsigned int) n,
855 get_index (peer),
856 channel);
857 peers[n].incoming_ch = channel;
858
859 return NULL;
860}
861
862
863/**
864 * Function called whenever an inbound channel is destroyed. Should clean up
865 * any associated state.
866 *
867 * @param cls closure (set from GNUNET_CADET_connect)
868 * @param channel connection to the other end (henceforth invalid)
869 * @param channel_ctx place where local state associated
870 * with the channel is stored
871 */
872static void
873channel_cleaner (void *cls,
874 const struct GNUNET_CADET_Channel *channel,
875 void *channel_ctx)
876{
877 long n = (long) cls;
878 struct CadetPeer *peer = &peers[n];
879
880 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
881 "Channel %p disconnected at peer %ld\n", channel, n);
882 if (peer->ch == channel)
883 peer->ch = NULL;
884}
885
886
887/**
888 * Select a random peer that has no incoming channel
889 *
890 * @param peer ID of the peer connecting. NULL if irrelevant (warmup).
891 *
892 * @return Random peer not yet connected to.
893 */
894static struct CadetPeer *
895select_random_peer (struct CadetPeer *peer)
896{
897 unsigned int r;
898
899 do
900 {
901 r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, peers_total);
902 }
903 while (NULL != peers[r].incoming);
904 peers[r].incoming = peer;
905
906 return &peers[r];
907}
908
909
910/**
911 * START THE TEST ITSELF, AS WE ARE CONNECTED TO THE CADET SERVICES.
912 *
913 * Testcase continues when the root receives confirmation of connected peers,
914 * on callback function ch.
915 *
916 * @param cls Closure (unused).
917 */
918static void
919start_test (void *cls)
920{
921 unsigned long i;
922
923 test_task = NULL;
924 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Start profiler\n");
925
926
927 for (i = 0; i < peers_pinging; i++)
928 {
929 peers[i].dest = select_random_peer (&peers[i]);
930 peers[i].ch = GNUNET_CADET_channel_create (peers[i].cadet, NULL,
931 &peers[i].dest->id,
932 GC_u2h (1));
933 if (NULL == peers[i].ch)
934 {
935 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Channel %lu failed\n", i);
936 GNUNET_CADET_TEST_cleanup (test_ctx);
937 return;
938 }
939 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
940 "%lu => %u %p\n",
941 i,
942 get_index (peers[i].dest),
943 peers[i].ch);
944 peers[i].ping_task = GNUNET_SCHEDULER_add_delayed (delay_ms_rnd (2000),
945 &ping, &peers[i]);
946 }
947 peers_running = peers_total;
948 if (NULL != disconnect_task)
949 GNUNET_SCHEDULER_cancel (disconnect_task);
950 disconnect_task =
951 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (round_time,
952 number_rounds
953 + 1),
954 &disconnect_cadet_peers,
955 (void *) __LINE__);
956 round_task = GNUNET_SCHEDULER_add_delayed (round_time,
957 &next_rnd,
958 NULL);
959}
960
961
962/**
963 * Do warmup: create some channels to spread information about the topology.
964 */
965static void
966warmup (void)
967{
968 struct CadetPeer *peer;
969 unsigned int i;
970
971 for (i = 0; i < peers_total; i++)
972 {
973 peer = select_random_peer (NULL);
974 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "WARMUP %u => %u\n",
975 i, get_index (peer));
976 peers[i].warmup_ch =
977 GNUNET_CADET_channel_create (peers[i].cadet, NULL, &peer->id,
978 GC_u2h (1));
979 if (NULL == peers[i].warmup_ch)
980 {
981 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Warmup %u failed\n", i);
982 GNUNET_CADET_TEST_cleanup (test_ctx);
983 return;
984 }
985 }
986}
987
988
989/**
990 * Callback to be called when the requested peer information is available
991 *
992 * @param cls the closure from GNUNET_TESTBED_peer_get_information()
993 * @param op the operation this callback corresponds to
994 * @param pinfo the result; will be NULL if the operation has failed
995 * @param emsg error message if the operation has failed;
996 * NULL if the operation is successful
997 */
998static void
999peer_id_cb (void *cls,
1000 struct GNUNET_TESTBED_Operation *op,
1001 const struct GNUNET_TESTBED_PeerInformation *pinfo,
1002 const char *emsg)
1003{
1004 long n = (long) cls;
1005
1006 if ((NULL == pinfo) || (NULL != emsg))
1007 {
1008 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "pi_cb: %s\n", emsg);
1009 abort_test (__LINE__);
1010 return;
1011 }
1012 peers[n].id = *(pinfo->result.id);
1013 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1014 "%ld id: %s\n",
1015 n,
1016 GNUNET_i2s (&peers[n].id));
1017 GNUNET_break (GNUNET_OK ==
1018 GNUNET_CONTAINER_multipeermap_put (ids, &peers[n].id, &peers[n],
1019 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
1020
1021 GNUNET_TESTBED_operation_done (peers[n].op);
1022 peers[n].op = NULL;
1023
1024 p_ids++;
1025 if (p_ids < peers_total)
1026 return;
1027 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Got all IDs, starting profiler\n");
1028 if (do_warmup)
1029 {
1030 struct GNUNET_TIME_Relative delay;
1031
1032 warmup ();
1033 delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
1034 100 * peers_total);
1035 test_task = GNUNET_SCHEDULER_add_delayed (delay, &start_test, NULL);
1036 return; /* start_test from incoming_channel */
1037 }
1038 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Starting in a second...\n");
1039 test_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
1040 &start_test, NULL);
1041}
1042
1043
1044/**
1045 * test main: start test when all peers are connected
1046 *
1047 * @param cls Closure.
1048 * @param ctx Argument to give to GNUNET_CADET_TEST_cleanup on test end.
1049 * @param num_peers Number of peers that are running.
1050 * @param testbed_peers Array of peers.
1051 * @param cadetes Handle to each of the CADETs of the peers.
1052 */
1053static void
1054tmain (void *cls,
1055 struct GNUNET_CADET_TEST_Context *ctx,
1056 unsigned int num_peers,
1057 struct GNUNET_TESTBED_Peer **testbed_peers,
1058 struct GNUNET_CADET_Handle **cadetes)
1059{
1060 unsigned long i;
1061
1062 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1063 "test main\n");
1064 test_ctx = ctx;
1065 GNUNET_assert (peers_total == num_peers);
1066 peers_running = num_peers;
1067 testbed_handles = testbed_peers;
1068 disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
1069 &disconnect_cadet_peers,
1070 (void *) __LINE__);
1071 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
1072 for (i = 0; i < peers_total; i++)
1073 {
1074 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1075 "requesting id %ld\n",
1076 i);
1077 peers[i].up = GNUNET_YES;
1078 peers[i].cadet = cadetes[i];
1079 peers[i].op =
1080 GNUNET_TESTBED_peer_get_information (testbed_handles[i],
1081 GNUNET_TESTBED_PIT_IDENTITY,
1082 &peer_id_cb, (void *) i);
1083 }
1084 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "requested peer ids\n");
1085 /* Continues from pi_cb -> do_test */
1086}
1087
1088
1089/**
1090 * Main: start profiler.
1091 */
1092int
1093main (int argc, char *argv[])
1094{
1095 static const struct GNUNET_HashCode *ports[2];
1096 const char *config_file;
1097
1098 config_file = ".profiler.conf";
1099
1100 if (4 > argc)
1101 {
1102 fprintf (stderr,
1103 "usage: %s ROUND_TIME PEERS PINGS [DO_WARMUP]\n",
1104 argv[0]);
1105 fprintf (stderr,
1106 "example: %s 30s 16 1 Y\n",
1107 argv[0]);
1108 return 1;
1109 }
1110
1111 if (GNUNET_OK !=
1112 GNUNET_STRINGS_fancy_time_to_relative (argv[1],
1113 &round_time))
1114 {
1115 fprintf (stderr,
1116 "%s is not a valid time\n",
1117 argv[1]);
1118 return 1;
1119 }
1120
1121 peers_total = atoll (argv[2]);
1122 if (2 > peers_total)
1123 {
1124 fprintf (stderr,
1125 "%s peers is not valid (> 2)\n",
1126 argv[1]);
1127 return 1;
1128 }
1129 peers = GNUNET_new_array (peers_total,
1130 struct CadetPeer);
1131 peers_pinging = atoll (argv[3]);
1132
1133 if (peers_total < 2 * peers_pinging)
1134 {
1135 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1136 "not enough peers, total should be > 2 * peers_pinging\n");
1137 return 1;
1138 }
1139
1140 do_warmup = (5 > argc || argv[4][0] != 'N');
1141
1142 ids = GNUNET_CONTAINER_multipeermap_create (2 * peers_total,
1143 GNUNET_YES);
1144 GNUNET_assert (NULL != ids);
1145 p_ids = 0;
1146 test_finished = GNUNET_NO;
1147 ports[0] = GC_u2h (1);
1148 ports[1] = 0;
1149 GNUNET_CADET_TEST_run ("cadet-profiler", config_file, peers_total,
1150 &tmain, NULL, /* tmain cls */
1151 &incoming_channel, &channel_cleaner,
1152 handlers, ports);
1153 GNUNET_free (peers);
1154
1155 return 0;
1156}
1157
1158
1159/* end of gnunet-cadet-profiler.c */
diff --git a/src/cadet/gnunet-cadet.c b/src/cadet/gnunet-cadet.c
deleted file mode 100644
index 9b7538ae7..000000000
--- a/src/cadet/gnunet-cadet.c
+++ /dev/null
@@ -1,851 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012, 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/**
22 * @file cadet/gnunet-cadet.c
23 * @brief Print information about cadet tunnels and peers.
24 * @author Bartlomiej Polot
25 * @author Christian Grothoff
26 */
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_cadet_service.h"
30#include "cadet.h"
31
32#define STREAM_BUFFER_SIZE 1024 // Pakets
33
34/**
35 * Option -P.
36 */
37static int request_peers;
38
39/**
40 * Option --peer
41 */
42static char *peer_id;
43
44/**
45 * Option -T.
46 */
47static int request_tunnels;
48
49/**
50 * Option --connection
51 */
52static char *conn_id;
53
54/**
55 * Option --channel
56 */
57static char *channel_id;
58
59/**
60 * Port to listen on (-o).
61 */
62static char *listen_port;
63
64/**
65 * Request echo service
66 */
67static int echo;
68
69/**
70 * Time of last echo request.
71 */
72static struct GNUNET_TIME_Absolute echo_time;
73
74/**
75 * Task for next echo request.
76 */
77static struct GNUNET_SCHEDULER_Task *echo_task;
78
79/**
80 * Peer to connect to.
81 */
82static char *target_id;
83
84/**
85 * Port to connect to
86 */
87static char *target_port = "default";
88
89/**
90 * Cadet handle.
91 */
92static struct GNUNET_CADET_Handle *mh;
93
94/**
95 * Our configuration.
96 */
97static const struct GNUNET_CONFIGURATION_Handle *my_cfg;
98
99/**
100 * Active get path operation.
101 */
102static struct GNUNET_CADET_GetPath *gpo;
103
104/**
105 * Active peer listing operation.
106 */
107static struct GNUNET_CADET_PeersLister *plo;
108
109/**
110 * Active tunnel listing operation.
111 */
112static struct GNUNET_CADET_ListTunnels *tio;
113
114/**
115 * Channel handle.
116 */
117static struct GNUNET_CADET_Channel *ch;
118
119/**
120 * HashCode of the given port string
121 */
122static struct GNUNET_HashCode porthash;
123
124/**
125 * Data structure for ongoing reception of incoming virtual circuits.
126 */
127struct GNUNET_CADET_Port *lp;
128
129/**
130 * Task for reading from stdin.
131 */
132static struct GNUNET_SCHEDULER_Task *rd_task;
133
134/**
135 * Task for main job.
136 */
137static struct GNUNET_SCHEDULER_Task *job;
138
139static unsigned int sent_pkt;
140
141
142/**
143 * Wait for input on STDIO and send it out over the #ch.
144 */
145static void
146listen_stdio (void);
147
148
149/**
150 * Convert encryption status to human readable string.
151 *
152 * @param status Encryption status.
153 *
154 * @return Human readable string.
155 */
156static const char *
157enc_2s (uint16_t status)
158{
159 switch (status)
160 {
161 case 0:
162 return "NULL ";
163
164 case 1:
165 return "KSENT";
166
167 case 2:
168 return "KRECV";
169
170 case 3:
171 return "READY";
172
173 default:
174 return "";
175 }
176}
177
178
179/**
180 * Convert connection status to human readable string.
181 *
182 * @param status Connection status.
183 *
184 * @return Human readable string.
185 */
186static const char *
187conn_2s (uint16_t status)
188{
189 switch (status)
190 {
191 case 0:
192 return "NEW ";
193
194 case 1:
195 return "SRCH ";
196
197 case 2:
198 return "WAIT ";
199
200 case 3:
201 return "READY";
202
203 case 4:
204 return "SHUTD";
205
206 default:
207 return "";
208 }
209}
210
211
212/**
213 * Task to shut down this application.
214 *
215 * @param cls Closure (unused).
216 */
217static void
218shutdown_task (void *cls)
219{
220 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown\n");
221 if (NULL != lp)
222 {
223 GNUNET_CADET_close_port (lp);
224 lp = NULL;
225 }
226 if (NULL != ch)
227 {
228 GNUNET_CADET_channel_destroy (ch);
229 ch = NULL;
230 }
231 if (NULL != gpo)
232 {
233 GNUNET_CADET_get_path_cancel (gpo);
234 gpo = NULL;
235 }
236 if (NULL != plo)
237 {
238 GNUNET_CADET_list_peers_cancel (plo);
239 plo = NULL;
240 }
241 if (NULL != tio)
242 {
243 GNUNET_CADET_list_tunnels_cancel (tio);
244 tio = NULL;
245 }
246 if (NULL != mh)
247 {
248 GNUNET_CADET_disconnect (mh);
249 mh = NULL;
250 }
251 if (NULL != rd_task)
252 {
253 GNUNET_SCHEDULER_cancel (rd_task);
254 rd_task = NULL;
255 }
256 if (NULL != echo_task)
257 {
258 GNUNET_SCHEDULER_cancel (echo_task);
259 echo_task = NULL;
260 }
261 if (NULL != job)
262 {
263 GNUNET_SCHEDULER_cancel (job);
264 job = NULL;
265 }
266}
267
268
269void
270mq_cb (void *cls)
271{
272 listen_stdio ();
273}
274
275
276/**
277 * Task run in stdio mode, after some data is available at stdin.
278 *
279 * @param cls Closure (unused).
280 */
281static void
282read_stdio (void *cls)
283{
284 struct GNUNET_MQ_Envelope *env;
285 struct GNUNET_MessageHeader *msg;
286 char buf[60000];
287 ssize_t data_size;
288
289 rd_task = NULL;
290 data_size = read (0, buf, 60000);
291 if (data_size < 1)
292 {
293 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
294 "read() returned %s\n",
295 strerror (errno));
296 GNUNET_SCHEDULER_shutdown ();
297 return;
298 }
299 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
300 "Read %u bytes from stdio\n",
301 (unsigned int) data_size);
302 env = GNUNET_MQ_msg_extra (msg, data_size, GNUNET_MESSAGE_TYPE_CADET_CLI);
303 GNUNET_memcpy (&msg[1], buf, data_size);
304 GNUNET_MQ_send (GNUNET_CADET_get_mq (ch), env);
305
306 sent_pkt++;
307
308 if (GNUNET_NO == echo)
309 {
310 // Use MQ's notification if too much data of stdin is pooring in too fast.
311 if (STREAM_BUFFER_SIZE < sent_pkt)
312 {
313 GNUNET_MQ_notify_sent (env, mq_cb, cls);
314 sent_pkt = 0;
315 }
316 else
317 {
318 listen_stdio ();
319 }
320 }
321 else
322 {
323 echo_time = GNUNET_TIME_absolute_get ();
324 }
325}
326
327
328/**
329 * Wait for input on STDIO and send it out over the #ch.
330 */
331static void
332listen_stdio ()
333{
334 struct GNUNET_NETWORK_FDSet *rs;
335
336 /* FIXME: why use 'rs' here, seems overly complicated... */
337 rs = GNUNET_NETWORK_fdset_create ();
338 GNUNET_NETWORK_fdset_set_native (rs, 0); /* STDIN */
339 rd_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
340 GNUNET_TIME_UNIT_FOREVER_REL,
341 rs,
342 NULL,
343 &read_stdio,
344 NULL);
345 GNUNET_NETWORK_fdset_destroy (rs);
346}
347
348
349/**
350 * Function called whenever a channel is destroyed. Should clean up
351 * any associated state.
352 *
353 * It must NOT call #GNUNET_CADET_channel_destroy on the channel.
354 *
355 * @param cls closure
356 * @param channel connection to the other end (henceforth invalid)
357 */
358static void
359channel_ended (void *cls, const struct GNUNET_CADET_Channel *channel)
360{
361 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Channel ended!\n");
362 GNUNET_assert (channel == ch);
363 ch = NULL;
364 GNUNET_SCHEDULER_shutdown ();
365}
366
367
368/**
369 * Method called whenever another peer has added us to a channel
370 * the other peer initiated.
371 * Only called (once) upon reception of data with a message type which was
372 * subscribed to in #GNUNET_CADET_connect.
373 *
374 * A call to #GNUNET_CADET_channel_destroy causes the channel to be ignored.
375 * In this case the handler MUST return NULL.
376 *
377 * @param cls closure
378 * @param channel new handle to the channel
379 * @param initiator peer that started the channel
380 * @return initial channel context for the channel, we use @a channel
381 */
382static void *
383channel_incoming (void *cls,
384 struct GNUNET_CADET_Channel *channel,
385 const struct GNUNET_PeerIdentity *initiator)
386{
387 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
388 "Incoming connection from %s\n",
389 GNUNET_i2s_full (initiator));
390 GNUNET_assert (NULL == ch);
391 GNUNET_assert (NULL != lp);
392 GNUNET_CADET_close_port (lp);
393 lp = NULL;
394 ch = channel;
395 if (GNUNET_NO == echo)
396 listen_stdio ();
397 return channel;
398}
399
400
401/**
402 * @brief Send an echo request to the remote peer.
403 *
404 * @param cls Closure (NULL).
405 */
406static void
407send_echo (void *cls)
408{
409 struct GNUNET_MQ_Envelope *env;
410 struct GNUNET_MessageHeader *msg;
411
412 echo_task = NULL;
413 if (NULL == ch)
414 return;
415 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_CLI);
416 GNUNET_MQ_send (GNUNET_CADET_get_mq (ch), env);
417}
418
419
420/**
421 * Check data message sanity. Does nothing so far (all messages are OK).
422 *
423 * @param cls Closure (unused).
424 * @param message The message to check.
425 * @return #GNUNET_OK to keep the channel open,
426 * #GNUNET_SYSERR to close it (signal serious error).
427 */
428static int
429check_data (void *cls, const struct GNUNET_MessageHeader *message)
430{
431 return GNUNET_OK; /* all is well-formed */
432}
433
434
435/**
436 * Function called whenever a message is received.
437 *
438 * Each time the function must call #GNUNET_CADET_receive_done on the channel
439 * in order to receive the next message. This doesn't need to be immediate:
440 * can be delayed if some processing is done on the message.
441 *
442 * @param cls NULL
443 * @param message The actual message.
444 */
445static void
446handle_data (void *cls, const struct GNUNET_MessageHeader *message)
447{
448 size_t payload_size = ntohs (message->size) - sizeof(*message);
449 uint16_t len;
450 ssize_t done;
451 uint16_t off;
452 const char *buf;
453
454 GNUNET_CADET_receive_done (ch);
455 if (GNUNET_YES == echo)
456 {
457 if (NULL != listen_port)
458 {
459 struct GNUNET_MQ_Envelope *env;
460 struct GNUNET_MessageHeader *msg;
461
462 env =
463 GNUNET_MQ_msg_extra (msg, payload_size, GNUNET_MESSAGE_TYPE_CADET_CLI);
464 GNUNET_memcpy (&msg[1], &message[1], payload_size);
465 GNUNET_MQ_send (GNUNET_CADET_get_mq (ch), env);
466 return;
467 }
468 else
469 {
470 struct GNUNET_TIME_Relative latency;
471
472 latency = GNUNET_TIME_absolute_get_duration (echo_time);
473 echo_time = GNUNET_TIME_UNIT_FOREVER_ABS;
474 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
475 "time: %s\n",
476 GNUNET_STRINGS_relative_time_to_string (latency, GNUNET_NO));
477 echo_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
478 &send_echo,
479 NULL);
480 }
481 }
482
483 len = ntohs (message->size) - sizeof(*message);
484 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got %u bytes\n", len);
485 buf = (const char *) &message[1];
486 off = 0;
487 while (off < len)
488 {
489 done = write (1, &buf[off], len - off);
490 if (done <= 0)
491 {
492 if (-1 == done)
493 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "write");
494 GNUNET_SCHEDULER_shutdown ();
495 return;
496 }
497 off += done;
498 }
499}
500
501
502/**
503 * Method called to retrieve information about all peers in CADET, called
504 * once per peer.
505 *
506 * After last peer has been reported, an additional call with NULL is done.
507 *
508 * @param cls Closure.
509 * @param ple information about peer, or NULL on "EOF".
510 */
511static void
512peers_callback (void *cls, const struct GNUNET_CADET_PeerListEntry *ple)
513{
514 if (NULL == ple)
515 {
516 plo = NULL;
517 GNUNET_SCHEDULER_shutdown ();
518 return;
519 }
520 fprintf (stdout,
521 "%s tunnel: %c, paths: %u\n",
522 GNUNET_i2s_full (&ple->peer),
523 ple->have_tunnel ? 'Y' : 'N',
524 ple->n_paths);
525}
526
527
528/**
529 * Method called to retrieve information about paths to a specific peer
530 * known to the service.
531 *
532 * @param cls Closure.
533 * @param ppd path detail
534 */
535static void
536path_callback (void *cls, const struct GNUNET_CADET_PeerPathDetail *ppd)
537{
538 if (NULL == ppd)
539 {
540 gpo = NULL;
541 GNUNET_SCHEDULER_shutdown ();
542 return;
543 }
544 fprintf (stdout, "Path of length %u: ", ppd->path_length);
545 for (unsigned int i = 0; i < ppd->path_length; i++)
546 fprintf (stdout,
547 (i == ppd->target_offset) ? "*%s* " : "%s ",
548 GNUNET_i2s (&ppd->path[i]));
549 fprintf (stdout, "\n");
550}
551
552
553/**
554 * Method called to retrieve information about all tunnels in CADET.
555 *
556 * @param cls Closure.
557 * @param td tunnel details
558 */
559static void
560tunnels_callback (void *cls, const struct GNUNET_CADET_TunnelDetails *td)
561{
562 if (NULL == td)
563 {
564 tio = NULL;
565 GNUNET_SCHEDULER_shutdown ();
566 return;
567 }
568 fprintf (stdout,
569 "%s [ENC: %s, CON: %s] CHs: %u, CONNs: %u\n",
570 GNUNET_i2s_full (&td->peer),
571 enc_2s (td->estate),
572 conn_2s (td->cstate),
573 td->channels,
574 td->connections);
575}
576
577
578/**
579 * Call CADET's meta API, get all peers known to a peer.
580 *
581 * @param cls Closure (unused).
582 */
583static void
584get_peers (void *cls)
585{
586 job = NULL;
587 plo = GNUNET_CADET_list_peers (my_cfg, &peers_callback, NULL);
588}
589
590
591/**
592 * Call CADET's monitor API, get info of one peer.
593 *
594 * @param cls Closure (unused).
595 */
596static void
597show_peer (void *cls)
598{
599 struct GNUNET_PeerIdentity pid;
600
601 job = NULL;
602 if (GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string (peer_id,
603 strlen (peer_id),
604 &pid.public_key))
605 {
606 fprintf (stderr, _ ("Invalid peer ID `%s'\n"), peer_id);
607 GNUNET_SCHEDULER_shutdown ();
608 return;
609 }
610 gpo = GNUNET_CADET_get_path (my_cfg, &pid, &path_callback, NULL);
611}
612
613
614/**
615 * Call CADET's meta API, get all tunnels known to a peer.
616 *
617 * @param cls Closure (unused).
618 */
619static void
620get_tunnels (void *cls)
621{
622 job = NULL;
623 tio = GNUNET_CADET_list_tunnels (my_cfg, &tunnels_callback, NULL);
624}
625
626
627/**
628 * Call CADET's monitor API, get info of one channel.
629 *
630 * @param cls Closure (unused).
631 */
632static void
633show_channel (void *cls)
634{
635 job = NULL;
636 GNUNET_break (0);
637}
638
639
640/**
641 * Call CADET's monitor API, get info of one connection.
642 *
643 * @param cls Closure (unused).
644 */
645static void
646show_connection (void *cls)
647{
648 job = NULL;
649 GNUNET_break (0);
650}
651
652
653/**
654 * Main function that will be run by the scheduler.
655 *
656 * @param cls closure
657 * @param args remaining command-line arguments
658 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
659 * @param cfg configuration
660 */
661static void
662run (void *cls,
663 char *const *args,
664 const char *cfgfile,
665 const struct GNUNET_CONFIGURATION_Handle *cfg)
666{
667 struct GNUNET_MQ_MessageHandler handlers[] =
668 { GNUNET_MQ_hd_var_size (data,
669 GNUNET_MESSAGE_TYPE_CADET_CLI,
670 struct GNUNET_MessageHeader,
671 NULL),
672 GNUNET_MQ_handler_end () };
673
674 /* FIXME add option to monitor apps */
675 my_cfg = cfg;
676 target_id = args[0];
677 if (target_id && args[1])
678 target_port = args[1];
679
680 if (((0 != (request_peers | request_tunnels)) || (NULL != conn_id) ||
681 (NULL != channel_id) ) &&
682 (target_id != NULL) )
683 {
684 fprintf (stderr,
685 _ ("Extra arguments are not applicable "
686 "in combination with this option.\n"));
687 return;
688 }
689
690 if (NULL != peer_id)
691 {
692 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show peer\n");
693 job = GNUNET_SCHEDULER_add_now (&show_peer, NULL);
694 }
695 else if (NULL != channel_id)
696 {
697 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show channel\n");
698 job = GNUNET_SCHEDULER_add_now (&show_channel, NULL);
699 }
700 else if (NULL != conn_id)
701 {
702 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show connection\n");
703 job = GNUNET_SCHEDULER_add_now (&show_connection, NULL);
704 }
705 else if (GNUNET_YES == request_peers)
706 {
707 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show all peers\n");
708 job = GNUNET_SCHEDULER_add_now (&get_peers, NULL);
709 }
710 else if (GNUNET_YES == request_tunnels)
711 {
712 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show all tunnels\n");
713 job = GNUNET_SCHEDULER_add_now (&get_tunnels, NULL);
714 }
715
716 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting to CADET service\n");
717 mh = GNUNET_CADET_connect (cfg);
718 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
719 if (NULL == mh)
720 {
721 GNUNET_SCHEDULER_shutdown ();
722 return;
723 }
724 if (NULL != listen_port)
725 {
726 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Opening CADET listen port\n");
727 GNUNET_CRYPTO_hash (listen_port, strlen (listen_port), &porthash);
728 lp = GNUNET_CADET_open_port (mh,
729 &porthash,
730 &channel_incoming,
731 NULL,
732 NULL /* window changes */,
733 &channel_ended,
734 handlers);
735 }
736 if (NULL != target_id)
737 {
738 struct GNUNET_PeerIdentity pid;
739
740 if (GNUNET_OK !=
741 GNUNET_CRYPTO_eddsa_public_key_from_string (target_id,
742 strlen (target_id),
743 &pid.public_key))
744 {
745 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
746 _ ("Invalid target `%s'\n"),
747 target_id);
748 GNUNET_SCHEDULER_shutdown ();
749 return;
750 }
751 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
752 "Connecting to `%s:%s'\n",
753 target_id,
754 target_port);
755 GNUNET_CRYPTO_hash (target_port, strlen (target_port), &porthash);
756 ch = GNUNET_CADET_channel_create (mh,
757 NULL,
758 &pid,
759 &porthash,
760 NULL /* window changes */,
761 &channel_ended,
762 handlers);
763 if (GNUNET_YES == echo)
764 {
765 echo_task = GNUNET_SCHEDULER_add_now (&send_echo, NULL);
766 }
767 else
768 {
769 listen_stdio ();
770 }
771 }
772
773 if ((NULL == lp) && (NULL == job) && (NULL == ch))
774 {
775 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, _ ("No action requested\n"));
776 GNUNET_SCHEDULER_shutdown ();
777 return;
778 }
779}
780
781
782/**
783 * The main function to obtain peer information.
784 *
785 * @param argc number of arguments from the command line
786 * @param argv command line arguments
787 * @return 0 ok, 1 on error
788 */
789int
790main (int argc, char *const *argv)
791{
792 int res;
793 const char helpstr[] =
794 "Create tunnels and retrieve info about CADET's status.";
795 struct GNUNET_GETOPT_CommandLineOption options[] = { /* I would use the terminology 'circuit' here... --lynX */
796 GNUNET_GETOPT_option_string (
797 'C',
798 "connection",
799 "CONNECTION_ID",
800 gettext_noop ("Provide information about a particular connection"),
801 &conn_id),
802 GNUNET_GETOPT_option_flag ('e',
803 "echo",
804 gettext_noop ("Activate echo mode"),
805 &echo),
806 GNUNET_GETOPT_option_string (
807 'o',
808 "open-port",
809 "SHARED_SECRET",
810 gettext_noop (
811 "Listen for connections using a shared secret among sender and recipient"),
812 &listen_port),
813 GNUNET_GETOPT_option_string ('p',
814 "peer",
815 "PEER_ID",
816 gettext_noop (
817 "Provide information about a patricular peer"),
818 &peer_id),
819 GNUNET_GETOPT_option_flag ('P',
820 "peers",
821 gettext_noop (
822 "Provide information about all peers"),
823 &request_peers),
824 GNUNET_GETOPT_option_flag ('T',
825 "tunnels",
826 gettext_noop (
827 "Provide information about all tunnels"),
828 &request_tunnels),
829 GNUNET_GETOPT_OPTION_END
830 };
831
832 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
833 return 2;
834
835 res = GNUNET_PROGRAM_run (argc,
836 argv,
837 "gnunet-cadet (OPTIONS | PEER_ID SHARED_SECRET)",
838 gettext_noop (helpstr),
839 options,
840 &run,
841 NULL);
842
843 GNUNET_free_nz ((void *) argv);
844
845 if (GNUNET_OK == res)
846 return 0;
847 return 1;
848}
849
850
851/* end of gnunet-cadet.c */
diff --git a/src/cadet/gnunet-service-cadet.c b/src/cadet/gnunet-service-cadet.c
deleted file mode 100644
index 73e463e9b..000000000
--- a/src/cadet/gnunet-service-cadet.c
+++ /dev/null
@@ -1,1381 +0,0 @@
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-service-cadet.h"
40#include "gnunet-service-cadet_channel.h"
41#include "gnunet-service-cadet_connection.h"
42#include "gnunet-service-cadet_core.h"
43#include "gnunet-service-cadet_dht.h"
44#include "gnunet-service-cadet_hello.h"
45#include "gnunet-service-cadet_tunnels.h"
46#include "gnunet-service-cadet_peer.h"
47#include "gnunet-service-cadet_paths.h"
48
49#define LOG(level, ...) GNUNET_log (level, __VA_ARGS__)
50
51
52/**
53 * Struct containing information about a client of the service
54 */
55struct CadetClient
56{
57 /**
58 * Linked list next
59 */
60 struct CadetClient *next;
61
62 /**
63 * Linked list prev
64 */
65 struct CadetClient *prev;
66
67 /**
68 * Tunnels that belong to this client, indexed by local id,
69 * value is a `struct CadetChannel`.
70 */
71 struct GNUNET_CONTAINER_MultiHashMap32 *channels;
72
73 /**
74 * Handle to communicate with the client
75 */
76 struct GNUNET_MQ_Handle *mq;
77
78 /**
79 * Client handle.
80 */
81 struct GNUNET_SERVICE_Client *client;
82
83 /**
84 * Ports that this client has declared interest in.
85 * Indexed by port, contains `struct OpenPort`
86 */
87 struct GNUNET_CONTAINER_MultiHashMap *ports;
88
89 /**
90 * Channel ID to use for the next incoming channel for this client.
91 * Wraps around (in theory).
92 */
93 struct GNUNET_CADET_ClientChannelNumber next_ccn;
94
95 /**
96 * ID of the client, mainly for debug messages. Purely internal to this file.
97 */
98 unsigned int id;
99};
100
101
102/******************************************************************************/
103/*********************** GLOBAL VARIABLES ****************************/
104/******************************************************************************/
105
106/****************************** Global variables ******************************/
107
108/**
109 * Handle to our configuration.
110 */
111const struct GNUNET_CONFIGURATION_Handle *cfg;
112
113/**
114 * Handle to the statistics service.
115 */
116struct GNUNET_STATISTICS_Handle *stats;
117
118/**
119 * Handle to communicate with ATS.
120 */
121struct GNUNET_ATS_ConnectivityHandle *ats_ch;
122
123/**
124 * Local peer own ID.
125 */
126struct GNUNET_PeerIdentity my_full_id;
127
128/**
129 * Own private key.
130 */
131struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key;
132
133/**
134 * Signal that shutdown is happening: prevent recovery measures.
135 */
136int shutting_down;
137
138/**
139 * DLL with all the clients, head.
140 */
141static struct CadetClient *clients_head;
142
143/**
144 * DLL with all the clients, tail.
145 */
146static struct CadetClient *clients_tail;
147
148/**
149 * Next ID to assign to a client.
150 */
151static unsigned int next_client_id;
152
153/**
154 * All ports clients of this peer have opened. Maps from
155 * a hashed port to a `struct OpenPort`.
156 */
157struct GNUNET_CONTAINER_MultiHashMap *open_ports;
158
159/**
160 * Map from ports to channels where the ports were closed at the
161 * time we got the inbound connection.
162 * Indexed by h_port, contains `struct CadetChannel`.
163 */
164struct GNUNET_CONTAINER_MultiHashMap *loose_channels;
165
166/**
167 * Map from PIDs to `struct CadetPeer` entries.
168 */
169struct GNUNET_CONTAINER_MultiPeerMap *peers;
170
171/**
172 * Map from `struct GNUNET_CADET_ConnectionTunnelIdentifier`
173 * hash codes to `struct CadetConnection` objects.
174 */
175struct GNUNET_CONTAINER_MultiShortmap *connections;
176
177/**
178 * How many messages are needed to trigger an AXOLOTL ratchet advance.
179 */
180unsigned long long ratchet_messages;
181
182/**
183 * How long until we trigger a ratched advance due to time.
184 */
185struct GNUNET_TIME_Relative ratchet_time;
186
187/**
188 * How frequently do we send KEEPALIVE messages on idle connections?
189 */
190struct GNUNET_TIME_Relative keepalive_period;
191
192/**
193 * Set to non-zero values to create random drops to test retransmissions.
194 */
195unsigned long long drop_percent;
196
197
198/**
199 * Send a message to a client.
200 *
201 * @param c client to get the message
202 * @param env envelope with the message
203 */
204void
205GSC_send_to_client (struct CadetClient *c,
206 struct GNUNET_MQ_Envelope *env)
207{
208 GNUNET_MQ_send (c->mq,
209 env);
210}
211
212
213/**
214 * Return identifier for a client as a string.
215 *
216 * @param c client to identify
217 * @return string for debugging
218 */
219const char *
220GSC_2s (struct CadetClient *c)
221{
222 static char buf[32];
223
224 GNUNET_snprintf (buf,
225 sizeof(buf),
226 "Client(%u)",
227 c->id);
228 return buf;
229}
230
231
232/**
233 * Lookup channel of client @a c by @a ccn.
234 *
235 * @param c client to look in
236 * @param ccn channel ID to look up
237 * @return NULL if no such channel exists
238 */
239static struct CadetChannel *
240lookup_channel (struct CadetClient *c,
241 struct GNUNET_CADET_ClientChannelNumber ccn)
242{
243 return GNUNET_CONTAINER_multihashmap32_get (c->channels,
244 ntohl (ccn.channel_of_client));
245}
246
247
248/**
249 * Obtain the next LID to use for incoming connections to
250 * the given client.
251 *
252 * @param c client handle
253 */
254static struct GNUNET_CADET_ClientChannelNumber
255client_get_next_ccn (struct CadetClient *c)
256{
257 struct GNUNET_CADET_ClientChannelNumber ccn = c->next_ccn;
258
259 /* increment until we have a free one... */
260 while (NULL !=
261 lookup_channel (c,
262 ccn))
263 {
264 ccn.channel_of_client
265 = htonl (1 + (ntohl (ccn.channel_of_client)));
266 if (ntohl (ccn.channel_of_client) >=
267 GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
268 ccn.channel_of_client = htonl (0);
269 }
270 c->next_ccn.channel_of_client
271 = htonl (1 + (ntohl (ccn.channel_of_client)));
272 return ccn;
273}
274
275
276/**
277 * Bind incoming channel to this client, and notify client about
278 * incoming connection. Caller is responsible for notifying the other
279 * peer about our acceptance of the channel.
280 *
281 * @param c client to bind to
282 * @param ch channel to be bound
283 * @param dest peer that establishes the connection
284 * @param port port number
285 * @param options options
286 * @return local channel number assigned to the new client
287 */
288struct GNUNET_CADET_ClientChannelNumber
289GSC_bind (struct CadetClient *c,
290 struct CadetChannel *ch,
291 struct CadetPeer *dest,
292 const struct GNUNET_HashCode *port,
293 uint32_t options)
294{
295 struct GNUNET_MQ_Envelope *env;
296 struct GNUNET_CADET_LocalChannelCreateMessage *cm;
297 struct GNUNET_CADET_ClientChannelNumber ccn;
298
299 ccn = client_get_next_ccn (c);
300 GNUNET_assert (GNUNET_YES ==
301 GNUNET_CONTAINER_multihashmap32_put (c->channels,
302 ntohl (
303 ccn.channel_of_client),
304 ch,
305 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
306 LOG (GNUNET_ERROR_TYPE_DEBUG,
307 "Accepting incoming %s from %s on open port %s (%u), assigning ccn %X\n",
308 GCCH_2s (ch),
309 GCP_2s (dest),
310 GNUNET_h2s (port),
311 (uint32_t) ntohl (options),
312 (uint32_t) ntohl (ccn.channel_of_client));
313 /* notify local client about incoming connection! */
314 env = GNUNET_MQ_msg (cm,
315 GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE);
316 cm->ccn = ccn;
317 cm->port = *port;
318 cm->opt = htonl (options);
319 cm->peer = *GCP_get_id (dest);
320 GSC_send_to_client (c,
321 env);
322 return ccn;
323}
324
325
326/**
327 * Callback invoked on all peers to destroy all tunnels
328 * that may still exist.
329 *
330 * @param cls NULL
331 * @param pid identify of a peer
332 * @param value a `struct CadetPeer` that may still have a tunnel
333 * @return #GNUNET_OK (iterate over all entries)
334 */
335static int
336destroy_tunnels_now (void *cls,
337 const struct GNUNET_PeerIdentity *pid,
338 void *value)
339{
340 struct CadetPeer *cp = value;
341 struct CadetTunnel *t = GCP_get_tunnel (cp,
342 GNUNET_NO);
343
344 if (NULL != t)
345 GCT_destroy_tunnel_now (t);
346 return GNUNET_OK;
347}
348
349
350/**
351 * Callback invoked on all peers to destroy all tunnels
352 * that may still exist.
353 *
354 * @param cls NULL
355 * @param pid identify of a peer
356 * @param value a `struct CadetPeer` that may still have a tunnel
357 * @return #GNUNET_OK (iterate over all entries)
358 */
359static int
360destroy_paths_now (void *cls,
361 const struct GNUNET_PeerIdentity *pid,
362 void *value)
363{
364 struct CadetPeer *cp = value;
365
366 GCP_drop_owned_paths (cp);
367 return GNUNET_OK;
368}
369
370
371/**
372 * Shutdown everything once the clients have disconnected.
373 */
374static void
375shutdown_rest ()
376{
377 if (NULL != stats)
378 {
379 GNUNET_STATISTICS_destroy (stats,
380 GNUNET_NO);
381 stats = NULL;
382 }
383 /* Destroy tunnels. Note that all channels must be destroyed first! */
384 GCP_iterate_all (&destroy_tunnels_now,
385 NULL);
386 /* All tunnels, channels, connections and CORE must be down before this point. */
387 GCP_iterate_all (&destroy_paths_now,
388 NULL);
389 /* All paths, tunnels, channels, connections and CORE must be down before this point. */
390 GCP_destroy_all_peers ();
391 if (NULL != open_ports)
392 {
393 GNUNET_CONTAINER_multihashmap_destroy (open_ports);
394 open_ports = NULL;
395 }
396 if (NULL != loose_channels)
397 {
398 GNUNET_CONTAINER_multihashmap_destroy (loose_channels);
399 loose_channels = NULL;
400 }
401 if (NULL != peers)
402 {
403 GNUNET_CONTAINER_multipeermap_destroy (peers);
404 peers = NULL;
405 }
406 if (NULL != connections)
407 {
408 GNUNET_CONTAINER_multishortmap_destroy (connections);
409 connections = NULL;
410 }
411 if (NULL != ats_ch)
412 {
413 GNUNET_ATS_connectivity_done (ats_ch);
414 ats_ch = NULL;
415 }
416 GCD_shutdown ();
417 GCH_shutdown ();
418 GNUNET_free (my_private_key);
419 my_private_key = NULL;
420}
421
422
423/**
424 * Task run during shutdown.
425 *
426 * @param cls unused
427 */
428static void
429shutdown_task (void *cls)
430{
431 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
432 "Shutting down\n");
433 shutting_down = GNUNET_YES;
434 GCO_shutdown ();
435 if (NULL == clients_head)
436 shutdown_rest ();
437}
438
439
440/**
441 * We had a remote connection @a value to port @a h_port before
442 * client @a cls opened port @a port. Bind them now.
443 *
444 * @param cls the `struct CadetClient`
445 * @param h_port the hashed port
446 * @param value the `struct CadetChannel`
447 * @return #GNUNET_YES (iterate over all such channels)
448 */
449static int
450bind_loose_channel (void *cls,
451 const struct GNUNET_HashCode *port,
452 void *value)
453{
454 struct OpenPort *op = cls;
455 struct CadetChannel *ch = value;
456
457 GCCH_bind (ch,
458 op->c,
459 &op->port);
460 GNUNET_assert (GNUNET_YES ==
461 GNUNET_CONTAINER_multihashmap_remove (loose_channels,
462 &op->h_port,
463 ch));
464 return GNUNET_YES;
465}
466
467
468/**
469 * Handle port open request. Creates a mapping from the
470 * port to the respective client and checks whether we have
471 * loose channels trying to bind to the port. If so, those
472 * are bound.
473 *
474 * @param cls Identification of the client.
475 * @param pmsg The actual message.
476 */
477static void
478handle_port_open (void *cls,
479 const struct GNUNET_CADET_PortMessage *pmsg)
480{
481 struct CadetClient *c = cls;
482 struct OpenPort *op;
483
484 LOG (GNUNET_ERROR_TYPE_DEBUG,
485 "Open port %s requested by %s\n",
486 GNUNET_h2s (&pmsg->port),
487 GSC_2s (c));
488 if (NULL == c->ports)
489 c->ports = GNUNET_CONTAINER_multihashmap_create (4,
490 GNUNET_NO);
491 op = GNUNET_new (struct OpenPort);
492 op->c = c;
493 op->port = pmsg->port;
494 GCCH_hash_port (&op->h_port,
495 &pmsg->port,
496 &my_full_id);
497 if (GNUNET_OK !=
498 GNUNET_CONTAINER_multihashmap_put (c->ports,
499 &op->port,
500 op,
501 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
502 {
503 GNUNET_break (0);
504 GNUNET_SERVICE_client_drop (c->client);
505 return;
506 }
507 (void) GNUNET_CONTAINER_multihashmap_put (open_ports,
508 &op->h_port,
509 op,
510 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
511 GNUNET_CONTAINER_multihashmap_get_multiple (loose_channels,
512 &op->h_port,
513 &bind_loose_channel,
514 op);
515 GNUNET_SERVICE_client_continue (c->client);
516}
517
518
519/**
520 * Handler for port close requests. Marks this port as closed
521 * (unless of course we have another client with the same port
522 * open). Note that existing channels accepted on the port are
523 * not affected.
524 *
525 * @param cls Identification of the client.
526 * @param pmsg The actual message.
527 */
528static void
529handle_port_close (void *cls,
530 const struct GNUNET_CADET_PortMessage *pmsg)
531{
532 struct CadetClient *c = cls;
533 struct OpenPort *op;
534
535 LOG (GNUNET_ERROR_TYPE_DEBUG,
536 "Closing port %s as requested by %s\n",
537 GNUNET_h2s (&pmsg->port),
538 GSC_2s (c));
539 if (NULL == c->ports)
540 {
541 /* Client closed a port despite _never_ having opened one? */
542 GNUNET_break (0);
543 GNUNET_SERVICE_client_drop (c->client);
544 return;
545 }
546 op = GNUNET_CONTAINER_multihashmap_get (c->ports,
547 &pmsg->port);
548 if (NULL == op)
549 {
550 GNUNET_break (0);
551 GNUNET_SERVICE_client_drop (c->client);
552 return;
553 }
554 GNUNET_assert (GNUNET_YES ==
555 GNUNET_CONTAINER_multihashmap_remove (c->ports,
556 &op->port,
557 op));
558 GNUNET_assert (GNUNET_YES ==
559 GNUNET_CONTAINER_multihashmap_remove (open_ports,
560 &op->h_port,
561 op));
562 GNUNET_free (op);
563 GNUNET_SERVICE_client_continue (c->client);
564}
565
566
567/**
568 * Handler for requests for us creating a new channel to another peer and port.
569 *
570 * @param cls Identification of the client.
571 * @param tcm The actual message.
572 */
573static void
574handle_channel_create (void *cls,
575 const struct GNUNET_CADET_LocalChannelCreateMessage *tcm)
576{
577 struct CadetClient *c = cls;
578 struct CadetChannel *ch;
579
580 if (ntohl (tcm->ccn.channel_of_client) < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
581 {
582 /* Channel ID not in allowed range. */
583 LOG (GNUNET_ERROR_TYPE_DEBUG,"Channel ID not in allowed range.");
584 GNUNET_break (0);
585 GNUNET_SERVICE_client_drop (c->client);
586 return;
587 }
588 ch = lookup_channel (c,
589 tcm->ccn);
590 if (NULL != ch)
591 {
592 /* Channel ID already in use. Not allowed. */
593 LOG (GNUNET_ERROR_TYPE_DEBUG,"Channel ID already in use. Not allowed.");
594 GNUNET_break (0);
595 GNUNET_SERVICE_client_drop (c->client);
596 return;
597 }
598 LOG (GNUNET_ERROR_TYPE_DEBUG,
599 "New channel to %s at port %s requested by %s\n",
600 GNUNET_i2s (&tcm->peer),
601 GNUNET_h2s (&tcm->port),
602 GSC_2s (c));
603
604 /* Create channel */
605 ch = GCCH_channel_local_new (c,
606 tcm->ccn,
607 GCP_get (&tcm->peer,
608 GNUNET_YES),
609 &tcm->port,
610 ntohl (tcm->opt));
611 if (NULL == ch)
612 {
613 GNUNET_break (0);
614 GNUNET_SERVICE_client_drop (c->client);
615 return;
616 }
617 GNUNET_assert (GNUNET_YES ==
618 GNUNET_CONTAINER_multihashmap32_put (c->channels,
619 ntohl (
620 tcm->ccn.
621 channel_of_client),
622 ch,
623 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
624
625 GNUNET_SERVICE_client_continue (c->client);
626}
627
628
629/**
630 * Handler for requests of destroying an existing channel.
631 *
632 * @param cls client identification of the client
633 * @param msg the actual message
634 */
635static void
636handle_channel_destroy (void *cls,
637 const struct
638 GNUNET_CADET_LocalChannelDestroyMessage *msg)
639{
640 struct CadetClient *c = cls;
641 struct CadetChannel *ch;
642
643 ch = lookup_channel (c,
644 msg->ccn);
645 if (NULL == ch)
646 {
647 /* Client attempted to destroy unknown channel.
648 Can happen if the other side went down at the same time.*/
649 LOG (GNUNET_ERROR_TYPE_DEBUG,
650 "%s tried to destroy unknown channel %X\n",
651 GSC_2s (c),
652 (uint32_t) ntohl (msg->ccn.channel_of_client));
653 GNUNET_SERVICE_client_continue (c->client);
654 return;
655 }
656 LOG (GNUNET_ERROR_TYPE_DEBUG,
657 "%s is destroying %s\n",
658 GSC_2s (c),
659 GCCH_2s (ch));
660 GNUNET_assert (GNUNET_YES ==
661 GNUNET_CONTAINER_multihashmap32_remove (c->channels,
662 ntohl (
663 msg->ccn.
664 channel_of_client),
665 ch));
666 GCCH_channel_local_destroy (ch,
667 c,
668 msg->ccn);
669 GNUNET_SERVICE_client_continue (c->client);
670}
671
672
673/**
674 * Check for client traffic data message is well-formed.
675 *
676 * @param cls identification of the client
677 * @param msg the actual message
678 * @return #GNUNET_OK if @a msg is OK, #GNUNET_SYSERR if not
679 */
680static int
681check_local_data (void *cls,
682 const struct GNUNET_CADET_LocalData *msg)
683{
684 size_t payload_size;
685 size_t payload_claimed_size;
686 const char *buf;
687 struct GNUNET_MessageHeader pa;
688
689 /* FIXME: what is the format we shall allow for @a msg?
690 ONE payload item or multiple? Seems current cadet_api
691 at least in theory allows more than one. Next-gen
692 cadet_api will likely no more, so we could then
693 simplify this mess again. *//* Sanity check for message size */payload_size = ntohs (msg->header.size) - sizeof(*msg);
694 buf = (const char *) &msg[1];
695 while (payload_size >= sizeof(struct GNUNET_MessageHeader))
696 {
697 /* need to memcpy() for alignment */
698 GNUNET_memcpy (&pa,
699 buf,
700 sizeof(pa));
701 payload_claimed_size = ntohs (pa.size);
702 if ((payload_size < payload_claimed_size) ||
703 (payload_claimed_size < sizeof(struct GNUNET_MessageHeader)) ||
704 (GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE < payload_claimed_size))
705 {
706 GNUNET_break (0);
707 LOG (GNUNET_ERROR_TYPE_DEBUG,
708 "Local data of %u total size had sub-message %u at %u with %u bytes\n",
709 ntohs (msg->header.size),
710 ntohs (pa.type),
711 (unsigned int) (buf - (const char *) &msg[1]),
712 (unsigned int) payload_claimed_size);
713 return GNUNET_SYSERR;
714 }
715 payload_size -= payload_claimed_size;
716 buf += payload_claimed_size;
717 }
718 if (0 != payload_size)
719 {
720 GNUNET_break_op (0);
721 return GNUNET_SYSERR;
722 }
723 return GNUNET_OK;
724}
725
726
727/**
728 * Handler for client payload traffic to be send on a channel to
729 * another peer.
730 *
731 * @param cls identification of the client
732 * @param msg the actual message
733 */
734static void
735handle_local_data (void *cls,
736 const struct GNUNET_CADET_LocalData *msg)
737{
738 struct CadetClient *c = cls;
739 struct CadetChannel *ch;
740 size_t payload_size;
741 const char *buf;
742
743 ch = lookup_channel (c,
744 msg->ccn);
745 if (NULL == ch)
746 {
747 /* Channel does not exist (anymore) */
748 LOG (GNUNET_ERROR_TYPE_WARNING,
749 "Dropping payload for channel %u from client (channel unknown, other endpoint may have disconnected)\n",
750 (unsigned int) ntohl (msg->ccn.channel_of_client));
751 GNUNET_SERVICE_client_continue (c->client);
752 return;
753 }
754 payload_size = ntohs (msg->header.size) - sizeof(*msg);
755 GNUNET_STATISTICS_update (stats,
756 "# payload received from clients",
757 payload_size,
758 GNUNET_NO);
759 buf = (const char *) &msg[1];
760 LOG (GNUNET_ERROR_TYPE_DEBUG,
761 "Received %u bytes payload from %s for %s\n",
762 (unsigned int) payload_size,
763 GSC_2s (c),
764 GCCH_2s (ch));
765 if (GNUNET_OK !=
766 GCCH_handle_local_data (ch,
767 msg->ccn,
768 buf,
769 payload_size))
770 {
771 GNUNET_break (0);
772 GNUNET_SERVICE_client_drop (c->client);
773 return;
774 }
775 GNUNET_SERVICE_client_continue (c->client);
776}
777
778
779/**
780 * Handler for client's ACKs for payload traffic.
781 *
782 * @param cls identification of the client.
783 * @param msg The actual message.
784 */
785static void
786handle_local_ack (void *cls,
787 const struct GNUNET_CADET_LocalAck *msg)
788{
789 struct CadetClient *c = cls;
790 struct CadetChannel *ch;
791
792 ch = lookup_channel (c,
793 msg->ccn);
794 if (NULL == ch)
795 {
796 /* Channel does not exist (anymore) */
797 LOG (GNUNET_ERROR_TYPE_WARNING,
798 "Ignoring local ACK for channel %u from client (channel unknown, other endpoint may have disconnected)\n",
799 (unsigned int) ntohl (msg->ccn.channel_of_client));
800 GNUNET_SERVICE_client_continue (c->client);
801 return;
802 }
803 LOG (GNUNET_ERROR_TYPE_DEBUG,
804 "Got a local ACK from %s for %s\n",
805 GSC_2s (c),
806 GCCH_2s (ch));
807 GCCH_handle_local_ack (ch,
808 msg->ccn);
809 GNUNET_SERVICE_client_continue (c->client);
810}
811
812
813/**
814 * Iterator over all peers to send a monitoring client info about each peer.
815 *
816 * @param cls Closure ().
817 * @param peer Peer ID (tunnel remote peer).
818 * @param value Peer info.
819 * @return #GNUNET_YES, to keep iterating.
820 */
821static int
822get_all_peers_iterator (void *cls,
823 const struct GNUNET_PeerIdentity *peer,
824 void *value)
825{
826 struct CadetClient *c = cls;
827 struct CadetPeer *p = value;
828 struct GNUNET_MQ_Envelope *env;
829 struct GNUNET_CADET_LocalInfoPeers *msg;
830
831 env = GNUNET_MQ_msg (msg,
832 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS);
833 msg->destination = *peer;
834 msg->paths = htons (GCP_count_paths (p));
835 msg->tunnel = htons (NULL != GCP_get_tunnel (p,
836 GNUNET_NO));
837 msg->best_path_length = htonl (0); // FIXME: get length of shortest known path!
838 GNUNET_MQ_send (c->mq,
839 env);
840 return GNUNET_YES;
841}
842
843
844/**
845 * Handler for client's INFO PEERS request.
846 *
847 * @param cls Identification of the client.
848 * @param message The actual message.
849 */
850static void
851handle_get_peers (void *cls,
852 const struct GNUNET_MessageHeader *message)
853{
854 struct CadetClient *c = cls;
855 struct GNUNET_MQ_Envelope *env;
856 struct GNUNET_MessageHeader *reply;
857
858 GCP_iterate_all (&get_all_peers_iterator,
859 c);
860 env = GNUNET_MQ_msg (reply,
861 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS_END);
862 GNUNET_MQ_send (c->mq,
863 env);
864 GNUNET_SERVICE_client_continue (c->client);
865}
866
867
868/**
869 * Iterator over all paths of a peer to build an InfoPeer message.
870 * Message contains blocks of peers, first not included.
871 *
872 * @param cls message queue for transmission
873 * @param path Path itself
874 * @param off offset of the peer on @a path
875 * @return #GNUNET_YES if should keep iterating.
876 * #GNUNET_NO otherwise.
877 */
878static int
879path_info_iterator (void *cls,
880 struct CadetPeerPath *path,
881 unsigned int off)
882{
883 struct GNUNET_MQ_Handle *mq = cls;
884 struct GNUNET_MQ_Envelope *env;
885 struct GNUNET_CADET_LocalInfoPath *resp;
886 struct GNUNET_PeerIdentity *id;
887 size_t path_size;
888 unsigned int path_length;
889
890 path_length = GCPP_get_length (path);
891 path_size = sizeof(struct GNUNET_PeerIdentity) * path_length;
892 if (sizeof(*resp) + path_size > UINT16_MAX)
893 {
894 /* try just giving the relevant path */
895 path_length = GNUNET_MIN ((UINT16_MAX - sizeof(*resp)) / sizeof(struct
896 GNUNET_PeerIdentity),
897 off);
898 path_size = sizeof(struct GNUNET_PeerIdentity) * path_length;
899 }
900 if (sizeof(*resp) + path_size > UINT16_MAX)
901 {
902 LOG (GNUNET_ERROR_TYPE_WARNING,
903 "Path of %u entries is too long for info message\n",
904 path_length);
905 return GNUNET_YES;
906 }
907 env = GNUNET_MQ_msg_extra (resp,
908 path_size,
909 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PATH);
910 id = (struct GNUNET_PeerIdentity *) &resp[1];
911
912 /* Don't copy first peer. First peer is always the local one. Last
913 * peer is always the destination (leave as 0, EOL).
914 */
915 for (unsigned int i = 0; i < path_length; i++)
916 id[i] = *GCP_get_id (GCPP_get_peer_at_offset (path,
917 i));
918 resp->off = htonl (off);
919 GNUNET_MQ_send (mq,
920 env);
921 return GNUNET_YES;
922}
923
924
925/**
926 * Handler for client's #GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_PATH request.
927 *
928 * @param cls Identification of the client.
929 * @param msg The actual message.
930 */
931static void
932handle_show_path (void *cls,
933 const struct GNUNET_CADET_RequestPathInfoMessage *msg)
934{
935 struct CadetClient *c = cls;
936 struct CadetPeer *p;
937 struct GNUNET_MQ_Envelope *env;
938 struct GNUNET_MessageHeader *resp;
939
940 p = GCP_get (&msg->peer,
941 GNUNET_NO);
942 if (NULL != p)
943 GCP_iterate_indirect_paths (p,
944 &path_info_iterator,
945 c->mq);
946 env = GNUNET_MQ_msg (resp,
947 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PATH_END);
948 GNUNET_MQ_send (c->mq,
949 env);
950 GNUNET_SERVICE_client_continue (c->client);
951}
952
953
954/**
955 * Iterator over all tunnels to send a monitoring client info about each tunnel.
956 *
957 * @param cls Closure ().
958 * @param peer Peer ID (tunnel remote peer).
959 * @param value a `struct CadetPeer`
960 * @return #GNUNET_YES, to keep iterating.
961 */
962static int
963get_all_tunnels_iterator (void *cls,
964 const struct GNUNET_PeerIdentity *peer,
965 void *value)
966{
967 struct CadetClient *c = cls;
968 struct CadetPeer *p = value;
969 struct GNUNET_MQ_Envelope *env;
970 struct GNUNET_CADET_LocalInfoTunnel *msg;
971 struct CadetTunnel *t;
972
973 t = GCP_get_tunnel (p,
974 GNUNET_NO);
975 if (NULL == t)
976 return GNUNET_YES;
977 env = GNUNET_MQ_msg (msg,
978 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS);
979 msg->destination = *peer;
980 msg->channels = htonl (GCT_count_channels (t));
981 msg->connections = htonl (GCT_count_any_connections (t));
982 msg->cstate = htons (0);
983 msg->estate = htons ((uint16_t) GCT_get_estate (t));
984 GNUNET_MQ_send (c->mq,
985 env);
986 return GNUNET_YES;
987}
988
989
990/**
991 * Handler for client's #GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_TUNNELS request.
992 *
993 * @param cls client Identification of the client.
994 * @param message The actual message.
995 */
996static void
997handle_info_tunnels (void *cls,
998 const struct GNUNET_MessageHeader *message)
999{
1000 struct CadetClient *c = cls;
1001 struct GNUNET_MQ_Envelope *env;
1002 struct GNUNET_MessageHeader *reply;
1003
1004 GCP_iterate_all (&get_all_tunnels_iterator,
1005 c);
1006 env = GNUNET_MQ_msg (reply,
1007 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS_END);
1008 GNUNET_MQ_send (c->mq,
1009 env);
1010 GNUNET_SERVICE_client_continue (c->client);
1011}
1012
1013
1014/**
1015 * Handler for client's #GNUNET_MESSAGE_TYPE_CADET_DROP_CADET_MESSAGE request.
1016 *
1017 * @param cls client Identification of the client.
1018 * @param message The actual message.
1019 */
1020static void
1021handle_drop_message (void *cls,
1022 const struct GNUNET_CADET_RequestDropCadetMessage *message)
1023{
1024 struct CadetClient *c = cls;
1025 struct CadetChannel *ch;
1026
1027 ch = lookup_channel (c,
1028 message->ccn);
1029
1030 if (NULL != ch)
1031 GCCH_assign_type_to_drop (ch, message);
1032
1033 GNUNET_SERVICE_client_continue (c->client);
1034}
1035
1036
1037/**
1038 * Callback called when a client connects to the service.
1039 *
1040 * @param cls closure for the service
1041 * @param client the new client that connected to the service
1042 * @param mq the message queue used to send messages to the client
1043 * @return @a c
1044 */
1045static void *
1046client_connect_cb (void *cls,
1047 struct GNUNET_SERVICE_Client *client,
1048 struct GNUNET_MQ_Handle *mq)
1049{
1050 struct CadetClient *c;
1051
1052 c = GNUNET_new (struct CadetClient);
1053 c->client = client;
1054 c->mq = mq;
1055 c->id = next_client_id++; /* overflow not important: just for debug */
1056 c->channels
1057 = GNUNET_CONTAINER_multihashmap32_create (32);
1058 GNUNET_CONTAINER_DLL_insert (clients_head,
1059 clients_tail,
1060 c);
1061 GNUNET_STATISTICS_update (stats,
1062 "# clients",
1063 +1,
1064 GNUNET_NO);
1065 LOG (GNUNET_ERROR_TYPE_DEBUG,
1066 "%s connected\n",
1067 GSC_2s (c));
1068 return c;
1069}
1070
1071
1072/**
1073 * A channel was destroyed by the other peer. Tell our client.
1074 *
1075 * @param c client that lost a channel
1076 * @param ccn channel identification number for the client
1077 * @param ch the channel object
1078 */
1079void
1080GSC_handle_remote_channel_destroy (struct CadetClient *c,
1081 struct GNUNET_CADET_ClientChannelNumber ccn,
1082 struct CadetChannel *ch)
1083{
1084 struct GNUNET_MQ_Envelope *env;
1085 struct GNUNET_CADET_LocalChannelDestroyMessage *tdm;
1086
1087 env = GNUNET_MQ_msg (tdm,
1088 GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY);
1089 tdm->ccn = ccn;
1090 GSC_send_to_client (c,
1091 env);
1092 GNUNET_assert (GNUNET_YES ==
1093 GNUNET_CONTAINER_multihashmap32_remove (c->channels,
1094 ntohl (
1095 ccn.channel_of_client),
1096 ch));
1097}
1098
1099
1100/**
1101 * A client that created a loose channel that was not bound to a port
1102 * disconnected, drop it from the #loose_channels list.
1103 *
1104 * @param h_port the hashed port the channel was trying to bind to
1105 * @param ch the channel that was lost
1106 */
1107void
1108GSC_drop_loose_channel (const struct GNUNET_HashCode *h_port,
1109 struct CadetChannel *ch)
1110{
1111 GNUNET_assert (GNUNET_YES ==
1112 GNUNET_CONTAINER_multihashmap_remove (loose_channels,
1113 h_port,
1114 ch));
1115}
1116
1117
1118/**
1119 * Iterator for deleting each channel whose client endpoint disconnected.
1120 *
1121 * @param cls Closure (client that has disconnected).
1122 * @param key The local channel id in host byte order
1123 * @param value The value stored at the key (channel to destroy).
1124 * @return #GNUNET_OK, keep iterating.
1125 */
1126static int
1127channel_destroy_iterator (void *cls,
1128 uint32_t key,
1129 void *value)
1130{
1131 struct CadetClient *c = cls;
1132 struct GNUNET_CADET_ClientChannelNumber ccn;
1133 struct CadetChannel *ch = value;
1134
1135 LOG (GNUNET_ERROR_TYPE_DEBUG,
1136 "Destroying %s, due to %s disconnecting.\n",
1137 GCCH_2s (ch),
1138 GSC_2s (c));
1139 ccn.channel_of_client = htonl (key);
1140 GNUNET_assert (GNUNET_YES ==
1141 GNUNET_CONTAINER_multihashmap32_remove (c->channels,
1142 key,
1143 ch));
1144 GCCH_channel_local_destroy (ch,
1145 c,
1146 ccn);
1147 return GNUNET_OK;
1148}
1149
1150
1151/**
1152 * Remove client's ports from the global hashmap on disconnect.
1153 *
1154 * @param cls the `struct CadetClient`
1155 * @param port the port.
1156 * @param value the `struct OpenPort` to remove
1157 * @return #GNUNET_OK, keep iterating.
1158 */
1159static int
1160client_release_ports (void *cls,
1161 const struct GNUNET_HashCode *port,
1162 void *value)
1163{
1164 struct CadetClient *c = cls;
1165 struct OpenPort *op = value;
1166
1167 GNUNET_assert (c == op->c);
1168 LOG (GNUNET_ERROR_TYPE_DEBUG,
1169 "Closing port %s due to %s disconnect.\n",
1170 GNUNET_h2s (port),
1171 GSC_2s (c));
1172 GNUNET_assert (GNUNET_YES ==
1173 GNUNET_CONTAINER_multihashmap_remove (open_ports,
1174 &op->h_port,
1175 op));
1176 GNUNET_assert (GNUNET_YES ==
1177 GNUNET_CONTAINER_multihashmap_remove (c->ports,
1178 port,
1179 op));
1180 GNUNET_free (op);
1181 return GNUNET_OK;
1182}
1183
1184
1185/**
1186 * Callback called when a client disconnected from the service
1187 *
1188 * @param cls closure for the service
1189 * @param client the client that disconnected
1190 * @param internal_cls should be equal to @a c
1191 */
1192static void
1193client_disconnect_cb (void *cls,
1194 struct GNUNET_SERVICE_Client *client,
1195 void *internal_cls)
1196{
1197 struct CadetClient *c = internal_cls;
1198
1199 GNUNET_assert (c->client == client);
1200 LOG (GNUNET_ERROR_TYPE_DEBUG,
1201 "%s is disconnecting.\n",
1202 GSC_2s (c));
1203 if (NULL != c->channels)
1204 {
1205 GNUNET_CONTAINER_multihashmap32_iterate (c->channels,
1206 &channel_destroy_iterator,
1207 c);
1208 GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap32_size (c->channels));
1209 GNUNET_CONTAINER_multihashmap32_destroy (c->channels);
1210 }
1211 if (NULL != c->ports)
1212 {
1213 GNUNET_CONTAINER_multihashmap_iterate (c->ports,
1214 &client_release_ports,
1215 c);
1216 GNUNET_CONTAINER_multihashmap_destroy (c->ports);
1217 }
1218 GNUNET_CONTAINER_DLL_remove (clients_head,
1219 clients_tail,
1220 c);
1221 GNUNET_STATISTICS_update (stats,
1222 "# clients",
1223 -1,
1224 GNUNET_NO);
1225 GNUNET_free (c);
1226 if ((NULL == clients_head) &&
1227 (GNUNET_YES == shutting_down))
1228 shutdown_rest ();
1229}
1230
1231
1232/**
1233 * Setup CADET internals.
1234 *
1235 * @param cls closure
1236 * @param server the initialized server
1237 * @param c configuration to use
1238 */
1239static void
1240run (void *cls,
1241 const struct GNUNET_CONFIGURATION_Handle *c,
1242 struct GNUNET_SERVICE_Handle *service)
1243{
1244 cfg = c;
1245 if (GNUNET_OK !=
1246 GNUNET_CONFIGURATION_get_value_number (c,
1247 "CADET",
1248 "RATCHET_MESSAGES",
1249 &ratchet_messages))
1250 {
1251 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
1252 "CADET",
1253 "RATCHET_MESSAGES",
1254 "needs to be a number");
1255 ratchet_messages = 64;
1256 }
1257 if (GNUNET_OK !=
1258 GNUNET_CONFIGURATION_get_value_time (c,
1259 "CADET",
1260 "RATCHET_TIME",
1261 &ratchet_time))
1262 {
1263 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
1264 "CADET",
1265 "RATCHET_TIME",
1266 "need delay value");
1267 ratchet_time = GNUNET_TIME_UNIT_HOURS;
1268 }
1269 if (GNUNET_OK !=
1270 GNUNET_CONFIGURATION_get_value_time (c,
1271 "CADET",
1272 "REFRESH_CONNECTION_TIME",
1273 &keepalive_period))
1274 {
1275 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
1276 "CADET",
1277 "REFRESH_CONNECTION_TIME",
1278 "need delay value");
1279 keepalive_period = GNUNET_TIME_UNIT_MINUTES;
1280 }
1281 if (GNUNET_OK !=
1282 GNUNET_CONFIGURATION_get_value_number (c,
1283 "CADET",
1284 "DROP_PERCENT",
1285 &drop_percent))
1286 {
1287 drop_percent = 0;
1288 }
1289 else
1290 {
1291 LOG (GNUNET_ERROR_TYPE_WARNING, "**************************************\n");
1292 LOG (GNUNET_ERROR_TYPE_WARNING, "Cadet is running with DROP enabled.\n");
1293 LOG (GNUNET_ERROR_TYPE_WARNING, "This is NOT a good idea!\n");
1294 LOG (GNUNET_ERROR_TYPE_WARNING, "Remove DROP_PERCENT from config file.\n");
1295 LOG (GNUNET_ERROR_TYPE_WARNING, "**************************************\n");
1296 }
1297 my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (c);
1298 if (NULL == my_private_key)
1299 {
1300 GNUNET_break (0);
1301 GNUNET_SCHEDULER_shutdown ();
1302 return;
1303 }
1304 GNUNET_CRYPTO_eddsa_key_get_public (my_private_key,
1305 &my_full_id.public_key);
1306 stats = GNUNET_STATISTICS_create ("cadet",
1307 c);
1308 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
1309 NULL);
1310 ats_ch = GNUNET_ATS_connectivity_init (c);
1311 /* FIXME: optimize code to allow GNUNET_YES here! */
1312 open_ports = GNUNET_CONTAINER_multihashmap_create (16,
1313 GNUNET_NO);
1314 loose_channels = GNUNET_CONTAINER_multihashmap_create (16,
1315 GNUNET_NO);
1316 peers = GNUNET_CONTAINER_multipeermap_create (16,
1317 GNUNET_YES);
1318 connections = GNUNET_CONTAINER_multishortmap_create (256,
1319 GNUNET_YES);
1320 GCH_init (c);
1321 GCD_init (c);
1322 GCO_init (c);
1323 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1324 "CADET started for peer %s\n",
1325 GNUNET_i2s (&my_full_id));
1326}
1327
1328
1329/**
1330 * Define "main" method using service macro.
1331 */
1332GNUNET_SERVICE_MAIN
1333 ("cadet",
1334 GNUNET_SERVICE_OPTION_NONE,
1335 &run,
1336 &client_connect_cb,
1337 &client_disconnect_cb,
1338 NULL,
1339 GNUNET_MQ_hd_fixed_size (port_open,
1340 GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN,
1341 struct GNUNET_CADET_PortMessage,
1342 NULL),
1343 GNUNET_MQ_hd_fixed_size (port_close,
1344 GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE,
1345 struct GNUNET_CADET_PortMessage,
1346 NULL),
1347 GNUNET_MQ_hd_fixed_size (channel_create,
1348 GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE,
1349 struct GNUNET_CADET_LocalChannelCreateMessage,
1350 NULL),
1351 GNUNET_MQ_hd_fixed_size (channel_destroy,
1352 GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY,
1353 struct GNUNET_CADET_LocalChannelDestroyMessage,
1354 NULL),
1355 GNUNET_MQ_hd_var_size (local_data,
1356 GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA,
1357 struct GNUNET_CADET_LocalData,
1358 NULL),
1359 GNUNET_MQ_hd_fixed_size (local_ack,
1360 GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK,
1361 struct GNUNET_CADET_LocalAck,
1362 NULL),
1363 GNUNET_MQ_hd_fixed_size (get_peers,
1364 GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_PEERS,
1365 struct GNUNET_MessageHeader,
1366 NULL),
1367 GNUNET_MQ_hd_fixed_size (show_path,
1368 GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_PATH,
1369 struct GNUNET_CADET_RequestPathInfoMessage,
1370 NULL),
1371 GNUNET_MQ_hd_fixed_size (info_tunnels,
1372 GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_TUNNELS,
1373 struct GNUNET_MessageHeader,
1374 NULL),
1375 GNUNET_MQ_hd_fixed_size (drop_message,
1376 GNUNET_MESSAGE_TYPE_CADET_DROP_CADET_MESSAGE,
1377 struct GNUNET_CADET_RequestDropCadetMessage,
1378 NULL),
1379 GNUNET_MQ_handler_end ());
1380
1381/* end of gnunet-service-cadet-new.c */
diff --git a/src/cadet/gnunet-service-cadet.h b/src/cadet/gnunet-service-cadet.h
deleted file mode 100644
index 3d61b9973..000000000
--- a/src/cadet/gnunet-service-cadet.h
+++ /dev/null
@@ -1,328 +0,0 @@
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 communicate with ATS.
201 */
202extern struct GNUNET_ATS_ConnectivityHandle *ats_ch;
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/cadet/gnunet-service-cadet_channel.c b/src/cadet/gnunet-service-cadet_channel.c
deleted file mode 100644
index 9a2180cc1..000000000
--- a/src/cadet/gnunet-service-cadet_channel.c
+++ /dev/null
@@ -1,2074 +0,0 @@
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
391/**
392 * Assign type of message to drop.
393 * @param ch CadetChannel to assign type to drop.
394 * @param message GNUNET_CADET_RequestDropCadetMessage to get the type from.
395 */
396void
397GCCH_assign_type_to_drop (struct CadetChannel *ch, const struct
398 GNUNET_CADET_RequestDropCadetMessage *message)
399{
400
401 ch->type = message->type;
402
403}
404
405
406/**
407 * Check if type of message is the one to drop.
408 * @param ch CadetChannel to check for message type to drop.
409 * @param message GNUNET_MessageHeader to compare the type with.
410 */
411int
412GCCH_is_type_to_drop (struct CadetChannel *ch, const struct
413 GNUNET_MessageHeader *message)
414{
415
416 if (ch->type == message->type)
417 {
418 ch->type = 0;
419 return GNUNET_YES;
420 }
421 else
422 return GNUNET_NO;
423}
424
425
426/**
427 * Get the static string for identification of the channel.
428 *
429 * @param ch Channel.
430 *
431 * @return Static string with the channel IDs.
432 */
433const char *
434GCCH_2s (const struct CadetChannel *ch)
435{
436 static char buf[128];
437
438 GNUNET_snprintf (buf,
439 sizeof(buf),
440 "Channel %s:%s ctn:%X(%X/%X)",
441 (GNUNET_YES == ch->is_loopback)
442 ? "loopback"
443 : GNUNET_i2s (GCP_get_id (GCT_get_destination (ch->t))),
444 GNUNET_h2s (&ch->port),
445 ch->ctn.cn,
446 (NULL == ch->owner)
447 ? 0
448 : ntohl (ch->owner->ccn.channel_of_client),
449 (NULL == ch->dest)
450 ? 0
451 : ntohl (ch->dest->ccn.channel_of_client));
452 return buf;
453}
454
455
456/**
457 * Hash the @a port and @a initiator and @a listener to
458 * calculate the "challenge" @a h_port we send to the other
459 * peer on #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN.
460 *
461 * @param[out] h_port set to the hash of @a port, @a initiator and @a listener
462 * @param port cadet port, as seen by CADET clients
463 * @param listener peer that is listining on @a port
464 */
465void
466GCCH_hash_port (struct GNUNET_HashCode *h_port,
467 const struct GNUNET_HashCode *port,
468 const struct GNUNET_PeerIdentity *listener)
469{
470 struct GNUNET_HashContext *hc;
471
472 hc = GNUNET_CRYPTO_hash_context_start ();
473 GNUNET_CRYPTO_hash_context_read (hc, port, sizeof(*port));
474 GNUNET_CRYPTO_hash_context_read (hc, listener, sizeof(*listener));
475 GNUNET_CRYPTO_hash_context_finish (hc, h_port);
476 LOG (GNUNET_ERROR_TYPE_DEBUG,
477 "Calculated port hash %s\n",
478 GNUNET_h2s (h_port));
479}
480
481
482/**
483 * Get the channel's public ID.
484 *
485 * @param ch Channel.
486 *
487 * @return ID used to identify the channel with the remote peer.
488 */
489struct GNUNET_CADET_ChannelTunnelNumber
490GCCH_get_id (const struct CadetChannel *ch)
491{
492 return ch->ctn;
493}
494
495
496/**
497 * Release memory associated with @a ccc
498 *
499 * @param ccc data structure to clean up
500 */
501static void
502free_channel_client (struct CadetChannelClient *ccc)
503{
504 struct CadetOutOfOrderMessage *com;
505
506 while (NULL != (com = ccc->head_recv))
507 {
508 GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, com);
509 ccc->num_recv--;
510 GNUNET_MQ_discard (com->env);
511 GNUNET_free (com);
512 }
513 GNUNET_free (ccc);
514}
515
516
517/**
518 * Destroy the given channel.
519 *
520 * @param ch channel to destroy
521 */
522static void
523channel_destroy (struct CadetChannel *ch)
524{
525 struct CadetReliableMessage *crm;
526
527 while (NULL != (crm = ch->head_sent))
528 {
529 GNUNET_assert (ch == crm->ch);
530 if (NULL != crm->qe)
531 {
532 GCT_send_cancel (crm->qe);
533 crm->qe = NULL;
534 }
535 GNUNET_CONTAINER_DLL_remove (ch->head_sent, ch->tail_sent, crm);
536 GNUNET_free (crm->data_message);
537 GNUNET_free (crm);
538 }
539 if (CADET_CHANNEL_LOOSE == ch->state)
540 {
541 GSC_drop_loose_channel (&ch->h_port, ch);
542 }
543 if (NULL != ch->owner)
544 {
545 free_channel_client (ch->owner);
546 ch->owner = NULL;
547 }
548 if (NULL != ch->dest)
549 {
550 free_channel_client (ch->dest);
551 ch->dest = NULL;
552 }
553 if (NULL != ch->last_control_qe)
554 {
555 GCT_send_cancel (ch->last_control_qe);
556 ch->last_control_qe = NULL;
557 }
558 if (NULL != ch->retry_data_task)
559 {
560 GNUNET_SCHEDULER_cancel (ch->retry_data_task);
561 ch->retry_data_task = NULL;
562 }
563 if (NULL != ch->retry_control_task)
564 {
565 GNUNET_SCHEDULER_cancel (ch->retry_control_task);
566 ch->retry_control_task = NULL;
567 }
568 if (GNUNET_NO == ch->is_loopback)
569 {
570 GCT_remove_channel (ch->t, ch, ch->ctn);
571 ch->t = NULL;
572 }
573 GNUNET_free (ch);
574}
575
576
577/**
578 * Send a channel create message.
579 *
580 * @param cls Channel for which to send.
581 */
582static void
583send_channel_open (void *cls);
584
585
586/**
587 * Function called once the tunnel confirms that we sent the
588 * create message. Delays for a bit until we retry.
589 *
590 * @param cls our `struct CadetChannel`.
591 * @param cid identifier of the connection within the tunnel, NULL
592 * if transmission failed
593 */
594static void
595channel_open_sent_cb (void *cls,
596 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
597{
598 struct CadetChannel *ch = cls;
599
600 GNUNET_assert (NULL != ch->last_control_qe);
601 ch->last_control_qe = NULL;
602 ch->retry_time = GNUNET_TIME_STD_BACKOFF (ch->retry_time);
603 LOG (GNUNET_ERROR_TYPE_DEBUG,
604 "Sent CADET_CHANNEL_OPEN on %s, retrying in %s\n",
605 GCCH_2s (ch),
606 GNUNET_STRINGS_relative_time_to_string (ch->retry_time, GNUNET_YES));
607 ch->retry_control_task =
608 GNUNET_SCHEDULER_add_delayed (ch->retry_time, &send_channel_open, ch);
609}
610
611
612/**
613 * Send a channel open message.
614 *
615 * @param cls Channel for which to send.
616 */
617static void
618send_channel_open (void *cls)
619{
620 struct CadetChannel *ch = cls;
621 struct GNUNET_CADET_ChannelOpenMessage msgcc;
622
623 ch->retry_control_task = NULL;
624 LOG (GNUNET_ERROR_TYPE_DEBUG,
625 "Sending CHANNEL_OPEN message for %s\n",
626 GCCH_2s (ch));
627 msgcc.header.size = htons (sizeof(msgcc));
628 msgcc.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN);
629 // 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.
630 msgcc.opt = 2;
631 msgcc.h_port = ch->h_port;
632 msgcc.ctn = ch->ctn;
633 ch->state = CADET_CHANNEL_OPEN_SENT;
634 if (NULL != ch->last_control_qe)
635 GCT_send_cancel (ch->last_control_qe);
636 ch->last_control_qe =
637 GCT_send (ch->t, &msgcc.header, &channel_open_sent_cb, ch, &msgcc.ctn);
638 GNUNET_assert (NULL == ch->retry_control_task);
639}
640
641
642/**
643 * Function called once and only once after a channel was bound
644 * to its tunnel via #GCT_add_channel() is ready for transmission.
645 * Note that this is only the case for channels that this peer
646 * initiates, as for incoming channels we assume that they are
647 * ready for transmission immediately upon receiving the open
648 * message. Used to bootstrap the #GCT_send() process.
649 *
650 * @param ch the channel for which the tunnel is now ready
651 */
652void
653GCCH_tunnel_up (struct CadetChannel *ch)
654{
655 GNUNET_assert (NULL == ch->retry_control_task);
656 LOG (GNUNET_ERROR_TYPE_DEBUG,
657 "Tunnel up, sending CHANNEL_OPEN on %s now\n",
658 GCCH_2s (ch));
659 ch->retry_control_task = GNUNET_SCHEDULER_add_now (&send_channel_open, ch);
660}
661
662
663/**
664 * Create a new channel.
665 *
666 * @param owner local client owning the channel
667 * @param ccn local number of this channel at the @a owner
668 * @param destination peer to which we should build the channel
669 * @param port desired port at @a destination
670 * @param options options for the channel
671 * @return handle to the new channel
672 */
673struct CadetChannel *
674GCCH_channel_local_new (struct CadetClient *owner,
675 struct GNUNET_CADET_ClientChannelNumber ccn,
676 struct CadetPeer *destination,
677 const struct GNUNET_HashCode *port,
678 uint32_t options)
679{
680 struct CadetChannel *ch;
681 struct CadetChannelClient *ccco;
682
683 ccco = GNUNET_new (struct CadetChannelClient);
684 ccco->c = owner;
685 ccco->ccn = ccn;
686 ccco->client_ready = GNUNET_YES;
687
688 ch = GNUNET_new (struct CadetChannel);
689 ch->mid_recv.mid = htonl (1); /* The OPEN_ACK counts as message 0! */
690 ch->nobuffer = GNUNET_NO;
691 ch->reliable = GNUNET_YES;
692 ch->out_of_order = GNUNET_NO;
693 ch->max_pending_messages =
694 (ch->nobuffer) ? 1 : 4; /* FIXME: 4!? Do not hardcode! */
695 ch->owner = ccco;
696 ch->port = *port;
697 GCCH_hash_port (&ch->h_port, port, GCP_get_id (destination));
698 if (0 == GNUNET_memcmp (&my_full_id, GCP_get_id (destination)))
699 {
700 struct OpenPort *op;
701
702 ch->is_loopback = GNUNET_YES;
703 op = GNUNET_CONTAINER_multihashmap_get (open_ports, &ch->h_port);
704 if (NULL == op)
705 {
706 /* port closed, wait for it to possibly open */
707 ch->state = CADET_CHANNEL_LOOSE;
708 (void) GNUNET_CONTAINER_multihashmap_put (
709 loose_channels,
710 &ch->h_port,
711 ch,
712 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
713 LOG (GNUNET_ERROR_TYPE_DEBUG,
714 "Created loose incoming loopback channel to port %s\n",
715 GNUNET_h2s (&ch->port));
716 }
717 else
718 {
719 GCCH_bind (ch, op->c, &op->port);
720 }
721 }
722 else
723 {
724 ch->t = GCP_get_tunnel (destination, GNUNET_YES);
725 ch->retry_time = CADET_INITIAL_RETRANSMIT_TIME;
726 ch->ctn = GCT_add_channel (ch->t, ch);
727 }
728 GNUNET_STATISTICS_update (stats, "# channels", 1, GNUNET_NO);
729 LOG (GNUNET_ERROR_TYPE_DEBUG,
730 "Created channel to port %s at peer %s for %s using %s\n",
731 GNUNET_h2s (port),
732 GCP_2s (destination),
733 GSC_2s (owner),
734 (GNUNET_YES == ch->is_loopback) ? "loopback" : GCT_2s (ch->t));
735 return ch;
736}
737
738
739/**
740 * We had an incoming channel to a port that is closed.
741 * It has not been opened for a while, drop it.
742 *
743 * @param cls the channel to drop
744 */
745static void
746timeout_closed_cb (void *cls)
747{
748 struct CadetChannel *ch = cls;
749
750 ch->retry_control_task = NULL;
751 LOG (GNUNET_ERROR_TYPE_DEBUG,
752 "Closing incoming channel to port %s from peer %s due to timeout\n",
753 GNUNET_h2s (&ch->port),
754 GCP_2s (GCT_get_destination (ch->t)));
755 channel_destroy (ch);
756}
757
758
759/**
760 * Create a new channel based on a request coming in over the network.
761 *
762 * @param t tunnel to the remote peer
763 * @param ctn identifier of this channel in the tunnel
764 * @param h_port desired hash of local port
765 * @param options options for the channel
766 * @return handle to the new channel
767 */
768struct CadetChannel *
769GCCH_channel_incoming_new (struct CadetTunnel *t,
770 struct GNUNET_CADET_ChannelTunnelNumber ctn,
771 const struct GNUNET_HashCode *h_port,
772 uint32_t options)
773{
774 struct CadetChannel *ch;
775 struct OpenPort *op;
776
777 ch = GNUNET_new (struct CadetChannel);
778 ch->h_port = *h_port;
779 ch->t = t;
780 ch->ctn = ctn;
781 ch->retry_time = CADET_INITIAL_RETRANSMIT_TIME;
782 ch->nobuffer = GNUNET_NO;
783 ch->reliable = GNUNET_YES;
784 ch->out_of_order = GNUNET_NO;
785 ch->max_pending_messages =
786 (ch->nobuffer) ? 1 : 4; /* FIXME: 4!? Do not hardcode! */
787 GNUNET_STATISTICS_update (stats, "# channels", 1, GNUNET_NO);
788
789 op = GNUNET_CONTAINER_multihashmap_get (open_ports, h_port);
790 if (NULL == op)
791 {
792 /* port closed, wait for it to possibly open */
793 ch->state = CADET_CHANNEL_LOOSE;
794 (void) GNUNET_CONTAINER_multihashmap_put (
795 loose_channels,
796 &ch->h_port,
797 ch,
798 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
799 GNUNET_assert (NULL == ch->retry_control_task);
800 ch->retry_control_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT_CLOSED_PORT,
801 &timeout_closed_cb,
802 ch);
803 LOG (GNUNET_ERROR_TYPE_DEBUG,
804 "Created loose incoming channel to port %s from peer %s\n",
805 GNUNET_h2s (&ch->port),
806 GCP_2s (GCT_get_destination (ch->t)));
807 }
808 else
809 {
810 GCCH_bind (ch, op->c, &op->port);
811 }
812 GNUNET_STATISTICS_update (stats, "# channels", 1, GNUNET_NO);
813 return ch;
814}
815
816
817/**
818 * Function called once the tunnel confirms that we sent the
819 * ACK message. Just remembers it was sent, we do not expect
820 * ACKs for ACKs ;-).
821 *
822 * @param cls our `struct CadetChannel`.
823 * @param cid identifier of the connection within the tunnel, NULL
824 * if transmission failed
825 */
826static void
827send_ack_cb (void *cls,
828 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
829{
830 struct CadetChannel *ch = cls;
831
832 GNUNET_assert (NULL != ch->last_control_qe);
833 ch->last_control_qe = NULL;
834}
835
836
837/**
838 * Compute and send the current #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK to the other peer.
839 *
840 * @param ch channel to send the #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK for
841 */
842static void
843send_channel_data_ack (struct CadetChannel *ch)
844{
845 struct GNUNET_CADET_ChannelDataAckMessage msg;
846
847 if (GNUNET_NO == ch->reliable)
848 return; /* no ACKs */
849 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK);
850 msg.header.size = htons (sizeof(msg));
851 msg.ctn = ch->ctn;
852 msg.mid.mid = htonl (ntohl (ch->mid_recv.mid));
853 msg.futures = GNUNET_htonll (ch->mid_futures);
854 LOG (GNUNET_ERROR_TYPE_DEBUG,
855 "Sending DATA_ACK %u:%llX via %s\n",
856 (unsigned int) ntohl (msg.mid.mid),
857 (unsigned long long) ch->mid_futures,
858 GCCH_2s (ch));
859 if (NULL != ch->last_control_qe)
860 GCT_send_cancel (ch->last_control_qe);
861 ch->last_control_qe = GCT_send (ch->t, &msg.header, &send_ack_cb, ch,
862 &msg.ctn);
863}
864
865
866/**
867 * Send our initial #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK to the client confirming that the
868 * connection is up.
869 *
870 * @param cls the `struct CadetChannel`
871 */
872static void
873send_open_ack (void *cls)
874{
875 struct CadetChannel *ch = cls;
876 struct GNUNET_CADET_ChannelOpenAckMessage msg;
877
878 ch->retry_control_task = NULL;
879 LOG (GNUNET_ERROR_TYPE_DEBUG,
880 "Sending CHANNEL_OPEN_ACK on %s\n",
881 GCCH_2s (ch));
882 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK);
883 msg.header.size = htons (sizeof(msg));
884 msg.reserved = htonl (0);
885 msg.ctn = ch->ctn;
886 msg.port = ch->port;
887 if (NULL != ch->last_control_qe)
888 GCT_send_cancel (ch->last_control_qe);
889 ch->last_control_qe = GCT_send (ch->t, &msg.header, &send_ack_cb, ch,
890 &msg.ctn);
891}
892
893
894/**
895 * We got a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN message again for
896 * this channel. If the binding was successful, (re)transmit the
897 * #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK.
898 *
899 * @param ch channel that got the duplicate open
900 * @param cti identifier of the connection that delivered the message
901 */
902void
903GCCH_handle_duplicate_open (
904 struct CadetChannel *ch,
905 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti)
906{
907 if (NULL == ch->dest)
908 {
909 LOG (GNUNET_ERROR_TYPE_DEBUG,
910 "Ignoring duplicate CHANNEL_OPEN on %s: port is closed\n",
911 GCCH_2s (ch));
912 return;
913 }
914 if (NULL != ch->retry_control_task)
915 {
916 LOG (GNUNET_ERROR_TYPE_DEBUG,
917 "Ignoring duplicate CHANNEL_OPEN on %s: control message is pending\n",
918 GCCH_2s (ch));
919 return;
920 }
921 LOG (GNUNET_ERROR_TYPE_DEBUG,
922 "Retransmitting CHANNEL_OPEN_ACK on %s\n",
923 GCCH_2s (ch));
924 ch->retry_control_task = GNUNET_SCHEDULER_add_now (&send_open_ack, ch);
925}
926
927
928/**
929 * Send a #GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK to the client to solicit more messages.
930 *
931 * @param ch channel the ack is for
932 * @param to_owner #GNUNET_YES to send to owner,
933 * #GNUNET_NO to send to dest
934 */
935static void
936send_ack_to_client (struct CadetChannel *ch, int to_owner)
937{
938 struct GNUNET_MQ_Envelope *env;
939 struct GNUNET_CADET_LocalAck *ack;
940 struct CadetChannelClient *ccc;
941
942 ccc = (GNUNET_YES == to_owner) ? ch->owner : ch->dest;
943 if (NULL == ccc)
944 {
945 /* This can happen if we are just getting ACKs after
946 our local client already disconnected. */
947 GNUNET_assert (GNUNET_YES == ch->destroy);
948 return;
949 }
950 env = GNUNET_MQ_msg (ack, GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK);
951 ack->ccn = ccc->ccn;
952 LOG (GNUNET_ERROR_TYPE_DEBUG,
953 "Sending CADET_LOCAL_ACK to %s (%s) at ccn %X (%u/%u pending)\n",
954 GSC_2s (ccc->c),
955 (GNUNET_YES == to_owner) ? "owner" : "dest",
956 ntohl (ack->ccn.channel_of_client),
957 ch->pending_messages,
958 ch->max_pending_messages);
959 GSC_send_to_client (ccc->c, env);
960}
961
962
963/**
964 * A client is bound to the port that we have a channel
965 * open to. Send the acknowledgement for the connection
966 * request and establish the link with the client.
967 *
968 * @param ch open incoming channel
969 * @param c client listening on the respective @a port
970 * @param port the port @a is listening on
971 */
972void
973GCCH_bind (struct CadetChannel *ch,
974 struct CadetClient *c,
975 const struct GNUNET_HashCode *port)
976{
977 uint32_t options;
978 struct CadetChannelClient *cccd;
979
980 LOG (GNUNET_ERROR_TYPE_DEBUG,
981 "Binding %s from %s to port %s of %s\n",
982 GCCH_2s (ch),
983 GCT_2s (ch->t),
984 GNUNET_h2s (&ch->port),
985 GSC_2s (c));
986 if (NULL != ch->retry_control_task)
987 {
988 /* there might be a timeout task here */
989 GNUNET_SCHEDULER_cancel (ch->retry_control_task);
990 ch->retry_control_task = NULL;
991 }
992 options = 0;
993 cccd = GNUNET_new (struct CadetChannelClient);
994 GNUNET_assert (NULL == ch->dest);
995 ch->dest = cccd;
996 ch->port = *port;
997 cccd->c = c;
998 cccd->client_ready = GNUNET_YES;
999 cccd->ccn = GSC_bind (c,
1000 ch,
1001 (GNUNET_YES == ch->is_loopback)
1002 ? GCP_get (&my_full_id, GNUNET_YES)
1003 : GCT_get_destination (ch->t),
1004 port,
1005 options);
1006 GNUNET_assert (ntohl (cccd->ccn.channel_of_client) <
1007 GNUNET_CADET_LOCAL_CHANNEL_ID_CLI);
1008 ch->mid_recv.mid = htonl (1); /* The OPEN counts as message 0! */
1009 if (GNUNET_YES == ch->is_loopback)
1010 {
1011 ch->state = CADET_CHANNEL_OPEN_SENT;
1012 GCCH_handle_channel_open_ack (ch, NULL, port);
1013 }
1014 else
1015 {
1016 /* notify other peer that we accepted the connection */
1017 ch->state = CADET_CHANNEL_READY;
1018 ch->retry_control_task = GNUNET_SCHEDULER_add_now (&send_open_ack, ch);
1019 }
1020 /* give client it's initial supply of ACKs */
1021 GNUNET_assert (ntohl (cccd->ccn.channel_of_client) <
1022 GNUNET_CADET_LOCAL_CHANNEL_ID_CLI);
1023 for (unsigned int i = 0; i < ch->max_pending_messages; i++)
1024 send_ack_to_client (ch, GNUNET_NO);
1025}
1026
1027
1028/**
1029 * One of our clients has disconnected, tell the other one that we
1030 * are finished. Done asynchronously to avoid concurrent modification
1031 * issues if this is the same client.
1032 *
1033 * @param cls the `struct CadetChannel` where one of the ends is now dead
1034 */
1035static void
1036signal_remote_destroy_cb (void *cls)
1037{
1038 struct CadetChannel *ch = cls;
1039 struct CadetChannelClient *ccc;
1040
1041 /* Find which end is left... */
1042 ch->retry_control_task = NULL;
1043 ccc = (NULL != ch->owner) ? ch->owner : ch->dest;
1044 GSC_handle_remote_channel_destroy (ccc->c, ccc->ccn, ch);
1045 channel_destroy (ch);
1046}
1047
1048
1049/**
1050 * Destroy locally created channel. Called by the local client, so no
1051 * need to tell the client.
1052 *
1053 * @param ch channel to destroy
1054 * @param c client that caused the destruction
1055 * @param ccn client number of the client @a c
1056 */
1057void
1058GCCH_channel_local_destroy (struct CadetChannel *ch,
1059 struct CadetClient *c,
1060 struct GNUNET_CADET_ClientChannelNumber ccn)
1061{
1062 LOG (GNUNET_ERROR_TYPE_DEBUG,
1063 "%s asks for destruction of %s\n",
1064 GSC_2s (c),
1065 GCCH_2s (ch));
1066 GNUNET_assert (NULL != c);
1067 if ((NULL != ch->owner) && (c == ch->owner->c) &&
1068 (ccn.channel_of_client == ch->owner->ccn.channel_of_client))
1069 {
1070 free_channel_client (ch->owner);
1071 ch->owner = NULL;
1072 }
1073 else if ((NULL != ch->dest) && (c == ch->dest->c) &&
1074 (ccn.channel_of_client == ch->dest->ccn.channel_of_client))
1075 {
1076 free_channel_client (ch->dest);
1077 ch->dest = NULL;
1078 }
1079 else
1080 {
1081 GNUNET_assert (0);
1082 }
1083
1084 if (GNUNET_YES == ch->destroy)
1085 {
1086 /* other end already destroyed, with the local client gone, no need
1087 to finish transmissions, just destroy immediately. */
1088 channel_destroy (ch);
1089 return;
1090 }
1091 if ((NULL != ch->head_sent) && ((NULL != ch->owner) || (NULL != ch->dest)))
1092 {
1093 /* Wait for other end to destroy us as well,
1094 and otherwise allow send queue to be transmitted first */
1095 ch->destroy = GNUNET_YES;
1096 return;
1097 }
1098 if ((GNUNET_YES == ch->is_loopback) &&
1099 ((NULL != ch->owner) || (NULL != ch->dest)))
1100 {
1101 if (NULL != ch->retry_control_task)
1102 GNUNET_SCHEDULER_cancel (ch->retry_control_task);
1103 ch->retry_control_task =
1104 GNUNET_SCHEDULER_add_now (&signal_remote_destroy_cb, ch);
1105 return;
1106 }
1107 if (GNUNET_NO == ch->is_loopback)
1108 {
1109 /* If the we ever sent the CHANNEL_CREATE, we need to send a destroy message. */
1110 switch (ch->state)
1111 {
1112 case CADET_CHANNEL_NEW:
1113 /* We gave up on a channel that we created as a client to a remote
1114 target, but that never went anywhere. Nothing to do here. */
1115 break;
1116
1117 case CADET_CHANNEL_LOOSE:
1118 break;
1119
1120 default:
1121 GCT_send_channel_destroy (ch->t, ch->ctn);
1122 }
1123 }
1124 /* Nothing left to do, just finish destruction */
1125 channel_destroy (ch);
1126}
1127
1128
1129/**
1130 * We got an acknowledgement for the creation of the channel
1131 * (the port is open on the other side). Verify that the
1132 * other end really has the right port, and begin transmissions.
1133 *
1134 * @param ch channel to destroy
1135 * @param cti identifier of the connection that delivered the message
1136 * @param port port number (needed to verify receiver knows the port)
1137 */
1138void
1139GCCH_handle_channel_open_ack (
1140 struct CadetChannel *ch,
1141 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti,
1142 const struct GNUNET_HashCode *port)
1143{
1144 switch (ch->state)
1145 {
1146 case CADET_CHANNEL_NEW:
1147 /* this should be impossible */
1148 GNUNET_break (0);
1149 break;
1150
1151 case CADET_CHANNEL_LOOSE:
1152 /* This makes no sense. */
1153 GNUNET_break_op (0);
1154 break;
1155
1156 case CADET_CHANNEL_OPEN_SENT:
1157 if (NULL == ch->owner)
1158 {
1159 /* We're not the owner, wrong direction! */
1160 GNUNET_break_op (0);
1161 return;
1162 }
1163 if (0 != GNUNET_memcmp (&ch->port, port))
1164 {
1165 /* Other peer failed to provide the right port,
1166 refuse connection. */
1167 GNUNET_break_op (0);
1168 return;
1169 }
1170 LOG (GNUNET_ERROR_TYPE_DEBUG,
1171 "Received CHANNEL_OPEN_ACK for waiting %s, entering READY state\n",
1172 GCCH_2s (ch));
1173 if (NULL != ch->retry_control_task) /* can be NULL if ch->is_loopback */
1174 {
1175 GNUNET_SCHEDULER_cancel (ch->retry_control_task);
1176 ch->retry_control_task = NULL;
1177 }
1178 ch->state = CADET_CHANNEL_READY;
1179 /* On first connect, send client as many ACKs as we allow messages
1180 to be buffered! */
1181 for (unsigned int i = 0; i < ch->max_pending_messages; i++)
1182 send_ack_to_client (ch, GNUNET_YES);
1183 break;
1184
1185 case CADET_CHANNEL_READY:
1186 /* duplicate ACK, maybe we retried the CREATE. Ignore. */
1187 LOG (GNUNET_ERROR_TYPE_DEBUG,
1188 "Received duplicate channel OPEN_ACK for %s\n",
1189 GCCH_2s (ch));
1190 GNUNET_STATISTICS_update (stats, "# duplicate CREATE_ACKs", 1, GNUNET_NO);
1191 break;
1192 }
1193}
1194
1195
1196/**
1197 * Test if element @a e1 comes before element @a e2.
1198 *
1199 * @param cls closure, to a flag where we indicate duplicate packets
1200 * @param m1 a message of to sort
1201 * @param m2 another message to sort
1202 * @return #GNUNET_YES if @e1 < @e2, otherwise #GNUNET_NO
1203 */
1204static int
1205is_before (void *cls,
1206 struct CadetOutOfOrderMessage *m1,
1207 struct CadetOutOfOrderMessage *m2)
1208{
1209 int *duplicate = cls;
1210 uint32_t v1 = ntohl (m1->mid.mid);
1211 uint32_t v2 = ntohl (m2->mid.mid);
1212 uint32_t delta;
1213
1214 delta = v2 - v1;
1215 if (0 == delta)
1216 *duplicate = GNUNET_YES;
1217 if (delta > (uint32_t) INT_MAX)
1218 {
1219 /* in overflow range, we can safely assume we wrapped around */
1220 return GNUNET_NO;
1221 }
1222 else
1223 {
1224 /* result is small, thus v2 > v1, thus m1 < m2 */
1225 return GNUNET_YES;
1226 }
1227}
1228
1229
1230/**
1231 * We got payload data for a channel. Pass it on to the client
1232 * and send an ACK to the other end (once flow control allows it!)
1233 *
1234 * @param ch channel that got data
1235 * @param cti identifier of the connection that delivered the message
1236 * @param msg message that was received
1237 */
1238void
1239GCCH_handle_channel_plaintext_data (
1240 struct CadetChannel *ch,
1241 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti,
1242 const struct GNUNET_CADET_ChannelAppDataMessage *msg)
1243{
1244 struct GNUNET_MQ_Envelope *env;
1245 struct GNUNET_CADET_LocalData *ld;
1246 struct CadetChannelClient *ccc;
1247 size_t payload_size;
1248 struct CadetOutOfOrderMessage *com;
1249 int duplicate;
1250 uint32_t mid_min;
1251 uint32_t mid_max;
1252 uint32_t mid_msg;
1253 uint32_t delta;
1254
1255 GNUNET_assert (GNUNET_NO == ch->is_loopback);
1256 if ((NULL == ch->owner) && (NULL == ch->dest))
1257 {
1258 /* This client is gone, but we still have messages to send to
1259 the other end (which is why @a ch is not yet dead). However,
1260 we cannot pass messages to our client anymore. */
1261 LOG (GNUNET_ERROR_TYPE_DEBUG,
1262 "Dropping incoming payload on %s as this end is already closed\n",
1263 GCCH_2s (ch));
1264 /* send back DESTROY notification to stop further retransmissions! */
1265 if (GNUNET_YES == ch->destroy)
1266 GCT_send_channel_destroy (ch->t, ch->ctn);
1267 return;
1268 }
1269 payload_size = ntohs (msg->header.size) - sizeof(*msg);
1270 env = GNUNET_MQ_msg_extra (ld,
1271 payload_size,
1272 GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA);
1273 ld->ccn = (NULL == ch->dest) ? ch->owner->ccn : ch->dest->ccn;
1274 GNUNET_memcpy (&ld[1], &msg[1], payload_size);
1275 ccc = (NULL != ch->owner) ? ch->owner : ch->dest;
1276 if (GNUNET_YES == ccc->client_ready)
1277 {
1278 /*
1279 * We ad-hoc send the message if
1280 * - The channel is out-of-order
1281 * - The channel is reliable and MID matches next expected MID
1282 * - The channel is unreliable and MID is before lowest seen MID
1283 */if ((GNUNET_YES == ch->out_of_order) ||
1284 ((msg->mid.mid == ch->mid_recv.mid) && (GNUNET_YES == ch->reliable)) ||
1285 ((GNUNET_NO == ch->reliable) &&
1286 (ntohl (msg->mid.mid) >= ntohl (ch->mid_recv.mid)) &&
1287 ((NULL == ccc->head_recv) ||
1288 (ntohl (msg->mid.mid) < ntohl (ccc->head_recv->mid.mid)))))
1289 {
1290 LOG (GNUNET_ERROR_TYPE_DEBUG,
1291 "Giving %u bytes of payload with MID %u from %s to client %s\n",
1292 (unsigned int) payload_size,
1293 ntohl (msg->mid.mid),
1294 GCCH_2s (ch),
1295 GSC_2s (ccc->c));
1296 ccc->client_ready = GNUNET_NO;
1297 GSC_send_to_client (ccc->c, env);
1298 if (GNUNET_NO == ch->out_of_order)
1299 ch->mid_recv.mid = htonl (1 + ntohl (msg->mid.mid));
1300 else
1301 ch->mid_recv.mid = htonl (1 + ntohl (ch->mid_recv.mid));
1302 ch->mid_futures >>= 1;
1303 if ((GNUNET_YES == ch->out_of_order) && (GNUNET_NO == ch->reliable))
1304 {
1305 /* possibly shift by more if we skipped messages */
1306 uint64_t delta = htonl (msg->mid.mid) - 1 - ntohl (ch->mid_recv.mid);
1307
1308 if (delta > 63)
1309 ch->mid_futures = 0;
1310 else
1311 ch->mid_futures >>= delta;
1312 ch->mid_recv.mid = htonl (1 + ntohl (msg->mid.mid));
1313 }
1314 send_channel_data_ack (ch);
1315 return;
1316 }
1317 }
1318
1319 if (GNUNET_YES == ch->reliable)
1320 {
1321 /* check if message ought to be dropped because it is ancient/too distant/duplicate */
1322 mid_min = ntohl (ch->mid_recv.mid);
1323 mid_max = mid_min + ch->max_pending_messages;
1324 mid_msg = ntohl (msg->mid.mid);
1325 if (((uint32_t) (mid_msg - mid_min) > ch->max_pending_messages) ||
1326 ((uint32_t) (mid_max - mid_msg) > ch->max_pending_messages))
1327 {
1328 LOG (GNUNET_ERROR_TYPE_DEBUG,
1329 "%s at %u drops ancient or far-future message %u\n",
1330 GCCH_2s (ch),
1331 (unsigned int) mid_min,
1332 ntohl (msg->mid.mid));
1333
1334 GNUNET_STATISTICS_update (stats,
1335 "# duplicate DATA (ancient or future)",
1336 1,
1337 GNUNET_NO);
1338 GNUNET_MQ_discard (env);
1339 send_channel_data_ack (ch);
1340 return;
1341 }
1342 /* mark bit for future ACKs */
1343 delta = mid_msg - mid_min - 1; /* overflow/underflow are OK here */
1344 if (delta < 64)
1345 {
1346 if (0 != (ch->mid_futures & (1LLU << delta)))
1347 {
1348 /* Duplicate within the queue, drop also */
1349 LOG (GNUNET_ERROR_TYPE_DEBUG,
1350 "Duplicate payload of %u bytes on %s (mid %u) dropped\n",
1351 (unsigned int) payload_size,
1352 GCCH_2s (ch),
1353 ntohl (msg->mid.mid));
1354 GNUNET_STATISTICS_update (stats, "# duplicate DATA", 1, GNUNET_NO);
1355 GNUNET_MQ_discard (env);
1356 send_channel_data_ack (ch);
1357 return;
1358 }
1359 ch->mid_futures |= (1LLU << delta);
1360 LOG (GNUNET_ERROR_TYPE_DEBUG,
1361 "Marked bit %llX for mid %u (base: %u); now: %llX\n",
1362 (1LLU << delta),
1363 mid_msg,
1364 mid_min,
1365 (unsigned long long) ch->mid_futures);
1366 }
1367 }
1368 else /* ! ch->reliable */
1369 {
1370 struct CadetOutOfOrderMessage *next_msg;
1371
1372 /**
1373 * We always send if possible in this case.
1374 * It is guaranteed that the queued MID < received MID
1375 **/
1376 if ((NULL != ccc->head_recv) && (GNUNET_YES == ccc->client_ready))
1377 {
1378 next_msg = ccc->head_recv;
1379 LOG (GNUNET_ERROR_TYPE_DEBUG,
1380 "Giving queued MID %u from %s to client %s\n",
1381 ntohl (next_msg->mid.mid),
1382 GCCH_2s (ch),
1383 GSC_2s (ccc->c));
1384 ccc->client_ready = GNUNET_NO;
1385 GSC_send_to_client (ccc->c, next_msg->env);
1386 ch->mid_recv.mid = htonl (1 + ntohl (next_msg->mid.mid));
1387 ch->mid_futures >>= 1;
1388 send_channel_data_ack (ch);
1389 GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, next_msg);
1390 ccc->num_recv--;
1391 /* Do not process duplicate MID */
1392 if (msg->mid.mid == next_msg->mid.mid) /* Duplicate */
1393 {
1394 /* Duplicate within the queue, drop */
1395 LOG (GNUNET_ERROR_TYPE_DEBUG,
1396 "Message on %s (mid %u) dropped, duplicate\n",
1397 GCCH_2s (ch),
1398 ntohl (msg->mid.mid));
1399 GNUNET_free (next_msg);
1400 GNUNET_MQ_discard (env);
1401 return;
1402 }
1403 GNUNET_free (next_msg);
1404 }
1405
1406 if (ntohl (msg->mid.mid) < ntohl (ch->mid_recv.mid)) /* Old */
1407 {
1408 /* Duplicate within the queue, drop */
1409 LOG (GNUNET_ERROR_TYPE_DEBUG,
1410 "Message on %s (mid %u) dropped, old.\n",
1411 GCCH_2s (ch),
1412 ntohl (msg->mid.mid));
1413 GNUNET_MQ_discard (env);
1414 return;
1415 }
1416
1417 /* Channel is unreliable, so we do not ACK. But we also cannot
1418 allow buffering everything, so check if we have space... */
1419 if (ccc->num_recv >= ch->max_pending_messages)
1420 {
1421 struct CadetOutOfOrderMessage *drop;
1422
1423 /* Yep, need to drop. Drop the oldest message in
1424 the buffer. */
1425 LOG (GNUNET_ERROR_TYPE_DEBUG,
1426 "Queue full due slow client on %s, dropping oldest message\n",
1427 GCCH_2s (ch));
1428 GNUNET_STATISTICS_update (stats,
1429 "# messages dropped due to slow client",
1430 1,
1431 GNUNET_NO);
1432 drop = ccc->head_recv;
1433 GNUNET_assert (NULL != drop);
1434 GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, drop);
1435 ccc->num_recv--;
1436 GNUNET_MQ_discard (drop->env);
1437 GNUNET_free (drop);
1438 }
1439 }
1440
1441 /* Insert message into sorted out-of-order queue */
1442 com = GNUNET_new (struct CadetOutOfOrderMessage);
1443 com->mid = msg->mid;
1444 com->env = env;
1445 duplicate = GNUNET_NO;
1446 GNUNET_CONTAINER_DLL_insert_sorted (struct CadetOutOfOrderMessage,
1447 is_before,
1448 &duplicate,
1449 ccc->head_recv,
1450 ccc->tail_recv,
1451 com);
1452 ccc->num_recv++;
1453 if (GNUNET_YES == duplicate)
1454 {
1455 /* Duplicate within the queue, drop also (this is not covered by
1456 the case above if "delta" >= 64, which could be the case if
1457 max_pending_messages is also >= 64 or if our client is unready
1458 and we are seeing retransmissions of the message our client is
1459 blocked on. */LOG (GNUNET_ERROR_TYPE_DEBUG,
1460 "Duplicate payload of %u bytes on %s (mid %u) dropped\n",
1461 (unsigned int) payload_size,
1462 GCCH_2s (ch),
1463 ntohl (msg->mid.mid));
1464 GNUNET_STATISTICS_update (stats, "# duplicate DATA", 1, GNUNET_NO);
1465 GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, com);
1466 ccc->num_recv--;
1467 GNUNET_MQ_discard (com->env);
1468 GNUNET_free (com);
1469 send_channel_data_ack (ch);
1470 return;
1471 }
1472 LOG (GNUNET_ERROR_TYPE_DEBUG,
1473 "Queued %s payload of %u bytes on %s-%X(%p) (mid %u, need %u first)\n",
1474 (GNUNET_YES == ccc->client_ready) ? "out-of-order" : "client-not-ready",
1475 (unsigned int) payload_size,
1476 GCCH_2s (ch),
1477 ntohl (ccc->ccn.channel_of_client),
1478 ccc,
1479 ntohl (msg->mid.mid),
1480 ntohl (ch->mid_recv.mid));
1481 /* NOTE: this ACK we _could_ skip, as the packet is out-of-order and
1482 the sender may already be transmitting the previous one. Needs
1483 experimental evaluation to see if/when this ACK helps or
1484 hurts. (We might even want another option.) */
1485 send_channel_data_ack (ch);
1486}
1487
1488
1489/**
1490 * Function called once the tunnel has sent one of our messages.
1491 * If the message is unreliable, simply frees the `crm`. If the
1492 * message was reliable, calculate retransmission time and
1493 * wait for ACK (or retransmit).
1494 *
1495 * @param cls the `struct CadetReliableMessage` that was sent
1496 * @param cid identifier of the connection within the tunnel, NULL
1497 * if transmission failed
1498 */
1499static void
1500data_sent_cb (void *cls,
1501 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid);
1502
1503
1504/**
1505 * We need to retry a transmission, the last one took too long to
1506 * be acknowledged.
1507 *
1508 * @param cls the `struct CadetChannel` where we need to retransmit
1509 */
1510static void
1511retry_transmission (void *cls)
1512{
1513 struct CadetChannel *ch = cls;
1514 struct CadetReliableMessage *crm = ch->head_sent;
1515
1516 ch->retry_data_task = NULL;
1517 GNUNET_assert (NULL == crm->qe);
1518 LOG (GNUNET_ERROR_TYPE_DEBUG,
1519 "Retrying transmission on %s of message %u\n",
1520 GCCH_2s (ch),
1521 (unsigned int) ntohl (crm->data_message->mid.mid));
1522 crm->qe = GCT_send (ch->t, &crm->data_message->header, &data_sent_cb, crm,
1523 &crm->data_message->ctn);
1524 GNUNET_assert (NULL == ch->retry_data_task);
1525}
1526
1527
1528/**
1529 * We got an PLAINTEXT_DATA_ACK for a message in our queue, remove it from
1530 * the queue and tell our client that it can send more.
1531 *
1532 * @param ch the channel that got the PLAINTEXT_DATA_ACK
1533 * @param cti identifier of the connection that delivered the message
1534 * @param crm the message that got acknowledged
1535 */
1536static void
1537handle_matching_ack (struct CadetChannel *ch,
1538 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti,
1539 struct CadetReliableMessage *crm)
1540{
1541 GNUNET_CONTAINER_DLL_remove (ch->head_sent, ch->tail_sent, crm);
1542 ch->pending_messages--;
1543 GNUNET_assert (ch->pending_messages < ch->max_pending_messages);
1544 LOG (GNUNET_ERROR_TYPE_DEBUG,
1545 "Received DATA_ACK on %s for message %u (%u ACKs pending)\n",
1546 GCCH_2s (ch),
1547 (unsigned int) ntohl (crm->data_message->mid.mid),
1548 ch->pending_messages);
1549 if (NULL != crm->qe)
1550 {
1551 GCT_send_cancel (crm->qe);
1552 crm->qe = NULL;
1553 }
1554 if ((1 == crm->num_transmissions) && (NULL != cti))
1555 {
1556 GCC_ack_observed (cti);
1557 if (0 == GNUNET_memcmp (cti, &crm->connection_taken))
1558 {
1559 GCC_latency_observed (cti,
1560 GNUNET_TIME_absolute_get_duration (
1561 crm->first_transmission_time));
1562 }
1563 }
1564 GNUNET_free (crm->data_message);
1565 GNUNET_free (crm);
1566 send_ack_to_client (ch, (NULL == ch->owner) ? GNUNET_NO : GNUNET_YES);
1567}
1568
1569
1570/**
1571 * We got an acknowledgement for payload data for a channel.
1572 * Possibly resume transmissions.
1573 *
1574 * @param ch channel that got the ack
1575 * @param cti identifier of the connection that delivered the message
1576 * @param ack details about what was received
1577 */
1578void
1579GCCH_handle_channel_plaintext_data_ack (
1580 struct CadetChannel *ch,
1581 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti,
1582 const struct GNUNET_CADET_ChannelDataAckMessage *ack)
1583{
1584 struct CadetReliableMessage *crm;
1585 struct CadetReliableMessage *crmn;
1586 int found;
1587 uint32_t mid_base;
1588 uint64_t mid_mask;
1589 unsigned int delta;
1590
1591 GNUNET_break (GNUNET_NO == ch->is_loopback);
1592 if (GNUNET_NO == ch->reliable)
1593 {
1594 /* not expecting ACKs on unreliable channel, odd */
1595 GNUNET_break_op (0);
1596 return;
1597 }
1598 /* mid_base is the MID of the next message that the
1599 other peer expects (i.e. that is missing!), everything
1600 LOWER (but excluding mid_base itself) was received. */
1601 mid_base = ntohl (ack->mid.mid);
1602 mid_mask = GNUNET_htonll (ack->futures);
1603 found = GNUNET_NO;
1604 for (crm = ch->head_sent; NULL != crm; crm = crmn)
1605 {
1606 crmn = crm->next;
1607 delta = (unsigned int) (ntohl (crm->data_message->mid.mid) - mid_base);
1608 if (delta >= UINT_MAX - ch->max_pending_messages)
1609 {
1610 /* overflow, means crm was a bit in the past, so this ACK counts for it. */
1611 LOG (GNUNET_ERROR_TYPE_DEBUG,
1612 "Got DATA_ACK with base %u satisfying past message %u on %s\n",
1613 (unsigned int) mid_base,
1614 ntohl (crm->data_message->mid.mid),
1615 GCCH_2s (ch));
1616 handle_matching_ack (ch, cti, crm);
1617 found = GNUNET_YES;
1618 continue;
1619 }
1620 delta--;
1621 if (delta >= 64)
1622 continue;
1623 LOG (GNUNET_ERROR_TYPE_DEBUG,
1624 "Testing bit %llX for mid %u (base: %u)\n",
1625 (1LLU << delta),
1626 ntohl (crm->data_message->mid.mid),
1627 mid_base);
1628 if (0 != (mid_mask & (1LLU << delta)))
1629 {
1630 LOG (GNUNET_ERROR_TYPE_DEBUG,
1631 "Got DATA_ACK with mask for %u on %s\n",
1632 ntohl (crm->data_message->mid.mid),
1633 GCCH_2s (ch));
1634 handle_matching_ack (ch, cti, crm);
1635 found = GNUNET_YES;
1636 }
1637 }
1638 if (GNUNET_NO == found)
1639 {
1640 /* ACK for message we already dropped, might have been a
1641 duplicate ACK? Ignore. */
1642 LOG (GNUNET_ERROR_TYPE_DEBUG,
1643 "Duplicate DATA_ACK on %s, ignoring\n",
1644 GCCH_2s (ch));
1645 GNUNET_STATISTICS_update (stats, "# duplicate DATA_ACKs", 1, GNUNET_NO);
1646 return;
1647 }
1648 if (NULL != ch->retry_data_task)
1649 {
1650 GNUNET_SCHEDULER_cancel (ch->retry_data_task);
1651 ch->retry_data_task = NULL;
1652 }
1653 if ((NULL != ch->head_sent) && (NULL == ch->head_sent->qe))
1654 ch->retry_data_task = GNUNET_SCHEDULER_add_at (ch->head_sent->next_retry,
1655 &retry_transmission,
1656 ch);
1657}
1658
1659
1660/**
1661 * Destroy channel, based on the other peer closing the
1662 * connection. Also needs to remove this channel from
1663 * the tunnel.
1664 *
1665 * @param ch channel to destroy
1666 * @param cti identifier of the connection that delivered the message,
1667 * NULL if we are simulating receiving a destroy due to shutdown
1668 */
1669void
1670GCCH_handle_remote_destroy (
1671 struct CadetChannel *ch,
1672 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti)
1673{
1674 struct CadetChannelClient *ccc;
1675
1676 GNUNET_assert (GNUNET_NO == ch->is_loopback);
1677 LOG (GNUNET_ERROR_TYPE_DEBUG,
1678 "Received remote channel DESTROY for %s\n",
1679 GCCH_2s (ch));
1680 if (GNUNET_YES == ch->destroy)
1681 {
1682 /* Local client already gone, this is instant-death. */
1683 channel_destroy (ch);
1684 return;
1685 }
1686 ccc = (NULL != ch->owner) ? ch->owner : ch->dest;
1687 if ((NULL != ccc) && (NULL != ccc->head_recv))
1688 {
1689 LOG (GNUNET_ERROR_TYPE_WARNING,
1690 "Lost end of transmission due to remote shutdown on %s\n",
1691 GCCH_2s (ch));
1692 /* FIXME: change API to notify client about truncated transmission! */
1693 }
1694 ch->destroy = GNUNET_YES;
1695 if (NULL != ccc)
1696 GSC_handle_remote_channel_destroy (ccc->c, ccc->ccn, ch);
1697 channel_destroy (ch);
1698}
1699
1700
1701/**
1702 * Test if element @a e1 comes before element @a e2.
1703 *
1704 * @param cls closure, to a flag where we indicate duplicate packets
1705 * @param crm1 an element of to sort
1706 * @param crm2 another element to sort
1707 * @return #GNUNET_YES if @e1 < @e2, otherwise #GNUNET_NO
1708 */
1709static int
1710cmp_crm_by_next_retry (void *cls,
1711 struct CadetReliableMessage *crm1,
1712 struct CadetReliableMessage *crm2)
1713{
1714 if (crm1->next_retry.abs_value_us < crm2->next_retry.abs_value_us)
1715 return GNUNET_YES;
1716 return GNUNET_NO;
1717}
1718
1719
1720/**
1721 * Function called once the tunnel has sent one of our messages.
1722 * If the message is unreliable, simply frees the `crm`. If the
1723 * message was reliable, calculate retransmission time and
1724 * wait for ACK (or retransmit).
1725 *
1726 * @param cls the `struct CadetReliableMessage` that was sent
1727 * @param cid identifier of the connection within the tunnel, NULL
1728 * if transmission failed
1729 */
1730static void
1731data_sent_cb (void *cls,
1732 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
1733{
1734 struct CadetReliableMessage *crm = cls;
1735 struct CadetChannel *ch = crm->ch;
1736
1737 GNUNET_assert (GNUNET_NO == ch->is_loopback);
1738 GNUNET_assert (NULL != crm->qe);
1739 crm->qe = NULL;
1740 GNUNET_CONTAINER_DLL_remove (ch->head_sent, ch->tail_sent, crm);
1741 if (GNUNET_NO == ch->reliable)
1742 {
1743 GNUNET_free (crm->data_message);
1744 GNUNET_free (crm);
1745 ch->pending_messages--;
1746 send_ack_to_client (ch, (NULL == ch->owner) ? GNUNET_NO : GNUNET_YES);
1747 return;
1748 }
1749 if (NULL == cid)
1750 {
1751 /* There was an error sending. */
1752 crm->num_transmissions = GNUNET_SYSERR;
1753 }
1754 else if (GNUNET_SYSERR != crm->num_transmissions)
1755 {
1756 /* Increment transmission counter, and possibly store @a cid
1757 if this was the first transmission. */
1758 crm->num_transmissions++;
1759 if (1 == crm->num_transmissions)
1760 {
1761 crm->first_transmission_time = GNUNET_TIME_absolute_get ();
1762 crm->connection_taken = *cid;
1763 GCC_ack_expected (cid);
1764 }
1765 }
1766 if ((0 == crm->retry_delay.rel_value_us) && (NULL != cid))
1767 {
1768 struct CadetConnection *cc = GCC_lookup (cid);
1769
1770 if (NULL != cc)
1771 crm->retry_delay = GCC_get_metrics (cc)->aged_latency;
1772 else
1773 crm->retry_delay = ch->retry_time;
1774 }
1775 crm->retry_delay = GNUNET_TIME_STD_BACKOFF (crm->retry_delay);
1776 crm->retry_delay = GNUNET_TIME_relative_max (crm->retry_delay, MIN_RTT_DELAY);
1777 crm->next_retry = GNUNET_TIME_relative_to_absolute (crm->retry_delay);
1778
1779 GNUNET_CONTAINER_DLL_insert_sorted (struct CadetReliableMessage,
1780 cmp_crm_by_next_retry,
1781 NULL,
1782 ch->head_sent,
1783 ch->tail_sent,
1784 crm);
1785 LOG (GNUNET_ERROR_TYPE_DEBUG,
1786 "Message %u sent, next transmission on %s in %s\n",
1787 (unsigned int) ntohl (crm->data_message->mid.mid),
1788 GCCH_2s (ch),
1789 GNUNET_STRINGS_relative_time_to_string (
1790 GNUNET_TIME_absolute_get_remaining (
1791 ch->head_sent->next_retry),
1792 GNUNET_YES));
1793 if (NULL == ch->head_sent->qe)
1794 {
1795 if (NULL != ch->retry_data_task)
1796 GNUNET_SCHEDULER_cancel (ch->retry_data_task);
1797 ch->retry_data_task = GNUNET_SCHEDULER_add_at (ch->head_sent->next_retry,
1798 &retry_transmission,
1799 ch);
1800 }
1801}
1802
1803
1804/**
1805 * Handle data given by a client.
1806 *
1807 * Check whether the client is allowed to send in this tunnel, save if
1808 * channel is reliable and send an ACK to the client if there is still
1809 * buffer space in the tunnel.
1810 *
1811 * @param ch Channel.
1812 * @param sender_ccn ccn of the sender
1813 * @param buf payload to transmit.
1814 * @param buf_len number of bytes in @a buf
1815 * @return #GNUNET_OK if everything goes well,
1816 * #GNUNET_SYSERR in case of an error.
1817 */
1818int
1819GCCH_handle_local_data (struct CadetChannel *ch,
1820 struct GNUNET_CADET_ClientChannelNumber sender_ccn,
1821 const char *buf,
1822 size_t buf_len)
1823{
1824 struct CadetReliableMessage *crm;
1825
1826 if (ch->pending_messages >= ch->max_pending_messages)
1827 {
1828 GNUNET_break (0); /* Fails: #5370 */
1829 return GNUNET_SYSERR;
1830 }
1831 if (GNUNET_YES == ch->destroy)
1832 {
1833 /* we are going down, drop messages */
1834 return GNUNET_OK;
1835 }
1836 ch->pending_messages++;
1837
1838 if (GNUNET_YES == ch->is_loopback)
1839 {
1840 struct CadetChannelClient *receiver;
1841 struct GNUNET_MQ_Envelope *env;
1842 struct GNUNET_CADET_LocalData *ld;
1843 int ack_to_owner;
1844
1845 env =
1846 GNUNET_MQ_msg_extra (ld, buf_len, GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA);
1847 if ((NULL != ch->owner) &&
1848 (sender_ccn.channel_of_client == ch->owner->ccn.channel_of_client))
1849 {
1850 receiver = ch->dest;
1851 ack_to_owner = GNUNET_YES;
1852 }
1853 else if ((NULL != ch->dest) &&
1854 (sender_ccn.channel_of_client == ch->dest->ccn.channel_of_client))
1855 {
1856 receiver = ch->owner;
1857 ack_to_owner = GNUNET_NO;
1858 }
1859 else
1860 {
1861 GNUNET_free (env);
1862 GNUNET_break (0);
1863 return GNUNET_SYSERR;
1864 }
1865 GNUNET_assert (NULL != receiver);
1866 ld->ccn = receiver->ccn;
1867 GNUNET_memcpy (&ld[1], buf, buf_len);
1868 if (GNUNET_YES == receiver->client_ready)
1869 {
1870 ch->pending_messages--;
1871 GSC_send_to_client (receiver->c, env);
1872 send_ack_to_client (ch, ack_to_owner);
1873 }
1874 else
1875 {
1876 struct CadetOutOfOrderMessage *oom;
1877
1878 oom = GNUNET_new (struct CadetOutOfOrderMessage);
1879 oom->env = env;
1880 GNUNET_CONTAINER_DLL_insert_tail (receiver->head_recv,
1881 receiver->tail_recv,
1882 oom);
1883 receiver->num_recv++;
1884 }
1885 return GNUNET_OK;
1886 }
1887
1888 /* Everything is correct, send the message. */
1889 crm = GNUNET_malloc (sizeof(*crm));
1890 crm->ch = ch;
1891 crm->data_message = GNUNET_malloc (
1892 sizeof(struct GNUNET_CADET_ChannelAppDataMessage) + buf_len);
1893 crm->data_message->header.size =
1894 htons (sizeof(struct GNUNET_CADET_ChannelAppDataMessage) + buf_len);
1895 crm->data_message->header.type =
1896 htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA);
1897 ch->mid_send.mid = htonl (ntohl (ch->mid_send.mid) + 1);
1898 crm->data_message->mid = ch->mid_send;
1899 crm->data_message->ctn = ch->ctn;
1900 GNUNET_memcpy (&crm->data_message[1], buf, buf_len);
1901 GNUNET_CONTAINER_DLL_insert_tail (ch->head_sent, ch->tail_sent, crm);
1902 LOG (GNUNET_ERROR_TYPE_DEBUG,
1903 "Sending message %u from local client to %s with %lu bytes\n",
1904 ntohl (crm->data_message->mid.mid),
1905 GCCH_2s (ch),
1906 (unsigned long) buf_len);
1907 if (NULL != ch->retry_data_task)
1908 {
1909 GNUNET_SCHEDULER_cancel (ch->retry_data_task);
1910 ch->retry_data_task = NULL;
1911 }
1912 crm->qe = GCT_send (ch->t, &crm->data_message->header, &data_sent_cb, crm,
1913 &crm->data_message->ctn);
1914 GNUNET_assert (NULL == ch->retry_data_task);
1915 return GNUNET_OK;
1916}
1917
1918
1919/**
1920 * Handle ACK from client on local channel. Means the client is ready
1921 * for more data, see if we have any for it.
1922 *
1923 * @param ch channel to destroy
1924 * @param client_ccn ccn of the client sending the ack
1925 */
1926void
1927GCCH_handle_local_ack (struct CadetChannel *ch,
1928 struct GNUNET_CADET_ClientChannelNumber client_ccn)
1929{
1930 struct CadetChannelClient *ccc;
1931 struct CadetOutOfOrderMessage *com;
1932
1933 if ((NULL != ch->owner) &&
1934 (ch->owner->ccn.channel_of_client == client_ccn.channel_of_client))
1935 ccc = ch->owner;
1936 else if ((NULL != ch->dest) &&
1937 (ch->dest->ccn.channel_of_client == client_ccn.channel_of_client))
1938 ccc = ch->dest;
1939 else
1940 GNUNET_assert (0);
1941 ccc->client_ready = GNUNET_YES;
1942 com = ccc->head_recv;
1943 if (NULL == com)
1944 {
1945 LOG (GNUNET_ERROR_TYPE_DEBUG,
1946 "Got LOCAL_ACK, %s-%X ready to receive more data, but none pending on %s-%X(%p)!\n",
1947 GSC_2s (ccc->c),
1948 ntohl (client_ccn.channel_of_client),
1949 GCCH_2s (ch),
1950 ntohl (ccc->ccn.channel_of_client),
1951 ccc);
1952 return; /* none pending */
1953 }
1954 if (GNUNET_YES == ch->is_loopback)
1955 {
1956 int to_owner;
1957
1958 /* Messages are always in-order, just send */
1959 GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, com);
1960 ccc->num_recv--;
1961 GSC_send_to_client (ccc->c, com->env);
1962 /* Notify sender that we can receive more */
1963 if ((NULL != ch->owner) &&
1964 (ccc->ccn.channel_of_client == ch->owner->ccn.channel_of_client))
1965 {
1966 to_owner = GNUNET_NO;
1967 }
1968 else
1969 {
1970 GNUNET_assert ((NULL != ch->dest) && (ccc->ccn.channel_of_client ==
1971 ch->dest->ccn.channel_of_client));
1972 to_owner = GNUNET_YES;
1973 }
1974 send_ack_to_client (ch, to_owner);
1975 GNUNET_free (com);
1976 return;
1977 }
1978
1979 if ((com->mid.mid != ch->mid_recv.mid) && (GNUNET_NO == ch->out_of_order) &&
1980 (GNUNET_YES == ch->reliable))
1981 {
1982 LOG (GNUNET_ERROR_TYPE_DEBUG,
1983 "Got LOCAL_ACK, %s-%X ready to receive more data (but next one is out-of-order %u vs. %u)!\n",
1984 GSC_2s (ccc->c),
1985 ntohl (ccc->ccn.channel_of_client),
1986 ntohl (com->mid.mid),
1987 ntohl (ch->mid_recv.mid));
1988 return; /* missing next one in-order */
1989 }
1990
1991 LOG (GNUNET_ERROR_TYPE_DEBUG,
1992 "Got LOCAL_ACK, giving payload message %u to %s-%X on %s\n",
1993 ntohl (com->mid.mid),
1994 GSC_2s (ccc->c),
1995 ntohl (ccc->ccn.channel_of_client),
1996 GCCH_2s (ch));
1997
1998 /* all good, pass next message to client */
1999 GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, com);
2000 ccc->num_recv--;
2001 /* FIXME: if unreliable, this is not aggressive
2002 enough, as it would be OK to have lost some! */
2003
2004 ch->mid_recv.mid = htonl (1 + ntohl (com->mid.mid));
2005 ch->mid_futures >>= 1; /* equivalent to division by 2 */
2006 ccc->client_ready = GNUNET_NO;
2007 GSC_send_to_client (ccc->c, com->env);
2008 GNUNET_free (com);
2009 send_channel_data_ack (ch);
2010 if (NULL != ccc->head_recv)
2011 return;
2012 if (GNUNET_NO == ch->destroy)
2013 return;
2014 GCT_send_channel_destroy (ch->t, ch->ctn);
2015 channel_destroy (ch);
2016}
2017
2018
2019#define LOG2(level, ...) \
2020 GNUNET_log_from_nocheck (level, "cadet-chn", __VA_ARGS__)
2021
2022
2023/**
2024 * Log channel info.
2025 *
2026 * @param ch Channel.
2027 * @param level Debug level to use.
2028 */
2029void
2030GCCH_debug (struct CadetChannel *ch, enum GNUNET_ErrorType level)
2031{
2032#if ! defined(GNUNET_CULL_LOGGING)
2033 int do_log;
2034
2035 do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
2036 "cadet-chn",
2037 __FILE__,
2038 __FUNCTION__,
2039 __LINE__);
2040 if (0 == do_log)
2041 return;
2042
2043 if (NULL == ch)
2044 {
2045 LOG2 (level, "CHN *** DEBUG NULL CHANNEL ***\n");
2046 return;
2047 }
2048 LOG2 (level, "CHN %s:%X (%p)\n", GCT_2s (ch->t), ch->ctn.cn, ch);
2049 if (NULL != ch->owner)
2050 {
2051 LOG2 (level,
2052 "CHN origin %s ready %s local-id: %u\n",
2053 GSC_2s (ch->owner->c),
2054 ch->owner->client_ready ? "YES" : "NO",
2055 ntohl (ch->owner->ccn.channel_of_client));
2056 }
2057 if (NULL != ch->dest)
2058 {
2059 LOG2 (level,
2060 "CHN destination %s ready %s local-id: %u\n",
2061 GSC_2s (ch->dest->c),
2062 ch->dest->client_ready ? "YES" : "NO",
2063 ntohl (ch->dest->ccn.channel_of_client));
2064 }
2065 LOG2 (level,
2066 "CHN Message IDs recv: %d (%llX), send: %d\n",
2067 ntohl (ch->mid_recv.mid),
2068 (unsigned long long) ch->mid_futures,
2069 ntohl (ch->mid_send.mid));
2070#endif
2071}
2072
2073
2074/* end of gnunet-service-cadet_channel.c */
diff --git a/src/cadet/gnunet-service-cadet_channel.h b/src/cadet/gnunet-service-cadet_channel.h
deleted file mode 100644
index 6d691cafc..000000000
--- a/src/cadet/gnunet-service-cadet_channel.h
+++ /dev/null
@@ -1,304 +0,0 @@
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 * Check if type of message is the one 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 origin peer to who initiated the channel
178 * @param h_port hash of desired local port
179 * @param options options for the channel
180 * @return handle to the new channel
181 */
182struct CadetChannel *
183GCCH_channel_incoming_new (struct CadetTunnel *t,
184 struct GNUNET_CADET_ChannelTunnelNumber chid,
185 const struct GNUNET_HashCode *h_port,
186 uint32_t options);
187
188
189/**
190 * We got a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN message again for
191 * this channel. If the binding was successful, (re)transmit the
192 * #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK.
193 *
194 * @param ch channel that got the duplicate open
195 * @param cti identifier of the connection that delivered the message
196 */
197void
198GCCH_handle_duplicate_open (struct CadetChannel *ch,
199 const struct
200 GNUNET_CADET_ConnectionTunnelIdentifier *cti);
201
202
203/**
204 * We got payload data for a channel. Pass it on to the client.
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). Begin transmissions.
238 *
239 * @param ch channel to destroy
240 * @param cti identifier of the connection that delivered the message,
241 * NULL if the ACK was inferred because we got payload or are on loopback
242 * @param port port number (needed to verify receiver knows the port)
243 */
244void
245GCCH_handle_channel_open_ack (struct CadetChannel *ch,
246 const struct
247 GNUNET_CADET_ConnectionTunnelIdentifier *cti,
248 const struct GNUNET_HashCode *port);
249
250
251/**
252 * Destroy channel, based on the other peer closing the
253 * connection. Also needs to remove this channel from
254 * the tunnel.
255 *
256 * FIXME: need to make it possible to defer destruction until we have
257 * received all messages up to the destroy, and right now the destroy
258 * message (and this API) fails to give is the information we need!
259 *
260 * FIXME: also need to know if the other peer got a destroy from
261 * us before!
262 *
263 * @param ch channel to destroy
264 * @param cti identifier of the connection that delivered the message,
265 * NULL during shutdown
266 */
267void
268GCCH_handle_remote_destroy (struct CadetChannel *ch,
269 const struct
270 GNUNET_CADET_ConnectionTunnelIdentifier *cti);
271
272
273/**
274 * Handle data given by a client.
275 *
276 * Check whether the client is allowed to send in this tunnel, save if
277 * channel is reliable and send an ACK to the client if there is still
278 * buffer space in the tunnel.
279 *
280 * @param ch Channel.
281 * @param sender_ccn ccn of the sender
282 * @param buf payload to transmit.
283 * @param buf_len number of bytes in @a buf
284 * @return #GNUNET_OK if everything goes well,
285 * #GNUNET_SYSERR in case of an error.
286 */
287int
288GCCH_handle_local_data (struct CadetChannel *ch,
289 struct GNUNET_CADET_ClientChannelNumber sender_ccn,
290 const char *buf,
291 size_t buf_len);
292
293
294/**
295 * Handle ACK from client on local channel.
296 *
297 * @param ch channel to destroy
298 * @param client_ccn ccn of the client sending the ack
299 */
300void
301GCCH_handle_local_ack (struct CadetChannel *ch,
302 struct GNUNET_CADET_ClientChannelNumber client_ccn);
303
304#endif
diff --git a/src/cadet/gnunet-service-cadet_connection.c b/src/cadet/gnunet-service-cadet_connection.c
deleted file mode 100644
index 637e8663b..000000000
--- a/src/cadet/gnunet-service-cadet_connection.c
+++ /dev/null
@@ -1,1106 +0,0 @@
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 cti.
435 *
436 * @param cti 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
452/**
453 * We observed some the given @a latency on the connection
454 * identified by @a cti. (The same connection was taken
455 * in both directions.)
456 *
457 * @param cid connection identifier where we measured latency
458 * @param latency the observed latency
459 */
460void
461GCC_latency_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
462 struct GNUNET_TIME_Relative latency)
463{
464 struct CadetConnection *cc;
465 double weight;
466 double result;
467
468 cc = GCC_lookup (cid);
469 if (NULL == cc)
470 return; /* whopise, connection already down? */
471 GNUNET_STATISTICS_update (stats, "# latencies observed", 1, GNUNET_NO);
472 cc->latency_datapoints++;
473 if (cc->latency_datapoints >= 7)
474 weight = 7.0;
475 else
476 weight = cc->latency_datapoints;
477 /* Compute weighted average, giving at MOST weight 7 to the
478 existing values, or less if that value is based on fewer than 7
479 measurements. */
480 result = (weight * cc->metrics.aged_latency.rel_value_us)
481 + 1.0 * latency.rel_value_us;
482 result /= (weight + 1.0);
483 cc->metrics.aged_latency.rel_value_us = (uint64_t) result;
484}
485
486
487/**
488 * A #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK was received for
489 * this connection, implying that the end-to-end connection is up.
490 * Process it.
491 *
492 * @param cc the connection that got the ACK.
493 */
494void
495GCC_handle_connection_create_ack (struct CadetConnection *cc)
496{
497 LOG (GNUNET_ERROR_TYPE_DEBUG,
498 "Received CADET_CONNECTION_CREATE_ACK for %s in state %d (%s)\n",
499 GCC_2s (cc),
500 cc->state,
501 (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy");
502 if (CADET_CONNECTION_READY == cc->state)
503 return; /* Duplicate ACK, ignore */
504 if (NULL != cc->task)
505 {
506 GNUNET_SCHEDULER_cancel (cc->task);
507 cc->task = NULL;
508 }
509 cc->metrics.age = GNUNET_TIME_absolute_get ();
510 update_state (cc, CADET_CONNECTION_READY, cc->mqm_ready);
511 if ((NULL == cc->keepalive_qe) && (GNUNET_YES == cc->mqm_ready) &&
512 (NULL == cc->task))
513 cc->task =
514 GNUNET_SCHEDULER_add_delayed (keepalive_period, &send_keepalive, cc);
515}
516
517
518/**
519 * Handle KX message.
520 *
521 * @param cc connection that received encrypted message
522 * @param msg the key exchange message
523 */
524void
525GCC_handle_kx (struct CadetConnection *cc,
526 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
527{
528 LOG (GNUNET_ERROR_TYPE_DEBUG,
529 "Received KX message with ephermal %s on CC %s in state %d\n",
530 GNUNET_e2s (&msg->ephemeral_key),
531 GNUNET_sh2s (&cc->cid.connection_of_tunnel),
532 cc->state);
533 if (CADET_CONNECTION_SENT == cc->state)
534 {
535 /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine,
536 clearly something is working, so pretend we got an ACK. */
537 LOG (GNUNET_ERROR_TYPE_DEBUG,
538 "Faking connection CADET_CONNECTION_CREATE_ACK for %s due to KX\n",
539 GCC_2s (cc));
540 GCC_handle_connection_create_ack (cc);
541 }
542 GCT_handle_kx (cc->ct, msg);
543}
544
545
546/**
547 * Handle KX_AUTH message.
548 *
549 * @param cc connection that received encrypted message
550 * @param msg the key exchange message
551 */
552void
553GCC_handle_kx_auth (struct CadetConnection *cc,
554 const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg)
555{
556 LOG (GNUNET_ERROR_TYPE_DEBUG,
557 "Received KX AUTH message with ephermal %s on CC %s in state %d\n",
558 GNUNET_e2s (&msg->kx.ephemeral_key),
559 GNUNET_sh2s (&cc->cid.connection_of_tunnel),
560 cc->state);
561 if (CADET_CONNECTION_SENT == cc->state)
562 {
563 /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine,
564 clearly something is working, so pretend we got an ACK. */
565 LOG (GNUNET_ERROR_TYPE_DEBUG,
566 "Faking connection CADET_CONNECTION_CREATE_ACK for %s due to KX\n",
567 GCC_2s (cc));
568 GCC_handle_connection_create_ack (cc);
569 }
570 GCT_handle_kx_auth (cc->ct, msg);
571}
572
573
574/**
575 * Handle encrypted message.
576 *
577 * @param cc connection that received encrypted message
578 * @param msg the encrypted message to decrypt
579 */
580void
581GCC_handle_encrypted (struct CadetConnection *cc,
582 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
583{
584 if (CADET_CONNECTION_SENT == cc->state)
585 {
586 /* We didn't get the CREATE_ACK, but instead got payload. That's fine,
587 clearly something is working, so pretend we got an ACK. */
588 LOG (GNUNET_ERROR_TYPE_DEBUG,
589 "Faking connection ACK for %s due to ENCRYPTED payload\n",
590 GCC_2s (cc));
591 GCC_handle_connection_create_ack (cc);
592 }
593 cc->metrics.last_use = GNUNET_TIME_absolute_get ();
594 GCT_handle_encrypted (cc->ct, msg);
595}
596
597
598/**
599 * Set the signature for a monotime value on a GNUNET_CADET_ConnectionCreateMessage.
600 *
601 * @param msg The GNUNET_CADET_ConnectionCreateMessage.
602 */
603void
604set_monotime_sig (struct GNUNET_CADET_ConnectionCreateMessage *msg)
605{
606
607 struct CadetConnectionCreatePS cp = { .purpose.purpose = htonl (
608 GNUNET_SIGNATURE_PURPOSE_CADET_CONNECTION_INITIATOR),
609 .purpose.size = htonl (sizeof(cp)),
610 .monotonic_time = msg->monotime};
611
612 GNUNET_CRYPTO_eddsa_sign (my_private_key, &cp,
613 &msg->monotime_sig);
614
615}
616
617
618/**
619 * Send a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE message to the
620 * first hop.
621 *
622 * @param cls the `struct CadetConnection` to initiate
623 */
624static void
625send_create (void *cls)
626{
627 struct CadetConnection *cc = cls;
628 struct GNUNET_CADET_ConnectionCreateMessage *create_msg;
629 struct GNUNET_PeerIdentity *pids;
630 struct GNUNET_MQ_Envelope *env;
631 struct CadetTunnel *t;
632
633 cc->task = NULL;
634 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
635 env =
636 GNUNET_MQ_msg_extra (create_msg,
637 (2 + cc->off) * sizeof(struct GNUNET_PeerIdentity),
638 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE);
639 // 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.
640 create_msg->options = 2;
641 create_msg->cid = cc->cid;
642
643 // check for tunnel state and set signed monotime (xrs,t3ss)
644 t = GCP_get_tunnel (cc->destination, GNUNET_YES);
645 if ((NULL != t) && (GCT_get_estate (t) == CADET_TUNNEL_KEY_UNINITIALIZED) &&
646 (GCT_alice_or_betty (GCP_get_id (cc->destination)) == GNUNET_NO))
647 {
648 create_msg->has_monotime = GNUNET_YES;
649 create_msg->monotime = GNUNET_TIME_absolute_hton (
650 GNUNET_TIME_absolute_get_monotonic (cfg));
651 set_monotime_sig (create_msg);
652 }
653
654 pids = (struct GNUNET_PeerIdentity *) &create_msg[1];
655 pids[0] = my_full_id;
656 for (unsigned int i = 0; i <= cc->off; i++)
657 pids[i + 1] = *GCP_get_id (GCPP_get_peer_at_offset (cc->path, i));
658 LOG (GNUNET_ERROR_TYPE_DEBUG,
659 "Sending CADET_CONNECTION_CREATE message for %s with %u hops\n",
660 GCC_2s (cc),
661 cc->off + 2);
662 cc->env = env;
663 cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay);
664 cc->create_at = GNUNET_TIME_relative_to_absolute (cc->retry_delay);
665 update_state (cc, CADET_CONNECTION_SENT, GNUNET_NO);
666 GCP_send (cc->mq_man, env);
667}
668
669
670/**
671 * Send a CREATE_ACK message towards the origin.
672 *
673 * @param cls the `struct CadetConnection` to initiate
674 */
675static void
676send_create_ack (void *cls)
677{
678 struct CadetConnection *cc = cls;
679 struct GNUNET_CADET_ConnectionCreateAckMessage *ack_msg;
680 struct GNUNET_MQ_Envelope *env;
681
682 cc->task = NULL;
683 LOG (GNUNET_ERROR_TYPE_DEBUG,
684 "Sending CONNECTION_CREATE_ACK message for %s\n",
685 GCC_2s (cc));
686 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
687 env =
688 GNUNET_MQ_msg (ack_msg, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK);
689 ack_msg->cid = cc->cid;
690 cc->env = env;
691 cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay);
692 cc->create_ack_at = GNUNET_TIME_relative_to_absolute (cc->retry_delay);
693 if (CADET_CONNECTION_CREATE_RECEIVED == cc->state)
694 update_state (cc, CADET_CONNECTION_READY, GNUNET_NO);
695 if (CADET_CONNECTION_READY == cc->state)
696 cc->task =
697 GNUNET_SCHEDULER_add_delayed (keepalive_period, &send_keepalive, cc);
698 GCP_send (cc->mq_man, env);
699}
700
701
702/**
703 * We got a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE for a
704 * connection that we already have. Either our ACK got lost
705 * or something is fishy. Consider retransmitting the ACK.
706 *
707 * @param cc connection that got the duplicate CREATE
708 */
709void
710GCC_handle_duplicate_create (struct CadetConnection *cc)
711{
712 if (GNUNET_YES == cc->mqm_ready)
713 {
714 LOG (GNUNET_ERROR_TYPE_DEBUG,
715 "Got duplicate CREATE for %s, scheduling another ACK (%s)\n",
716 GCC_2s (cc),
717 (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy");
718 /* Revert back to the state of having only received the 'CREATE',
719 and immediately proceed to send the CREATE_ACK. */
720 update_state (cc, CADET_CONNECTION_CREATE_RECEIVED, cc->mqm_ready);
721 if (NULL != cc->task)
722 GNUNET_SCHEDULER_cancel (cc->task);
723 cc->task =
724 GNUNET_SCHEDULER_add_at (cc->create_ack_at, &send_create_ack, cc);
725 }
726 else
727 {
728 /* We are currently sending something else back, which
729 can only be an ACK or payload, either of which would
730 do. So actually no need to do anything. */
731 LOG (GNUNET_ERROR_TYPE_DEBUG,
732 "Got duplicate CREATE for %s. MQ is busy, not queueing another ACK\n",
733 GCC_2s (cc));
734 }
735}
736
737
738/**
739 * There has been a change in the message queue existence for our
740 * peer at the first hop. Adjust accordingly.
741 *
742 * @param cls the `struct CadetConnection`
743 * @param available #GNUNET_YES if sending is now possible,
744 * #GNUNET_NO if sending is no longer possible
745 * #GNUNET_SYSERR if sending is no longer possible
746 * and the last envelope was discarded
747 */
748static void
749manage_first_hop_mq (void *cls, int available)
750{
751 struct CadetConnection *cc = cls;
752
753 if (GNUNET_YES != available)
754 {
755 /* Connection is down, for now... */
756 LOG (GNUNET_ERROR_TYPE_DEBUG, "Core MQ for %s went down\n", GCC_2s (cc));
757 update_state (cc, CADET_CONNECTION_NEW, GNUNET_NO);
758 cc->retry_delay = INITIAL_CONNECTION_CREATE_RETRY_DELAY;
759 if (NULL != cc->task)
760 {
761 GNUNET_SCHEDULER_cancel (cc->task);
762 cc->task = NULL;
763 }
764 return;
765 }
766
767 update_state (cc, cc->state, GNUNET_YES);
768 LOG (GNUNET_ERROR_TYPE_DEBUG,
769 "Core MQ for %s became available in state %d\n",
770 GCC_2s (cc),
771 cc->state);
772 switch (cc->state)
773 {
774 case CADET_CONNECTION_NEW:
775 /* Transmit immediately */
776 cc->task = GNUNET_SCHEDULER_add_at (cc->create_at, &send_create, cc);
777 break;
778
779 case CADET_CONNECTION_SENDING_CREATE:
780 /* Should not be possible to be called in this state. */
781 GNUNET_assert (0);
782 break;
783
784 case CADET_CONNECTION_SENT:
785 /* Retry a bit later... */
786 cc->task = GNUNET_SCHEDULER_add_at (cc->create_at, &send_create, cc);
787 break;
788
789 case CADET_CONNECTION_CREATE_RECEIVED:
790 /* We got the 'CREATE' (incoming connection), should send the CREATE_ACK */
791 cc->metrics.age = GNUNET_TIME_absolute_get ();
792 cc->task =
793 GNUNET_SCHEDULER_add_at (cc->create_ack_at, &send_create_ack, cc);
794 break;
795
796 case CADET_CONNECTION_READY:
797 if ((NULL == cc->keepalive_qe) && (GNUNET_YES == cc->mqm_ready) &&
798 (NULL == cc->task))
799 {
800 LOG (GNUNET_ERROR_TYPE_DEBUG,
801 "Scheduling keepalive for %s in %s\n",
802 GCC_2s (cc),
803 GNUNET_STRINGS_relative_time_to_string (keepalive_period,
804 GNUNET_YES));
805 cc->task =
806 GNUNET_SCHEDULER_add_delayed (keepalive_period, &send_keepalive, cc);
807 }
808 break;
809 }
810}
811
812
813/**
814 * Create a connection to @a destination via @a path and notify @a cb
815 * whenever we are ready for more data. Shared logic independent of
816 * who is initiating the connection.
817 *
818 * @param destination where to go
819 * @param path which path to take (may not be the full path)
820 * @param off offset of @a destination on @a path
821 * @param ct which tunnel uses this connection
822 * @param init_state initial state for the connection
823 * @param ready_cb function to call when ready to transmit
824 * @param ready_cb_cls closure for @a cb
825 * @return handle to the connection
826 */
827static struct CadetConnection *
828connection_create (struct CadetPeer *destination,
829 struct CadetPeerPath *path,
830 unsigned int off,
831 struct CadetTConnection *ct,
832 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
833 enum CadetConnectionState init_state,
834 GCC_ReadyCallback ready_cb,
835 void *ready_cb_cls)
836{
837 struct CadetConnection *cc;
838 struct CadetPeer *first_hop;
839
840 cc = GNUNET_new (struct CadetConnection);
841 cc->state = init_state;
842 cc->ct = ct;
843 cc->destination = destination; /* xrs,t3ss,lurchi*/
844 cc->cid = *cid;
845 cc->retry_delay =
846 GNUNET_TIME_relative_multiply (INITIAL_CONNECTION_CREATE_RETRY_DELAY, off);
847 GNUNET_assert (GNUNET_OK ==
848 GNUNET_CONTAINER_multishortmap_put (
849 connections,
850 &GCC_get_id (cc)->connection_of_tunnel,
851 cc,
852 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
853 cc->ready_cb = ready_cb;
854 cc->ready_cb_cls = ready_cb_cls;
855 cc->path = path;
856 cc->off = off;
857 LOG (GNUNET_ERROR_TYPE_DEBUG,
858 "Creating %s using path %s (offset: %u)\n",
859 GCC_2s (cc),
860 GCPP_2s (path),
861 off);
862 GCPP_add_connection (path, off, cc);
863 for (unsigned int i = 0; i < off; i++)
864 GCP_add_connection (GCPP_get_peer_at_offset (path, i), cc);
865 first_hop = GCPP_get_peer_at_offset (path, 0);
866 cc->mq_man = GCP_request_mq (first_hop, &manage_first_hop_mq, cc);
867 return cc;
868}
869
870
871/**
872 * Create a connection to @a destination via @a path and
873 * notify @a cb whenever we are ready for more data. This
874 * is an inbound tunnel, so we must use the existing @a cid
875 *
876 * @param destination where to go
877 * @param path which path to take (may not be the full path)
878 * @param ct which tunnel uses this connection
879 * @param ready_cb function to call when ready to transmit
880 * @param ready_cb_cls closure for @a cb
881 * @return handle to the connection, NULL if we already have
882 * a connection that takes precedence on @a path
883 */
884struct CadetConnection *
885GCC_create_inbound (struct CadetPeer *destination,
886 struct CadetPeerPath *path,
887 struct CadetTConnection *ct,
888 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
889 GCC_ReadyCallback ready_cb,
890 void *ready_cb_cls)
891{
892 struct CadetConnection *cc;
893 unsigned int off;
894
895 off = GCPP_find_peer (path, destination);
896 GNUNET_assert (UINT_MAX != off);
897 cc = GCPP_get_connection (path, destination, off);
898 if (NULL != cc)
899 {
900 int cmp;
901
902 cmp = GNUNET_memcmp (cid, &cc->cid);
903 if (0 == cmp)
904 {
905 /* Two peers picked the SAME random connection identifier at the
906 same time for the same path? Must be malicious. Drop
907 connection (existing and inbound), even if it is the only
908 one. */
909 GNUNET_break_op (0);
910 GCT_connection_lost (cc->ct);
911 GCC_destroy_without_tunnel (cc);
912 return NULL;
913 }
914 if (0 < cmp)
915 {
916 /* drop existing */
917 LOG (GNUNET_ERROR_TYPE_DEBUG,
918 "Got two connections on %s, dropping my existing %s\n",
919 GCPP_2s (path),
920 GCC_2s (cc));
921 GCT_connection_lost (cc->ct);
922 GCC_destroy_without_tunnel (cc);
923 }
924 else
925 {
926 /* keep existing */
927 LOG (GNUNET_ERROR_TYPE_DEBUG,
928 "Got two connections on %s, keeping my existing %s\n",
929 GCPP_2s (path),
930 GCC_2s (cc));
931 return NULL;
932 }
933 }
934
935 return connection_create (destination,
936 path,
937 off,
938 ct,
939 cid,
940 CADET_CONNECTION_CREATE_RECEIVED,
941 ready_cb,
942 ready_cb_cls);
943}
944
945
946/**
947 * Create a connection to @a destination via @a path and
948 * notify @a cb whenever we are ready for more data.
949 *
950 * @param destination where to go
951 * @param path which path to take (may not be the full path)
952 * @param off offset of @a destination on @a path
953 * @param ct tunnel that uses the connection
954 * @param ready_cb function to call when ready to transmit
955 * @param ready_cb_cls closure for @a cb
956 * @return handle to the connection
957 */
958struct CadetConnection *
959GCC_create (struct CadetPeer *destination,
960 struct CadetPeerPath *path,
961 unsigned int off,
962 struct CadetTConnection *ct,
963 GCC_ReadyCallback ready_cb,
964 void *ready_cb_cls)
965{
966 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
967
968 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, &cid, sizeof(cid));
969 return connection_create (destination,
970 path,
971 off,
972 ct,
973 &cid,
974 CADET_CONNECTION_NEW,
975 ready_cb,
976 ready_cb_cls);
977}
978
979
980/**
981 * Transmit message @a msg via connection @a cc. Must only be called
982 * (once) after the connection has signalled that it is ready via the
983 * `ready_cb`. Clients can also use #GCC_is_ready() to check if the
984 * connection is right now ready for transmission.
985 *
986 * @param cc connection identification
987 * @param env envelope with message to transmit; must NOT
988 * yet have a #GNUNET_MQ_notify_sent() callback attached to it
989 */
990void
991GCC_transmit (struct CadetConnection *cc, struct GNUNET_MQ_Envelope *env)
992{
993 LOG (GNUNET_ERROR_TYPE_DEBUG,
994 "Scheduling message for transmission on %s\n",
995 GCC_2s (cc));
996 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
997 GNUNET_assert (CADET_CONNECTION_READY == cc->state);
998 cc->metrics.last_use = GNUNET_TIME_absolute_get ();
999 cc->mqm_ready = GNUNET_NO;
1000 if (NULL != cc->task)
1001 {
1002 GNUNET_SCHEDULER_cancel (cc->task);
1003 cc->task = NULL;
1004 }
1005 GCP_send (cc->mq_man, env);
1006}
1007
1008
1009/**
1010 * Obtain the path used by this connection.
1011 *
1012 * @param cc connection
1013 * @param off[out] set to the length of the path we use
1014 * @return path to @a cc
1015 */
1016struct CadetPeerPath *
1017GCC_get_path (struct CadetConnection *cc, unsigned int *off)
1018{
1019 *off = cc->off;
1020 return cc->path;
1021}
1022
1023
1024/**
1025 * Obtain unique ID for the connection.
1026 *
1027 * @param cc connection.
1028 * @return unique number of the connection
1029 */
1030const struct GNUNET_CADET_ConnectionTunnelIdentifier *
1031GCC_get_id (struct CadetConnection *cc)
1032{
1033 return &cc->cid;
1034}
1035
1036
1037/**
1038 * Get a (static) string for a connection.
1039 *
1040 * @param cc Connection.
1041 */
1042const char *
1043GCC_2s (const struct CadetConnection *cc)
1044{
1045 static char buf[128];
1046
1047 if (NULL == cc)
1048 return "Connection(NULL)";
1049
1050 if (NULL != cc->ct)
1051 {
1052 GNUNET_snprintf (buf,
1053 sizeof(buf),
1054 "Connection %s (%s)",
1055 GNUNET_sh2s (&cc->cid.connection_of_tunnel),
1056 GCT_2s (cc->ct->t));
1057 return buf;
1058 }
1059 GNUNET_snprintf (buf,
1060 sizeof(buf),
1061 "Connection %s",
1062 GNUNET_sh2s (&cc->cid.connection_of_tunnel));
1063 return buf;
1064}
1065
1066
1067#define LOG2(level, ...) \
1068 GNUNET_log_from_nocheck (level, "cadet-con", __VA_ARGS__)
1069
1070
1071/**
1072 * Log connection info.
1073 *
1074 * @param cc connection
1075 * @param level Debug level to use.
1076 */
1077void
1078GCC_debug (struct CadetConnection *cc, enum GNUNET_ErrorType level)
1079{
1080#if ! defined(GNUNET_CULL_LOGGING)
1081 int do_log;
1082
1083 do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
1084 "cadet-con",
1085 __FILE__,
1086 __FUNCTION__,
1087 __LINE__);
1088 if (0 == do_log)
1089 return;
1090 if (NULL == cc)
1091 {
1092 LOG2 (level, "Connection (NULL)\n");
1093 return;
1094 }
1095 LOG2 (level,
1096 "%s to %s via path %s in state %d is %s\n",
1097 GCC_2s (cc),
1098 GCP_2s (cc->destination),
1099 GCPP_2s (cc->path),
1100 cc->state,
1101 (GNUNET_YES == cc->mqm_ready) ? "ready" : "busy");
1102#endif
1103}
1104
1105
1106/* end of gnunet-service-cadet_connection.c */
diff --git a/src/cadet/gnunet-service-cadet_connection.h b/src/cadet/gnunet-service-cadet_connection.h
deleted file mode 100644
index d646b3dc2..000000000
--- a/src/cadet/gnunet-service-cadet_connection.h
+++ /dev/null
@@ -1,361 +0,0 @@
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 CREATE_ACK was received for this connection, process it.
146 *
147 * @param cc the connection that got the ACK.
148 */
149void
150GCC_handle_connection_create_ack (struct CadetConnection *cc);
151
152
153/**
154 * We got a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE for a
155 * connection that we already have. Either our ACK got lost
156 * or something is fishy. Consider retransmitting the ACK.
157 *
158 * @param cc connection that got the duplicate CREATE
159 */
160void
161GCC_handle_duplicate_create (struct CadetConnection *cc);
162
163
164/**
165 * Handle KX message.
166 *
167 * @param cc connection that received encrypted message
168 * @param msg the key exchange message
169 */
170void
171GCC_handle_kx (struct CadetConnection *cc,
172 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg);
173
174
175/**
176 * Handle KX_AUTH message.
177 *
178 * @param cc connection that received encrypted message
179 * @param msg the key exchange message
180 */
181void
182GCC_handle_kx_auth (struct CadetConnection *cc,
183 const struct
184 GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg);
185
186/**
187 * Purpose for the signature of a monotime.
188 */
189struct CadetConnectionCreatePS
190{
191
192 /**
193 * Purpose is #GNUNET_SIGNATURE_PURPOSE_CADET_CONNECTION_INITIATOR
194 */
195 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
196
197 /**
198 * Time at the initiator when generating the signature.
199 *
200 * Note that the receiver MUST IGNORE the absolute time, and only interpret
201 * the value as a mononic time and reject "older" values than the last one
202 * observed. This is necessary as we do not want to require synchronized
203 * clocks and may not have a bidirectional communication channel.
204 *
205 * Even with this, there is no real guarantee against replay achieved here,
206 * unless the latest timestamp is persisted. Persistence should be
207 * provided via PEERSTORE if possible.
208 */
209 struct GNUNET_TIME_AbsoluteNBO monotonic_time;
210
211};
212
213/**
214 * Performance metrics for a connection.
215 */
216struct CadetConnectionMetrics
217{
218 /**
219 * Our current best estimate of the latency, based on a weighted
220 * average of at least @a latency_datapoints values.
221 */
222 struct GNUNET_TIME_Relative aged_latency;
223
224 /**
225 * When was this connection first established? (by us sending or
226 * receiving the CREATE_ACK for the first time)
227 */
228 struct GNUNET_TIME_Absolute age;
229
230 /**
231 * When was this connection last used? (by us sending or
232 * receiving a PAYLOAD message on it)
233 */
234 struct GNUNET_TIME_Absolute last_use;
235
236 /**
237 * How many packets that ought to generate an ACK did we send via
238 * this connection?
239 */
240 unsigned long long num_acked_transmissions;
241
242 /**
243 * Number of packets that were sent via this connection did actually
244 * receive an ACK? (Note: ACKs may be transmitted and lost via
245 * other connections, so this value should only be interpreted
246 * relative to @e num_acked_transmissions and in relation to other
247 * connections.)
248 */
249 unsigned long long num_successes;
250};
251
252
253/**
254 * Obtain performance @a metrics from @a cc.
255 *
256 * @param cc connection to query
257 * @return the metrics
258 */
259const struct CadetConnectionMetrics *
260GCC_get_metrics (struct CadetConnection *cc);
261
262
263/**
264 * Handle encrypted message.
265 *
266 * @param cc connection that received encrypted message
267 * @param msg the encrypted message to decrypt
268 */
269void
270GCC_handle_encrypted (struct CadetConnection *cc,
271 const struct GNUNET_CADET_TunnelEncryptedMessage *msg);
272
273
274/**
275 * We sent a message for which we expect to receive an ACK via
276 * the connection identified by @a cti.
277 *
278 * @param cid connection identifier where we expect an ACK
279 */
280void
281GCC_ack_expected (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid);
282
283
284/**
285 * We observed an ACK for a message that was originally sent via
286 * the connection identified by @a cti.
287 *
288 * @param cid connection identifier where we got an ACK for a message
289 * that was originally sent via this connection (the ACK
290 * may have gotten back to us via a different connection).
291 */
292void
293GCC_ack_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid);
294
295
296/**
297 * We observed some the given @a latency on the connection
298 * identified by @a cti. (The same connection was taken
299 * in both directions.)
300 *
301 * @param cti connection identifier where we measured latency
302 * @param latency the observed latency
303 */
304void
305GCC_latency_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti,
306 struct GNUNET_TIME_Relative latency);
307
308
309/**
310 * Return the tunnel associated with this connection.
311 *
312 * @param cc connection to query
313 * @return corresponding entry in the tunnel's connection list
314 */
315struct CadetTConnection *
316GCC_get_ct (struct CadetConnection *cc);
317
318
319/**
320 * Obtain the path used by this connection.
321 *
322 * @param cc connection
323 * @param off[out] set to offset in this path where the connection @a cc ends
324 * @return path to @a cc
325 */
326struct CadetPeerPath *
327GCC_get_path (struct CadetConnection *cc,
328 unsigned int *off);
329
330
331/**
332 * Obtain unique ID for the connection.
333 *
334 * @param cc connection.
335 * @return unique number of the connection
336 */
337const struct GNUNET_CADET_ConnectionTunnelIdentifier *
338GCC_get_id (struct CadetConnection *cc);
339
340
341/**
342 * Get a (static) string for a connection.
343 *
344 * @param cc Connection.
345 */
346const char *
347GCC_2s (const struct CadetConnection *cc);
348
349
350/**
351 * Log connection info.
352 *
353 * @param cc connection
354 * @param level Debug level to use.
355 */
356void
357GCC_debug (struct CadetConnection *cc,
358 enum GNUNET_ErrorType level);
359
360
361#endif
diff --git a/src/cadet/gnunet-service-cadet_core.c b/src/cadet/gnunet-service-cadet_core.c
deleted file mode 100644
index 95a5d3f63..000000000
--- a/src/cadet/gnunet-service-cadet_core.c
+++ /dev/null
@@ -1,1348 +0,0 @@
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
142/**
143 * Description of a segment of a `struct CadetConnection` at the
144 * intermediate peers. Routes are basically entries in a peer's
145 * routing table for forwarding traffic. At both endpoints, the
146 * routes are terminated by a `struct CadetConnection`, which knows
147 * the complete `struct CadetPath` that is formed by the individual
148 * routes.
149 */
150struct CadetRoute
151{
152 /**
153 * Information about the next hop on this route.
154 */
155 struct RouteDirection next;
156
157 /**
158 * Information about the previous hop on this route.
159 */
160 struct RouteDirection prev;
161
162 /**
163 * Unique identifier for the connection that uses this route.
164 */
165 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
166
167 /**
168 * When was this route last in use?
169 */
170 struct GNUNET_TIME_Absolute last_use;
171
172 /**
173 * Position of this route in the #route_heap.
174 */
175 struct GNUNET_CONTAINER_HeapNode *hn;
176};
177
178
179/**
180 * Handle to the CORE service.
181 */
182static struct GNUNET_CORE_Handle *core;
183
184/**
185 * Routes on which this peer is an intermediate.
186 */
187static struct GNUNET_CONTAINER_MultiShortmap *routes;
188
189/**
190 * Heap of routes, MIN-sorted by last activity.
191 */
192static struct GNUNET_CONTAINER_Heap *route_heap;
193
194/**
195 * Rung zero (always pointed to by #rung_head).
196 */
197static struct Rung rung_zero;
198
199/**
200 * DLL of rungs, with the head always point to a rung of
201 * route directions with no messages in the queue.
202 */
203static struct Rung *rung_head = &rung_zero;
204
205/**
206 * Tail of the #rung_head DLL.
207 */
208static struct Rung *rung_tail = &rung_zero;
209
210/**
211 * Maximum number of concurrent routes this peer will support.
212 */
213static unsigned long long max_routes;
214
215/**
216 * Maximum number of envelopes we will buffer at this peer.
217 */
218static unsigned long long max_buffers;
219
220/**
221 * Current number of envelopes we have buffered at this peer.
222 */
223static unsigned long long cur_buffers;
224
225/**
226 * Task to timeout routes.
227 */
228static struct GNUNET_SCHEDULER_Task *timeout_task;
229
230/**
231 * Get the route corresponding to a hash.
232 *
233 * @param cid hash generated from the connection identifier
234 */
235static struct CadetRoute *
236get_route (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
237{
238 return GNUNET_CONTAINER_multishortmap_get (routes,
239 &cid->connection_of_tunnel);
240}
241
242
243/**
244 * Lower the rung in which @a dir is by 1.
245 *
246 * @param dir direction to lower in rung.
247 */
248static void
249lower_rung (struct RouteDirection *dir)
250{
251 struct Rung *rung = dir->rung;
252 struct Rung *prev;
253
254 GNUNET_CONTAINER_DLL_remove (rung->rd_head, rung->rd_tail, dir);
255 prev = rung->prev;
256 GNUNET_assert (NULL != prev);
257 if (prev->rung_off != rung->rung_off - 1)
258 {
259 prev = GNUNET_new (struct Rung);
260 prev->rung_off = rung->rung_off - 1;
261 GNUNET_CONTAINER_DLL_insert_after (rung_head, rung_tail, rung->prev, prev);
262 }
263 GNUNET_assert (NULL != prev);
264 GNUNET_CONTAINER_DLL_insert (prev->rd_head, prev->rd_tail, dir);
265 dir->rung = prev;
266}
267
268
269/**
270 * Discard the buffer @a env from the route direction @a dir and
271 * move @a dir down a rung.
272 *
273 * @param dir direction that contains the @a env in the buffer
274 * @param env envelope to discard
275 */
276static void
277discard_buffer (struct RouteDirection *dir, struct GNUNET_MQ_Envelope *env)
278{
279 GNUNET_MQ_dll_remove (&dir->env_head, &dir->env_tail, env);
280 cur_buffers--;
281 GNUNET_MQ_discard (env);
282 lower_rung (dir);
283 GNUNET_STATISTICS_set (stats, "# buffer use", cur_buffers, GNUNET_NO);
284}
285
286
287/**
288 * Discard all messages from the highest rung, to make space.
289 */
290static void
291discard_all_from_rung_tail ()
292{
293 struct Rung *tail = rung_tail;
294 struct RouteDirection *dir;
295
296 while (NULL != (dir = tail->rd_head))
297 {
298 LOG (GNUNET_ERROR_TYPE_DEBUG,
299 "Queue full due new message on connection %s, dropping old message\n",
300 GNUNET_sh2s (&dir->my_route->cid.connection_of_tunnel));
301 GNUNET_STATISTICS_update (stats,
302 "# messages dropped due to full buffer",
303 1,
304 GNUNET_NO);
305 discard_buffer (dir, dir->env_head);
306 }
307 GNUNET_CONTAINER_DLL_remove (rung_head, rung_tail, tail);
308 GNUNET_free (tail);
309}
310
311
312/**
313 * We message @a msg from @a prev. Find its route by @a cid and
314 * forward to the next hop. Drop and signal broken route if we do not
315 * have a route.
316 *
317 * @param prev previous hop (sender)
318 * @param cid connection identifier, tells us which route to use
319 * @param msg the message to forward
320 */
321static void
322route_message (struct CadetPeer *prev,
323 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
324 const struct GNUNET_MessageHeader *msg,
325 const enum GNUNET_MQ_PriorityPreferences priority)
326{
327 struct CadetRoute *route;
328 struct RouteDirection *dir;
329 struct Rung *rung;
330 struct Rung *nxt;
331 struct GNUNET_MQ_Envelope *env;
332
333 route = get_route (cid);
334 if (NULL == route)
335 {
336 struct GNUNET_MQ_Envelope *env;
337 struct GNUNET_CADET_ConnectionBrokenMessage *bm;
338
339 LOG (GNUNET_ERROR_TYPE_DEBUG,
340 "Failed to route message of type %u from %s on connection %s: no route\n",
341 ntohs (msg->type),
342 GCP_2s (prev),
343 GNUNET_sh2s (&cid->connection_of_tunnel));
344 switch (ntohs (msg->type))
345 {
346 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY:
347 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN:
348 /* No need to respond to these! */
349 return;
350 }
351 env = GNUNET_MQ_msg (bm, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
352 bm->cid = *cid;
353 bm->peer1 = my_full_id;
354 GCP_send_ooo (prev, env);
355 return;
356 }
357 route->last_use = GNUNET_TIME_absolute_get ();
358 GNUNET_CONTAINER_heap_update_cost (route->hn, route->last_use.abs_value_us);
359 dir = (prev == route->prev.hop) ? &route->next : &route->prev;
360 if (GNUNET_YES == dir->is_ready)
361 {
362 LOG (GNUNET_ERROR_TYPE_DEBUG,
363 "Routing message of type %u from %s to %s on connection %s\n",
364 ntohs (msg->type),
365 GCP_2s (prev),
366 GNUNET_i2s (GCP_get_id (dir->hop)),
367 GNUNET_sh2s (&cid->connection_of_tunnel));
368 dir->is_ready = GNUNET_NO;
369 GCP_send (dir->mqm, GNUNET_MQ_msg_copy (msg));
370 return;
371 }
372 /* Check if low latency is required and if the previous message was
373 unreliable; if so, make sure we only queue one message per
374 direction (no buffering). */
375 if ((0 != (priority & GNUNET_MQ_PREF_LOW_LATENCY)) &&
376 (NULL != dir->env_head) &&
377 (0 ==
378 (GNUNET_MQ_env_get_options (dir->env_head) & GNUNET_MQ_PREF_UNRELIABLE)))
379 discard_buffer (dir, dir->env_head);
380 /* Check for duplicates */
381 for (const struct GNUNET_MQ_Envelope *env = dir->env_head; NULL != env;
382 env = GNUNET_MQ_env_next (env))
383 {
384 const struct GNUNET_MessageHeader *hdr = GNUNET_MQ_env_get_msg (env);
385
386 if ((hdr->size == msg->size) && (0 == memcmp (hdr, msg, ntohs (msg->size))))
387 {
388 LOG (GNUNET_ERROR_TYPE_DEBUG,
389 "Received duplicate of message already in buffer, dropping\n");
390 GNUNET_STATISTICS_update (stats,
391 "# messages dropped due to duplicate in buffer",
392 1,
393 GNUNET_NO);
394 return;
395 }
396 }
397
398 rung = dir->rung;
399 if (cur_buffers == max_buffers)
400 {
401 /* Need to make room. */
402 if (NULL != rung->next)
403 {
404 /* Easy case, drop messages from route directions in highest rung */
405 discard_all_from_rung_tail ();
406 }
407 else
408 {
409 /* We are in the highest rung, drop our own! */
410 LOG (GNUNET_ERROR_TYPE_DEBUG,
411 "Queue full due new message on connection %s, dropping old message\n",
412 GNUNET_sh2s (&dir->my_route->cid.connection_of_tunnel));
413 GNUNET_STATISTICS_update (stats,
414 "# messages dropped due to full buffer",
415 1,
416 GNUNET_NO);
417 discard_buffer (dir, dir->env_head);
418 rung = dir->rung;
419 }
420 }
421 /* remove 'dir' from current rung */
422 GNUNET_CONTAINER_DLL_remove (rung->rd_head, rung->rd_tail, dir);
423 /* make 'nxt' point to the next higher rung, create if necessary */
424 nxt = rung->next;
425 if ((NULL == nxt) || (rung->rung_off + 1 != nxt->rung_off))
426 {
427 nxt = GNUNET_new (struct Rung);
428 nxt->rung_off = rung->rung_off + 1;
429 GNUNET_CONTAINER_DLL_insert_after (rung_head, rung_tail, rung, nxt);
430 }
431 /* insert 'dir' into next higher rung */
432 GNUNET_CONTAINER_DLL_insert (nxt->rd_head, nxt->rd_tail, dir);
433 dir->rung = nxt;
434
435 /* add message into 'dir' buffer */
436 LOG (GNUNET_ERROR_TYPE_DEBUG,
437 "Queueing new message of type %u from %s to %s on connection %s\n",
438 ntohs (msg->type),
439 GCP_2s (prev),
440 GNUNET_i2s (GCP_get_id (dir->hop)),
441 GNUNET_sh2s (&cid->connection_of_tunnel));
442 env = GNUNET_MQ_msg_copy (msg);
443 GNUNET_MQ_env_set_options (env, priority);
444 if ((0 != (priority & GNUNET_MQ_PREF_LOW_LATENCY)) &&
445 (0 != (priority & GNUNET_MQ_PREF_OUT_OF_ORDER)) &&
446 (NULL != dir->env_head) &&
447 (0 == (GNUNET_MQ_env_get_options (dir->env_head)
448 & GNUNET_MQ_PREF_LOW_LATENCY)))
449 GNUNET_MQ_dll_insert_head (&dir->env_head, &dir->env_tail, env);
450 else
451 GNUNET_MQ_dll_insert_tail (&dir->env_head, &dir->env_tail, env);
452 cur_buffers++;
453 GNUNET_STATISTICS_set (stats, "# buffer use", cur_buffers, GNUNET_NO);
454 /* Clean up 'rung' if now empty (and not head) */
455 if ((NULL == rung->rd_head) && (rung != rung_head))
456 {
457 GNUNET_CONTAINER_DLL_remove (rung_head, rung_tail, rung);
458 GNUNET_free (rung);
459 }
460}
461
462
463/**
464 * Check if the create_connection message has the appropriate size.
465 *
466 * @param cls Closure (unused).
467 * @param msg Message to check.
468 *
469 * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
470 */
471static int
472check_connection_create (void *cls,
473 const struct GNUNET_CADET_ConnectionCreateMessage *msg)
474{
475 uint16_t size = ntohs (msg->header.size) - sizeof(*msg);
476
477 if (0 != (size % sizeof(struct GNUNET_PeerIdentity)))
478 {
479 GNUNET_break_op (0);
480 return GNUNET_NO;
481 }
482 return GNUNET_YES;
483}
484
485
486/**
487 * Free internal data of a route direction.
488 *
489 * @param dir direction to destroy (do NOT free memory of 'dir' itself)
490 */
491static void
492destroy_direction (struct RouteDirection *dir)
493{
494 struct GNUNET_MQ_Envelope *env;
495
496 while (NULL != (env = dir->env_head))
497 {
498 GNUNET_STATISTICS_update (stats,
499 "# messages dropped due to route destruction",
500 1,
501 GNUNET_NO);
502 discard_buffer (dir, env);
503 }
504 if (NULL != dir->mqm)
505 {
506 GCP_request_mq_cancel (dir->mqm, NULL);
507 dir->mqm = NULL;
508 }
509 GNUNET_CONTAINER_DLL_remove (rung_head->rd_head, rung_head->rd_tail, dir);
510}
511
512
513/**
514 * Destroy our state for @a route.
515 *
516 * @param route route to destroy
517 */
518static void
519destroy_route (struct CadetRoute *route)
520{
521 LOG (GNUNET_ERROR_TYPE_DEBUG,
522 "Destroying route from %s to %s of connection %s\n",
523 GNUNET_i2s (GCP_get_id (route->prev.hop)),
524 GNUNET_i2s2 (GCP_get_id (route->next.hop)),
525 GNUNET_sh2s (&route->cid.connection_of_tunnel));
526 GNUNET_assert (route == GNUNET_CONTAINER_heap_remove_node (route->hn));
527 GNUNET_assert (
528 GNUNET_YES ==
529 GNUNET_CONTAINER_multishortmap_remove (routes,
530 &route->cid.connection_of_tunnel,
531 route));
532 GNUNET_STATISTICS_set (stats,
533 "# routes",
534 GNUNET_CONTAINER_multishortmap_size (routes),
535 GNUNET_NO);
536 destroy_direction (&route->prev);
537 destroy_direction (&route->next);
538 GNUNET_free (route);
539}
540
541
542/**
543 * Send message that a route is broken between @a peer1 and @a peer2.
544 *
545 * @param target where to send the message
546 * @param cid connection identifier to use
547 * @param peer1 one of the peers where a link is broken
548 * @param peer2 another one of the peers where a link is broken
549 */
550static void
551send_broken (struct RouteDirection *target,
552 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
553 const struct GNUNET_PeerIdentity *peer1,
554 const struct GNUNET_PeerIdentity *peer2)
555{
556 struct GNUNET_MQ_Envelope *env;
557 struct GNUNET_CADET_ConnectionBrokenMessage *bm;
558
559 if (NULL == target->mqm)
560 return; /* Can't send notification, connection is down! */
561 LOG (GNUNET_ERROR_TYPE_DEBUG,
562 "Notifying %s about BROKEN route at %s-%s of connection %s\n",
563 GCP_2s (target->hop),
564 GNUNET_i2s (peer1),
565 GNUNET_i2s2 (peer2),
566 GNUNET_sh2s (&cid->connection_of_tunnel));
567
568 env = GNUNET_MQ_msg (bm, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
569 bm->cid = *cid;
570 if (NULL != peer1)
571 bm->peer1 = *peer1;
572 if (NULL != peer2)
573 bm->peer2 = *peer2;
574 GCP_request_mq_cancel (target->mqm, env);
575 target->mqm = NULL;
576}
577
578
579/**
580 * Function called to check if any routes have timed out, and if
581 * so, to clean them up. Finally, schedules itself again at the
582 * earliest time where there might be more work.
583 *
584 * @param cls NULL
585 */
586static void
587timeout_cb (void *cls)
588{
589 struct CadetRoute *r;
590 struct GNUNET_TIME_Relative linger;
591 struct GNUNET_TIME_Absolute exp;
592
593 timeout_task = NULL;
594 linger = GNUNET_TIME_relative_multiply (keepalive_period, 3);
595 while (NULL != (r = GNUNET_CONTAINER_heap_peek (route_heap)))
596 {
597 exp = GNUNET_TIME_absolute_add (r->last_use, linger);
598 if (0 != GNUNET_TIME_absolute_get_remaining (exp).rel_value_us)
599 {
600 /* Route not yet timed out, wait until it does. */
601 timeout_task = GNUNET_SCHEDULER_add_at (exp, &timeout_cb, NULL);
602 return;
603 }
604 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
605 "Sending BROKEN due to timeout (%s was last use, %s linger)\n",
606 GNUNET_STRINGS_absolute_time_to_string (r->last_use),
607 GNUNET_STRINGS_relative_time_to_string (linger, GNUNET_YES));
608 send_broken (&r->prev, &r->cid, NULL, NULL);
609 send_broken (&r->next, &r->cid, NULL, NULL);
610 destroy_route (r);
611 }
612 /* No more routes left, so no need for a #timeout_task */
613}
614
615
616/**
617 * Function called when the message queue to the previous hop
618 * becomes available/unavailable. We expect this function to
619 * be called immediately when we register, and then again
620 * later if the connection ever goes down.
621 *
622 * @param cls the `struct RouteDirection`
623 * @param available #GNUNET_YES if sending is now possible,
624 * #GNUNET_NO if sending is no longer possible
625 * #GNUNET_SYSERR if sending is no longer possible
626 * and the last envelope was discarded
627 */
628static void
629dir_ready_cb (void *cls, int ready)
630{
631 struct RouteDirection *dir = cls;
632 struct CadetRoute *route = dir->my_route;
633 struct RouteDirection *odir;
634
635 if (GNUNET_YES == ready)
636 {
637 struct GNUNET_MQ_Envelope *env;
638
639 dir->is_ready = GNUNET_YES;
640 if (NULL != (env = dir->env_head))
641 {
642 GNUNET_MQ_dll_remove (&dir->env_head, &dir->env_tail, env);
643 cur_buffers--;
644 GNUNET_STATISTICS_set (stats, "# buffer use", cur_buffers, GNUNET_NO);
645 lower_rung (dir);
646 dir->is_ready = GNUNET_NO;
647 GCP_send (dir->mqm, env);
648 }
649 return;
650 }
651 odir = (dir == &route->next) ? &route->prev : &route->next;
652 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending BROKEN due to MQ going down\n");
653 send_broken (&route->next, &route->cid, GCP_get_id (odir->hop), &my_full_id);
654 destroy_route (route);
655}
656
657
658/**
659 * Initialize one of the directions of a route.
660 *
661 * @param route route the direction belongs to
662 * @param dir direction to initialize
663 * @param hop next hop on in the @a dir
664 */
665static void
666dir_init (struct RouteDirection *dir,
667 struct CadetRoute *route,
668 struct CadetPeer *hop)
669{
670 dir->hop = hop;
671 dir->my_route = route;
672 dir->mqm = GCP_request_mq (hop, &dir_ready_cb, dir);
673 GNUNET_CONTAINER_DLL_insert (rung_head->rd_head, rung_head->rd_tail, dir);
674 dir->rung = rung_head;
675 GNUNET_assert (GNUNET_YES == dir->is_ready);
676}
677
678
679/**
680 * We could not create the desired route. Send a
681 * #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN
682 * message to @a target.
683 *
684 * @param target who should receive the message
685 * @param cid identifier of the connection/route that failed
686 * @param failure_at neighbour with which we failed to route,
687 * or NULL.
688 */
689static void
690send_broken_without_mqm (
691 struct CadetPeer *target,
692 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
693 const struct GNUNET_PeerIdentity *failure_at)
694{
695 struct GNUNET_MQ_Envelope *env;
696 struct GNUNET_CADET_ConnectionBrokenMessage *bm;
697
698 env = GNUNET_MQ_msg (bm, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
699 bm->cid = *cid;
700 bm->peer1 = my_full_id;
701 if (NULL != failure_at)
702 bm->peer2 = *failure_at;
703 GCP_send_ooo (target, env);
704}
705
706
707/**
708 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE
709 *
710 * @param cls Closure (CadetPeer for neighbor that sent the message).
711 * @param msg Message itself.
712 */
713static void
714handle_connection_create (
715 void *cls,
716 const struct GNUNET_CADET_ConnectionCreateMessage *msg)
717{
718 struct CadetPeer *sender = cls;
719 struct CadetPeer *next;
720 const struct GNUNET_PeerIdentity *pids =
721 (const struct GNUNET_PeerIdentity *) &msg[1];
722 struct CadetRoute *route;
723 uint16_t size = ntohs (msg->header.size) - sizeof(*msg);
724 unsigned int path_length;
725 unsigned int off;
726 struct CadetTunnel *t;
727
728 path_length = size / sizeof(struct GNUNET_PeerIdentity);
729 if (0 == path_length)
730 {
731 LOG (GNUNET_ERROR_TYPE_DEBUG,
732 "Dropping CADET_CONNECTION_CREATE with empty path\n");
733 GNUNET_break_op (0);
734 return;
735 }
736 LOG (GNUNET_ERROR_TYPE_DEBUG,
737 "Handling CADET_CONNECTION_CREATE from %s for CID %s with %u hops\n",
738 GCP_2s (sender),
739 GNUNET_sh2s (&msg->cid.connection_of_tunnel),
740 path_length);
741 /* Check for loops */
742 {
743 struct GNUNET_CONTAINER_MultiPeerMap *map;
744
745 map = GNUNET_CONTAINER_multipeermap_create (path_length * 2, GNUNET_YES);
746 GNUNET_assert (NULL != map);
747 for (unsigned int i = 0; i < path_length; i++)
748 {
749 LOG (GNUNET_ERROR_TYPE_DEBUG,
750 "CADET_CONNECTION_CREATE has peer %s at offset %u\n",
751 GNUNET_i2s (&pids[i]),
752 i);
753 if (GNUNET_SYSERR == GNUNET_CONTAINER_multipeermap_put (
754 map,
755 &pids[i],
756 NULL,
757 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
758 {
759 /* bogus request */
760 GNUNET_CONTAINER_multipeermap_destroy (map);
761 LOG (GNUNET_ERROR_TYPE_DEBUG,
762 "Dropping CADET_CONNECTION_CREATE with cyclic path\n");
763 GNUNET_break_op (0);
764 return;
765 }
766 }
767 GNUNET_CONTAINER_multipeermap_destroy (map);
768 }
769 /* Initiator is at offset 0, find us */
770 for (off = 1; off < path_length; off++)
771 if (0 == GNUNET_memcmp (&my_full_id, &pids[off]))
772 break;
773 if (off == path_length)
774 {
775 LOG (GNUNET_ERROR_TYPE_DEBUG,
776 "Dropping CADET_CONNECTION_CREATE without us in the path\n");
777 GNUNET_break_op (0);
778 return;
779 }
780 /* Check previous hop */
781 if (sender != GCP_get (&pids[off - 1], GNUNET_NO))
782 {
783 LOG (GNUNET_ERROR_TYPE_DEBUG,
784 "Dropping CADET_CONNECTION_CREATE without sender at previous hop in the path\n");
785 GNUNET_break_op (0);
786 return;
787 }
788 if (NULL != (route = get_route (&msg->cid)))
789 {
790 /* Duplicate CREATE, pass it on, previous one might have been lost! */
791
792 LOG (GNUNET_ERROR_TYPE_DEBUG,
793 "Passing on duplicate CADET_CONNECTION_CREATE message on connection %s\n",
794 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
795 route_message (sender,
796 &msg->cid,
797 &msg->header,
798 GNUNET_MQ_PRIO_CRITICAL_CONTROL
799 | GNUNET_MQ_PREF_LOW_LATENCY);
800 return;
801 }
802 if (off == path_length - 1)
803 {
804 /* We are the destination, create connection */
805 struct CadetConnection *cc;
806 struct CadetPeerPath *path;
807 struct CadetPeer *origin;
808
809 cc = GCC_lookup (&msg->cid);
810 if (NULL != cc)
811 {
812 LOG (GNUNET_ERROR_TYPE_DEBUG,
813 "Received duplicate CADET_CONNECTION_CREATE message on connection %s\n",
814 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
815 GCC_handle_duplicate_create (cc);
816 return;
817 }
818
819 origin = GCP_get (&pids[0], GNUNET_YES);
820 LOG (GNUNET_ERROR_TYPE_DEBUG,
821 "I am destination for CADET_CONNECTION_CREATE message from %s for connection %s, building inverse path\n",
822 GCP_2s (origin),
823 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
824 path = GCPP_get_path_from_route (path_length - 1, pids);
825 t = GCP_get_tunnel (origin, GNUNET_YES);
826
827 // Check for CADET state in case the other side has lost the tunnel (xrs,t3ss)
828 if ((GNUNET_YES == msg->has_monotime) &&
829 (GNUNET_YES == GCP_check_and_update_monotime (origin, msg->monotime)) &&
830 (GNUNET_OK == GCP_check_monotime_sig (origin, msg)) &&
831 (CADET_TUNNEL_KEY_OK == GCT_get_estate (t)))
832 {
833 GCT_change_estate (t, CADET_TUNNEL_KEY_UNINITIALIZED);
834 }
835
836 if (GNUNET_OK !=
837 GCT_add_inbound_connection (t,
838 &msg->cid,
839 path))
840 {
841 /* Send back BROKEN: duplicate connection on the same path,
842 we will use the other one. */
843 LOG (GNUNET_ERROR_TYPE_DEBUG,
844 "Received CADET_CONNECTION_CREATE from %s for %s, but %s already has a connection. Sending BROKEN\n",
845 GCP_2s (sender),
846 GNUNET_sh2s (&msg->cid.connection_of_tunnel),
847 GCPP_2s (path));
848 send_broken_without_mqm (sender, &msg->cid, NULL);
849 return;
850 }
851 return;
852 }
853 /* We are merely a hop on the way, check if we can support the route */
854 next = GCP_get (&pids[off + 1], GNUNET_NO);
855 if ((NULL == next) || (GNUNET_NO == GCP_has_core_connection (next)))
856 {
857 /* unworkable, send back BROKEN notification */
858 LOG (GNUNET_ERROR_TYPE_DEBUG,
859 "Received CADET_CONNECTION_CREATE from %s for %s. Next hop %s:%u is down. Sending BROKEN\n",
860 GCP_2s (sender),
861 GNUNET_sh2s (&msg->cid.connection_of_tunnel),
862 GNUNET_i2s (&pids[off + 1]),
863 off + 1);
864 send_broken_without_mqm (sender, &msg->cid, &pids[off + 1]);
865 return;
866 }
867 if (max_routes <= GNUNET_CONTAINER_multishortmap_size (routes))
868 {
869 LOG (GNUNET_ERROR_TYPE_DEBUG,
870 "Received CADET_CONNECTION_CREATE from %s for %s. We have reached our route limit. Sending BROKEN\n",
871 GCP_2s (sender),
872 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
873 send_broken_without_mqm (sender, &msg->cid, &pids[off - 1]);
874 return;
875 }
876
877 /* Workable route, create routing entry */
878 LOG (GNUNET_ERROR_TYPE_DEBUG,
879 "Received CADET_CONNECTION_CREATE from %s for %s. Next hop %s:%u is up. Creating route\n",
880 GCP_2s (sender),
881 GNUNET_sh2s (&msg->cid.connection_of_tunnel),
882 GNUNET_i2s (&pids[off + 1]),
883 off + 1);
884 route = GNUNET_new (struct CadetRoute);
885 route->cid = msg->cid;
886 route->last_use = GNUNET_TIME_absolute_get ();
887 dir_init (&route->prev, route, sender);
888 dir_init (&route->next, route, next);
889 GNUNET_assert (GNUNET_OK ==
890 GNUNET_CONTAINER_multishortmap_put (
891 routes,
892 &route->cid.connection_of_tunnel,
893 route,
894 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
895 GNUNET_STATISTICS_set (stats,
896 "# routes",
897 GNUNET_CONTAINER_multishortmap_size (routes),
898 GNUNET_NO);
899 route->hn = GNUNET_CONTAINER_heap_insert (route_heap,
900 route,
901 route->last_use.abs_value_us);
902 if (NULL == timeout_task)
903 timeout_task =
904 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (
905 keepalive_period,
906 3),
907 &timeout_cb,
908 NULL);
909 /* also pass CREATE message along to next hop */
910 route_message (sender,
911 &msg->cid,
912 &msg->header,
913 GNUNET_MQ_PRIO_CRITICAL_CONTROL | GNUNET_MQ_PREF_LOW_LATENCY);
914}
915
916
917/**
918 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK
919 *
920 * @param cls Closure (CadetPeer for neighbor that sent the message).
921 * @param msg Message itself.
922 */
923static void
924handle_connection_create_ack (
925 void *cls,
926 const struct GNUNET_CADET_ConnectionCreateAckMessage *msg)
927{
928 struct CadetPeer *peer = cls;
929 struct CadetConnection *cc;
930
931 /* First, check if ACK belongs to a connection that ends here. */
932 cc = GCC_lookup (&msg->cid);
933 if (NULL != cc)
934 {
935 /* verify ACK came from the right direction */
936 unsigned int len;
937 struct CadetPeerPath *path = GCC_get_path (cc, &len);
938
939 if (peer != GCPP_get_peer_at_offset (path, 0))
940 {
941 /* received ACK from unexpected direction, ignore! */
942 GNUNET_break_op (0);
943 return;
944 }
945 LOG (GNUNET_ERROR_TYPE_DEBUG,
946 "Received CONNECTION_CREATE_ACK for connection %s.\n",
947 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
948 GCC_handle_connection_create_ack (cc);
949 return;
950 }
951
952 /* We're just an intermediary peer, route the message along its path */
953 route_message (peer,
954 &msg->cid,
955 &msg->header,
956 GNUNET_MQ_PRIO_CRITICAL_CONTROL | GNUNET_MQ_PREF_LOW_LATENCY);
957}
958
959
960/**
961 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN
962 *
963 * @param cls Closure (CadetPeer for neighbor that sent the message).
964 * @param msg Message itself.
965 * @deprecated duplicate logic with #handle_destroy(); dedup!
966 */
967static void
968handle_connection_broken (
969 void *cls,
970 const struct GNUNET_CADET_ConnectionBrokenMessage *msg)
971{
972 struct CadetPeer *peer = cls;
973 struct CadetConnection *cc;
974 struct CadetRoute *route;
975
976 /* First, check if message belongs to a connection that ends here. */
977 cc = GCC_lookup (&msg->cid);
978 if (NULL != cc)
979 {
980 /* verify message came from the right direction */
981 unsigned int len;
982 struct CadetPeerPath *path = GCC_get_path (cc, &len);
983
984 if (peer != GCPP_get_peer_at_offset (path, 0))
985 {
986 /* received message from unexpected direction, ignore! */
987 GNUNET_break_op (0);
988 return;
989 }
990 LOG (GNUNET_ERROR_TYPE_DEBUG,
991 "Received CONNECTION_BROKEN for connection %s. Destroying it.\n",
992 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
993 GCC_destroy_without_core (cc);
994
995 /* FIXME: also destroy the path up to the specified link! */
996 return;
997 }
998
999 /* We're just an intermediary peer, route the message along its path */
1000 route_message (peer,
1001 &msg->cid,
1002 &msg->header,
1003 GNUNET_MQ_PREF_LOW_LATENCY | GNUNET_MQ_PRIO_CRITICAL_CONTROL);
1004 route = get_route (&msg->cid);
1005 if (NULL != route)
1006 destroy_route (route);
1007 /* FIXME: also destroy paths we MAY have up to the specified link! */
1008}
1009
1010
1011/**
1012 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY
1013 *
1014 * @param cls Closure (CadetPeer for neighbor that sent the message).
1015 * @param msg Message itself.
1016 */
1017static void
1018handle_connection_destroy (
1019 void *cls,
1020 const struct GNUNET_CADET_ConnectionDestroyMessage *msg)
1021{
1022 struct CadetPeer *peer = cls;
1023 struct CadetConnection *cc;
1024 struct CadetRoute *route;
1025
1026 /* First, check if message belongs to a connection that ends here. */
1027 cc = GCC_lookup (&msg->cid);
1028 if (NULL != cc)
1029 {
1030 /* verify message came from the right direction */
1031 unsigned int len;
1032 struct CadetPeerPath *path = GCC_get_path (cc, &len);
1033
1034 if (peer != GCPP_get_peer_at_offset (path, 0))
1035 {
1036 /* received message from unexpected direction, ignore! */
1037 GNUNET_break_op (0);
1038 return;
1039 }
1040 LOG (GNUNET_ERROR_TYPE_DEBUG,
1041 "Received CONNECTION_DESTROY for connection %s. Destroying connection.\n",
1042 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
1043
1044 GCC_destroy_without_core (cc);
1045 return;
1046 }
1047
1048 /* We're just an intermediary peer, route the message along its path */
1049 LOG (GNUNET_ERROR_TYPE_DEBUG,
1050 "Received CONNECTION_DESTROY for connection %s. Destroying route.\n",
1051 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
1052 route_message (peer,
1053 &msg->cid,
1054 &msg->header,
1055 GNUNET_MQ_PREF_LOW_LATENCY | GNUNET_MQ_PRIO_CRITICAL_CONTROL);
1056 route = get_route (&msg->cid);
1057 if (NULL != route)
1058 destroy_route (route);
1059}
1060
1061
1062/**
1063 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX
1064 *
1065 * @param cls Closure (CadetPeer for neighbor that sent the message).
1066 * @param msg Message itself.
1067 */
1068static void
1069handle_tunnel_kx (void *cls,
1070 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
1071{
1072 struct CadetPeer *peer = cls;
1073 struct CadetConnection *cc;
1074
1075 /* First, check if message belongs to a connection that ends here. */
1076 LOG (GNUNET_ERROR_TYPE_DEBUG,
1077 "Routing KX with ephemeral %s on CID %s\n",
1078 GNUNET_e2s (&msg->ephemeral_key),
1079 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
1080
1081
1082 cc = GCC_lookup (&msg->cid);
1083 if (NULL != cc)
1084 {
1085 /* verify message came from the right direction */
1086 unsigned int len;
1087 struct CadetPeerPath *path = GCC_get_path (cc, &len);
1088
1089 if (peer != GCPP_get_peer_at_offset (path, 0))
1090 {
1091 /* received message from unexpected direction, ignore! */
1092 GNUNET_break_op (0);
1093 return;
1094 }
1095 GCC_handle_kx (cc, msg);
1096 return;
1097 }
1098
1099 /* We're just an intermediary peer, route the message along its path */
1100 route_message (peer,
1101 &msg->cid,
1102 &msg->header,
1103 GNUNET_MQ_PRIO_CRITICAL_CONTROL | GNUNET_MQ_PREF_LOW_LATENCY);
1104}
1105
1106
1107/**
1108 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX_AUTH
1109 *
1110 * @param cls Closure (CadetPeer for neighbor that sent the message).
1111 * @param msg Message itself.
1112 */
1113static void
1114handle_tunnel_kx_auth (
1115 void *cls,
1116 const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg)
1117{
1118 struct CadetPeer *peer = cls;
1119 struct CadetConnection *cc;
1120
1121 /* First, check if message belongs to a connection that ends here. */
1122 cc = GCC_lookup (&msg->kx.cid);
1123 if (NULL != cc)
1124 {
1125 /* verify message came from the right direction */
1126 unsigned int len;
1127 struct CadetPeerPath *path = GCC_get_path (cc, &len);
1128
1129 if (peer != GCPP_get_peer_at_offset (path, 0))
1130 {
1131 /* received message from unexpected direction, ignore! */
1132 GNUNET_break_op (0);
1133 return;
1134 }
1135 GCC_handle_kx_auth (cc, msg);
1136 return;
1137 }
1138
1139 /* We're just an intermediary peer, route the message along its path */
1140 route_message (peer,
1141 &msg->kx.cid,
1142 &msg->kx.header,
1143 GNUNET_MQ_PRIO_CRITICAL_CONTROL | GNUNET_MQ_PREF_LOW_LATENCY);
1144}
1145
1146
1147/**
1148 * Check if the encrypted message has the appropriate size.
1149 *
1150 * @param cls Closure (unused).
1151 * @param msg Message to check.
1152 *
1153 * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
1154 */
1155static int
1156check_tunnel_encrypted (void *cls,
1157 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
1158{
1159 return GNUNET_YES;
1160}
1161
1162
1163/**
1164 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED.
1165 *
1166 * @param cls Closure (CadetPeer for neighbor that sent the message).
1167 * @param msg Message itself.
1168 */
1169static void
1170handle_tunnel_encrypted (void *cls,
1171 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
1172{
1173 struct CadetPeer *peer = cls;
1174 struct CadetConnection *cc;
1175
1176 /* First, check if message belongs to a connection that ends here. */
1177 cc = GCC_lookup (&msg->cid);
1178 if (NULL != cc)
1179 {
1180 /* verify message came from the right direction */
1181 unsigned int len;
1182 struct CadetPeerPath *path = GCC_get_path (cc, &len);
1183
1184 if (peer != GCPP_get_peer_at_offset (path, 0))
1185 {
1186 /* received message from unexpected direction, ignore! */
1187 GNUNET_break_op (0);
1188 return;
1189 }
1190 GCC_handle_encrypted (cc, msg);
1191 return;
1192 }
1193 /* We're just an intermediary peer, route the message along its path */
1194 route_message (peer, &msg->cid, &msg->header, GNUNET_MQ_PRIO_BEST_EFFORT);
1195}
1196
1197
1198/**
1199 * Function called after #GNUNET_CORE_connect has succeeded (or failed
1200 * for good). Note that the private key of the peer is intentionally
1201 * not exposed here; if you need it, your process should try to read
1202 * the private key file directly (which should work if you are
1203 * authorized...). Implementations of this function must not call
1204 * #GNUNET_CORE_disconnect (other than by scheduling a new task to
1205 * do this later).
1206 *
1207 * @param cls closure
1208 * @param my_identity ID of this peer, NULL if we failed
1209 */
1210static void
1211core_init_cb (void *cls, const struct GNUNET_PeerIdentity *my_identity)
1212{
1213 if (NULL == my_identity)
1214 {
1215 GNUNET_break (0);
1216 return;
1217 }
1218 GNUNET_break (0 == GNUNET_memcmp (my_identity, &my_full_id));
1219}
1220
1221
1222/**
1223 * Method called whenever a given peer connects.
1224 *
1225 * @param cls closure
1226 * @param peer peer identity this notification is about
1227 */
1228static void *
1229core_connect_cb (void *cls,
1230 const struct GNUNET_PeerIdentity *peer,
1231 struct GNUNET_MQ_Handle *mq)
1232{
1233 struct CadetPeer *cp;
1234
1235 LOG (GNUNET_ERROR_TYPE_DEBUG,
1236 "CORE connection to peer %s was established.\n",
1237 GNUNET_i2s (peer));
1238 cp = GCP_get (peer, GNUNET_YES);
1239 GCP_set_mq (cp, mq);
1240 return cp;
1241}
1242
1243
1244/**
1245 * Method called whenever a peer disconnects.
1246 *
1247 * @param cls closure
1248 * @param peer peer identity this notification is about
1249 */
1250static void
1251core_disconnect_cb (void *cls,
1252 const struct GNUNET_PeerIdentity *peer,
1253 void *peer_cls)
1254{
1255 struct CadetPeer *cp = peer_cls;
1256
1257 LOG (GNUNET_ERROR_TYPE_DEBUG,
1258 "CORE connection to peer %s went down.\n",
1259 GNUNET_i2s (peer));
1260 GCP_set_mq (cp, NULL);
1261}
1262
1263
1264/**
1265 * Initialize the CORE subsystem.
1266 *
1267 * @param c Configuration.
1268 */
1269void
1270GCO_init (const struct GNUNET_CONFIGURATION_Handle *c)
1271{
1272 struct GNUNET_MQ_MessageHandler handlers[] =
1273 { GNUNET_MQ_hd_var_size (connection_create,
1274 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE,
1275 struct GNUNET_CADET_ConnectionCreateMessage,
1276 NULL),
1277 GNUNET_MQ_hd_fixed_size (connection_create_ack,
1278 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK,
1279 struct GNUNET_CADET_ConnectionCreateAckMessage,
1280 NULL),
1281 GNUNET_MQ_hd_fixed_size (connection_broken,
1282 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN,
1283 struct GNUNET_CADET_ConnectionBrokenMessage,
1284 NULL),
1285 GNUNET_MQ_hd_fixed_size (connection_destroy,
1286 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY,
1287 struct GNUNET_CADET_ConnectionDestroyMessage,
1288 NULL),
1289 GNUNET_MQ_hd_fixed_size (tunnel_kx,
1290 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX,
1291 struct GNUNET_CADET_TunnelKeyExchangeMessage,
1292 NULL),
1293 GNUNET_MQ_hd_fixed_size (tunnel_kx_auth,
1294 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX_AUTH,
1295 struct GNUNET_CADET_TunnelKeyExchangeAuthMessage,
1296 NULL),
1297 GNUNET_MQ_hd_var_size (tunnel_encrypted,
1298 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED,
1299 struct GNUNET_CADET_TunnelEncryptedMessage,
1300 NULL),
1301 GNUNET_MQ_handler_end () };
1302
1303 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (c,
1304 "CADET",
1305 "MAX_ROUTES",
1306 &max_routes))
1307 max_routes = 5000;
1308 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (c,
1309 "CADET",
1310 "MAX_MSGS_QUEUE",
1311 &max_buffers))
1312 max_buffers = 10000;
1313 routes = GNUNET_CONTAINER_multishortmap_create (1024, GNUNET_NO);
1314 route_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
1315 core = GNUNET_CORE_connect (c,
1316 NULL,
1317 &core_init_cb,
1318 &core_connect_cb,
1319 &core_disconnect_cb,
1320 handlers);
1321}
1322
1323
1324/**
1325 * Shut down the CORE subsystem.
1326 */
1327void
1328GCO_shutdown ()
1329{
1330 if (NULL != core)
1331 {
1332 GNUNET_CORE_disconnect (core);
1333 core = NULL;
1334 }
1335 GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (routes));
1336 GNUNET_CONTAINER_multishortmap_destroy (routes);
1337 routes = NULL;
1338 GNUNET_CONTAINER_heap_destroy (route_heap);
1339 route_heap = NULL;
1340 if (NULL != timeout_task)
1341 {
1342 GNUNET_SCHEDULER_cancel (timeout_task);
1343 timeout_task = NULL;
1344 }
1345}
1346
1347
1348/* end of gnunet-cadet-service_core.c */
diff --git a/src/cadet/gnunet-service-cadet_core.h b/src/cadet/gnunet-service-cadet_core.h
deleted file mode 100644
index 3438dcb31..000000000
--- a/src/cadet/gnunet-service-cadet_core.h
+++ /dev/null
@@ -1,69 +0,0 @@
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/cadet/gnunet-service-cadet_dht.c b/src/cadet/gnunet-service-cadet_dht.c
deleted file mode 100644
index 6caac474d..000000000
--- a/src/cadet/gnunet-service-cadet_dht.c
+++ /dev/null
@@ -1,353 +0,0 @@
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
58/**
59 * Handle for DHT searches.
60 */
61struct GCD_search_handle
62{
63 /**
64 * DHT_GET handle.
65 */
66 struct GNUNET_DHT_GetHandle *dhtget;
67};
68
69
70/**
71 * Handle to use DHT.
72 */
73static struct GNUNET_DHT_Handle *dht_handle;
74
75/**
76 * How often to PUT own ID in the DHT.
77 */
78static struct GNUNET_TIME_Relative id_announce_time;
79
80/**
81 * DHT replication level, see DHT API: #GNUNET_DHT_get_start(), #GNUNET_DHT_put().
82 */
83static unsigned long long dht_replication_level;
84
85/**
86 * Task to periodically announce itself in the network.
87 */
88static struct GNUNET_SCHEDULER_Task *announce_id_task;
89
90/**
91 * Delay for the next ID announce.
92 */
93static struct GNUNET_TIME_Relative announce_delay;
94
95
96/**
97 * Function to process paths received for a new peer addition. The recorded
98 * paths form the initial tunnel, which can be optimized later.
99 * Called on each result obtained for the DHT search.
100 *
101 * @param cls closure
102 * @param exp when will this value expire
103 * @param key key of the result
104 * @param get_path path of the get request
105 * @param get_path_length length of @a get_path
106 * @param put_path path of the put request
107 * @param put_path_length length of the @a put_path
108 * @param type type of the result
109 * @param size number of bytes in data
110 * @param data pointer to the result data
111 */
112static void
113dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp,
114 const struct GNUNET_HashCode *key,
115 const struct GNUNET_PeerIdentity *get_path,
116 unsigned int get_path_length,
117 const struct GNUNET_PeerIdentity *put_path,
118 unsigned int put_path_length,
119 enum GNUNET_BLOCK_Type type,
120 size_t size,
121 const void *data)
122{
123 const struct GNUNET_HELLO_Message *hello = data;
124 struct CadetPeer *peer;
125
126 GCPP_try_path_from_dht (get_path,
127 get_path_length,
128 put_path,
129 put_path_length);
130 if ((size >= sizeof(struct GNUNET_HELLO_Message)) &&
131 (ntohs (hello->header.size) == size) &&
132 (size == GNUNET_HELLO_size (hello)))
133 {
134 peer = GCP_get (&put_path[0],
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 }
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_HELLO_Message *hello;
155 size_t size;
156 struct GNUNET_TIME_Absolute expiration;
157 struct GNUNET_TIME_Relative next_put;
158
159 hello = GCH_get_mine ();
160 size = (NULL != hello) ? GNUNET_HELLO_size (hello) : 0;
161 if (0 == size)
162 {
163 expiration = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
164 announce_delay);
165 announce_delay = GNUNET_TIME_STD_BACKOFF (announce_delay);
166 }
167 else
168 {
169 expiration = GNUNET_HELLO_get_last_expiration (hello);
170 announce_delay = GNUNET_TIME_UNIT_SECONDS;
171 }
172
173 /* Call again in id_announce_time, unless HELLO expires first,
174 * but wait at least 1s. */
175 next_put
176 = GNUNET_TIME_absolute_get_remaining (expiration);
177 next_put
178 = GNUNET_TIME_relative_min (next_put,
179 id_announce_time);
180 next_put
181 = GNUNET_TIME_relative_max (next_put,
182 GNUNET_TIME_UNIT_SECONDS);
183 announce_id_task
184 = GNUNET_SCHEDULER_add_delayed (next_put,
185 &announce_id,
186 cls);
187 GNUNET_STATISTICS_update (stats,
188 "# DHT announce",
189 1,
190 GNUNET_NO);
191 memset (&phash,
192 0,
193 sizeof(phash));
194 GNUNET_memcpy (&phash,
195 &my_full_id,
196 sizeof(my_full_id));
197 LOG (GNUNET_ERROR_TYPE_DEBUG,
198 "Announcing my HELLO (%lu bytes) in the DHT\n",
199 (unsigned long) size);
200 GNUNET_DHT_put (dht_handle, /* DHT handle */
201 &phash, /* Key to use */
202 dht_replication_level, /* Replication level */
203 GNUNET_DHT_RO_RECORD_ROUTE
204 | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, /* DHT options */
205 GNUNET_BLOCK_TYPE_DHT_HELLO, /* Block type */
206 size, /* Size of the data */
207 (const char *) hello, /* Data itself */
208 expiration, /* Data expiration */
209 NULL, /* Continuation */
210 NULL); /* Continuation closure */
211}
212
213
214/**
215 * Function called by the HELLO subsystem whenever OUR hello
216 * changes. Re-triggers the DHT PUT immediately.
217 */
218void
219GCD_hello_update ()
220{
221 if (NULL == announce_id_task)
222 return; /* too early */
223 GNUNET_SCHEDULER_cancel (announce_id_task);
224 announce_id_task
225 = GNUNET_SCHEDULER_add_delayed (CHANGE_DELAY,
226 &announce_id,
227 NULL);
228}
229
230
231/**
232 * Initialize the DHT subsystem.
233 *
234 * @param c Configuration.
235 */
236void
237GCD_init (const struct GNUNET_CONFIGURATION_Handle *c)
238{
239 if (GNUNET_OK !=
240 GNUNET_CONFIGURATION_get_value_number (c,
241 "CADET",
242 "DHT_REPLICATION_LEVEL",
243 &dht_replication_level))
244 {
245 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
246 "CADET",
247 "DHT_REPLICATION_LEVEL",
248 "USING DEFAULT");
249 dht_replication_level = 3;
250 }
251
252 if (GNUNET_OK !=
253 GNUNET_CONFIGURATION_get_value_time (c,
254 "CADET",
255 "ID_ANNOUNCE_TIME",
256 &id_announce_time))
257 {
258 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
259 "CADET",
260 "ID_ANNOUNCE_TIME",
261 "MISSING");
262 GNUNET_SCHEDULER_shutdown ();
263 return;
264 }
265
266 dht_handle = GNUNET_DHT_connect (c,
267 64);
268 GNUNET_break (NULL != dht_handle);
269 announce_delay = GNUNET_TIME_UNIT_SECONDS;
270 announce_id_task = GNUNET_SCHEDULER_add_delayed (STARTUP_DELAY,
271 &announce_id,
272 NULL);
273}
274
275
276/**
277 * Shut down the DHT subsystem.
278 */
279void
280GCD_shutdown (void)
281{
282 if (NULL != dht_handle)
283 {
284 GNUNET_DHT_disconnect (dht_handle);
285 dht_handle = NULL;
286 }
287 if (NULL != announce_id_task)
288 {
289 GNUNET_SCHEDULER_cancel (announce_id_task);
290 announce_id_task = NULL;
291 }
292}
293
294
295/**
296 * Search DHT for paths to @a peeR_id
297 *
298 * @param peer_id peer to search for
299 * @return handle to abort search
300 */
301struct GCD_search_handle *
302GCD_search (const struct GNUNET_PeerIdentity *peer_id)
303{
304 struct GNUNET_HashCode phash;
305 struct GCD_search_handle *h;
306
307 GNUNET_STATISTICS_update (stats,
308 "# DHT search",
309 1,
310 GNUNET_NO);
311 memset (&phash,
312 0,
313 sizeof(phash));
314 GNUNET_memcpy (&phash,
315 peer_id,
316 sizeof(*peer_id));
317
318 h = GNUNET_new (struct GCD_search_handle);
319 h->dhtget = GNUNET_DHT_get_start (dht_handle, /* handle */
320 GNUNET_BLOCK_TYPE_DHT_HELLO, /* type */
321 &phash, /* key to search */
322 dht_replication_level, /* replication level */
323 GNUNET_DHT_RO_RECORD_ROUTE
324 | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
325 NULL, /* xquery */
326 0, /* xquery bits */
327 &dht_get_id_handler,
328 h);
329 LOG (GNUNET_ERROR_TYPE_DEBUG,
330 "Starting DHT GET for peer %s (%p)\n",
331 GNUNET_i2s (peer_id),
332 h);
333 return h;
334}
335
336
337/**
338 * Stop DHT search started with #GCD_search().
339 *
340 * @param h handle to search to stop
341 */
342void
343GCD_search_stop (struct GCD_search_handle *h)
344{
345 LOG (GNUNET_ERROR_TYPE_DEBUG,
346 "Stopping DHT GET %p\n",
347 h);
348 GNUNET_DHT_get_stop (h->dhtget);
349 GNUNET_free (h);
350}
351
352
353/* end of gnunet-service-cadet_dht.c */
diff --git a/src/cadet/gnunet-service-cadet_dht.h b/src/cadet/gnunet-service-cadet_dht.h
deleted file mode 100644
index bcc27f5d2..000000000
--- a/src/cadet/gnunet-service-cadet_dht.h
+++ /dev/null
@@ -1,100 +0,0 @@
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/cadet/gnunet-service-cadet_hello.c b/src/cadet/gnunet-service-cadet_hello.c
deleted file mode 100644
index c7857032b..000000000
--- a/src/cadet/gnunet-service-cadet_hello.c
+++ /dev/null
@@ -1,150 +0,0 @@
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 "platform.h"
28#include "gnunet_util_lib.h"
29
30#include "gnunet_statistics_service.h"
31#include "gnunet_peerinfo_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_HELLO_Message *mine;
44
45/**
46 * Handle to peerinfo service.
47 */
48static struct GNUNET_PEERINFO_Handle *peerinfo;
49
50/**
51 * Iterator context.
52 */
53static struct GNUNET_PEERINFO_NotifyContext *nc;
54
55
56/**
57 * Process each hello message received from peerinfo.
58 *
59 * @param cls Closure (unused).
60 * @param peer Identity of the peer.
61 * @param hello Hello of the peer.
62 * @param err_msg Error message.
63 */
64static void
65got_hello (void *cls,
66 const struct GNUNET_PeerIdentity *id,
67 const struct GNUNET_HELLO_Message *hello,
68 const char *err_msg)
69{
70 struct CadetPeer *peer;
71
72 if ((NULL == id) ||
73 (NULL == hello))
74 return;
75 if (0 == GNUNET_memcmp (id,
76 &my_full_id))
77 {
78 GNUNET_free (mine);
79 mine = (struct GNUNET_HELLO_Message *) GNUNET_copy_message (&hello->header);
80 GCD_hello_update ();
81 return;
82 }
83
84 LOG (GNUNET_ERROR_TYPE_DEBUG,
85 "Hello for %s (%d bytes), expires on %s\n",
86 GNUNET_i2s (id),
87 GNUNET_HELLO_size (hello),
88 GNUNET_STRINGS_absolute_time_to_string (
89 GNUNET_HELLO_get_last_expiration (hello)));
90 peer = GCP_get (id,
91 GNUNET_YES);
92 GCP_set_hello (peer,
93 hello);
94}
95
96
97/**
98 * Initialize the hello subsystem.
99 *
100 * @param c Configuration.
101 */
102void
103GCH_init (const struct GNUNET_CONFIGURATION_Handle *c)
104{
105 GNUNET_assert (NULL == nc);
106 peerinfo = GNUNET_PEERINFO_connect (c);
107 nc = GNUNET_PEERINFO_notify (c,
108 GNUNET_NO,
109 &got_hello,
110 NULL);
111}
112
113
114/**
115 * Shut down the hello subsystem.
116 */
117void
118GCH_shutdown ()
119{
120 if (NULL != nc)
121 {
122 GNUNET_PEERINFO_notify_cancel (nc);
123 nc = NULL;
124 }
125 if (NULL != peerinfo)
126 {
127 GNUNET_PEERINFO_disconnect (peerinfo);
128 peerinfo = NULL;
129 }
130 if (NULL != mine)
131 {
132 GNUNET_free (mine);
133 mine = NULL;
134 }
135}
136
137
138/**
139 * Get own hello message.
140 *
141 * @return Own hello message.
142 */
143const struct GNUNET_HELLO_Message *
144GCH_get_mine (void)
145{
146 return mine;
147}
148
149
150/* end of gnunet-service-cadet-new_hello.c */
diff --git a/src/cadet/gnunet-service-cadet_hello.h b/src/cadet/gnunet-service-cadet_hello.h
deleted file mode 100644
index 2cb444b4a..000000000
--- a/src/cadet/gnunet-service-cadet_hello.h
+++ /dev/null
@@ -1,80 +0,0 @@
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_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_HELLO_Message *
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/cadet/gnunet-service-cadet_paths.c b/src/cadet/gnunet-service-cadet_paths.c
deleted file mode 100644
index 2da4e2708..000000000
--- a/src/cadet/gnunet-service-cadet_paths.c
+++ /dev/null
@@ -1,785 +0,0 @@
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_PeerIdentity *get_path,
472 unsigned int get_path_length,
473 const struct GNUNET_PeerIdentity *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]
494 : &put_path[get_path_length + put_path_length - off - 1];
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
597/**
598 * We got an incoming connection, obtain the corresponding path.
599 *
600 * @param path_length number of segments on the @a path
601 * @param pids path through the network, in reverse order (we are at the end at index @a path_length)
602 * @return corresponding path object
603 */
604struct CadetPeerPath *
605GCPP_get_path_from_route (unsigned int path_length,
606 const struct GNUNET_PeerIdentity *pids)
607{
608 struct CheckMatchContext cm_ctx;
609 struct CadetPeer *cpath[path_length];
610 struct CadetPeerPath *path;
611
612 /* precompute inverted 'cpath' so we can avoid doing the lookups and
613 have the correct order */
614 for (unsigned int off = 0; off < path_length; off++)
615 cpath[off] = GCP_get (&pids[path_length - 1 - off],
616 GNUNET_YES);
617
618 /* First figure out if this path is a subset of an existing path, an
619 extension of an existing path, or a new path. */
620 cm_ctx.cpath = cpath;
621 cm_ctx.cpath_length = path_length;
622 cm_ctx.match = NULL;
623 for (int i = path_length - 1; i >= 0; i--)
624 {
625 GCP_iterate_paths_at (cpath[i],
626 (unsigned int) i,
627 &check_match,
628 &cm_ctx);
629 if (NULL != cm_ctx.match)
630 {
631 if (i == path_length - 1)
632 {
633 /* Existing path includes this one, return the match! */
634 LOG (GNUNET_ERROR_TYPE_DEBUG,
635 "Returning existing path %s as inverse for incoming connection\n",
636 GCPP_2s (cm_ctx.match));
637 return cm_ctx.match;
638 }
639 if (cm_ctx.match->entries_length == i + 1)
640 {
641 /* Existing path ends in the middle of new path, extend it! */
642 LOG (GNUNET_ERROR_TYPE_DEBUG,
643 "Extending existing path %s to create inverse for incoming connection\n",
644 GCPP_2s (cm_ctx.match));
645 extend_path (cm_ctx.match,
646 &cpath[i + 1],
647 path_length - i - 1,
648 GNUNET_YES);
649 /* Check that extension was successful */
650 GNUNET_assert (cm_ctx.match->entries_length == path_length);
651 return cm_ctx.match;
652 }
653 /* Eh, we found a match but couldn't use it? Something is wrong. */
654 GNUNET_break (0);
655 }
656 }
657
658 /* No match at all, create completely new path */
659 path = GNUNET_new (struct CadetPeerPath);
660 path->entries_length = path_length;
661 path->entries = GNUNET_new_array (path->entries_length,
662 struct CadetPeerPathEntry *);
663 for (int i = path_length - 1; i >= 0; i--)
664 {
665 struct CadetPeerPathEntry *entry = GNUNET_new (struct CadetPeerPathEntry);
666
667 path->entries[i] = entry;
668 entry->peer = cpath[i];
669 entry->path = path;
670 }
671 for (int i = path_length - 1; i >= 0; i--)
672 {
673 struct CadetPeerPathEntry *entry = path->entries[i];
674
675 GCP_path_entry_add (entry->peer,
676 entry,
677 i);
678 }
679 recalculate_path_desirability (path);
680 LOG (GNUNET_ERROR_TYPE_DEBUG,
681 "Created new path %s to create inverse for incoming connection\n",
682 GCPP_2s (path));
683 path->hn = GCP_attach_path (cpath[path_length - 1],
684 path,
685 path_length - 1,
686 GNUNET_YES);
687 return path;
688}
689
690
691/**
692 * Return the length of the path. Excludes one end of the
693 * path, so the loopback path has length 0.
694 *
695 * @param path path to return the length for
696 * @return number of peers on the path
697 */
698unsigned int
699GCPP_get_length (struct CadetPeerPath *path)
700{
701 return path->entries_length;
702}
703
704
705/**
706 * Find peer's offset on path.
707 *
708 * @param path path to search
709 * @param cp peer to look for
710 * @return offset of @a cp on @a path, or UINT_MAX if not found
711 */
712unsigned int
713GCPP_find_peer (struct CadetPeerPath *path,
714 struct CadetPeer *cp)
715{
716 for (unsigned int off = 0;
717 off < path->entries_length;
718 off++)
719 if (cp == GCPP_get_peer_at_offset (path,
720 off))
721 return off;
722 return UINT_MAX;
723}
724
725
726/**
727 * Obtain the peer at offset @a off in @a path.
728 *
729 * @param path peer path to inspect
730 * @param off offset to return, must be smaller than path length
731 * @return the peer at offset @a off
732 */
733struct CadetPeer *
734GCPP_get_peer_at_offset (struct CadetPeerPath *path,
735 unsigned int off)
736{
737 GNUNET_assert (off < path->entries_length);
738 return path->entries[off]->peer;
739}
740
741
742/**
743 * Convert a path to a human-readable string.
744 *
745 * @param path path to convert
746 * @return string, to be freed by caller (unlike other *_2s APIs!)
747 */
748const char *
749GCPP_2s (struct CadetPeerPath *path)
750{
751 static char buf[2048];
752 size_t off;
753 const unsigned int max_plen = (sizeof(buf) - 16) / 5 - 2; /* 5 characters per entry */
754
755 off = 0;
756 for (unsigned int i = 0;
757 i < path->entries_length;
758 i++)
759 {
760 if ((path->entries_length > max_plen) &&
761 (i == max_plen / 2))
762 off += GNUNET_snprintf (&buf[off],
763 sizeof(buf) - off,
764 "...-");
765 if ((path->entries_length > max_plen) &&
766 (i > max_plen / 2) &&
767 (i < path->entries_length - max_plen / 2))
768 continue;
769 off += GNUNET_snprintf (&buf[off],
770 sizeof(buf) - off,
771 "%s%s",
772 GNUNET_i2s (GCP_get_id (GCPP_get_peer_at_offset (
773 path,
774 i))),
775 (i == path->entries_length - 1) ? "" : "-");
776 }
777 GNUNET_snprintf (&buf[off],
778 sizeof(buf) - off,
779 "(%p)",
780 path);
781 return buf;
782}
783
784
785/* end of gnunet-service-cadet-new_paths.c */
diff --git a/src/cadet/gnunet-service-cadet_paths.h b/src/cadet/gnunet-service-cadet_paths.h
deleted file mode 100644
index 3961dd721..000000000
--- a/src/cadet/gnunet-service-cadet_paths.h
+++ /dev/null
@@ -1,181 +0,0 @@
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-service-cadet.h"
32
33/**
34 * Create a peer path based on the result of a DHT lookup. If we
35 * already know this path, or one that is longer, simply return NULL.
36 * Otherwise, we try to extend an existing path, or create a new one
37 * if applicable.
38 *
39 * @param get_path path of the get request
40 * @param get_path_length length of @a get_path
41 * @param put_path path of the put request
42 * @param put_path_length length of the @a put_path
43 */
44void
45GCPP_try_path_from_dht (const struct GNUNET_PeerIdentity *get_path,
46 unsigned int get_path_length,
47 const struct GNUNET_PeerIdentity *put_path,
48 unsigned int put_path_length);
49
50
51/**
52 * We got an incoming connection, obtain the corresponding path.
53 *
54 * @param path_length number of segments on the @a path
55 * @param path through the network, in reverse order (we are at the end!)
56 * @return corresponding path object
57 */
58struct CadetPeerPath *
59GCPP_get_path_from_route (unsigned int path_length,
60 const struct GNUNET_PeerIdentity *pids);
61
62
63/**
64 * Return the length of the path. Excludes one end of the
65 * path, so the loopback path has length 0.
66 *
67 * @param path path to return the length for
68 * @return number of peers on the path
69 */
70unsigned int
71GCPP_get_length (struct CadetPeerPath *path);
72
73
74/**
75 * Return connection to @a destination using @a path, or return
76 * NULL if no such connection exists.
77 *
78 * @param path path to traverse
79 * @param destination destination node to get to, must be on path
80 * @param off offset of @a destination on @a path
81 * @return NULL if we have no existing connection
82 * otherwise connection from us to @a destination via @a path
83 */
84struct CadetConnection *
85GCPP_get_connection (struct CadetPeerPath *path,
86 struct CadetPeer *destination,
87 unsigned int off);
88
89
90/**
91 * Notify @a path that it is used for connection @a cc
92 * which ends at the path's offset @a off.
93 *
94 * @param path the path to remember the @a cc
95 * @param off the offset where the @a cc ends
96 * @param cc the connection to remember
97 */
98void
99GCPP_add_connection (struct CadetPeerPath *path,
100 unsigned int off,
101 struct CadetConnection *cc);
102
103
104/**
105 * Notify @a path that it is no longer used for connection @a cc which
106 * ended at the path's offset @a off.
107 *
108 * @param path the path to forget the @a cc
109 * @param off the offset where the @a cc ended
110 * @param cc the connection to forget
111 */
112void
113GCPP_del_connection (struct CadetPeerPath *path,
114 unsigned int off,
115 struct CadetConnection *cc);
116
117
118/**
119 * Find peer's offset on path.
120 *
121 * @param path path to search
122 * @param cp peer to look for
123 * @return offset of @a cp on @a path, or UINT_MAX if not found
124 */
125unsigned int
126GCPP_find_peer (struct CadetPeerPath *path,
127 struct CadetPeer *cp);
128
129
130/**
131 * Return how much we like keeping the path. This is an aggregate
132 * score based on various factors, including the age of the path
133 * (older == better), and the value of this path to all of its adjacent
134 * peers. For example, long paths that end at a peer that we have no
135 * shorter way to reach are very desirable, while long paths that end
136 * at a peer for which we have a shorter way as well are much less
137 * desirable. Higher values indicate more valuable paths. The
138 * returned value should be used to decide which paths to remember.
139 *
140 * @param path path to return the length for
141 * @return desirability of the path, larger is more desirable
142 */
143GNUNET_CONTAINER_HeapCostType
144GCPP_get_desirability (const struct CadetPeerPath *path);
145
146
147/**
148 * The given peer @a cp used to own this @a path. However, it is no
149 * longer interested in maintaining it, so the path should be
150 * discarded or shortened (in case a previous peer on the path finds
151 * the path desirable).
152 *
153 * @param path the path that is being released
154 */
155void
156GCPP_release (struct CadetPeerPath *path);
157
158
159/**
160 * Obtain the peer at offset @a off in @a path.
161 *
162 * @param path peer path to inspect
163 * @param off offset to return, must be smaller than path length
164 * @return peer at offset @a off
165 */
166struct CadetPeer *
167GCPP_get_peer_at_offset (struct CadetPeerPath *path,
168 unsigned int off);
169
170
171/**
172 * Convert a path to a human-readable string.
173 *
174 * @param path path to convert
175 * @return string, statically allocated
176 */
177const char *
178GCPP_2s (struct CadetPeerPath *p);
179
180
181#endif
diff --git a/src/cadet/gnunet-service-cadet_peer.c b/src/cadet/gnunet-service-cadet_peer.c
deleted file mode 100644
index 2437a3e1b..000000000
--- a/src/cadet/gnunet-service-cadet_peer.c
+++ /dev/null
@@ -1,1609 +0,0 @@
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_lib.h"
37#include "gnunet_signatures.h"
38#include "gnunet_transport_service.h"
39#include "gnunet_ats_service.h"
40#include "gnunet_core_service.h"
41#include "gnunet_statistics_service.h"
42#include "gnunet-service-cadet_peer.h"
43#include "gnunet-service-cadet.h"
44#include "gnunet-service-cadet_connection.h"
45#include "gnunet-service-cadet_dht.h"
46#include "gnunet-service-cadet_paths.h"
47#include "gnunet-service-cadet_tunnels.h"
48
49
50#define LOG(level, ...) GNUNET_log_from (level, "cadet-per", __VA_ARGS__)
51
52
53/**
54 * How long do we wait until tearing down an idle peer?
55 */
56#define IDLE_PEER_TIMEOUT GNUNET_TIME_relative_multiply ( \
57 GNUNET_TIME_UNIT_MINUTES, 5)
58
59/**
60 * How long do we keep paths around if we no longer care about the peer?
61 */
62#define IDLE_PATH_TIMEOUT GNUNET_TIME_relative_multiply ( \
63 GNUNET_TIME_UNIT_MINUTES, 2)
64
65/**
66 * Queue size when we start dropping OOO messages.
67 */
68#define MAX_OOO_QUEUE_SIZE 100
69
70/**
71 * Data structure used to track whom we have to notify about changes
72 * to our message queue.
73 */
74struct GCP_MessageQueueManager
75{
76 /**
77 * Kept in a DLL.
78 */
79 struct GCP_MessageQueueManager *next;
80
81 /**
82 * Kept in a DLL.
83 */
84 struct GCP_MessageQueueManager *prev;
85
86 /**
87 * Function to call with updated message queue object.
88 */
89 GCP_MessageQueueNotificationCallback cb;
90
91 /**
92 * Closure for @e cb.
93 */
94 void *cb_cls;
95
96 /**
97 * The peer this is for.
98 */
99 struct CadetPeer *cp;
100
101 /**
102 * Envelope this manager would like to transmit once it is its turn.
103 */
104 struct GNUNET_MQ_Envelope *env;
105};
106
107
108/**
109 * Struct containing all information regarding a given peer
110 */
111struct CadetPeer
112{
113 /**
114 * ID of the peer
115 */
116 struct GNUNET_PeerIdentity pid;
117
118 /**
119 * Last time we heard from this peer (currently not used!)
120 */
121 struct GNUNET_TIME_Absolute last_connection_create;
122
123 /**
124 * Array of DLLs of paths traversing the peer, organized by the
125 * offset of the peer on the larger path.
126 */
127 struct CadetPeerPathEntry **path_heads;
128
129 /**
130 * Array of DLL of paths traversing the peer, organized by the
131 * offset of the peer on the larger path.
132 */
133 struct CadetPeerPathEntry **path_tails;
134
135 /**
136 * Notifications to call when @e core_mq changes.
137 */
138 struct GCP_MessageQueueManager *mqm_head;
139
140 /**
141 * Notifications to call when @e core_mq changes.
142 */
143 struct GCP_MessageQueueManager *mqm_tail;
144
145 /**
146 * Pointer to first "ready" entry in @e mqm_head.
147 */
148 struct GCP_MessageQueueManager *mqm_ready_ptr;
149
150 /**
151 * MIN-heap of paths owned by this peer (they also end at this
152 * peer). Ordered by desirability.
153 */
154 struct GNUNET_CONTAINER_Heap *path_heap;
155
156 /**
157 * Handle to stop the DHT search for paths to this peer
158 */
159 struct GCD_search_handle *search_h;
160
161 /**
162 * Task to clean up @e path_heap asynchronously.
163 */
164 struct GNUNET_SCHEDULER_Task *heap_cleanup_task;
165
166 /**
167 * Task to destroy this entry.
168 */
169 struct GNUNET_SCHEDULER_Task *destroy_task;
170
171 /**
172 * Tunnel to this peer, if any.
173 */
174 struct CadetTunnel *t;
175
176 /**
177 * Connections that go through this peer; indexed by tid.
178 */
179 struct GNUNET_CONTAINER_MultiShortmap *connections;
180
181 /**
182 * Handle for core transmissions.
183 */
184 struct GNUNET_MQ_Handle *core_mq;
185
186 /**
187 * Hello message of the peer.
188 */
189 struct GNUNET_HELLO_Message *hello;
190
191 /**
192 * Handle to us offering the HELLO to the transport.
193 */
194 struct GNUNET_TRANSPORT_OfferHelloHandle *hello_offer;
195
196 /**
197 * Handle to our ATS request asking ATS to suggest an address
198 * to TRANSPORT for this peer (to establish a direct link).
199 */
200 struct GNUNET_ATS_ConnectivitySuggestHandle *connectivity_suggestion;
201
202 /**
203 * How many messages are in the queue to this peer.
204 */
205 unsigned int queue_n;
206
207 /**
208 * How many paths do we have to this peer (in all @e path_heads DLLs combined).
209 */
210 unsigned int num_paths;
211
212 /**
213 * Sum over all of the offsets of all of the paths in the @a path_heads DLLs.
214 * Used to speed-up @GCP_get_desirability_of_path() calculation.
215 */
216 unsigned int off_sum;
217
218 /**
219 * Number of message queue managers of this peer that have a message in waiting.
220 *
221 * Used to quickly see if we need to bother scanning the @e msm_head DLL.
222 * TODO: could be replaced by another DLL that would then allow us to avoid
223 * the O(n)-scan of the DLL for ready entries!
224 */
225 unsigned int mqm_ready_counter;
226
227 /**
228 * Current length of the @e path_heads and @path_tails arrays.
229 * The arrays should be grown as needed.
230 */
231 unsigned int path_dll_length;
232};
233
234
235/**
236 * Get the static string for a peer ID.
237 *
238 * @param cp Peer.
239 * @return Static string for it's ID.
240 */
241const char *
242GCP_2s (const struct CadetPeer *cp)
243{
244 static char buf[5];
245 char *ret;
246
247 if ((NULL == cp) ||
248 (GNUNET_YES == GNUNET_is_zero (&cp->pid.public_key)))
249 return "NULL";
250
251 ret = GNUNET_CRYPTO_eddsa_public_key_to_string (&cp->pid.public_key);
252 if (NULL == ret)
253 return "NULL";
254
255 GNUNET_strlcpy (buf,
256 ret,
257 sizeof(buf));
258 GNUNET_free (ret);
259 return buf;
260}
261
262
263/**
264 * Calculate how desirable a path is for @a cp if @a cp
265 * is at offset @a off.
266 *
267 * The 'desirability_table.c' program can be used to compute a list of
268 * sample outputs for different scenarios. Basically, we score paths
269 * lower if there are many alternatives, and higher if they are
270 * shorter than average, and very high if they are much shorter than
271 * average and without many alternatives.
272 *
273 * @param cp a peer reachable via a path
274 * @param off offset of @a cp in the path
275 * @return score how useful a path is to reach @a cp,
276 * positive scores mean path is more desirable
277 */
278double
279GCP_get_desirability_of_path (struct CadetPeer *cp,
280 unsigned int off)
281{
282 unsigned int num_alts = cp->num_paths;
283 unsigned int off_sum;
284 double avg_sum;
285 double path_delta;
286 double weight_alts;
287
288 GNUNET_assert (num_alts >= 1); /* 'path' should be in there! */
289 GNUNET_assert (0 != cp->path_dll_length);
290
291 /* We maintain 'off_sum' in 'peer' and thereby
292 avoid the SLOW recalculation each time. Kept here
293 just to document what is going on. */
294#if SLOW
295 off_sum = 0;
296 for (unsigned int j = 0; j < cp->path_dll_length; j++)
297 for (struct CadetPeerPathEntry *pe = cp->path_heads[j];
298 NULL != pe;
299 pe = pe->next)
300 off_sum += j;
301 GNUNET_assert (off_sum == cp->off_sum);
302#else
303 off_sum = cp->off_sum;
304#endif
305 avg_sum = off_sum * 1.0 / cp->path_dll_length;
306 path_delta = off - avg_sum;
307 /* path_delta positive: path off of peer above average (bad path for peer),
308 path_delta negative: path off of peer below average (good path for peer) */
309 if (path_delta <= -1.0)
310 weight_alts = -num_alts / path_delta; /* discount alternative paths */
311 else if (path_delta >= 1.0)
312 weight_alts = num_alts * path_delta; /* overcount alternative paths */
313 else
314 weight_alts = num_alts; /* count alternative paths normally */
315
316
317 /* off+1: long paths are generally harder to find and thus count
318 a bit more as they get longer. However, above-average paths
319 still need to count less, hence the squaring of that factor. */
320 return (off + 1.0) / (weight_alts * weight_alts);
321}
322
323
324/**
325 * This peer is no longer be needed, clean it up now.
326 *
327 * @param cls peer to clean up
328 */
329static void
330destroy_peer (void *cls)
331{
332 struct CadetPeer *cp = cls;
333
334 LOG (GNUNET_ERROR_TYPE_DEBUG,
335 "Destroying state about peer %s\n",
336 GCP_2s (cp));
337 cp->destroy_task = NULL;
338 GNUNET_assert (NULL == cp->t);
339 GNUNET_assert (NULL == cp->core_mq);
340 GNUNET_assert (0 == cp->num_paths);
341 for (unsigned int i = 0; i < cp->path_dll_length; i++)
342 GNUNET_assert (NULL == cp->path_heads[i]);
343 GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (cp->connections));
344 GNUNET_assert (GNUNET_YES ==
345 GNUNET_CONTAINER_multipeermap_remove (peers,
346 &cp->pid,
347 cp));
348 GNUNET_free (cp->path_heads);
349 GNUNET_free (cp->path_tails);
350 cp->path_dll_length = 0;
351 if (NULL != cp->search_h)
352 {
353 GCD_search_stop (cp->search_h);
354 cp->search_h = NULL;
355 }
356 /* FIXME: clean up search_delayedXXX! */
357
358 if (NULL != cp->hello_offer)
359 {
360 GNUNET_TRANSPORT_offer_hello_cancel (cp->hello_offer);
361 cp->hello_offer = NULL;
362 }
363 if (NULL != cp->connectivity_suggestion)
364 {
365 GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
366 cp->connectivity_suggestion = NULL;
367 }
368 GNUNET_CONTAINER_multishortmap_destroy (cp->connections);
369 if (NULL != cp->path_heap)
370 {
371 GNUNET_CONTAINER_heap_destroy (cp->path_heap);
372 cp->path_heap = NULL;
373 }
374 if (NULL != cp->heap_cleanup_task)
375 {
376 GNUNET_SCHEDULER_cancel (cp->heap_cleanup_task);
377 cp->heap_cleanup_task = NULL;
378 }
379 GNUNET_free (cp->hello);
380 /* Peer should not be freed if paths exist; if there are no paths,
381 there ought to be no connections, and without connections, no
382 notifications. Thus we can assert that mqm_head is empty at this
383 point. */
384 GNUNET_assert (NULL == cp->mqm_head);
385 GNUNET_assert (NULL == cp->mqm_ready_ptr);
386 GNUNET_free (cp);
387}
388
389
390/**
391 * This peer is now on more "active" duty, activate processes related to it.
392 *
393 * @param cp the more-active peer
394 */
395static void
396consider_peer_activate (struct CadetPeer *cp)
397{
398 uint32_t strength;
399
400 LOG (GNUNET_ERROR_TYPE_DEBUG,
401 "Updating peer %s activation state (%u connections)%s%s\n",
402 GCP_2s (cp),
403 GNUNET_CONTAINER_multishortmap_size (cp->connections),
404 (NULL == cp->t) ? "" : " with tunnel",
405 (NULL == cp->core_mq) ? "" : " with CORE link");
406 if (NULL != cp->destroy_task)
407 {
408 /* It's active, do not destroy! */
409 GNUNET_SCHEDULER_cancel (cp->destroy_task);
410 cp->destroy_task = NULL;
411 }
412 if ((0 == GNUNET_CONTAINER_multishortmap_size (cp->connections)) &&
413 (NULL == cp->t))
414 {
415 /* We're just on a path or directly connected; don't bother too much */
416 if (NULL != cp->connectivity_suggestion)
417 {
418 GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
419 cp->connectivity_suggestion = NULL;
420 }
421 if (NULL != cp->search_h)
422 {
423 GCD_search_stop (cp->search_h);
424 cp->search_h = NULL;
425 }
426 return;
427 }
428 if (NULL == cp->core_mq)
429 {
430 /* Lacks direct connection, try to create one by querying the DHT */
431 if ((NULL == cp->search_h) &&
432 (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths))
433 cp->search_h
434 = GCD_search (&cp->pid);
435 }
436 else
437 {
438 /* Have direct connection, stop DHT search if active */
439 if (NULL != cp->search_h)
440 {
441 GCD_search_stop (cp->search_h);
442 cp->search_h = NULL;
443 }
444 }
445
446 /* If we have a tunnel, our urge for connections is much bigger */
447 strength = (NULL != cp->t) ? 32 : 1;
448 if (NULL != cp->connectivity_suggestion)
449 GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
450 cp->connectivity_suggestion
451 = GNUNET_ATS_connectivity_suggest (ats_ch,
452 &cp->pid,
453 strength);
454}
455
456
457/**
458 * This peer may no longer be needed, consider cleaning it up.
459 *
460 * @param cp peer to clean up
461 */
462static void
463consider_peer_destroy (struct CadetPeer *cp);
464
465
466/**
467 * We really no longere care about a peer, stop hogging memory with paths to it.
468 * Afterwards, see if there is more to be cleaned up about this peer.
469 *
470 * @param cls a `struct CadetPeer`.
471 */
472static void
473drop_paths (void *cls)
474{
475 struct CadetPeer *cp = cls;
476 struct CadetPeerPath *path;
477
478 cp->destroy_task = NULL;
479 while (NULL != (path = GNUNET_CONTAINER_heap_remove_root (cp->path_heap)))
480 GCPP_release (path);
481 consider_peer_destroy (cp);
482}
483
484
485/**
486 * This peer may no longer be needed, consider cleaning it up.
487 *
488 * @param cp peer to clean up
489 */
490static void
491consider_peer_destroy (struct CadetPeer *cp)
492{
493 struct GNUNET_TIME_Relative exp;
494
495 if (NULL != cp->destroy_task)
496 {
497 GNUNET_SCHEDULER_cancel (cp->destroy_task);
498 cp->destroy_task = NULL;
499 }
500 if (NULL != cp->t)
501 return; /* still relevant! */
502 if (NULL != cp->core_mq)
503 return; /* still relevant! */
504 if (0 != GNUNET_CONTAINER_multishortmap_size (cp->connections))
505 return; /* still relevant! */
506 if ((NULL != cp->path_heap) &&
507 (0 < GNUNET_CONTAINER_heap_get_size (cp->path_heap)))
508 {
509 cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PATH_TIMEOUT,
510 &drop_paths,
511 cp);
512 return;
513 }
514 if (0 != cp->num_paths)
515 return; /* still relevant! */
516 if (NULL != cp->hello)
517 {
518 /* relevant only until HELLO expires */
519 exp = GNUNET_TIME_absolute_get_remaining (GNUNET_HELLO_get_last_expiration (
520 cp->hello));
521 cp->destroy_task = GNUNET_SCHEDULER_add_delayed (exp,
522 &destroy_peer,
523 cp);
524 return;
525 }
526 cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PEER_TIMEOUT,
527 &destroy_peer,
528 cp);
529}
530
531
532/**
533 * Set the message queue to @a mq for peer @a cp and notify watchers.
534 *
535 * @param cp peer to modify
536 * @param mq message queue to set (can be NULL)
537 */
538void
539GCP_set_mq (struct CadetPeer *cp,
540 struct GNUNET_MQ_Handle *mq)
541{
542 LOG (GNUNET_ERROR_TYPE_DEBUG,
543 "Message queue for peer %s is now %p\n",
544 GCP_2s (cp),
545 mq);
546 cp->core_mq = mq;
547 for (struct GCP_MessageQueueManager *mqm = cp->mqm_head, *next;
548 NULL != mqm;
549 mqm = next)
550 {
551 /* Save next pointer in case mqm gets freed by the callback */
552 next = mqm->next;
553 if (NULL == mq)
554 {
555 if (NULL != mqm->env)
556 {
557 GNUNET_MQ_discard (mqm->env);
558 mqm->env = NULL;
559 mqm->cb (mqm->cb_cls,
560 GNUNET_SYSERR);
561 }
562 else
563 {
564 mqm->cb (mqm->cb_cls,
565 GNUNET_NO);
566 }
567 }
568 else
569 {
570 GNUNET_assert (NULL == mqm->env);
571 mqm->cb (mqm->cb_cls,
572 GNUNET_YES);
573 }
574 }
575 if ((NULL != mq) ||
576 (NULL != cp->t))
577 consider_peer_activate (cp);
578 else
579 consider_peer_destroy (cp);
580
581 if ((NULL != mq) &&
582 (NULL != cp->t))
583 {
584 /* have a new, direct path to the target, notify tunnel */
585 struct CadetPeerPath *path;
586
587 path = GCPP_get_path_from_route (1,
588 &cp->pid);
589 GCT_consider_path (cp->t,
590 path,
591 0);
592 }
593}
594
595
596/**
597 * Debug function should NEVER return true in production code, useful to
598 * simulate losses for testcases.
599 *
600 * @return #GNUNET_YES or #GNUNET_NO with the decision to drop.
601 */
602static int
603should_I_drop (void)
604{
605 if (0 == drop_percent)
606 return GNUNET_NO;
607 if (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
608 101) < drop_percent)
609 return GNUNET_YES;
610 return GNUNET_NO;
611}
612
613
614/**
615 * Function called when CORE took one of the messages from
616 * a message queue manager and transmitted it.
617 *
618 * @param cls the `struct CadetPeeer` where we made progress
619 */
620static void
621mqm_send_done (void *cls);
622
623
624/**
625 * Transmit current envelope from this @a mqm.
626 *
627 * @param mqm mqm to transmit message for now
628 */
629static void
630mqm_execute (struct GCP_MessageQueueManager *mqm)
631{
632 struct CadetPeer *cp = mqm->cp;
633
634 /* Move ready pointer to the next entry that might be ready. */
635 if ((mqm == cp->mqm_ready_ptr) &&
636 (NULL != mqm->next))
637 cp->mqm_ready_ptr = mqm->next;
638 /* Move entry to the end of the DLL, to be fair. */
639 if (mqm != cp->mqm_tail)
640 {
641 GNUNET_CONTAINER_DLL_remove (cp->mqm_head,
642 cp->mqm_tail,
643 mqm);
644 GNUNET_CONTAINER_DLL_insert_tail (cp->mqm_head,
645 cp->mqm_tail,
646 mqm);
647 }
648 cp->mqm_ready_counter--;
649 if (GNUNET_YES == should_I_drop ())
650 {
651 LOG (GNUNET_ERROR_TYPE_DEBUG,
652 "DROPPING message to peer %s from MQM %p\n",
653 GCP_2s (cp),
654 mqm);
655 GNUNET_MQ_discard (mqm->env);
656 mqm->env = NULL;
657 mqm_send_done (cp);
658 }
659 else
660 {
661 {
662 const struct GNUNET_MessageHeader *mh;
663
664 mh = GNUNET_MQ_env_get_msg (mqm->env);
665 switch (ntohs (mh->type))
666 {
667 case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX:
668 {
669 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg
670 = (const struct GNUNET_CADET_TunnelKeyExchangeMessage *) mh;
671 LOG (GNUNET_ERROR_TYPE_DEBUG,
672 "P2P forwarding KX with ephemeral %s to %s on CID %s\n",
673 GNUNET_e2s (&msg->ephemeral_key),
674 GCP_2s (cp),
675 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
676 }
677 break;
678
679 default:
680 break;
681 }
682 }
683 LOG (GNUNET_ERROR_TYPE_DEBUG,
684 "Sending to peer %s from MQM %p\n",
685 GCP_2s (cp),
686 mqm);
687 GNUNET_MQ_send (cp->core_mq,
688 mqm->env);
689 mqm->env = NULL;
690 }
691 mqm->cb (mqm->cb_cls,
692 GNUNET_YES);
693}
694
695
696/**
697 * Find the next ready message in the queue (starting
698 * the search from the `cp->mqm_ready_ptr`) and if possible
699 * execute the transmission.
700 *
701 * @param cp peer to try to send the next ready message to
702 */
703static void
704send_next_ready (struct CadetPeer *cp)
705{
706 struct GCP_MessageQueueManager *mqm;
707
708 if (0 == cp->mqm_ready_counter)
709 return;
710 while ((NULL != (mqm = cp->mqm_ready_ptr)) &&
711 (NULL == mqm->env))
712 cp->mqm_ready_ptr = mqm->next;
713 if (NULL == mqm)
714 return; /* nothing to do */
715 mqm_execute (mqm);
716}
717
718
719/**
720 * Function called when CORE took one of the messages from
721 * a message queue manager and transmitted it.
722 *
723 * @param cls the `struct CadetPeeer` where we made progress
724 */
725static void
726mqm_send_done (void *cls)
727{
728 struct CadetPeer *cp = cls;
729
730 LOG (GNUNET_ERROR_TYPE_DEBUG,
731 "Sending to peer %s completed\n",
732 GCP_2s (cp));
733 send_next_ready (cp);
734}
735
736
737/**
738 * Send the message in @a env to @a cp.
739 *
740 * @param mqm the message queue manager to use for transmission
741 * @param env envelope with the message to send; must NOT
742 * yet have a #GNUNET_MQ_notify_sent() callback attached to it
743 */
744void
745GCP_send (struct GCP_MessageQueueManager *mqm,
746 struct GNUNET_MQ_Envelope *env)
747{
748 struct CadetPeer *cp = mqm->cp;
749
750 GNUNET_assert (NULL != env);
751 LOG (GNUNET_ERROR_TYPE_DEBUG,
752 "Queueing message to peer %s in MQM %p\n",
753 GCP_2s (cp),
754 mqm);
755 GNUNET_assert (NULL != cp->core_mq);
756 GNUNET_assert (NULL == mqm->env);
757 GNUNET_MQ_notify_sent (env,
758 &mqm_send_done,
759 cp);
760 mqm->env = env;
761 cp->mqm_ready_counter++;
762 if (mqm != cp->mqm_ready_ptr)
763 cp->mqm_ready_ptr = cp->mqm_head;
764 if (1 == cp->mqm_ready_counter)
765 cp->mqm_ready_ptr = mqm;
766 if (0 != GNUNET_MQ_get_length (cp->core_mq))
767 return;
768 send_next_ready (cp);
769}
770
771
772/**
773 * Function called to destroy a peer now.
774 *
775 * @param cls NULL
776 * @param pid identity of the peer (unused)
777 * @param value the `struct CadetPeer` to clean up
778 * @return #GNUNET_OK (continue to iterate)
779 */
780static int
781destroy_iterator_cb (void *cls,
782 const struct GNUNET_PeerIdentity *pid,
783 void *value)
784{
785 struct CadetPeer *cp = value;
786
787 if (NULL != cp->destroy_task)
788 {
789 GNUNET_SCHEDULER_cancel (cp->destroy_task);
790 cp->destroy_task = NULL;
791 }
792 destroy_peer (cp);
793 return GNUNET_OK;
794}
795
796
797/**
798 * Clean up all entries about all peers.
799 * Must only be called after all tunnels, CORE-connections and
800 * connections are down.
801 */
802void
803GCP_destroy_all_peers ()
804{
805 LOG (GNUNET_ERROR_TYPE_DEBUG,
806 "Destroying all peers now\n");
807 GNUNET_CONTAINER_multipeermap_iterate (peers,
808 &destroy_iterator_cb,
809 NULL);
810}
811
812
813/**
814 * Drop all paths owned by this peer, and do not
815 * allow new ones to be added: We are shutting down.
816 *
817 * @param cp peer to drop paths to
818 */
819void
820GCP_drop_owned_paths (struct CadetPeer *cp)
821{
822 struct CadetPeerPath *path;
823
824 LOG (GNUNET_ERROR_TYPE_DEBUG,
825 "Destroying all paths to %s\n",
826 GCP_2s (cp));
827 while (NULL != (path =
828 GNUNET_CONTAINER_heap_remove_root (cp->path_heap)))
829 GCPP_release (path);
830 GNUNET_CONTAINER_heap_destroy (cp->path_heap);
831 cp->path_heap = NULL;
832}
833
834
835/**
836 * Add an entry to the DLL of all of the paths that this peer is on.
837 *
838 * @param cp peer to modify
839 * @param entry an entry on a path
840 * @param off offset of this peer on the path
841 */
842void
843GCP_path_entry_add (struct CadetPeer *cp,
844 struct CadetPeerPathEntry *entry,
845 unsigned int off)
846{
847 GNUNET_assert (cp == GCPP_get_peer_at_offset (entry->path,
848 off));
849 LOG (GNUNET_ERROR_TYPE_DEBUG,
850 "Discovered that peer %s is on path %s at offset %u\n",
851 GCP_2s (cp),
852 GCPP_2s (entry->path),
853 off);
854 if (off >= cp->path_dll_length)
855 {
856 unsigned int len = cp->path_dll_length;
857
858 GNUNET_array_grow (cp->path_heads,
859 len,
860 off + 4);
861 GNUNET_array_grow (cp->path_tails,
862 cp->path_dll_length,
863 off + 4);
864 }
865 GNUNET_CONTAINER_DLL_insert (cp->path_heads[off],
866 cp->path_tails[off],
867 entry);
868 cp->off_sum += off;
869 cp->num_paths++;
870
871 /* If we have a tunnel to this peer, tell the tunnel that there is a
872 new path available. */
873 if (NULL != cp->t)
874 GCT_consider_path (cp->t,
875 entry->path,
876 off);
877
878 if ((NULL != cp->search_h) &&
879 (DESIRED_CONNECTIONS_PER_TUNNEL <= cp->num_paths))
880 {
881 /* Now I have enough paths, stop search */
882 GCD_search_stop (cp->search_h);
883 cp->search_h = NULL;
884 }
885 if (NULL != cp->destroy_task)
886 {
887 /* paths changed, this resets the destroy timeout counter
888 and aborts a destroy task that may no longer be valid
889 to have (as we now have more paths via this peer). */
890 consider_peer_destroy (cp);
891 }
892}
893
894
895/**
896 * Remove an entry from the DLL of all of the paths that this peer is on.
897 *
898 * @param cp peer to modify
899 * @param entry an entry on a path
900 * @param off offset of this peer on the path
901 */
902void
903GCP_path_entry_remove (struct CadetPeer *cp,
904 struct CadetPeerPathEntry *entry,
905 unsigned int off)
906{
907 LOG (GNUNET_ERROR_TYPE_DEBUG,
908 "Removing knowledge about peer %s beging on path %s at offset %u\n",
909 GCP_2s (cp),
910 GCPP_2s (entry->path),
911 off);
912 GNUNET_CONTAINER_DLL_remove (cp->path_heads[off],
913 cp->path_tails[off],
914 entry);
915 GNUNET_assert (0 < cp->num_paths);
916 cp->off_sum -= off;
917 cp->num_paths--;
918 if ((NULL == cp->core_mq) &&
919 (NULL != cp->t) &&
920 (NULL == cp->search_h) &&
921 (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths))
922 cp->search_h
923 = GCD_search (&cp->pid);
924 if (NULL == cp->destroy_task)
925 {
926 /* paths changed, we might now be ready for destruction, check again */
927 consider_peer_destroy (cp);
928 }
929}
930
931
932/**
933 * Prune down the number of paths to this peer, we seem to
934 * have way too many.
935 *
936 * @param cls the `struct CadetPeer` to maintain the path heap for
937 */
938static void
939path_heap_cleanup (void *cls)
940{
941 struct CadetPeer *cp = cls;
942 struct CadetPeerPath *root;
943
944 cp->heap_cleanup_task = NULL;
945 while (GNUNET_CONTAINER_heap_get_size (cp->path_heap) >=
946 2 * DESIRED_CONNECTIONS_PER_TUNNEL)
947 {
948 /* Now we have way too many, drop least desirable UNLESS it is in use!
949 (Note that this intentionally keeps highly desirable, but currently
950 unused paths around in the hope that we might be able to switch, even
951 if the number of paths exceeds the threshold.) */
952 root = GNUNET_CONTAINER_heap_peek (cp->path_heap);
953 GNUNET_assert (NULL != root);
954 if (NULL !=
955 GCPP_get_connection (root,
956 cp,
957 GCPP_get_length (root) - 1))
958 break; /* can't fix */
959 /* Got plenty of paths to this destination, and this is a low-quality
960 one that we don't care about. Allow it to die. */
961 GNUNET_assert (root ==
962 GNUNET_CONTAINER_heap_remove_root (cp->path_heap));
963 GCPP_release (root);
964 }
965}
966
967
968/**
969 * Try adding a @a path to this @a peer. If the peer already
970 * has plenty of paths, return NULL.
971 *
972 * @param cp peer to which the @a path leads to
973 * @param path a path looking for an owner; may not be fully initialized yet!
974 * @param off offset of @a cp in @a path
975 * @param force force attaching the path
976 * @return NULL if this peer does not care to become a new owner,
977 * otherwise the node in the peer's path heap for the @a path.
978 */
979struct GNUNET_CONTAINER_HeapNode *
980GCP_attach_path (struct CadetPeer *cp,
981 struct CadetPeerPath *path,
982 unsigned int off,
983 int force)
984{
985 GNUNET_CONTAINER_HeapCostType desirability;
986 struct CadetPeerPath *root;
987 GNUNET_CONTAINER_HeapCostType root_desirability;
988 struct GNUNET_CONTAINER_HeapNode *hn;
989
990 GNUNET_assert (off == GCPP_get_length (path) - 1);
991 GNUNET_assert (cp == GCPP_get_peer_at_offset (path,
992 off));
993 if (NULL == cp->path_heap)
994 {
995 /* #GCP_drop_owned_paths() was already called, we cannot take new ones! */
996 GNUNET_assert (GNUNET_NO == force);
997 return NULL;
998 }
999 desirability = GCPP_get_desirability (path);
1000 if (GNUNET_NO == force)
1001 {
1002 /* FIXME: desirability is not yet initialized; tricky! */
1003 if (GNUNET_NO ==
1004 GNUNET_CONTAINER_heap_peek2 (cp->path_heap,
1005 (void **) &root,
1006 &root_desirability))
1007 {
1008 root = NULL;
1009 root_desirability = 0;
1010 }
1011
1012 if ((DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) &&
1013 (desirability < root_desirability))
1014 {
1015 LOG (GNUNET_ERROR_TYPE_DEBUG,
1016 "Decided to not attach path %s to peer %s due to undesirability\n",
1017 GCPP_2s (path),
1018 GCP_2s (cp));
1019 return NULL;
1020 }
1021 }
1022
1023 LOG (GNUNET_ERROR_TYPE_DEBUG,
1024 "Attaching path %s to peer %s (%s)\n",
1025 GCPP_2s (path),
1026 GCP_2s (cp),
1027 (GNUNET_NO == force) ? "desirable" : "forced");
1028
1029 /* Yes, we'd like to add this path, add to our heap */
1030 hn = GNUNET_CONTAINER_heap_insert (cp->path_heap,
1031 path,
1032 desirability);
1033
1034 /* Consider maybe dropping other paths because of the new one */
1035 if ((GNUNET_CONTAINER_heap_get_size (cp->path_heap) >=
1036 2 * DESIRED_CONNECTIONS_PER_TUNNEL) &&
1037 (NULL != cp->heap_cleanup_task))
1038 cp->heap_cleanup_task = GNUNET_SCHEDULER_add_now (&path_heap_cleanup,
1039 cp);
1040 return hn;
1041}
1042
1043
1044/**
1045 * This peer can no longer own @a path as the path
1046 * has been extended and a peer further down the line
1047 * is now the new owner.
1048 *
1049 * @param cp old owner of the @a path
1050 * @param path path where the ownership is lost
1051 * @param hn note in @a cp's path heap that must be deleted
1052 */
1053void
1054GCP_detach_path (struct CadetPeer *cp,
1055 struct CadetPeerPath *path,
1056 struct GNUNET_CONTAINER_HeapNode *hn)
1057{
1058 LOG (GNUNET_ERROR_TYPE_DEBUG,
1059 "Detaching path %s from peer %s\n",
1060 GCPP_2s (path),
1061 GCP_2s (cp));
1062 GNUNET_assert (path ==
1063 GNUNET_CONTAINER_heap_remove_node (hn));
1064}
1065
1066
1067/**
1068 * Add a @a connection to this @a cp.
1069 *
1070 * @param cp peer via which the @a connection goes
1071 * @param cc the connection to add
1072 */
1073void
1074GCP_add_connection (struct CadetPeer *cp,
1075 struct CadetConnection *cc)
1076{
1077 LOG (GNUNET_ERROR_TYPE_DEBUG,
1078 "Adding %s to peer %s\n",
1079 GCC_2s (cc),
1080 GCP_2s (cp));
1081 GNUNET_assert (GNUNET_OK ==
1082 GNUNET_CONTAINER_multishortmap_put (cp->connections,
1083 &GCC_get_id (
1084 cc)->connection_of_tunnel,
1085 cc,
1086 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1087 if (NULL != cp->destroy_task)
1088 {
1089 GNUNET_SCHEDULER_cancel (cp->destroy_task);
1090 cp->destroy_task = NULL;
1091 }
1092}
1093
1094
1095/**
1096 * Remove a @a connection that went via this @a cp.
1097 *
1098 * @param cp peer via which the @a connection went
1099 * @param cc the connection to remove
1100 */
1101void
1102GCP_remove_connection (struct CadetPeer *cp,
1103 struct CadetConnection *cc)
1104{
1105 LOG (GNUNET_ERROR_TYPE_DEBUG,
1106 "Removing connection %s from peer %s\n",
1107 GCC_2s (cc),
1108 GCP_2s (cp));
1109 GNUNET_assert (GNUNET_YES ==
1110 GNUNET_CONTAINER_multishortmap_remove (cp->connections,
1111 &GCC_get_id (
1112 cc)->
1113 connection_of_tunnel,
1114 cc));
1115 consider_peer_destroy (cp);
1116}
1117
1118
1119/**
1120 * Retrieve the CadetPeer structure associated with the
1121 * peer. Optionally create one and insert it in the appropriate
1122 * structures if the peer is not known yet.
1123 *
1124 * @param peer_id Full identity of the peer.
1125 * @param create #GNUNET_YES if a new peer should be created if unknown.
1126 * #GNUNET_NO to return NULL if peer is unknown.
1127 * @return Existing or newly created peer structure.
1128 * NULL if unknown and not requested @a create
1129 */
1130struct CadetPeer *
1131GCP_get (const struct GNUNET_PeerIdentity *peer_id,
1132 int create)
1133{
1134 struct CadetPeer *cp;
1135
1136 cp = GNUNET_CONTAINER_multipeermap_get (peers,
1137 peer_id);
1138 if (NULL != cp)
1139 return cp;
1140 if (GNUNET_NO == create)
1141 return NULL;
1142 cp = GNUNET_new (struct CadetPeer);
1143 cp->pid = *peer_id;
1144 cp->connections = GNUNET_CONTAINER_multishortmap_create (32,
1145 GNUNET_YES);
1146 cp->path_heap = GNUNET_CONTAINER_heap_create (
1147 GNUNET_CONTAINER_HEAP_ORDER_MIN);
1148 GNUNET_assert (GNUNET_YES ==
1149 GNUNET_CONTAINER_multipeermap_put (peers,
1150 &cp->pid,
1151 cp,
1152 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1153 LOG (GNUNET_ERROR_TYPE_DEBUG,
1154 "Creating peer %s\n",
1155 GCP_2s (cp));
1156 return cp;
1157}
1158
1159
1160/**
1161 * Obtain the peer identity for a `struct CadetPeer`.
1162 *
1163 * @param cp our peer handle
1164 * @return the peer identity
1165 */
1166const struct GNUNET_PeerIdentity *
1167GCP_get_id (struct CadetPeer *cp)
1168{
1169 return &cp->pid;
1170}
1171
1172
1173/**
1174 * Iterate over all known peers.
1175 *
1176 * @param iter Iterator.
1177 * @param cls Closure for @c iter.
1178 */
1179void
1180GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter,
1181 void *cls)
1182{
1183 GNUNET_CONTAINER_multipeermap_iterate (peers,
1184 iter,
1185 cls);
1186}
1187
1188
1189/**
1190 * Count the number of known paths toward the peer.
1191 *
1192 * @param cp Peer to get path info.
1193 * @return Number of known paths.
1194 */
1195unsigned int
1196GCP_count_paths (const struct CadetPeer *cp)
1197{
1198 return cp->num_paths;
1199}
1200
1201
1202/**
1203 * Iterate over the paths to a peer.
1204 *
1205 * @param cp Peer to get path info.
1206 * @param callback Function to call for every path.
1207 * @param callback_cls Closure for @a callback.
1208 * @return Number of iterated paths.
1209 */
1210unsigned int
1211GCP_iterate_paths (struct CadetPeer *cp,
1212 GCP_PathIterator callback,
1213 void *callback_cls)
1214{
1215 unsigned int ret = 0;
1216
1217 LOG (GNUNET_ERROR_TYPE_DEBUG,
1218 "Iterating over paths to peer %s%s\n",
1219 GCP_2s (cp),
1220 (NULL == cp->core_mq) ? "" : " including direct link");
1221 if (NULL != cp->core_mq)
1222 {
1223 /* FIXME: this branch seems to duplicate the
1224 i=0 case below (direct link). Leave out!??? -CG */
1225 struct CadetPeerPath *path;
1226
1227 path = GCPP_get_path_from_route (1,
1228 &cp->pid);
1229 ret++;
1230 if (GNUNET_NO ==
1231 callback (callback_cls,
1232 path,
1233 0))
1234 return ret;
1235 }
1236 for (unsigned int i = 0; i < cp->path_dll_length; i++)
1237 {
1238 for (struct CadetPeerPathEntry *pe = cp->path_heads[i];
1239 NULL != pe;
1240 pe = pe->next)
1241 {
1242 ret++;
1243 if (GNUNET_NO ==
1244 callback (callback_cls,
1245 pe->path,
1246 i))
1247 return ret;
1248 }
1249 }
1250 return ret;
1251}
1252
1253
1254/**
1255 * Iterate over the paths to a peer without direct link.
1256 *
1257 * @param cp Peer to get path info.
1258 * @param callback Function to call for every path.
1259 * @param callback_cls Closure for @a callback.
1260 * @return Number of iterated paths.
1261 */
1262unsigned int
1263GCP_iterate_indirect_paths (struct CadetPeer *cp,
1264 GCP_PathIterator callback,
1265 void *callback_cls)
1266{
1267 unsigned int ret = 0;
1268
1269 LOG (GNUNET_ERROR_TYPE_DEBUG,
1270 "Iterating over paths to peer %s without direct link\n",
1271 GCP_2s (cp));
1272 for (unsigned int i = 1; i < cp->path_dll_length; i++)
1273 {
1274 for (struct CadetPeerPathEntry *pe = cp->path_heads[i];
1275 NULL != pe;
1276 pe = pe->next)
1277 {
1278 ret++;
1279 if (GNUNET_NO ==
1280 callback (callback_cls,
1281 pe->path,
1282 i))
1283 return ret;
1284 }
1285 }
1286 return ret;
1287}
1288
1289
1290/**
1291 * Iterate over the paths to @a cp where
1292 * @a cp is at distance @a dist from us.
1293 *
1294 * @param cp Peer to get path info.
1295 * @param dist desired distance of @a cp to us on the path
1296 * @param callback Function to call for every path.
1297 * @param callback_cls Closure for @a callback.
1298 * @return Number of iterated paths.
1299 */
1300unsigned int
1301GCP_iterate_paths_at (struct CadetPeer *cp,
1302 unsigned int dist,
1303 GCP_PathIterator callback,
1304 void *callback_cls)
1305{
1306 unsigned int ret = 0;
1307
1308 if (dist >= cp->path_dll_length)
1309 {
1310 LOG (GNUNET_ERROR_TYPE_DEBUG,
1311 "Asked to look for paths at distance %u, but maximum for me is < %u\n",
1312 dist,
1313 cp->path_dll_length);
1314 return 0;
1315 }
1316 for (struct CadetPeerPathEntry *pe = cp->path_heads[dist];
1317 NULL != pe;
1318 pe = pe->next)
1319 {
1320 if (GNUNET_NO ==
1321 callback (callback_cls,
1322 pe->path,
1323 dist))
1324 return ret;
1325 ret++;
1326 }
1327 return ret;
1328}
1329
1330
1331/**
1332 * Get the tunnel towards a peer.
1333 *
1334 * @param cp Peer to get from.
1335 * @param create #GNUNET_YES to create a tunnel if we do not have one
1336 * @return Tunnel towards peer.
1337 */
1338struct CadetTunnel *
1339GCP_get_tunnel (struct CadetPeer *cp,
1340 int create)
1341{
1342 if (NULL == cp)
1343 return NULL;
1344 if ((NULL != cp->t) ||
1345 (GNUNET_NO == create))
1346 return cp->t;
1347 cp->t = GCT_create_tunnel (cp);
1348 consider_peer_activate (cp);
1349 return cp->t;
1350}
1351
1352
1353/**
1354 * Hello offer was passed to the transport service. Mark it
1355 * as done.
1356 *
1357 * @param cls the `struct CadetPeer` where the offer completed
1358 */
1359static void
1360hello_offer_done (void *cls)
1361{
1362 struct CadetPeer *cp = cls;
1363
1364 cp->hello_offer = NULL;
1365}
1366
1367
1368/**
1369 * We got a HELLO for a @a peer, remember it, and possibly
1370 * trigger adequate actions (like trying to connect).
1371 *
1372 * @param cp the peer we got a HELLO for
1373 * @param hello the HELLO to remember
1374 */
1375void
1376GCP_set_hello (struct CadetPeer *cp,
1377 const struct GNUNET_HELLO_Message *hello)
1378{
1379 struct GNUNET_HELLO_Message *mrg;
1380
1381 LOG (GNUNET_ERROR_TYPE_DEBUG,
1382 "Got %u byte HELLO for peer %s\n",
1383 (unsigned int) GNUNET_HELLO_size (hello),
1384 GCP_2s (cp));
1385 if (NULL != cp->hello_offer)
1386 {
1387 GNUNET_TRANSPORT_offer_hello_cancel (cp->hello_offer);
1388 cp->hello_offer = NULL;
1389 }
1390 if (NULL != cp->hello)
1391 {
1392 mrg = GNUNET_HELLO_merge (hello,
1393 cp->hello);
1394 GNUNET_free (cp->hello);
1395 cp->hello = mrg;
1396 }
1397 else
1398 {
1399 cp->hello = GNUNET_memdup (hello,
1400 GNUNET_HELLO_size (hello));
1401 }
1402 cp->hello_offer
1403 = GNUNET_TRANSPORT_offer_hello (cfg,
1404 GNUNET_HELLO_get_header (cp->hello),
1405 &hello_offer_done,
1406 cp);
1407 /* New HELLO means cp's destruction time may change... */
1408 consider_peer_destroy (cp);
1409}
1410
1411
1412/**
1413 * The tunnel to the given peer no longer exists, remove it from our
1414 * data structures, and possibly clean up the peer itself.
1415 *
1416 * @param cp the peer affected
1417 * @param t the dead tunnel
1418 */
1419void
1420GCP_drop_tunnel (struct CadetPeer *cp,
1421 struct CadetTunnel *t)
1422{
1423 LOG (GNUNET_ERROR_TYPE_DEBUG,
1424 "Dropping tunnel %s to peer %s\n",
1425 GCT_2s (t),
1426 GCP_2s (cp));
1427 GNUNET_assert (cp->t == t);
1428 cp->t = NULL;
1429 consider_peer_destroy (cp);
1430}
1431
1432
1433/**
1434 * Test if @a cp has a core-level connection
1435 *
1436 * @param cp peer to test
1437 * @return #GNUNET_YES if @a cp has a core-level connection
1438 */
1439int
1440GCP_has_core_connection (struct CadetPeer *cp)
1441{
1442 return (NULL != cp->core_mq) ? GNUNET_YES : GNUNET_NO;
1443}
1444
1445
1446/**
1447 * Start message queue change notifications.
1448 *
1449 * @param cp peer to notify for
1450 * @param cb function to call if mq becomes available or unavailable
1451 * @param cb_cls closure for @a cb
1452 * @return handle to cancel request
1453 */
1454struct GCP_MessageQueueManager *
1455GCP_request_mq (struct CadetPeer *cp,
1456 GCP_MessageQueueNotificationCallback cb,
1457 void *cb_cls)
1458{
1459 struct GCP_MessageQueueManager *mqm;
1460
1461 mqm = GNUNET_new (struct GCP_MessageQueueManager);
1462 mqm->cb = cb;
1463 mqm->cb_cls = cb_cls;
1464 mqm->cp = cp;
1465 GNUNET_CONTAINER_DLL_insert (cp->mqm_head,
1466 cp->mqm_tail,
1467 mqm);
1468 LOG (GNUNET_ERROR_TYPE_DEBUG,
1469 "Creating MQM %p for peer %s\n",
1470 mqm,
1471 GCP_2s (cp));
1472 if (NULL != cp->core_mq)
1473 cb (cb_cls,
1474 GNUNET_YES);
1475 return mqm;
1476}
1477
1478
1479/**
1480 * Stops message queue change notifications.
1481 *
1482 * @param mqm handle matching request to cancel
1483 * @param last_env final message to transmit, or NULL
1484 */
1485void
1486GCP_request_mq_cancel (struct GCP_MessageQueueManager *mqm,
1487 struct GNUNET_MQ_Envelope *last_env)
1488{
1489 struct CadetPeer *cp = mqm->cp;
1490
1491 LOG (GNUNET_ERROR_TYPE_DEBUG,
1492 "Destroying MQM %p for peer %s%s\n",
1493 mqm,
1494 GCP_2s (cp),
1495 (NULL == last_env) ? "" : " with last ditch transmission");
1496 if (NULL != mqm->env)
1497 GNUNET_MQ_discard (mqm->env);
1498 if (NULL != last_env)
1499 {
1500 if (NULL != cp->core_mq)
1501 {
1502 GNUNET_MQ_notify_sent (last_env,
1503 &mqm_send_done,
1504 cp);
1505 GNUNET_MQ_send (cp->core_mq,
1506 last_env);
1507 }
1508 else
1509 {
1510 GNUNET_MQ_discard (last_env);
1511 }
1512 }
1513 if (cp->mqm_ready_ptr == mqm)
1514 cp->mqm_ready_ptr = mqm->next;
1515 GNUNET_CONTAINER_DLL_remove (cp->mqm_head,
1516 cp->mqm_tail,
1517 mqm);
1518 GNUNET_free (mqm);
1519}
1520
1521
1522/**
1523 * Send the message in @a env to @a cp, overriding queueing logic.
1524 * This function should only be used to send error messages outside
1525 * of flow and congestion control, similar to ICMP. Note that
1526 * the envelope may be silently discarded as well.
1527 *
1528 * @param cp peer to send the message to
1529 * @param env envelope with the message to send
1530 */
1531void
1532GCP_send_ooo (struct CadetPeer *cp,
1533 struct GNUNET_MQ_Envelope *env)
1534{
1535 LOG (GNUNET_ERROR_TYPE_DEBUG,
1536 "Sending message to %s out of management\n",
1537 GCP_2s (cp));
1538 if (NULL == cp->core_mq)
1539 {
1540 GNUNET_MQ_discard (env);
1541 return;
1542 }
1543 if (GNUNET_MQ_get_length (cp->core_mq) > MAX_OOO_QUEUE_SIZE)
1544 {
1545 GNUNET_MQ_discard (env);
1546 return;
1547 }
1548 GNUNET_MQ_notify_sent (env,
1549 &mqm_send_done,
1550 cp);
1551 GNUNET_MQ_send (cp->core_mq,
1552 env);
1553}
1554
1555
1556/**
1557 * 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.
1558 *
1559 * @param peer The peer we received a new time value from.
1560 * @param monotime Time value we check against the last time value we received from a peer.
1561 * @return GNUNET_YES if monotime is newer than the last received time value, GNUNET_NO if monotime is not newer.
1562 */
1563int
1564GCP_check_and_update_monotime (struct CadetPeer *peer,
1565 struct GNUNET_TIME_AbsoluteNBO monotime)
1566{
1567
1568 struct GNUNET_TIME_Absolute mt = GNUNET_TIME_absolute_ntoh (monotime);
1569
1570 if (mt.abs_value_us > *(&peer->last_connection_create.abs_value_us))
1571 {
1572 peer->last_connection_create = mt;
1573 return GNUNET_YES;
1574 }
1575 return GNUNET_NO;
1576}
1577
1578
1579/**
1580 * Checking the signature for a monotime of a GNUNET_CADET_ConnectionCreateMessage.
1581 *
1582 * @param peer The peer that signed the monotime value.
1583 * @param msg The GNUNET_CADET_ConnectionCreateMessage with the monotime value.
1584 * @return GNUNET_OK if the signature is good, GNUNET_SYSERR if not.
1585 */
1586int
1587GCP_check_monotime_sig (struct CadetPeer *peer,
1588 const struct GNUNET_CADET_ConnectionCreateMessage *msg)
1589{
1590 struct CadetConnectionCreatePS cp = { .purpose.purpose = htonl (
1591 GNUNET_SIGNATURE_PURPOSE_CADET_CONNECTION_INITIATOR),
1592 .purpose.size = htonl (sizeof(cp)),
1593 .monotonic_time = msg->monotime};
1594
1595 if (GNUNET_OK !=
1596 GNUNET_CRYPTO_eddsa_verify (
1597 GNUNET_SIGNATURE_PURPOSE_CADET_CONNECTION_INITIATOR,
1598 &cp,
1599 &msg->monotime_sig,
1600 &peer->pid.public_key))
1601 {
1602 GNUNET_break_op (0);
1603 return GNUNET_SYSERR;
1604 }
1605 return GNUNET_OK;
1606}
1607
1608
1609/* end of gnunet-service-cadet-new_peer.c */
diff --git a/src/cadet/gnunet-service-cadet_peer.h b/src/cadet/gnunet-service-cadet_peer.h
deleted file mode 100644
index 7a39615ff..000000000
--- a/src/cadet/gnunet-service-cadet_peer.h
+++ /dev/null
@@ -1,427 +0,0 @@
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_hello_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 * @param cp a peer reachable via a path
66 * @param off offset of @a cp in a path
67 * @return score how useful a path is to reach @a cp,
68 * positive scores mean path is more desirable
69 */
70double
71GCP_get_desirability_of_path (struct CadetPeer *cp,
72 unsigned int off);
73
74
75/**
76 * Obtain the peer identity for a `struct CadetPeer`.
77 *
78 * @param cp our peer handle
79 * @return the peer identity
80 */
81const struct GNUNET_PeerIdentity *
82GCP_get_id (struct CadetPeer *cp);
83
84
85/**
86 * Iterate over all known peers.
87 *
88 * @param iter Iterator.
89 * @param cls Closure for @c iter.
90 */
91void
92GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter,
93 void *cls);
94
95
96/**
97 * Count the number of known paths toward the peer.
98 *
99 * @param cp Peer to get path info.
100 * @return Number of known paths.
101 */
102unsigned int
103GCP_count_paths (const struct CadetPeer *cp);
104
105
106/**
107 * Drop all paths owned by this peer, and do not
108 * allow new ones to be added: We are shutting down.
109 *
110 * @param cp peer to drop paths to
111 */
112void
113GCP_drop_owned_paths (struct CadetPeer *cp);
114
115
116/**
117 * Peer path iterator.
118 *
119 * @param cls Closure.
120 * @param path Path itself
121 * @param off offset of the target peer in @a path
122 * @return #GNUNET_YES if should keep iterating.
123 * #GNUNET_NO otherwise.
124 */
125typedef int
126(*GCP_PathIterator) (void *cls,
127 struct CadetPeerPath *path,
128 unsigned int off);
129
130
131/**
132 * Iterate over the paths to a peer.
133 *
134 * @param cp Peer to get path info.
135 * @param callback Function to call for every path.
136 * @param callback_cls Closure for @a callback.
137 * @return Number of iterated paths.
138 */
139unsigned int
140GCP_iterate_paths (struct CadetPeer *cp,
141 GCP_PathIterator callback,
142 void *callback_cls);
143
144/**
145 * Iterate over the paths to a peer without direct link.
146 *
147 * @param cp Peer to get path info.
148 * @param callback Function to call for every path.
149 * @param callback_cls Closure for @a callback.
150 * @return Number of iterated paths.
151 */
152unsigned int
153GCP_iterate_indirect_paths (struct CadetPeer *cp,
154 GCP_PathIterator callback,
155 void *callback_cls);
156
157
158/**
159 * Iterate over the paths to @a peer where
160 * @a peer is at distance @a dist from us.
161 *
162 * @param cp Peer to get path info.
163 * @param dist desired distance of @a peer to us on the path
164 * @param callback Function to call for every path.
165 * @param callback_cls Closure for @a callback.
166 * @return Number of iterated paths.
167 */
168unsigned int
169GCP_iterate_paths_at (struct CadetPeer *cp,
170 unsigned int dist,
171 GCP_PathIterator callback,
172 void *callback_cls);
173
174
175/**
176 * Remove an entry from the DLL of all of the paths that this peer is on.
177 *
178 * @param cp peer to modify
179 * @param entry an entry on a path
180 * @param off offset of this peer on the path
181 */
182void
183GCP_path_entry_remove (struct CadetPeer *cp,
184 struct CadetPeerPathEntry *entry,
185 unsigned int off);
186
187
188/**
189 * Add an entry to the DLL of all of the paths that this peer is on.
190 *
191 * @param cp peer to modify
192 * @param entry an entry on a path
193 * @param off offset of this peer on the path
194 */
195void
196GCP_path_entry_add (struct CadetPeer *cp,
197 struct CadetPeerPathEntry *entry,
198 unsigned int off);
199
200
201/**
202 * Get the tunnel towards a peer.
203 *
204 * @param cp Peer to get from.
205 * @param create #GNUNET_YES to create a tunnel if we do not have one
206 * @return Tunnel towards peer.
207 */
208struct CadetTunnel *
209GCP_get_tunnel (struct CadetPeer *cp,
210 int create);
211
212
213/**
214 * The tunnel to the given peer no longer exists, remove it from our
215 * data structures, and possibly clean up the peer itself.
216 *
217 * @param cp the peer affected
218 * @param t the dead tunnel
219 */
220void
221GCP_drop_tunnel (struct CadetPeer *cp,
222 struct CadetTunnel *t);
223
224
225/**
226 * Try adding a @a path to this @a cp. If the peer already
227 * has plenty of paths, return NULL.
228 *
229 * @param cp peer to which the @a path leads to
230 * @param path a path looking for an owner; may not be fully initialized yet!
231 * @param off offset of @a cp in @a path
232 * @param force for attaching the path
233 * @return NULL if this peer does not care to become a new owner,
234 * otherwise the node in the peer's path heap for the @a path.
235 */
236struct GNUNET_CONTAINER_HeapNode *
237GCP_attach_path (struct CadetPeer *cp,
238 struct CadetPeerPath *path,
239 unsigned int off,
240 int force);
241
242
243/**
244 * This peer can no longer own @a path as the path
245 * has been extended and a peer further down the line
246 * is now the new owner.
247 *
248 * @param cp old owner of the @a path
249 * @param path path where the ownership is lost
250 * @param hn note in @a cp's path heap that must be deleted
251 */
252void
253GCP_detach_path (struct CadetPeer *cp,
254 struct CadetPeerPath *path,
255 struct GNUNET_CONTAINER_HeapNode *hn);
256
257
258/**
259 * Add a @a connection to this @a cp.
260 *
261 * @param cp peer via which the @a connection goes
262 * @param cc the connection to add
263 */
264void
265GCP_add_connection (struct CadetPeer *cp,
266 struct CadetConnection *cc);
267
268
269/**
270 * Remove a @a connection that went via this @a cp.
271 *
272 * @param cp peer via which the @a connection went
273 * @param cc the connection to remove
274 */
275void
276GCP_remove_connection (struct CadetPeer *cp,
277 struct CadetConnection *cc);
278
279
280/**
281 * We got a HELLO for a @a cp, remember it, and possibly
282 * trigger adequate actions (like trying to connect).
283 *
284 * @param cp the peer we got a HELLO for
285 * @param hello the HELLO to remember
286 */
287void
288GCP_set_hello (struct CadetPeer *cp,
289 const struct GNUNET_HELLO_Message *hello);
290
291
292/**
293 * Clean up all entries about all peers.
294 * Must only be called after all tunnels, CORE-connections and
295 * connections are down.
296 */
297void
298GCP_destroy_all_peers (void);
299
300
301/**
302 * Data structure used to track whom we have to notify about changes
303 * in our ability to transmit to a given peer.
304 *
305 * All queue managers will be given equal chance for sending messages
306 * to @a cp. This construct this guarantees fairness for access to @a
307 * cp among the different message queues. Each connection or route
308 * will have its respective message queue managers for each direction.
309 */
310struct GCP_MessageQueueManager;
311
312
313/**
314 * Function to call with updated message queue object.
315 *
316 * @param cls closure
317 * @param available #GNUNET_YES if sending is now possible,
318 * #GNUNET_NO if sending is no longer possible
319 * #GNUNET_SYSERR if sending is no longer possible
320 * and the last envelope was discarded
321 */
322typedef void
323(*GCP_MessageQueueNotificationCallback)(void *cls,
324 int available);
325
326
327/**
328 * Start message queue change notifications. Will create a new slot
329 * to manage the message queue to the given @a cp.
330 *
331 * @param cp peer to notify for
332 * @param cb function to call if mq becomes available or unavailable
333 * @param cb_cls closure for @a cb
334 * @return handle to cancel request
335 */
336struct GCP_MessageQueueManager *
337GCP_request_mq (struct CadetPeer *cp,
338 GCP_MessageQueueNotificationCallback cb,
339 void *cb_cls);
340
341
342/**
343 * Test if @a cp has a core-level connection
344 *
345 * @param cp peer to test
346 * @return #GNUNET_YES if @a cp has a core-level connection
347 */
348int
349GCP_has_core_connection (struct CadetPeer *cp);
350
351
352/**
353 * Send the message in @a env via a @a mqm. Must only be called at
354 * most once after the respective
355 * #GCP_MessageQueueNotificationCallback was called with `available`
356 * set to #GNUNET_YES, and not after the callback was called with
357 * `available` set to #GNUNET_NO or #GNUNET_SYSERR.
358 *
359 * @param mqm message queue manager for the transmission
360 * @param env envelope with the message to send; must NOT
361 * yet have a #GNUNET_MQ_notify_sent() callback attached to it
362 */
363void
364GCP_send (struct GCP_MessageQueueManager *mqm,
365 struct GNUNET_MQ_Envelope *env);
366
367
368/**
369 * Send the message in @a env to @a cp, overriding queueing logic.
370 * This function should only be used to send error messages outside
371 * of flow and congestion control, similar to ICMP. Note that
372 * the envelope may be silently discarded as well.
373 *
374 * @param cp peer to send the message to
375 * @param env envelope with the message to send
376 */
377void
378GCP_send_ooo (struct CadetPeer *cp,
379 struct GNUNET_MQ_Envelope *env);
380
381
382/**
383 * Stops message queue change notifications and sends a last message.
384 * In practice, this is implemented by sending that @a last_env
385 * message immediately (if any), ignoring queue order.
386 *
387 * @param mqm handle matching request to cancel
388 * @param last_env final message to transmit, or NULL
389 */
390void
391GCP_request_mq_cancel (struct GCP_MessageQueueManager *mqm,
392 struct GNUNET_MQ_Envelope *last_env);
393
394
395/**
396 * Set the message queue to @a mq for peer @a cp and notify watchers.
397 *
398 * @param cp peer to modify
399 * @param mq message queue to set (can be NULL)
400 */
401void
402GCP_set_mq (struct CadetPeer *cp,
403 struct GNUNET_MQ_Handle *mq);
404
405/**
406 * Checking the signature for a monotime of a GNUNET_CADET_ConnectionCreateMessage.
407 *
408 * @param peer The peer that signed the monotime value.
409 * @param msg The GNUNET_CADET_ConnectionCreateMessage with the monotime value.
410 * @return GNUNET_OK if the signature is good, GNUNET_SYSERR if not.
411 */
412int
413GCP_check_monotime_sig (struct CadetPeer *peer, const struct
414 GNUNET_CADET_ConnectionCreateMessage *msg);
415
416/**
417 * 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.
418 *
419 * @param peer The peer we received a new time value from.
420 * @param monotime Time value we check against the last time value we received from a peer.
421 * @return GNUNET_YES if monotime is newer than the last received time value, GNUNET_NO if monotime is not newer.
422 */
423int
424GCP_check_and_update_monotime (struct CadetPeer *peer,
425 struct GNUNET_TIME_AbsoluteNBO monotime);
426
427#endif
diff --git a/src/cadet/gnunet-service-cadet_tunnels.c b/src/cadet/gnunet-service-cadet_tunnels.c
deleted file mode 100644
index cabbeed0c..000000000
--- a/src/cadet/gnunet-service-cadet_tunnels.c
+++ /dev/null
@@ -1,3728 +0,0 @@
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 @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
579/**
580 * Count channels of a tunnel.
581 *
582 * @param t Tunnel on which to count.
583 *
584 * @return Number of channels.
585 */
586unsigned int
587GCT_count_channels (struct CadetTunnel *t)
588{
589 return GNUNET_CONTAINER_multihashmap32_size (t->channels);
590}
591
592
593/**
594 * Lookup a channel by its @a ctn.
595 *
596 * @param t tunnel to look in
597 * @param ctn number of channel to find
598 * @return NULL if channel does not exist
599 */
600struct CadetChannel *
601lookup_channel (struct CadetTunnel *t,
602 struct GNUNET_CADET_ChannelTunnelNumber ctn)
603{
604 return GNUNET_CONTAINER_multihashmap32_get (t->channels,
605 ntohl (ctn.cn));
606}
607
608
609/**
610 * Count all created connections of a tunnel. Not necessarily ready connections!
611 *
612 * @param t Tunnel on which to count.
613 *
614 * @return Number of connections created, either being established or ready.
615 */
616unsigned int
617GCT_count_any_connections (const struct CadetTunnel *t)
618{
619 return t->num_ready_connections + t->num_busy_connections;
620}
621
622
623/**
624 * Find first connection that is ready in the list of
625 * our connections. Picks ready connections round-robin.
626 *
627 * @param t tunnel to search
628 * @return NULL if we have no connection that is ready
629 */
630static struct CadetTConnection *
631get_ready_connection (struct CadetTunnel *t)
632{
633 struct CadetTConnection *hd = t->connection_ready_head;
634
635 GNUNET_assert ((NULL == hd) ||
636 (GNUNET_YES == hd->is_ready));
637 return hd;
638}
639
640
641/**
642 * Get the encryption state of a tunnel.
643 *
644 * @param t Tunnel.
645 *
646 * @return Tunnel's encryption state.
647 */
648enum CadetTunnelEState
649GCT_get_estate (struct CadetTunnel *t)
650{
651 return t->estate;
652}
653
654
655/**
656 * Called when either we have a new connection, or a new message in the
657 * queue, or some existing connection has transmission capacity. Looks
658 * at our message queue and if there is a message, picks a connection
659 * to send it on.
660 *
661 * @param cls the `struct CadetTunnel` to process messages on
662 */
663static void
664trigger_transmissions (void *cls);
665
666
667/* ************************************** start core crypto ***************************** */
668
669
670/**
671 * Create a new Axolotl ephemeral (ratchet) key.
672 *
673 * @param ax key material to update
674 */
675static void
676new_ephemeral (struct CadetTunnelAxolotl *ax)
677{
678 LOG (GNUNET_ERROR_TYPE_DEBUG,
679 "Creating new ephemeral ratchet key (DHRs)\n");
680 GNUNET_CRYPTO_ecdhe_key_create (&ax->DHRs);
681}
682
683
684/**
685 * Calculate HMAC.
686 *
687 * @param plaintext Content to HMAC.
688 * @param size Size of @c plaintext.
689 * @param iv Initialization vector for the message.
690 * @param key Key to use.
691 * @param hmac[out] Destination to store the HMAC.
692 */
693static void
694t_hmac (const void *plaintext,
695 size_t size,
696 uint32_t iv,
697 const struct GNUNET_CRYPTO_SymmetricSessionKey *key,
698 struct GNUNET_ShortHashCode *hmac)
699{
700 static const char ctx[] = "cadet authentication key";
701 struct GNUNET_CRYPTO_AuthKey auth_key;
702 struct GNUNET_HashCode hash;
703
704 GNUNET_CRYPTO_hmac_derive_key (&auth_key,
705 key,
706 &iv, sizeof(iv),
707 key, sizeof(*key),
708 ctx, sizeof(ctx),
709 NULL);
710 /* Two step: GNUNET_ShortHash is only 256 bits,
711 GNUNET_HashCode is 512, so we truncate. */
712 GNUNET_CRYPTO_hmac (&auth_key,
713 plaintext,
714 size,
715 &hash);
716 GNUNET_memcpy (hmac,
717 &hash,
718 sizeof(*hmac));
719}
720
721
722/**
723 * Perform a HMAC.
724 *
725 * @param key Key to use.
726 * @param[out] hash Resulting HMAC.
727 * @param source Source key material (data to HMAC).
728 * @param len Length of @a source.
729 */
730static void
731t_ax_hmac_hash (const struct GNUNET_CRYPTO_SymmetricSessionKey *key,
732 struct GNUNET_HashCode *hash,
733 const void *source,
734 unsigned int len)
735{
736 static const char ctx[] = "axolotl HMAC-HASH";
737 struct GNUNET_CRYPTO_AuthKey auth_key;
738
739 GNUNET_CRYPTO_hmac_derive_key (&auth_key,
740 key,
741 ctx, sizeof(ctx),
742 NULL);
743 GNUNET_CRYPTO_hmac (&auth_key,
744 source,
745 len,
746 hash);
747}
748
749
750/**
751 * Derive a symmetric encryption key from an HMAC-HASH.
752 *
753 * @param key Key to use for the HMAC.
754 * @param[out] out Key to generate.
755 * @param source Source key material (data to HMAC).
756 * @param len Length of @a source.
757 */
758static void
759t_hmac_derive_key (const struct GNUNET_CRYPTO_SymmetricSessionKey *key,
760 struct GNUNET_CRYPTO_SymmetricSessionKey *out,
761 const void *source,
762 unsigned int len)
763{
764 static const char ctx[] = "axolotl derive key";
765 struct GNUNET_HashCode h;
766
767 t_ax_hmac_hash (key,
768 &h,
769 source,
770 len);
771 GNUNET_CRYPTO_kdf (out, sizeof(*out),
772 ctx, sizeof(ctx),
773 &h, sizeof(h),
774 NULL);
775}
776
777
778/**
779 * Encrypt data with the axolotl tunnel key.
780 *
781 * @param ax key material to use.
782 * @param dst Destination with @a size bytes for the encrypted data.
783 * @param src Source of the plaintext. Can overlap with @c dst, must contain @a size bytes
784 * @param size Size of the buffers at @a src and @a dst
785 */
786static void
787t_ax_encrypt (struct CadetTunnelAxolotl *ax,
788 void *dst,
789 const void *src,
790 size_t size)
791{
792 struct GNUNET_CRYPTO_SymmetricSessionKey MK;
793 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
794 size_t out_size;
795
796 ax->ratchet_counter++;
797 if ((GNUNET_YES == ax->ratchet_allowed) &&
798 ((ratchet_messages <= ax->ratchet_counter) ||
799 (0 == GNUNET_TIME_absolute_get_remaining (
800 ax->ratchet_expiration).rel_value_us)))
801 {
802 ax->ratchet_flag = GNUNET_YES;
803 }
804 if (GNUNET_YES == ax->ratchet_flag)
805 {
806 /* Advance ratchet */
807 struct GNUNET_CRYPTO_SymmetricSessionKey keys[3];
808 struct GNUNET_HashCode dh;
809 struct GNUNET_HashCode hmac;
810 static const char ctx[] = "axolotl ratchet";
811
812 new_ephemeral (ax);
813 ax->HKs = ax->NHKs;
814
815 /* RK, NHKs, CKs = KDF( HMAC-HASH(RK, DH(DHRs, DHRr)) ) */
816 GNUNET_CRYPTO_ecc_ecdh (&ax->DHRs,
817 &ax->DHRr,
818 &dh);
819 t_ax_hmac_hash (&ax->RK,
820 &hmac,
821 &dh,
822 sizeof(dh));
823 GNUNET_CRYPTO_kdf (keys, sizeof(keys),
824 ctx, sizeof(ctx),
825 &hmac, sizeof(hmac),
826 NULL);
827 ax->RK = keys[0];
828 ax->NHKs = keys[1];
829 ax->CKs = keys[2];
830
831 ax->PNs = ax->Ns;
832 ax->Ns = 0;
833 ax->ratchet_flag = GNUNET_NO;
834 ax->ratchet_allowed = GNUNET_NO;
835 ax->ratchet_counter = 0;
836 ax->ratchet_expiration
837 = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
838 ratchet_time);
839 }
840
841 t_hmac_derive_key (&ax->CKs,
842 &MK,
843 "0",
844 1);
845 GNUNET_CRYPTO_symmetric_derive_iv (&iv,
846 &MK,
847 NULL, 0,
848 NULL);
849
850 out_size = GNUNET_CRYPTO_symmetric_encrypt (src,
851 size,
852 &MK,
853 &iv,
854 dst);
855 GNUNET_assert (size == out_size);
856 t_hmac_derive_key (&ax->CKs,
857 &ax->CKs,
858 "1",
859 1);
860}
861
862
863/**
864 * Decrypt data with the axolotl tunnel key.
865 *
866 * @param ax key material to use.
867 * @param dst Destination for the decrypted data, must contain @a size bytes.
868 * @param src Source of the ciphertext. Can overlap with @c dst, must contain @a size bytes.
869 * @param size Size of the @a src and @a dst buffers
870 */
871static void
872t_ax_decrypt (struct CadetTunnelAxolotl *ax,
873 void *dst,
874 const void *src,
875 size_t size)
876{
877 struct GNUNET_CRYPTO_SymmetricSessionKey MK;
878 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
879 size_t out_size;
880
881 t_hmac_derive_key (&ax->CKr,
882 &MK,
883 "0",
884 1);
885 GNUNET_CRYPTO_symmetric_derive_iv (&iv,
886 &MK,
887 NULL, 0,
888 NULL);
889 GNUNET_assert (size >= sizeof(struct GNUNET_MessageHeader));
890 out_size = GNUNET_CRYPTO_symmetric_decrypt (src,
891 size,
892 &MK,
893 &iv,
894 dst);
895 GNUNET_assert (out_size == size);
896 t_hmac_derive_key (&ax->CKr,
897 &ax->CKr,
898 "1",
899 1);
900}
901
902
903/**
904 * Encrypt header with the axolotl header key.
905 *
906 * @param ax key material to use.
907 * @param[in|out] msg Message whose header to encrypt.
908 */
909static void
910t_h_encrypt (struct CadetTunnelAxolotl *ax,
911 struct GNUNET_CADET_TunnelEncryptedMessage *msg)
912{
913 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
914 size_t out_size;
915
916 GNUNET_CRYPTO_symmetric_derive_iv (&iv,
917 &ax->HKs,
918 NULL, 0,
919 NULL);
920 out_size = GNUNET_CRYPTO_symmetric_encrypt (&msg->ax_header,
921 sizeof(struct
922 GNUNET_CADET_AxHeader),
923 &ax->HKs,
924 &iv,
925 &msg->ax_header);
926 GNUNET_assert (sizeof(struct GNUNET_CADET_AxHeader) == out_size);
927}
928
929
930/**
931 * Decrypt header with the current axolotl header key.
932 *
933 * @param ax key material to use.
934 * @param src Message whose header to decrypt.
935 * @param dst Where to decrypt header to.
936 */
937static void
938t_h_decrypt (struct CadetTunnelAxolotl *ax,
939 const struct GNUNET_CADET_TunnelEncryptedMessage *src,
940 struct GNUNET_CADET_TunnelEncryptedMessage *dst)
941{
942 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
943 size_t out_size;
944
945 GNUNET_CRYPTO_symmetric_derive_iv (&iv,
946 &ax->HKr,
947 NULL, 0,
948 NULL);
949 out_size = GNUNET_CRYPTO_symmetric_decrypt (&src->ax_header.Ns,
950 sizeof(struct
951 GNUNET_CADET_AxHeader),
952 &ax->HKr,
953 &iv,
954 &dst->ax_header.Ns);
955 GNUNET_assert (sizeof(struct GNUNET_CADET_AxHeader) == out_size);
956}
957
958
959/**
960 * Delete a key from the list of skipped keys.
961 *
962 * @param ax key material to delete @a key from.
963 * @param key Key to delete.
964 */
965static void
966delete_skipped_key (struct CadetTunnelAxolotl *ax,
967 struct CadetTunnelSkippedKey *key)
968{
969 GNUNET_CONTAINER_DLL_remove (ax->skipped_head,
970 ax->skipped_tail,
971 key);
972 GNUNET_free (key);
973 ax->skipped--;
974}
975
976
977/**
978 * Decrypt and verify data with the appropriate tunnel key and verify that the
979 * data has not been altered since it was sent by the remote peer.
980 *
981 * @param ax key material to use.
982 * @param dst Destination for the plaintext.
983 * @param src Source of the message. Can overlap with @c dst.
984 * @param size Size of the message.
985 * @return Size of the decrypted data, -1 if an error was encountered.
986 */
987static ssize_t
988try_old_ax_keys (struct CadetTunnelAxolotl *ax,
989 void *dst,
990 const struct GNUNET_CADET_TunnelEncryptedMessage *src,
991 size_t size)
992{
993 struct CadetTunnelSkippedKey *key;
994 struct GNUNET_ShortHashCode *hmac;
995 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
996 struct GNUNET_CADET_TunnelEncryptedMessage plaintext_header;
997 struct GNUNET_CRYPTO_SymmetricSessionKey *valid_HK;
998 size_t esize;
999 size_t res;
1000 size_t len;
1001 unsigned int N;
1002
1003 LOG (GNUNET_ERROR_TYPE_DEBUG,
1004 "Trying skipped keys\n");
1005 hmac = &plaintext_header.hmac;
1006 esize = size - sizeof(struct GNUNET_CADET_TunnelEncryptedMessage);
1007
1008 /* Find a correct Header Key */
1009 valid_HK = NULL;
1010 for (key = ax->skipped_head; NULL != key; key = key->next)
1011 {
1012 t_hmac (&src->ax_header,
1013 sizeof(struct GNUNET_CADET_AxHeader) + esize,
1014 0,
1015 &key->HK,
1016 hmac);
1017 if (0 == GNUNET_memcmp (hmac,
1018 &src->hmac))
1019 {
1020 valid_HK = &key->HK;
1021 break;
1022 }
1023 }
1024 if (NULL == key)
1025 return -1;
1026
1027 /* Should've been checked in -cadet_connection.c handle_cadet_encrypted. */
1028 GNUNET_assert (size > sizeof(struct GNUNET_CADET_TunnelEncryptedMessage));
1029 len = size - sizeof(struct GNUNET_CADET_TunnelEncryptedMessage);
1030 GNUNET_assert (len >= sizeof(struct GNUNET_MessageHeader));
1031
1032 /* Decrypt header */
1033 GNUNET_CRYPTO_symmetric_derive_iv (&iv,
1034 &key->HK,
1035 NULL, 0,
1036 NULL);
1037 res = GNUNET_CRYPTO_symmetric_decrypt (&src->ax_header.Ns,
1038 sizeof(struct GNUNET_CADET_AxHeader),
1039 &key->HK,
1040 &iv,
1041 &plaintext_header.ax_header.Ns);
1042 GNUNET_assert (sizeof(struct GNUNET_CADET_AxHeader) == res);
1043
1044 /* Find the correct message key */
1045 N = ntohl (plaintext_header.ax_header.Ns);
1046 while ((NULL != key) &&
1047 (N != key->Kn))
1048 key = key->next;
1049 if ((NULL == key) ||
1050 (0 != GNUNET_memcmp (&key->HK,
1051 valid_HK)))
1052 return -1;
1053
1054 /* Decrypt payload */
1055 GNUNET_CRYPTO_symmetric_derive_iv (&iv,
1056 &key->MK,
1057 NULL,
1058 0,
1059 NULL);
1060 res = GNUNET_CRYPTO_symmetric_decrypt (&src[1],
1061 len,
1062 &key->MK,
1063 &iv,
1064 dst);
1065 delete_skipped_key (ax,
1066 key);
1067 return res;
1068}
1069
1070
1071/**
1072 * Delete a key from the list of skipped keys.
1073 *
1074 * @param ax key material to delete from.
1075 * @param HKr Header Key to use.
1076 */
1077static void
1078store_skipped_key (struct CadetTunnelAxolotl *ax,
1079 const struct GNUNET_CRYPTO_SymmetricSessionKey *HKr)
1080{
1081 struct CadetTunnelSkippedKey *key;
1082
1083 key = GNUNET_new (struct CadetTunnelSkippedKey);
1084 key->timestamp = GNUNET_TIME_absolute_get ();
1085 key->Kn = ax->Nr;
1086 key->HK = ax->HKr;
1087 t_hmac_derive_key (&ax->CKr,
1088 &key->MK,
1089 "0",
1090 1);
1091 t_hmac_derive_key (&ax->CKr,
1092 &ax->CKr,
1093 "1",
1094 1);
1095 GNUNET_CONTAINER_DLL_insert (ax->skipped_head,
1096 ax->skipped_tail,
1097 key);
1098 ax->skipped++;
1099 ax->Nr++;
1100}
1101
1102
1103/**
1104 * Stage skipped AX keys and calculate the message key.
1105 * Stores each HK and MK for skipped messages.
1106 *
1107 * @param ax key material to use
1108 * @param HKr Header key.
1109 * @param Np Received meesage number.
1110 * @return #GNUNET_OK if keys were stored.
1111 * #GNUNET_SYSERR if an error occurred (@a Np not expected).
1112 */
1113static int
1114store_ax_keys (struct CadetTunnelAxolotl *ax,
1115 const struct GNUNET_CRYPTO_SymmetricSessionKey *HKr,
1116 uint32_t Np)
1117{
1118 int gap;
1119
1120 gap = Np - ax->Nr;
1121 LOG (GNUNET_ERROR_TYPE_DEBUG,
1122 "Storing skipped keys [%u, %u)\n",
1123 ax->Nr,
1124 Np);
1125 if (MAX_KEY_GAP < gap)
1126 {
1127 /* Avoid DoS (forcing peer to do more than #MAX_KEY_GAP HMAC operations) */
1128 /* TODO: start new key exchange on return */
1129 GNUNET_break_op (0);
1130 LOG (GNUNET_ERROR_TYPE_WARNING,
1131 "Got message %u, expected %u+\n",
1132 Np,
1133 ax->Nr);
1134 return GNUNET_SYSERR;
1135 }
1136 if (0 > gap)
1137 {
1138 /* Delayed message: don't store keys, flag to try old keys. */
1139 return GNUNET_SYSERR;
1140 }
1141
1142 while (ax->Nr < Np)
1143 store_skipped_key (ax,
1144 HKr);
1145
1146 while (ax->skipped > MAX_SKIPPED_KEYS)
1147 delete_skipped_key (ax,
1148 ax->skipped_tail);
1149 return GNUNET_OK;
1150}
1151
1152
1153/**
1154 * Decrypt and verify data with the appropriate tunnel key and verify that the
1155 * data has not been altered since it was sent by the remote peer.
1156 *
1157 * @param ax key material to use
1158 * @param dst Destination for the plaintext.
1159 * @param src Source of the message. Can overlap with @c dst.
1160 * @param size Size of the message.
1161 * @return Size of the decrypted data, -1 if an error was encountered.
1162 */
1163static ssize_t
1164t_ax_decrypt_and_validate (struct CadetTunnelAxolotl *ax,
1165 void *dst,
1166 const struct
1167 GNUNET_CADET_TunnelEncryptedMessage *src,
1168 size_t size)
1169{
1170 struct GNUNET_ShortHashCode msg_hmac;
1171 struct GNUNET_HashCode hmac;
1172 struct GNUNET_CADET_TunnelEncryptedMessage plaintext_header;
1173 uint32_t Np;
1174 uint32_t PNp;
1175 size_t esize; /* Size of encryped payload */
1176
1177 esize = size - sizeof(struct GNUNET_CADET_TunnelEncryptedMessage);
1178
1179 /* Try current HK */
1180 t_hmac (&src->ax_header,
1181 sizeof(struct GNUNET_CADET_AxHeader) + esize,
1182 0, &ax->HKr,
1183 &msg_hmac);
1184 if (0 != GNUNET_memcmp (&msg_hmac,
1185 &src->hmac))
1186 {
1187 static const char ctx[] = "axolotl ratchet";
1188 struct GNUNET_CRYPTO_SymmetricSessionKey keys[3]; /* RKp, NHKp, CKp */
1189 struct GNUNET_CRYPTO_SymmetricSessionKey HK;
1190 struct GNUNET_HashCode dh;
1191 struct GNUNET_CRYPTO_EcdhePublicKey *DHRp;
1192
1193 /* Try Next HK */
1194 t_hmac (&src->ax_header,
1195 sizeof(struct GNUNET_CADET_AxHeader) + esize,
1196 0,
1197 &ax->NHKr,
1198 &msg_hmac);
1199 if (0 != GNUNET_memcmp (&msg_hmac,
1200 &src->hmac))
1201 {
1202 /* Try the skipped keys, if that fails, we're out of luck. */
1203 return try_old_ax_keys (ax,
1204 dst,
1205 src,
1206 size);
1207 }
1208 HK = ax->HKr;
1209 ax->HKr = ax->NHKr;
1210 t_h_decrypt (ax,
1211 src,
1212 &plaintext_header);
1213 Np = ntohl (plaintext_header.ax_header.Ns);
1214 PNp = ntohl (plaintext_header.ax_header.PNs);
1215 DHRp = &plaintext_header.ax_header.DHRs;
1216 store_ax_keys (ax,
1217 &HK,
1218 PNp);
1219
1220 /* RKp, NHKp, CKp = KDF (HMAC-HASH (RK, DH (DHRp, DHRs))) */
1221 GNUNET_CRYPTO_ecc_ecdh (&ax->DHRs,
1222 DHRp,
1223 &dh);
1224 t_ax_hmac_hash (&ax->RK,
1225 &hmac,
1226 &dh, sizeof(dh));
1227 GNUNET_CRYPTO_kdf (keys, sizeof(keys),
1228 ctx, sizeof(ctx),
1229 &hmac, sizeof(hmac),
1230 NULL);
1231
1232 /* Commit "purported" keys */
1233 ax->RK = keys[0];
1234 ax->NHKr = keys[1];
1235 ax->CKr = keys[2];
1236 ax->DHRr = *DHRp;
1237 ax->Nr = 0;
1238 ax->ratchet_allowed = GNUNET_YES;
1239 }
1240 else
1241 {
1242 t_h_decrypt (ax,
1243 src,
1244 &plaintext_header);
1245 Np = ntohl (plaintext_header.ax_header.Ns);
1246 PNp = ntohl (plaintext_header.ax_header.PNs);
1247 }
1248 if ((Np != ax->Nr) &&
1249 (GNUNET_OK != store_ax_keys (ax,
1250 &ax->HKr,
1251 Np)))
1252 {
1253 /* Try the skipped keys, if that fails, we're out of luck. */
1254 return try_old_ax_keys (ax,
1255 dst,
1256 src,
1257 size);
1258 }
1259
1260 t_ax_decrypt (ax,
1261 dst,
1262 &src[1],
1263 esize);
1264 ax->Nr = Np + 1;
1265 return esize;
1266}
1267
1268
1269/**
1270 * Our tunnel became ready for the first time, notify channels
1271 * that have been waiting.
1272 *
1273 * @param cls our tunnel, not used
1274 * @param key unique ID of the channel, not used
1275 * @param value the `struct CadetChannel` to notify
1276 * @return #GNUNET_OK (continue to iterate)
1277 */
1278static int
1279notify_tunnel_up_cb (void *cls,
1280 uint32_t key,
1281 void *value)
1282{
1283 struct CadetChannel *ch = value;
1284
1285 GCCH_tunnel_up (ch);
1286 return GNUNET_OK;
1287}
1288
1289
1290/**
1291 * Change the tunnel encryption state.
1292 * If the encryption state changes to OK, stop the rekey task.
1293 *
1294 * @param t Tunnel whose encryption state to change, or NULL.
1295 * @param state New encryption state.
1296 */
1297void
1298GCT_change_estate (struct CadetTunnel *t,
1299 enum CadetTunnelEState state)
1300{
1301 enum CadetTunnelEState old = t->estate;
1302
1303 t->estate = state;
1304 LOG (GNUNET_ERROR_TYPE_DEBUG,
1305 "%s estate changed from %s to %s\n",
1306 GCT_2s (t),
1307 estate2s (old),
1308 estate2s (state));
1309
1310 if ((CADET_TUNNEL_KEY_OK != old) &&
1311 (CADET_TUNNEL_KEY_OK == t->estate))
1312 {
1313 if (NULL != t->kx_task)
1314 {
1315 GNUNET_SCHEDULER_cancel (t->kx_task);
1316 t->kx_task = NULL;
1317 }
1318 /* notify all channels that have been waiting */
1319 GNUNET_CONTAINER_multihashmap32_iterate (t->channels,
1320 &notify_tunnel_up_cb,
1321 t);
1322 if (NULL != t->send_task)
1323 GNUNET_SCHEDULER_cancel (t->send_task);
1324 t->send_task = GNUNET_SCHEDULER_add_now (&trigger_transmissions,
1325 t);
1326 }
1327}
1328
1329
1330/**
1331 * Send a KX message.
1332 *
1333 * @param t tunnel on which to send the KX_AUTH
1334 * @param ct Tunnel and connection on which to send the KX_AUTH, NULL if
1335 * we are to find one that is ready.
1336 * @param ax axolotl key context to use
1337 */
1338static void
1339send_kx (struct CadetTunnel *t,
1340 struct CadetTConnection *ct,
1341 struct CadetTunnelAxolotl *ax)
1342{
1343 struct CadetConnection *cc;
1344 struct GNUNET_MQ_Envelope *env;
1345 struct GNUNET_CADET_TunnelKeyExchangeMessage *msg;
1346 enum GNUNET_CADET_KX_Flags flags;
1347
1348 if (GNUNET_YES != GCT_alice_or_betty (GCP_get_id (t->destination)))
1349 return; /* only Alice may send KX */
1350 if ((NULL == ct) ||
1351 (GNUNET_NO == ct->is_ready))
1352 ct = get_ready_connection (t);
1353 if (NULL == ct)
1354 {
1355 LOG (GNUNET_ERROR_TYPE_DEBUG,
1356 "Wanted to send %s in state %s, but no connection is ready, deferring\n",
1357 GCT_2s (t),
1358 estate2s (t->estate));
1359 t->next_kx_attempt = GNUNET_TIME_absolute_get ();
1360 return;
1361 }
1362 cc = ct->cc;
1363 env = GNUNET_MQ_msg (msg,
1364 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX);
1365 flags = GNUNET_CADET_KX_FLAG_FORCE_REPLY; /* always for KX */
1366 msg->flags = htonl (flags);
1367 msg->cid = *GCC_get_id (cc);
1368 GNUNET_CRYPTO_ecdhe_key_get_public (&ax->kx_0,
1369 &msg->ephemeral_key);
1370#if DEBUG_KX
1371 msg->ephemeral_key_XXX = ax->kx_0;
1372 msg->private_key_XXX = *my_private_key;
1373#endif
1374 LOG (GNUNET_ERROR_TYPE_DEBUG,
1375 "Sending KX message to %s with ephemeral %s on CID %s\n",
1376 GCT_2s (t),
1377 GNUNET_e2s (&msg->ephemeral_key),
1378 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
1379 GNUNET_CRYPTO_ecdhe_key_get_public (&ax->DHRs,
1380 &msg->ratchet_key);
1381 mark_connection_unready (ct);
1382 t->kx_retry_delay = GNUNET_TIME_STD_BACKOFF (t->kx_retry_delay);
1383 t->next_kx_attempt = GNUNET_TIME_relative_to_absolute (t->kx_retry_delay);
1384 if (CADET_TUNNEL_KEY_UNINITIALIZED == t->estate)
1385 GCT_change_estate (t,
1386 CADET_TUNNEL_KEY_AX_SENT);
1387 else if (CADET_TUNNEL_KEY_AX_RECV == t->estate)
1388 GCT_change_estate (t,
1389 CADET_TUNNEL_KEY_AX_SENT_AND_RECV);
1390 GCC_transmit (cc,
1391 env);
1392 GNUNET_STATISTICS_update (stats,
1393 "# KX transmitted",
1394 1,
1395 GNUNET_NO);
1396}
1397
1398
1399/**
1400 * Send a KX_AUTH message.
1401 *
1402 * @param t tunnel on which to send the KX_AUTH
1403 * @param ct Tunnel and connection on which to send the KX_AUTH, NULL if
1404 * we are to find one that is ready.
1405 * @param ax axolotl key context to use
1406 * @param force_reply Force the other peer to reply with a KX_AUTH message
1407 * (set if we would like to transmit right now, but cannot)
1408 */
1409static void
1410send_kx_auth (struct CadetTunnel *t,
1411 struct CadetTConnection *ct,
1412 struct CadetTunnelAxolotl *ax,
1413 int force_reply)
1414{
1415 struct CadetConnection *cc;
1416 struct GNUNET_MQ_Envelope *env;
1417 struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg;
1418 enum GNUNET_CADET_KX_Flags flags;
1419
1420 if ((NULL == ct) ||
1421 (GNUNET_NO == ct->is_ready))
1422 ct = get_ready_connection (t);
1423 if (NULL == ct)
1424 {
1425 LOG (GNUNET_ERROR_TYPE_DEBUG,
1426 "Wanted to send KX_AUTH on %s, but no connection is ready, deferring\n",
1427 GCT_2s (t));
1428 t->next_kx_attempt = GNUNET_TIME_absolute_get ();
1429 t->kx_auth_requested = GNUNET_YES; /* queue KX_AUTH independent of estate */
1430 return;
1431 }
1432 t->kx_auth_requested = GNUNET_NO; /* clear flag */
1433 cc = ct->cc;
1434 env = GNUNET_MQ_msg (msg,
1435 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX_AUTH);
1436 flags = GNUNET_CADET_KX_FLAG_NONE;
1437 if (GNUNET_YES == force_reply)
1438 flags |= GNUNET_CADET_KX_FLAG_FORCE_REPLY;
1439 msg->kx.flags = htonl (flags);
1440 msg->kx.cid = *GCC_get_id (cc);
1441 GNUNET_CRYPTO_ecdhe_key_get_public (&ax->kx_0,
1442 &msg->kx.ephemeral_key);
1443 GNUNET_CRYPTO_ecdhe_key_get_public (&ax->DHRs,
1444 &msg->kx.ratchet_key);
1445#if DEBUG_KX
1446 msg->kx.ephemeral_key_XXX = ax->kx_0;
1447 msg->kx.private_key_XXX = *my_private_key;
1448 msg->r_ephemeral_key_XXX = ax->last_ephemeral;
1449#endif
1450 LOG (GNUNET_ERROR_TYPE_DEBUG,
1451 "Sending KX_AUTH message to %s with ephemeral %s on CID %s\n",
1452 GCT_2s (t),
1453 GNUNET_e2s (&msg->kx.ephemeral_key),
1454 GNUNET_sh2s (&msg->kx.cid.connection_of_tunnel));
1455
1456 /* Compute authenticator (this is the main difference to #send_kx()) */
1457 GNUNET_CRYPTO_hash (&ax->RK,
1458 sizeof(ax->RK),
1459 &msg->auth);
1460 /* Compute when to be triggered again; actual job will
1461 be scheduled via #connection_ready_cb() */
1462 t->kx_retry_delay
1463 = GNUNET_TIME_STD_BACKOFF (t->kx_retry_delay);
1464 t->next_kx_attempt
1465 = GNUNET_TIME_relative_to_absolute (t->kx_retry_delay);
1466
1467 /* Send via cc, mark it as unready */
1468 mark_connection_unready (ct);
1469
1470 /* Update state machine, unless we are already OK */
1471 if (CADET_TUNNEL_KEY_OK != t->estate)
1472 GCT_change_estate (t,
1473 CADET_TUNNEL_KEY_AX_AUTH_SENT);
1474 GCC_transmit (cc,
1475 env);
1476 GNUNET_STATISTICS_update (stats,
1477 "# KX_AUTH transmitted",
1478 1,
1479 GNUNET_NO);
1480}
1481
1482
1483/**
1484 * Cleanup state used by @a ax.
1485 *
1486 * @param ax state to free, but not memory of @a ax itself
1487 */
1488static void
1489cleanup_ax (struct CadetTunnelAxolotl *ax)
1490{
1491 while (NULL != ax->skipped_head)
1492 delete_skipped_key (ax,
1493 ax->skipped_head);
1494 GNUNET_assert (0 == ax->skipped);
1495 GNUNET_CRYPTO_ecdhe_key_clear (&ax->kx_0);
1496 GNUNET_CRYPTO_ecdhe_key_clear (&ax->DHRs);
1497}
1498
1499
1500/**
1501 * Update our Axolotl key state based on the KX data we received.
1502 * Computes the new chain keys, and root keys, etc, and also checks
1503 * whether this is a replay of the current chain.
1504 *
1505 * @param[in|out] axolotl chain key state to recompute
1506 * @param pid peer identity of the other peer
1507 * @param ephemeral_key ephemeral public key of the other peer
1508 * @param ratchet_key senders next ephemeral public key
1509 * @return #GNUNET_OK on success, #GNUNET_NO if the resulting
1510 * root key is already in @a ax and thus the KX is useless;
1511 * #GNUNET_SYSERR on hard errors (i.e. @a pid is #my_full_id)
1512 */
1513static int
1514update_ax_by_kx (struct CadetTunnelAxolotl *ax,
1515 const struct GNUNET_PeerIdentity *pid,
1516 const struct GNUNET_CRYPTO_EcdhePublicKey *ephemeral_key,
1517 const struct GNUNET_CRYPTO_EcdhePublicKey *ratchet_key)
1518{
1519 struct GNUNET_HashCode key_material[3];
1520 struct GNUNET_CRYPTO_SymmetricSessionKey keys[5];
1521 const char salt[] = "CADET Axolotl salt";
1522 int am_I_alice;
1523
1524 if (GNUNET_SYSERR == (am_I_alice = GCT_alice_or_betty (pid)))
1525 {
1526 GNUNET_break_op (0);
1527 return GNUNET_SYSERR;
1528 }
1529 if (0 == GNUNET_memcmp (&ax->DHRr,
1530 ratchet_key))
1531 {
1532 GNUNET_STATISTICS_update (stats,
1533 "# Ratchet key already known",
1534 1,
1535 GNUNET_NO);
1536 LOG (GNUNET_ERROR_TYPE_DEBUG,
1537 "Ratchet key already known. Ignoring KX.\n");
1538 return GNUNET_NO;
1539 }
1540
1541 ax->DHRr = *ratchet_key;
1542 ax->last_ephemeral = *ephemeral_key;
1543 /* ECDH A B0 */
1544 if (GNUNET_YES == am_I_alice)
1545 {
1546 GNUNET_CRYPTO_eddsa_ecdh (my_private_key, /* a */
1547 ephemeral_key, /* B0 */
1548 &key_material[0]);
1549 }
1550 else
1551 {
1552 GNUNET_CRYPTO_ecdh_eddsa (&ax->kx_0, /* b0 */
1553 &pid->public_key, /* A */
1554 &key_material[0]);
1555 }
1556 /* ECDH A0 B */
1557 if (GNUNET_YES == am_I_alice)
1558 {
1559 GNUNET_CRYPTO_ecdh_eddsa (&ax->kx_0, /* a0 */
1560 &pid->public_key, /* B */
1561 &key_material[1]);
1562 }
1563 else
1564 {
1565 GNUNET_CRYPTO_eddsa_ecdh (my_private_key, /* b */
1566 ephemeral_key, /* A0 */
1567 &key_material[1]);
1568 }
1569
1570 /* ECDH A0 B0 */
1571 GNUNET_CRYPTO_ecc_ecdh (&ax->kx_0, /* a0 or b0 */
1572 ephemeral_key, /* B0 or A0 */
1573 &key_material[2]);
1574 /* KDF */
1575 GNUNET_CRYPTO_kdf (keys, sizeof(keys),
1576 salt, sizeof(salt),
1577 &key_material, sizeof(key_material),
1578 NULL);
1579
1580 if (0 == memcmp (&ax->RK,
1581 &keys[0],
1582 sizeof(ax->RK)))
1583 {
1584 LOG (GNUNET_ERROR_TYPE_DEBUG,
1585 "Root key already known. Ignoring KX.\n");
1586 GNUNET_STATISTICS_update (stats,
1587 "# Root key already known",
1588 1,
1589 GNUNET_NO);
1590 return GNUNET_NO;
1591 }
1592
1593 ax->RK = keys[0];
1594 if (GNUNET_YES == am_I_alice)
1595 {
1596 ax->HKr = keys[1];
1597 ax->NHKs = keys[2];
1598 ax->NHKr = keys[3];
1599 ax->CKr = keys[4];
1600 ax->ratchet_flag = GNUNET_YES;
1601 }
1602 else
1603 {
1604 ax->HKs = keys[1];
1605 ax->NHKr = keys[2];
1606 ax->NHKs = keys[3];
1607 ax->CKs = keys[4];
1608 ax->ratchet_flag = GNUNET_NO;
1609 ax->ratchet_expiration
1610 = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
1611 ratchet_time);
1612 }
1613 return GNUNET_OK;
1614}
1615
1616
1617/**
1618 * Try to redo the KX or KX_AUTH handshake, if we can.
1619 *
1620 * @param cls the `struct CadetTunnel` to do KX for.
1621 */
1622static void
1623retry_kx (void *cls)
1624{
1625 struct CadetTunnel *t = cls;
1626 struct CadetTunnelAxolotl *ax;
1627
1628 t->kx_task = NULL;
1629 LOG (GNUNET_ERROR_TYPE_DEBUG,
1630 "Trying to make KX progress on %s in state %s\n",
1631 GCT_2s (t),
1632 estate2s (t->estate));
1633 switch (t->estate)
1634 {
1635 case CADET_TUNNEL_KEY_UNINITIALIZED: /* first attempt */
1636 case CADET_TUNNEL_KEY_AX_SENT: /* trying again */
1637 send_kx (t,
1638 NULL,
1639 &t->ax);
1640 break;
1641
1642 case CADET_TUNNEL_KEY_AX_RECV:
1643 case CADET_TUNNEL_KEY_AX_SENT_AND_RECV:
1644 /* We are responding, so only require reply
1645 if WE have a channel waiting. */
1646 if (NULL != t->unverified_ax)
1647 {
1648 /* Send AX_AUTH so we might get this one verified */
1649 ax = t->unverified_ax;
1650 }
1651 else
1652 {
1653 /* How can this be? */
1654 GNUNET_break (0);
1655 ax = &t->ax;
1656 }
1657 send_kx_auth (t,
1658 NULL,
1659 ax,
1660 (0 == GCT_count_channels (t))
1661 ? GNUNET_NO
1662 : GNUNET_YES);
1663 break;
1664
1665 case CADET_TUNNEL_KEY_AX_AUTH_SENT:
1666 /* We are responding, so only require reply
1667 if WE have a channel waiting. */
1668 if (NULL != t->unverified_ax)
1669 {
1670 /* Send AX_AUTH so we might get this one verified */
1671 ax = t->unverified_ax;
1672 }
1673 else
1674 {
1675 /* How can this be? */
1676 GNUNET_break (0);
1677 ax = &t->ax;
1678 }
1679 send_kx_auth (t,
1680 NULL,
1681 ax,
1682 (0 == GCT_count_channels (t))
1683 ? GNUNET_NO
1684 : GNUNET_YES);
1685 break;
1686
1687 case CADET_TUNNEL_KEY_OK:
1688 /* Must have been the *other* peer asking us to
1689 respond with a KX_AUTH. */
1690 if (NULL != t->unverified_ax)
1691 {
1692 /* Sending AX_AUTH in response to AX so we might get this one verified */
1693 ax = t->unverified_ax;
1694 }
1695 else
1696 {
1697 /* Sending AX_AUTH in response to AX_AUTH */
1698 ax = &t->ax;
1699 }
1700 send_kx_auth (t,
1701 NULL,
1702 ax,
1703 GNUNET_NO);
1704 break;
1705 }
1706}
1707
1708
1709/**
1710 * Handle KX message that lacks authentication (and which will thus
1711 * only be considered authenticated after we respond with our own
1712 * KX_AUTH and finally successfully decrypt payload).
1713 *
1714 * @param ct connection/tunnel combo that received encrypted message
1715 * @param msg the key exchange message
1716 */
1717void
1718GCT_handle_kx (struct CadetTConnection *ct,
1719 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
1720{
1721 struct CadetTunnel *t = ct->t;
1722 int ret;
1723
1724 GNUNET_STATISTICS_update (stats,
1725 "# KX received",
1726 1,
1727 GNUNET_NO);
1728 if (GNUNET_YES ==
1729 GCT_alice_or_betty (GCP_get_id (t->destination)))
1730 {
1731 /* Betty/Bob is not allowed to send KX! */
1732 GNUNET_break_op (0);
1733 return;
1734 }
1735 LOG (GNUNET_ERROR_TYPE_DEBUG,
1736 "Received KX message from %s with ephemeral %s from %s on connection %s\n",
1737 GCT_2s (t),
1738 GNUNET_e2s (&msg->ephemeral_key),
1739 GNUNET_i2s (GCP_get_id (t->destination)),
1740 GCC_2s (ct->cc));
1741#if 1
1742 if ((0 ==
1743 memcmp (&t->ax.DHRr,
1744 &msg->ratchet_key,
1745 sizeof(msg->ratchet_key))) &&
1746 (0 ==
1747 memcmp (&t->ax.last_ephemeral,
1748 &msg->ephemeral_key,
1749 sizeof(msg->ephemeral_key))))
1750
1751 {
1752 GNUNET_STATISTICS_update (stats,
1753 "# Duplicate KX received",
1754 1,
1755 GNUNET_NO);
1756 send_kx_auth (t,
1757 ct,
1758 &t->ax,
1759 GNUNET_NO);
1760 return;
1761 }
1762#endif
1763 /* We only keep ONE unverified KX around, so if there is an existing one,
1764 clean it up. */
1765 if (NULL != t->unverified_ax)
1766 {
1767 if ((0 ==
1768 memcmp (&t->unverified_ax->DHRr,
1769 &msg->ratchet_key,
1770 sizeof(msg->ratchet_key))) &&
1771 (0 ==
1772 memcmp (&t->unverified_ax->last_ephemeral,
1773 &msg->ephemeral_key,
1774 sizeof(msg->ephemeral_key))))
1775 {
1776 GNUNET_STATISTICS_update (stats,
1777 "# Duplicate unverified KX received",
1778 1,
1779 GNUNET_NO);
1780#if 1
1781 send_kx_auth (t,
1782 ct,
1783 t->unverified_ax,
1784 GNUNET_NO);
1785 return;
1786#endif
1787 }
1788 LOG (GNUNET_ERROR_TYPE_DEBUG,
1789 "Dropping old unverified KX state.\n");
1790 GNUNET_STATISTICS_update (stats,
1791 "# Unverified KX dropped for fresh KX",
1792 1,
1793 GNUNET_NO);
1794 GNUNET_break (NULL == t->unverified_ax->skipped_head);
1795 memset (t->unverified_ax,
1796 0,
1797 sizeof(struct CadetTunnelAxolotl));
1798 }
1799 else
1800 {
1801 LOG (GNUNET_ERROR_TYPE_DEBUG,
1802 "Creating fresh unverified KX for %s\n",
1803 GCT_2s (t));
1804 GNUNET_STATISTICS_update (stats,
1805 "# Fresh KX setup",
1806 1,
1807 GNUNET_NO);
1808 t->unverified_ax = GNUNET_new (struct CadetTunnelAxolotl);
1809 }
1810 /* Set as the 'current' RK/DHRr the one we are currently using,
1811 so that the duplicate-detection logic of
1812 #update_ax_by_kx can work. */
1813 t->unverified_ax->RK = t->ax.RK;
1814 t->unverified_ax->DHRr = t->ax.DHRr;
1815 t->unverified_ax->DHRs = t->ax.DHRs;
1816 t->unverified_ax->kx_0 = t->ax.kx_0;
1817 t->unverified_attempts = 0;
1818
1819 /* Update 'ax' by the new key material */
1820 ret = update_ax_by_kx (t->unverified_ax,
1821 GCP_get_id (t->destination),
1822 &msg->ephemeral_key,
1823 &msg->ratchet_key);
1824 GNUNET_break (GNUNET_SYSERR != ret);
1825 if (GNUNET_OK != ret)
1826 {
1827 GNUNET_STATISTICS_update (stats,
1828 "# Useless KX",
1829 1,
1830 GNUNET_NO);
1831 return; /* duplicate KX, nothing to do */
1832 }
1833 /* move ahead in our state machine */
1834 if (CADET_TUNNEL_KEY_UNINITIALIZED == t->estate)
1835 GCT_change_estate (t,
1836 CADET_TUNNEL_KEY_AX_RECV);
1837 else if (CADET_TUNNEL_KEY_AX_SENT == t->estate)
1838 GCT_change_estate (t,
1839 CADET_TUNNEL_KEY_AX_SENT_AND_RECV);
1840
1841 /* KX is still not done, try again our end. */
1842 if (CADET_TUNNEL_KEY_OK != t->estate)
1843 {
1844 if (NULL != t->kx_task)
1845 GNUNET_SCHEDULER_cancel (t->kx_task);
1846 t->kx_task
1847 = GNUNET_SCHEDULER_add_now (&retry_kx,
1848 t);
1849 }
1850}
1851
1852
1853#if DEBUG_KX
1854static void
1855check_ee (const struct GNUNET_CRYPTO_EcdhePrivateKey *e1,
1856 const struct GNUNET_CRYPTO_EcdhePrivateKey *e2)
1857{
1858 struct GNUNET_CRYPTO_EcdhePublicKey p1;
1859 struct GNUNET_CRYPTO_EcdhePublicKey p2;
1860 struct GNUNET_HashCode hc1;
1861 struct GNUNET_HashCode hc2;
1862
1863 GNUNET_CRYPTO_ecdhe_key_get_public (e1,
1864 &p1);
1865 GNUNET_CRYPTO_ecdhe_key_get_public (e2,
1866 &p2);
1867 GNUNET_assert (GNUNET_OK ==
1868 GNUNET_CRYPTO_ecc_ecdh (e1,
1869 &p2,
1870 &hc1));
1871 GNUNET_assert (GNUNET_OK ==
1872 GNUNET_CRYPTO_ecc_ecdh (e2,
1873 &p1,
1874 &hc2));
1875 GNUNET_break (0 == GNUNET_memcmp (&hc1,
1876 &hc2));
1877}
1878
1879
1880static void
1881check_ed (const struct GNUNET_CRYPTO_EcdhePrivateKey *e1,
1882 const struct GNUNET_CRYPTO_EddsaPrivateKey *e2)
1883{
1884 struct GNUNET_CRYPTO_EcdhePublicKey p1;
1885 struct GNUNET_CRYPTO_EddsaPublicKey p2;
1886 struct GNUNET_HashCode hc1;
1887 struct GNUNET_HashCode hc2;
1888
1889 GNUNET_CRYPTO_ecdhe_key_get_public (e1,
1890 &p1);
1891 GNUNET_CRYPTO_eddsa_key_get_public (e2,
1892 &p2);
1893 GNUNET_assert (GNUNET_OK ==
1894 GNUNET_CRYPTO_ecdh_eddsa (e1,
1895 &p2,
1896 &hc1));
1897 GNUNET_assert (GNUNET_OK ==
1898 GNUNET_CRYPTO_eddsa_ecdh (e2,
1899 &p1,
1900 &hc2));
1901 GNUNET_break (0 == GNUNET_memcmp (&hc1,
1902 &hc2));
1903}
1904
1905
1906static void
1907test_crypto_bug (const struct GNUNET_CRYPTO_EcdhePrivateKey *e1,
1908 const struct GNUNET_CRYPTO_EcdhePrivateKey *e2,
1909 const struct GNUNET_CRYPTO_EddsaPrivateKey *d1,
1910 const struct GNUNET_CRYPTO_EddsaPrivateKey *d2)
1911{
1912 check_ee (e1, e2);
1913 check_ed (e1, d2);
1914 check_ed (e2, d1);
1915}
1916
1917
1918#endif
1919
1920
1921/**
1922 * Handle KX_AUTH message.
1923 *
1924 * @param ct connection/tunnel combo that received encrypted message
1925 * @param msg the key exchange message
1926 */
1927void
1928GCT_handle_kx_auth (struct CadetTConnection *ct,
1929 const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg)
1930{
1931 struct CadetTunnel *t = ct->t;
1932 struct CadetTunnelAxolotl ax_tmp;
1933 struct GNUNET_HashCode kx_auth;
1934 int ret;
1935
1936 GNUNET_STATISTICS_update (stats,
1937 "# KX_AUTH received",
1938 1,
1939 GNUNET_NO);
1940 if ((CADET_TUNNEL_KEY_UNINITIALIZED == t->estate) ||
1941 (CADET_TUNNEL_KEY_AX_RECV == t->estate))
1942 {
1943 /* Confusing, we got a KX_AUTH before we even send our own
1944 KX. This should not happen. We'll send our own KX ASAP anyway,
1945 so let's ignore this here. */
1946 GNUNET_break_op (0);
1947 return;
1948 }
1949 LOG (GNUNET_ERROR_TYPE_DEBUG,
1950 "Handling KX_AUTH message from %s with ephemeral %s\n",
1951 GCT_2s (t),
1952 GNUNET_e2s (&msg->kx.ephemeral_key));
1953 /* We do everything in ax_tmp until we've checked the authentication
1954 so we don't clobber anything we care about by accident. */
1955 ax_tmp = t->ax;
1956
1957 /* Update 'ax' by the new key material */
1958 ret = update_ax_by_kx (&ax_tmp,
1959 GCP_get_id (t->destination),
1960 &msg->kx.ephemeral_key,
1961 &msg->kx.ratchet_key);
1962 if (GNUNET_OK != ret)
1963 {
1964 if (GNUNET_NO == ret)
1965 GNUNET_STATISTICS_update (stats,
1966 "# redundant KX_AUTH received",
1967 1,
1968 GNUNET_NO);
1969 else
1970 GNUNET_break (0); /* connect to self!? */
1971 return;
1972 }
1973 GNUNET_CRYPTO_hash (&ax_tmp.RK,
1974 sizeof(ax_tmp.RK),
1975 &kx_auth);
1976 if (0 != GNUNET_memcmp (&kx_auth,
1977 &msg->auth))
1978 {
1979 /* This KX_AUTH is not using the latest KX/KX_AUTH data
1980 we transmitted to the sender, refuse it, try KX again. */
1981 GNUNET_STATISTICS_update (stats,
1982 "# KX_AUTH not using our last KX received (auth failure)",
1983 1,
1984 GNUNET_NO);
1985 LOG (GNUNET_ERROR_TYPE_WARNING,
1986 "KX AUTH mismatch!\n");
1987#if DEBUG_KX
1988 {
1989 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
1990
1991 GNUNET_CRYPTO_ecdhe_key_get_public (&ax_tmp.kx_0,
1992 &ephemeral_key);
1993 if (0 != GNUNET_memcmp (&ephemeral_key,
1994 &msg->r_ephemeral_key_XXX))
1995 {
1996 LOG (GNUNET_ERROR_TYPE_WARNING,
1997 "My ephemeral is %s!\n",
1998 GNUNET_e2s (&ephemeral_key));
1999 LOG (GNUNET_ERROR_TYPE_WARNING,
2000 "Response is for ephemeral %s!\n",
2001 GNUNET_e2s (&msg->r_ephemeral_key_XXX));
2002 }
2003 else
2004 {
2005 test_crypto_bug (&ax_tmp.kx_0,
2006 &msg->kx.ephemeral_key_XXX,
2007 my_private_key,
2008 &msg->kx.private_key_XXX);
2009 }
2010 }
2011#endif
2012 if (NULL == t->kx_task)
2013 t->kx_task
2014 = GNUNET_SCHEDULER_add_at (t->next_kx_attempt,
2015 &retry_kx,
2016 t);
2017 return;
2018 }
2019 /* Yep, we're good. */
2020 t->ax = ax_tmp;
2021 if (NULL != t->unverified_ax)
2022 {
2023 /* We got some "stale" KX before, drop that. */
2024 cleanup_ax (t->unverified_ax);
2025 GNUNET_free (t->unverified_ax);
2026 t->unverified_ax = NULL;
2027 }
2028
2029 /* move ahead in our state machine */
2030 switch (t->estate)
2031 {
2032 case CADET_TUNNEL_KEY_UNINITIALIZED:
2033 case CADET_TUNNEL_KEY_AX_RECV:
2034 /* Checked above, this is impossible. */
2035 GNUNET_assert (0);
2036 break;
2037
2038 case CADET_TUNNEL_KEY_AX_SENT: /* This is the normal case */
2039 case CADET_TUNNEL_KEY_AX_SENT_AND_RECV: /* both peers started KX */
2040 case CADET_TUNNEL_KEY_AX_AUTH_SENT: /* both peers now did KX_AUTH */
2041 GCT_change_estate (t,
2042 CADET_TUNNEL_KEY_OK);
2043 break;
2044
2045 case CADET_TUNNEL_KEY_OK:
2046 /* Did not expect another KX_AUTH, but so what, still acceptable.
2047 Nothing to do here. */
2048 break;
2049 }
2050 if (0 != (GNUNET_CADET_KX_FLAG_FORCE_REPLY & ntohl (msg->kx.flags)))
2051 {
2052 send_kx_auth (t,
2053 NULL,
2054 &t->ax,
2055 GNUNET_NO);
2056 }
2057}
2058
2059
2060/* ************************************** end core crypto ***************************** */
2061
2062
2063/**
2064 * Compute the next free channel tunnel number for this tunnel.
2065 *
2066 * @param t the tunnel
2067 * @return unused number that can uniquely identify a channel in the tunnel
2068 */
2069static struct GNUNET_CADET_ChannelTunnelNumber
2070get_next_free_ctn (struct CadetTunnel *t)
2071{
2072#define HIGH_BIT 0x8000000
2073 struct GNUNET_CADET_ChannelTunnelNumber ret;
2074 uint32_t ctn;
2075 int cmp;
2076 uint32_t highbit;
2077
2078 cmp = GNUNET_memcmp (&my_full_id,
2079 GCP_get_id (GCT_get_destination (t)));
2080 if (0 < cmp)
2081 highbit = HIGH_BIT;
2082 else if (0 > cmp)
2083 highbit = 0;
2084 else
2085 GNUNET_assert (0); // loopback must never go here!
2086 ctn = ntohl (t->next_ctn.cn);
2087 while (NULL !=
2088 GNUNET_CONTAINER_multihashmap32_get (t->channels,
2089 ctn | highbit))
2090 {
2091 ctn = ((ctn + 1) & (~HIGH_BIT));
2092 }
2093 t->next_ctn.cn = htonl ((ctn + 1) & (~HIGH_BIT));
2094 ret.cn = htonl (ctn | highbit);
2095 return ret;
2096}
2097
2098
2099/**
2100 * Add a channel to a tunnel, and notify channel that we are ready
2101 * for transmission if we are already up. Otherwise that notification
2102 * will be done later in #notify_tunnel_up_cb().
2103 *
2104 * @param t Tunnel.
2105 * @param ch Channel
2106 * @return unique number identifying @a ch within @a t
2107 */
2108struct GNUNET_CADET_ChannelTunnelNumber
2109GCT_add_channel (struct CadetTunnel *t,
2110 struct CadetChannel *ch)
2111{
2112 struct GNUNET_CADET_ChannelTunnelNumber ctn;
2113
2114 ctn = get_next_free_ctn (t);
2115 if (NULL != t->destroy_task)
2116 {
2117 GNUNET_SCHEDULER_cancel (t->destroy_task);
2118 t->destroy_task = NULL;
2119 }
2120 GNUNET_assert (GNUNET_YES ==
2121 GNUNET_CONTAINER_multihashmap32_put (t->channels,
2122 ntohl (ctn.cn),
2123 ch,
2124 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
2125 LOG (GNUNET_ERROR_TYPE_DEBUG,
2126 "Adding %s to %s with state %d\n",
2127 GCCH_2s (ch),
2128 GCT_2s (t),
2129 t->estate);
2130 switch (t->estate)
2131 {
2132 case CADET_TUNNEL_KEY_UNINITIALIZED:
2133 /* waiting for connection to start KX */
2134 break;
2135
2136 case CADET_TUNNEL_KEY_AX_RECV:
2137 case CADET_TUNNEL_KEY_AX_SENT:
2138 case CADET_TUNNEL_KEY_AX_SENT_AND_RECV:
2139 /* we're currently waiting for KX to complete */
2140 break;
2141
2142 case CADET_TUNNEL_KEY_AX_AUTH_SENT:
2143 /* waiting for OTHER peer to send us data,
2144 we might need to prompt more aggressively! */
2145 if (NULL == t->kx_task)
2146 t->kx_task
2147 = GNUNET_SCHEDULER_add_at (t->next_kx_attempt,
2148 &retry_kx,
2149 t);
2150 break;
2151
2152 case CADET_TUNNEL_KEY_OK:
2153 /* We are ready. Tell the new channel that we are up. */
2154 GCCH_tunnel_up (ch);
2155 break;
2156 }
2157 return ctn;
2158}
2159
2160
2161/**
2162 * We lost a connection, remove it from our list and clean up
2163 * the connection object itself.
2164 *
2165 * @param ct binding of connection to tunnel of the connection that was lost.
2166 */
2167void
2168GCT_connection_lost (struct CadetTConnection *ct)
2169{
2170 struct CadetTunnel *t = ct->t;
2171
2172 if (GNUNET_YES == ct->is_ready)
2173 {
2174 GNUNET_CONTAINER_DLL_remove (t->connection_ready_head,
2175 t->connection_ready_tail,
2176 ct);
2177 t->num_ready_connections--;
2178 }
2179 else
2180 {
2181 GNUNET_CONTAINER_DLL_remove (t->connection_busy_head,
2182 t->connection_busy_tail,
2183 ct);
2184 t->num_busy_connections--;
2185 }
2186 GNUNET_free (ct);
2187}
2188
2189
2190/**
2191 * Clean up connection @a ct of a tunnel.
2192 *
2193 * @param cls the `struct CadetTunnel`
2194 * @param ct connection to clean up
2195 */
2196static void
2197destroy_t_connection (void *cls,
2198 struct CadetTConnection *ct)
2199{
2200 struct CadetTunnel *t = cls;
2201 struct CadetConnection *cc = ct->cc;
2202
2203 GNUNET_assert (ct->t == t);
2204 GCT_connection_lost (ct);
2205 GCC_destroy_without_tunnel (cc);
2206}
2207
2208
2209/**
2210 * This tunnel is no longer used, destroy it.
2211 *
2212 * @param cls the idle tunnel
2213 */
2214static void
2215destroy_tunnel (void *cls)
2216{
2217 struct CadetTunnel *t = cls;
2218 struct CadetTunnelQueueEntry *tq;
2219
2220 t->destroy_task = NULL;
2221 LOG (GNUNET_ERROR_TYPE_DEBUG,
2222 "Destroying idle %s\n",
2223 GCT_2s (t));
2224 GNUNET_assert (0 == GCT_count_channels (t));
2225 GCT_iterate_connections (t,
2226 &destroy_t_connection,
2227 t);
2228 GNUNET_assert (NULL == t->connection_ready_head);
2229 GNUNET_assert (NULL == t->connection_busy_head);
2230 while (NULL != (tq = t->tq_head))
2231 {
2232 if (NULL != tq->cont)
2233 tq->cont (tq->cont_cls,
2234 NULL);
2235 GCT_send_cancel (tq);
2236 }
2237 GCP_drop_tunnel (t->destination,
2238 t);
2239 GNUNET_CONTAINER_multihashmap32_destroy (t->channels);
2240 if (NULL != t->maintain_connections_task)
2241 {
2242 GNUNET_SCHEDULER_cancel (t->maintain_connections_task);
2243 t->maintain_connections_task = NULL;
2244 }
2245 if (NULL != t->send_task)
2246 {
2247 GNUNET_SCHEDULER_cancel (t->send_task);
2248 t->send_task = NULL;
2249 }
2250 if (NULL != t->kx_task)
2251 {
2252 GNUNET_SCHEDULER_cancel (t->kx_task);
2253 t->kx_task = NULL;
2254 }
2255 GNUNET_MST_destroy (t->mst);
2256 GNUNET_MQ_destroy (t->mq);
2257 if (NULL != t->unverified_ax)
2258 {
2259 cleanup_ax (t->unverified_ax);
2260 GNUNET_free (t->unverified_ax);
2261 }
2262 cleanup_ax (&t->ax);
2263 GNUNET_assert (NULL == t->destroy_task);
2264 GNUNET_free (t);
2265}
2266
2267
2268/**
2269 * Remove a channel from a tunnel.
2270 *
2271 * @param t Tunnel.
2272 * @param ch Channel
2273 * @param ctn unique number identifying @a ch within @a t
2274 */
2275void
2276GCT_remove_channel (struct CadetTunnel *t,
2277 struct CadetChannel *ch,
2278 struct GNUNET_CADET_ChannelTunnelNumber ctn)
2279{
2280 LOG (GNUNET_ERROR_TYPE_DEBUG,
2281 "Removing %s from %s\n",
2282 GCCH_2s (ch),
2283 GCT_2s (t));
2284 GNUNET_assert (GNUNET_YES ==
2285 GNUNET_CONTAINER_multihashmap32_remove (t->channels,
2286 ntohl (ctn.cn),
2287 ch));
2288 if ((0 ==
2289 GCT_count_channels (t)) &&
2290 (NULL == t->destroy_task))
2291 {
2292 t->destroy_task
2293 = GNUNET_SCHEDULER_add_delayed (IDLE_DESTROY_DELAY,
2294 &destroy_tunnel,
2295 t);
2296 }
2297}
2298
2299
2300/**
2301 * Destroy remaining channels during shutdown.
2302 *
2303 * @param cls the `struct CadetTunnel` of the channel
2304 * @param key key of the channel
2305 * @param value the `struct CadetChannel`
2306 * @return #GNUNET_OK (continue to iterate)
2307 */
2308static int
2309destroy_remaining_channels (void *cls,
2310 uint32_t key,
2311 void *value)
2312{
2313 struct CadetChannel *ch = value;
2314
2315 GCCH_handle_remote_destroy (ch,
2316 NULL);
2317 return GNUNET_OK;
2318}
2319
2320
2321/**
2322 * Destroys the tunnel @a t now, without delay. Used during shutdown.
2323 *
2324 * @param t tunnel to destroy
2325 */
2326void
2327GCT_destroy_tunnel_now (struct CadetTunnel *t)
2328{
2329 GNUNET_assert (GNUNET_YES == shutting_down);
2330 GNUNET_CONTAINER_multihashmap32_iterate (t->channels,
2331 &destroy_remaining_channels,
2332 t);
2333 GNUNET_assert (0 ==
2334 GCT_count_channels (t));
2335 if (NULL != t->destroy_task)
2336 {
2337 GNUNET_SCHEDULER_cancel (t->destroy_task);
2338 t->destroy_task = NULL;
2339 }
2340 destroy_tunnel (t);
2341}
2342
2343
2344/**
2345 * Send normal payload from queue in @a t via connection @a ct.
2346 * Does nothing if our payload queue is empty.
2347 *
2348 * @param t tunnel to send data from
2349 * @param ct connection to use for transmission (is ready)
2350 */
2351static void
2352try_send_normal_payload (struct CadetTunnel *t,
2353 struct CadetTConnection *ct)
2354{
2355 struct CadetTunnelQueueEntry *tq;
2356
2357 GNUNET_assert (GNUNET_YES == ct->is_ready);
2358 tq = t->tq_head;
2359 if (NULL == tq)
2360 {
2361 /* no messages pending right now */
2362 LOG (GNUNET_ERROR_TYPE_DEBUG,
2363 "Not sending payload of %s on ready %s (nothing pending)\n",
2364 GCT_2s (t),
2365 GCC_2s (ct->cc));
2366 return;
2367 }
2368 /* ready to send message 'tq' on tunnel 'ct' */
2369 GNUNET_assert (t == tq->t);
2370 GNUNET_CONTAINER_DLL_remove (t->tq_head,
2371 t->tq_tail,
2372 tq);
2373 if (NULL != tq->cid)
2374 *tq->cid = *GCC_get_id (ct->cc);
2375 mark_connection_unready (ct);
2376 LOG (GNUNET_ERROR_TYPE_DEBUG,
2377 "Sending payload of %s on %s\n",
2378 GCT_2s (t),
2379 GCC_2s (ct->cc));
2380 GCC_transmit (ct->cc,
2381 tq->env);
2382 if (NULL != tq->cont)
2383 tq->cont (tq->cont_cls,
2384 GCC_get_id (ct->cc));
2385 GNUNET_free (tq);
2386}
2387
2388
2389/**
2390 * A connection is @a is_ready for transmission. Looks at our message
2391 * queue and if there is a message, sends it out via the connection.
2392 *
2393 * @param cls the `struct CadetTConnection` that is @a is_ready
2394 * @param is_ready #GNUNET_YES if connection are now ready,
2395 * #GNUNET_NO if connection are no longer ready
2396 */
2397static void
2398connection_ready_cb (void *cls,
2399 int is_ready)
2400{
2401 struct CadetTConnection *ct = cls;
2402 struct CadetTunnel *t = ct->t;
2403
2404 if (GNUNET_NO == is_ready)
2405 {
2406 LOG (GNUNET_ERROR_TYPE_DEBUG,
2407 "%s no longer ready for %s\n",
2408 GCC_2s (ct->cc),
2409 GCT_2s (t));
2410 mark_connection_unready (ct);
2411 return;
2412 }
2413 GNUNET_assert (GNUNET_NO == ct->is_ready);
2414 GNUNET_CONTAINER_DLL_remove (t->connection_busy_head,
2415 t->connection_busy_tail,
2416 ct);
2417 GNUNET_assert (0 < t->num_busy_connections);
2418 t->num_busy_connections--;
2419 ct->is_ready = GNUNET_YES;
2420 GNUNET_CONTAINER_DLL_insert_tail (t->connection_ready_head,
2421 t->connection_ready_tail,
2422 ct);
2423 t->num_ready_connections++;
2424
2425 LOG (GNUNET_ERROR_TYPE_DEBUG,
2426 "%s now ready for %s in state %s\n",
2427 GCC_2s (ct->cc),
2428 GCT_2s (t),
2429 estate2s (t->estate));
2430 switch (t->estate)
2431 {
2432 case CADET_TUNNEL_KEY_UNINITIALIZED:
2433 LOG (GNUNET_ERROR_TYPE_DEBUG,
2434 "Do not begin KX for %s if WE have no channels waiting. Retrying after %llu\n",
2435 GCT_2s (t),
2436 (unsigned long long) GNUNET_TIME_absolute_get_remaining (
2437 t->next_kx_attempt).rel_value_us);
2438 /* Do not begin KX if WE have no channels waiting! */
2439 if (0 != GNUNET_TIME_absolute_get_remaining (
2440 t->next_kx_attempt).rel_value_us)
2441 return; /* wait for timeout before retrying */
2442 /* We are uninitialized, just transmit immediately,
2443 without undue delay. */
2444
2445 LOG (GNUNET_ERROR_TYPE_DEBUG,
2446 "Why for %s \n",
2447 GCT_2s (t));
2448
2449 if (NULL != t->kx_task)
2450 {
2451 GNUNET_SCHEDULER_cancel (t->kx_task);
2452 t->kx_task = NULL;
2453 }
2454 send_kx (t,
2455 ct,
2456 &t->ax);
2457 if ((0 ==
2458 GCT_count_channels (t)) &&
2459 (NULL == t->destroy_task))
2460 {
2461 t->destroy_task
2462 = GNUNET_SCHEDULER_add_delayed (IDLE_DESTROY_DELAY,
2463 &destroy_tunnel,
2464 t);
2465 }
2466 break;
2467
2468 case CADET_TUNNEL_KEY_AX_RECV:
2469 case CADET_TUNNEL_KEY_AX_SENT:
2470 case CADET_TUNNEL_KEY_AX_SENT_AND_RECV:
2471 case CADET_TUNNEL_KEY_AX_AUTH_SENT:
2472 /* we're currently waiting for KX to complete, schedule job */
2473 if (NULL == t->kx_task)
2474 t->kx_task
2475 = GNUNET_SCHEDULER_add_at (t->next_kx_attempt,
2476 &retry_kx,
2477 t);
2478 break;
2479
2480 case CADET_TUNNEL_KEY_OK:
2481 if (GNUNET_YES == t->kx_auth_requested)
2482 {
2483 if (0 != GNUNET_TIME_absolute_get_remaining (
2484 t->next_kx_attempt).rel_value_us)
2485 return; /* wait for timeout */
2486 if (NULL != t->kx_task)
2487 {
2488 GNUNET_SCHEDULER_cancel (t->kx_task);
2489 t->kx_task = NULL;
2490 }
2491 send_kx_auth (t,
2492 ct,
2493 &t->ax,
2494 GNUNET_NO);
2495 return;
2496 }
2497 try_send_normal_payload (t,
2498 ct);
2499 break;
2500 }
2501}
2502
2503
2504/**
2505 * Called when either we have a new connection, or a new message in the
2506 * queue, or some existing connection has transmission capacity. Looks
2507 * at our message queue and if there is a message, picks a connection
2508 * to send it on.
2509 *
2510 * @param cls the `struct CadetTunnel` to process messages on
2511 */
2512static void
2513trigger_transmissions (void *cls)
2514{
2515 struct CadetTunnel *t = cls;
2516 struct CadetTConnection *ct;
2517
2518 t->send_task = NULL;
2519 if (NULL == t->tq_head)
2520 return; /* no messages pending right now */
2521 ct = get_ready_connection (t);
2522 if (NULL == ct)
2523 return; /* no connections ready */
2524 try_send_normal_payload (t,
2525 ct);
2526}
2527
2528
2529/**
2530 * Closure for #evaluate_connection. Used to assemble summary information
2531 * about the existing connections so we can evaluate a new path.
2532 */
2533struct EvaluationSummary
2534{
2535 /**
2536 * Minimum length of any of our connections, `UINT_MAX` if we have none.
2537 */
2538 unsigned int min_length;
2539
2540 /**
2541 * Maximum length of any of our connections, 0 if we have none.
2542 */
2543 unsigned int max_length;
2544
2545 /**
2546 * Minimum desirability of any of our connections, UINT64_MAX if we have none.
2547 */
2548 GNUNET_CONTAINER_HeapCostType min_desire;
2549
2550 /**
2551 * Maximum desirability of any of our connections, 0 if we have none.
2552 */
2553 GNUNET_CONTAINER_HeapCostType max_desire;
2554
2555 /**
2556 * Path we are comparing against for #evaluate_connection, can be NULL.
2557 */
2558 struct CadetPeerPath *path;
2559
2560 /**
2561 * Connection deemed the "worst" so far encountered by #evaluate_connection,
2562 * NULL if we did not yet encounter any connections.
2563 */
2564 struct CadetTConnection *worst;
2565
2566 /**
2567 * Numeric score of @e worst, only set if @e worst is non-NULL.
2568 */
2569 double worst_score;
2570
2571 /**
2572 * Set to #GNUNET_YES if we have a connection over @e path already.
2573 */
2574 int duplicate;
2575};
2576
2577
2578/**
2579 * Evaluate a connection, updating our summary information in @a cls about
2580 * what kinds of connections we have.
2581 *
2582 * @param cls the `struct EvaluationSummary *` to update
2583 * @param ct a connection to include in the summary
2584 */
2585static void
2586evaluate_connection (void *cls,
2587 struct CadetTConnection *ct)
2588{
2589 struct EvaluationSummary *es = cls;
2590 struct CadetConnection *cc = ct->cc;
2591 unsigned int ct_length;
2592 struct CadetPeerPath *ps;
2593 const struct CadetConnectionMetrics *metrics;
2594 GNUNET_CONTAINER_HeapCostType ct_desirability;
2595 struct GNUNET_TIME_Relative uptime;
2596 struct GNUNET_TIME_Relative last_use;
2597 double score;
2598 double success_rate;
2599
2600 ps = GCC_get_path (cc,
2601 &ct_length);
2602 LOG (GNUNET_ERROR_TYPE_DEBUG,
2603 "Evaluating path %s of existing %s\n",
2604 GCPP_2s (ps),
2605 GCC_2s (cc));
2606 if (ps == es->path)
2607 {
2608 LOG (GNUNET_ERROR_TYPE_DEBUG,
2609 "Ignoring duplicate path %s.\n",
2610 GCPP_2s (es->path));
2611 es->duplicate = GNUNET_YES;
2612 return;
2613 }
2614 if (NULL != es->path)
2615 {
2616 int duplicate = GNUNET_YES;
2617
2618 for (unsigned int i = 0; i < ct_length; i++)
2619 {
2620 GNUNET_assert (GCPP_get_length (es->path) > i);
2621 if (GCPP_get_peer_at_offset (es->path,
2622 i) !=
2623 GCPP_get_peer_at_offset (ps,
2624 i))
2625 {
2626 duplicate = GNUNET_NO;
2627 break;
2628 }
2629 }
2630 if (GNUNET_YES == duplicate)
2631 {
2632 LOG (GNUNET_ERROR_TYPE_DEBUG,
2633 "Ignoring overlapping path %s.\n",
2634 GCPP_2s (es->path));
2635 es->duplicate = GNUNET_YES;
2636 return;
2637 }
2638 else
2639 {
2640 LOG (GNUNET_ERROR_TYPE_DEBUG,
2641 "Known path %s differs from proposed path\n",
2642 GCPP_2s (ps));
2643 }
2644 }
2645
2646 ct_desirability = GCPP_get_desirability (ps);
2647 metrics = GCC_get_metrics (cc);
2648 uptime = GNUNET_TIME_absolute_get_duration (metrics->age);
2649 last_use = GNUNET_TIME_absolute_get_duration (metrics->last_use);
2650 /* We add 1.0 here to avoid division by zero. */
2651 success_rate = (metrics->num_acked_transmissions + 1.0)
2652 / (metrics->num_successes + 1.0);
2653 score
2654 = ct_desirability
2655 + 100.0 / (1.0 + ct_length) /* longer paths = better */
2656 + sqrt (uptime.rel_value_us / 60000000LL) /* larger uptime = better */
2657 - last_use.rel_value_us / 1000L; /* longer idle = worse */
2658 score *= success_rate; /* weigh overall by success rate */
2659
2660 if ((NULL == es->worst) ||
2661 (score < es->worst_score))
2662 {
2663 es->worst = ct;
2664 es->worst_score = score;
2665 }
2666 es->min_length = GNUNET_MIN (es->min_length,
2667 ct_length);
2668 es->max_length = GNUNET_MAX (es->max_length,
2669 ct_length);
2670 es->min_desire = GNUNET_MIN (es->min_desire,
2671 ct_desirability);
2672 es->max_desire = GNUNET_MAX (es->max_desire,
2673 ct_desirability);
2674}
2675
2676
2677/**
2678 * Consider using the path @a p for the tunnel @a t.
2679 * The tunnel destination is at offset @a off in path @a p.
2680 *
2681 * @param cls our tunnel
2682 * @param path a path to our destination
2683 * @param off offset of the destination on path @a path
2684 * @return #GNUNET_YES (should keep iterating)
2685 */
2686static int
2687consider_path_cb (void *cls,
2688 struct CadetPeerPath *path,
2689 unsigned int off)
2690{
2691 struct CadetTunnel *t = cls;
2692 struct EvaluationSummary es;
2693 struct CadetTConnection *ct;
2694
2695 GNUNET_assert (off < GCPP_get_length (path));
2696 GNUNET_assert (GCPP_get_peer_at_offset (path,
2697 off) == t->destination);
2698 es.min_length = UINT_MAX;
2699 es.max_length = 0;
2700 es.max_desire = 0;
2701 es.min_desire = UINT64_MAX;
2702 es.path = path;
2703 es.duplicate = GNUNET_NO;
2704 es.worst = NULL;
2705
2706 /* Compute evaluation summary over existing connections. */
2707 LOG (GNUNET_ERROR_TYPE_DEBUG,
2708 "Evaluating proposed path %s for target %s\n",
2709 GCPP_2s (path),
2710 GCT_2s (t));
2711 /* FIXME: suspect this does not ACTUALLY iterate
2712 over all existing paths, otherwise dup detection
2713 should work!!! */
2714 GCT_iterate_connections (t,
2715 &evaluate_connection,
2716 &es);
2717 if (GNUNET_YES == es.duplicate)
2718 return GNUNET_YES;
2719
2720 /* FIXME: not sure we should really just count
2721 'num_connections' here, as they may all have
2722 consistently failed to connect. */
2723
2724 /* We iterate by increasing path length; if we have enough paths and
2725 this one is more than twice as long than what we are currently
2726 using, then ignore all of these super-long ones! */
2727 if ((GCT_count_any_connections (t) > DESIRED_CONNECTIONS_PER_TUNNEL) &&
2728 (es.min_length * 2 < off) &&
2729 (es.max_length < off))
2730 {
2731 LOG (GNUNET_ERROR_TYPE_DEBUG,
2732 "Ignoring paths of length %u, they are way too long.\n",
2733 es.min_length * 2);
2734 return GNUNET_NO;
2735 }
2736 /* If we have enough paths and this one looks no better, ignore it. */
2737 if ((GCT_count_any_connections (t) >= DESIRED_CONNECTIONS_PER_TUNNEL) &&
2738 (es.min_length < GCPP_get_length (path)) &&
2739 (es.min_desire > GCPP_get_desirability (path)) &&
2740 (es.max_length < off))
2741 {
2742 LOG (GNUNET_ERROR_TYPE_DEBUG,
2743 "Ignoring path (%u/%llu) to %s, got something better already.\n",
2744 GCPP_get_length (path),
2745 (unsigned long long) GCPP_get_desirability (path),
2746 GCP_2s (t->destination));
2747 return GNUNET_YES;
2748 }
2749
2750 /* Path is interesting (better by some metric, or we don't have
2751 enough paths yet). */
2752 ct = GNUNET_new (struct CadetTConnection);
2753 ct->created = GNUNET_TIME_absolute_get ();
2754 ct->t = t;
2755 ct->cc = GCC_create (t->destination,
2756 path,
2757 off,
2758 ct,
2759 &connection_ready_cb,
2760 ct);
2761
2762 /* FIXME: schedule job to kill connection (and path?) if it takes
2763 too long to get ready! (And track performance data on how long
2764 other connections took with the tunnel!)
2765 => Note: to be done within 'connection'-logic! */
2766 GNUNET_CONTAINER_DLL_insert (t->connection_busy_head,
2767 t->connection_busy_tail,
2768 ct);
2769 t->num_busy_connections++;
2770 LOG (GNUNET_ERROR_TYPE_DEBUG,
2771 "Found interesting path %s for %s, created %s\n",
2772 GCPP_2s (path),
2773 GCT_2s (t),
2774 GCC_2s (ct->cc));
2775 return GNUNET_YES;
2776}
2777
2778
2779/**
2780 * Function called to maintain the connections underlying our tunnel.
2781 * Tries to maintain (incl. tear down) connections for the tunnel, and
2782 * if there is a significant change, may trigger transmissions.
2783 *
2784 * Basically, needs to check if there are connections that perform
2785 * badly, and if so eventually kill them and trigger a replacement.
2786 * The strategy is to open one more connection than
2787 * #DESIRED_CONNECTIONS_PER_TUNNEL, and then periodically kick out the
2788 * least-performing one, and then inquire for new ones.
2789 *
2790 * @param cls the `struct CadetTunnel`
2791 */
2792static void
2793maintain_connections_cb (void *cls)
2794{
2795 struct CadetTunnel *t = cls;
2796 struct GNUNET_TIME_Relative delay;
2797 struct EvaluationSummary es;
2798
2799 t->maintain_connections_task = NULL;
2800 LOG (GNUNET_ERROR_TYPE_DEBUG,
2801 "Performing connection maintenance for %s.\n",
2802 GCT_2s (t));
2803
2804 es.min_length = UINT_MAX;
2805 es.max_length = 0;
2806 es.max_desire = 0;
2807 es.min_desire = UINT64_MAX;
2808 es.path = NULL;
2809 es.worst = NULL;
2810 es.duplicate = GNUNET_NO;
2811 GCT_iterate_connections (t,
2812 &evaluate_connection,
2813 &es);
2814 if ((NULL != es.worst) &&
2815 (GCT_count_any_connections (t) > DESIRED_CONNECTIONS_PER_TUNNEL))
2816 {
2817 /* Clear out worst-performing connection 'es.worst'. */
2818 destroy_t_connection (t,
2819 es.worst);
2820 }
2821
2822 /* Consider additional paths */
2823 (void) GCP_iterate_paths (t->destination,
2824 &consider_path_cb,
2825 t);
2826
2827 /* FIXME: calculate when to try again based on how well we are doing;
2828 in particular, if we have to few connections, we might be able
2829 to do without this (as PATHS should tell us whenever a new path
2830 is available instantly; however, need to make sure this job is
2831 restarted after that happens).
2832 Furthermore, if the paths we do know are in a reasonably narrow
2833 quality band and are plentyful, we might also consider us stabilized
2834 and then reduce the frequency accordingly. */delay = GNUNET_TIME_UNIT_MINUTES;
2835 t->maintain_connections_task
2836 = GNUNET_SCHEDULER_add_delayed (delay,
2837 &maintain_connections_cb,
2838 t);
2839}
2840
2841
2842/**
2843 * Consider using the path @a p for the tunnel @a t.
2844 * The tunnel destination is at offset @a off in path @a p.
2845 *
2846 * @param cls our tunnel
2847 * @param path a path to our destination
2848 * @param off offset of the destination on path @a path
2849 */
2850void
2851GCT_consider_path (struct CadetTunnel *t,
2852 struct CadetPeerPath *p,
2853 unsigned int off)
2854{
2855 LOG (GNUNET_ERROR_TYPE_DEBUG,
2856 "Considering %s for %s (offset %u)\n",
2857 GCPP_2s (p),
2858 GCT_2s (t),
2859 off);
2860 (void) consider_path_cb (t,
2861 p,
2862 off);
2863}
2864
2865
2866/**
2867 * We got a keepalive. Track in statistics.
2868 *
2869 * @param cls the `struct CadetTunnel` for which we decrypted the message
2870 * @param msg the message we received on the tunnel
2871 */
2872static void
2873handle_plaintext_keepalive (void *cls,
2874 const struct GNUNET_MessageHeader *msg)
2875{
2876 struct CadetTunnel *t = cls;
2877
2878 LOG (GNUNET_ERROR_TYPE_DEBUG,
2879 "Received KEEPALIVE on %s\n",
2880 GCT_2s (t));
2881 GNUNET_STATISTICS_update (stats,
2882 "# keepalives received",
2883 1,
2884 GNUNET_NO);
2885}
2886
2887
2888/**
2889 * Check that @a msg is well-formed.
2890 *
2891 * @param cls the `struct CadetTunnel` for which we decrypted the message
2892 * @param msg the message we received on the tunnel
2893 * @return #GNUNET_OK (any variable-size payload goes)
2894 */
2895static int
2896check_plaintext_data (void *cls,
2897 const struct GNUNET_CADET_ChannelAppDataMessage *msg)
2898{
2899 return GNUNET_OK;
2900}
2901
2902
2903/**
2904 * We received payload data for a channel. Locate the channel
2905 * and process the data, or return an error if the channel is unknown.
2906 *
2907 * @param cls the `struct CadetTunnel` for which we decrypted the message
2908 * @param msg the message we received on the tunnel
2909 */
2910static void
2911handle_plaintext_data (void *cls,
2912 const struct GNUNET_CADET_ChannelAppDataMessage *msg)
2913{
2914 struct CadetTunnel *t = cls;
2915 struct CadetChannel *ch;
2916
2917 ch = lookup_channel (t,
2918 msg->ctn);
2919 if (NULL == ch)
2920 {
2921 /* We don't know about such a channel, might have been destroyed on our
2922 end in the meantime, or never existed. Send back a DESTROY. */
2923 LOG (GNUNET_ERROR_TYPE_DEBUG,
2924 "Received %u bytes of application data for unknown channel %u, sending DESTROY\n",
2925 (unsigned int) (ntohs (msg->header.size) - sizeof(*msg)),
2926 ntohl (msg->ctn.cn));
2927 GCT_send_channel_destroy (t,
2928 msg->ctn);
2929 return;
2930 }
2931 GCCH_handle_channel_plaintext_data (ch,
2932 GCC_get_id (t->current_ct->cc),
2933 msg);
2934}
2935
2936
2937/**
2938 * We received an acknowledgement for data we sent on a channel.
2939 * Locate the channel and process it, or return an error if the
2940 * channel is unknown.
2941 *
2942 * @param cls the `struct CadetTunnel` for which we decrypted the message
2943 * @param ack the message we received on the tunnel
2944 */
2945static void
2946handle_plaintext_data_ack (void *cls,
2947 const struct GNUNET_CADET_ChannelDataAckMessage *ack)
2948{
2949 struct CadetTunnel *t = cls;
2950 struct CadetChannel *ch;
2951
2952 ch = lookup_channel (t,
2953 ack->ctn);
2954 if (NULL == ch)
2955 {
2956 /* We don't know about such a channel, might have been destroyed on our
2957 end in the meantime, or never existed. Send back a DESTROY. */
2958 LOG (GNUNET_ERROR_TYPE_DEBUG,
2959 "Received DATA_ACK for unknown channel %u, sending DESTROY\n",
2960 ntohl (ack->ctn.cn));
2961 GCT_send_channel_destroy (t,
2962 ack->ctn);
2963 return;
2964 }
2965 GCCH_handle_channel_plaintext_data_ack (ch,
2966 GCC_get_id (t->current_ct->cc),
2967 ack);
2968}
2969
2970
2971/**
2972 * We have received a request to open a channel to a port from
2973 * another peer. Creates the incoming channel.
2974 *
2975 * @param cls the `struct CadetTunnel` for which we decrypted the message
2976 * @param copen the message we received on the tunnel
2977 */
2978static void
2979handle_plaintext_channel_open (void *cls,
2980 const struct
2981 GNUNET_CADET_ChannelOpenMessage *copen)
2982{
2983 struct CadetTunnel *t = cls;
2984 struct CadetChannel *ch;
2985
2986 ch = GNUNET_CONTAINER_multihashmap32_get (t->channels,
2987 ntohl (copen->ctn.cn));
2988 if (NULL != ch)
2989 {
2990 LOG (GNUNET_ERROR_TYPE_DEBUG,
2991 "Received duplicate channel CHANNEL_OPEN on h_port %s from %s (%s), resending ACK\n",
2992 GNUNET_h2s (&copen->h_port),
2993 GCT_2s (t),
2994 GCCH_2s (ch));
2995 GCCH_handle_duplicate_open (ch,
2996 GCC_get_id (t->current_ct->cc));
2997 return;
2998 }
2999 LOG (GNUNET_ERROR_TYPE_DEBUG,
3000 "Received CHANNEL_OPEN on h_port %s from %s\n",
3001 GNUNET_h2s (&copen->h_port),
3002 GCT_2s (t));
3003 ch = GCCH_channel_incoming_new (t,
3004 copen->ctn,
3005 &copen->h_port,
3006 ntohl (copen->opt));
3007 if (NULL != t->destroy_task)
3008 {
3009 GNUNET_SCHEDULER_cancel (t->destroy_task);
3010 t->destroy_task = NULL;
3011 }
3012 GNUNET_assert (GNUNET_OK ==
3013 GNUNET_CONTAINER_multihashmap32_put (t->channels,
3014 ntohl (copen->ctn.cn),
3015 ch,
3016 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
3017}
3018
3019
3020/**
3021 * Send a DESTROY message via the tunnel.
3022 *
3023 * @param t the tunnel to transmit over
3024 * @param ctn ID of the channel to destroy
3025 */
3026void
3027GCT_send_channel_destroy (struct CadetTunnel *t,
3028 struct GNUNET_CADET_ChannelTunnelNumber ctn)
3029{
3030 struct GNUNET_CADET_ChannelDestroyMessage msg;
3031
3032 LOG (GNUNET_ERROR_TYPE_DEBUG,
3033 "Sending DESTROY message for channel ID %u\n",
3034 ntohl (ctn.cn));
3035 msg.header.size = htons (sizeof(msg));
3036 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY);
3037 msg.reserved = htonl (0);
3038 msg.ctn = ctn;
3039 GCT_send (t,
3040 &msg.header,
3041 NULL,
3042 NULL,
3043 &ctn);
3044}
3045
3046
3047/**
3048 * We have received confirmation from the target peer that the
3049 * given channel could be established (the port is open).
3050 * Tell the client.
3051 *
3052 * @param cls the `struct CadetTunnel` for which we decrypted the message
3053 * @param cm the message we received on the tunnel
3054 */
3055static void
3056handle_plaintext_channel_open_ack (void *cls,
3057 const struct
3058 GNUNET_CADET_ChannelOpenAckMessage *cm)
3059{
3060 struct CadetTunnel *t = cls;
3061 struct CadetChannel *ch;
3062
3063 ch = lookup_channel (t,
3064 cm->ctn);
3065 if (NULL == ch)
3066 {
3067 /* We don't know about such a channel, might have been destroyed on our
3068 end in the meantime, or never existed. Send back a DESTROY. */
3069 LOG (GNUNET_ERROR_TYPE_DEBUG,
3070 "Received channel OPEN_ACK for unknown channel %u, sending DESTROY\n",
3071 ntohl (cm->ctn.cn));
3072 GCT_send_channel_destroy (t,
3073 cm->ctn);
3074 return;
3075 }
3076 LOG (GNUNET_ERROR_TYPE_DEBUG,
3077 "Received channel OPEN_ACK on channel %s from %s\n",
3078 GCCH_2s (ch),
3079 GCT_2s (t));
3080 GCCH_handle_channel_open_ack (ch,
3081 GCC_get_id (t->current_ct->cc),
3082 &cm->port);
3083}
3084
3085
3086/**
3087 * We received a message saying that a channel should be destroyed.
3088 * Pass it on to the correct channel.
3089 *
3090 * @param cls the `struct CadetTunnel` for which we decrypted the message
3091 * @param cm the message we received on the tunnel
3092 */
3093static void
3094handle_plaintext_channel_destroy (void *cls,
3095 const struct
3096 GNUNET_CADET_ChannelDestroyMessage *cm)
3097{
3098 struct CadetTunnel *t = cls;
3099 struct CadetChannel *ch;
3100
3101 ch = lookup_channel (t,
3102 cm->ctn);
3103 if (NULL == ch)
3104 {
3105 /* We don't know about such a channel, might have been destroyed on our
3106 end in the meantime, or never existed. */
3107 LOG (GNUNET_ERROR_TYPE_DEBUG,
3108 "Received channel DESTROY for unknown channel %u. Ignoring.\n",
3109 ntohl (cm->ctn.cn));
3110 return;
3111 }
3112 LOG (GNUNET_ERROR_TYPE_DEBUG,
3113 "Received channel DESTROY on %s from %s\n",
3114 GCCH_2s (ch),
3115 GCT_2s (t));
3116 GCCH_handle_remote_destroy (ch,
3117 GCC_get_id (t->current_ct->cc));
3118}
3119
3120
3121/**
3122 * Handles a message we decrypted, by injecting it into
3123 * our message queue (which will do the dispatching).
3124 *
3125 * @param cls the `struct CadetTunnel` that got the message
3126 * @param msg the message
3127 * @return #GNUNET_OK on success (always)
3128 * #GNUNET_NO to stop further processing (no error)
3129 * #GNUNET_SYSERR to stop further processing with error
3130 */
3131static int
3132handle_decrypted (void *cls,
3133 const struct GNUNET_MessageHeader *msg)
3134{
3135 struct CadetTunnel *t = cls;
3136
3137 GNUNET_assert (NULL != t->current_ct);
3138 GNUNET_MQ_inject_message (t->mq,
3139 msg);
3140 return GNUNET_OK;
3141}
3142
3143
3144/**
3145 * Function called if we had an error processing
3146 * an incoming decrypted message.
3147 *
3148 * @param cls the `struct CadetTunnel`
3149 * @param error error code
3150 */
3151static void
3152decrypted_error_cb (void *cls,
3153 enum GNUNET_MQ_Error error)
3154{
3155 GNUNET_break_op (0);
3156}
3157
3158
3159/**
3160 * Create a tunnel to @a destination. Must only be called
3161 * from within #GCP_get_tunnel().
3162 *
3163 * @param destination where to create the tunnel to
3164 * @return new tunnel to @a destination
3165 */
3166struct CadetTunnel *
3167GCT_create_tunnel (struct CadetPeer *destination)
3168{
3169 struct CadetTunnel *t = GNUNET_new (struct CadetTunnel);
3170 struct GNUNET_MQ_MessageHandler handlers[] = {
3171 GNUNET_MQ_hd_fixed_size (plaintext_keepalive,
3172 GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE,
3173 struct GNUNET_MessageHeader,
3174 t),
3175 GNUNET_MQ_hd_var_size (plaintext_data,
3176 GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA,
3177 struct GNUNET_CADET_ChannelAppDataMessage,
3178 t),
3179 GNUNET_MQ_hd_fixed_size (plaintext_data_ack,
3180 GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK,
3181 struct GNUNET_CADET_ChannelDataAckMessage,
3182 t),
3183 GNUNET_MQ_hd_fixed_size (plaintext_channel_open,
3184 GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN,
3185 struct GNUNET_CADET_ChannelOpenMessage,
3186 t),
3187 GNUNET_MQ_hd_fixed_size (plaintext_channel_open_ack,
3188 GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK,
3189 struct GNUNET_CADET_ChannelOpenAckMessage,
3190 t),
3191 GNUNET_MQ_hd_fixed_size (plaintext_channel_destroy,
3192 GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY,
3193 struct GNUNET_CADET_ChannelDestroyMessage,
3194 t),
3195 GNUNET_MQ_handler_end ()
3196 };
3197
3198 t->kx_retry_delay = INITIAL_KX_RETRY_DELAY;
3199 new_ephemeral (&t->ax);
3200 GNUNET_CRYPTO_ecdhe_key_create (&t->ax.kx_0);
3201 t->destination = destination;
3202 t->channels = GNUNET_CONTAINER_multihashmap32_create (8);
3203 t->maintain_connections_task
3204 = GNUNET_SCHEDULER_add_now (&maintain_connections_cb,
3205 t);
3206 t->mq = GNUNET_MQ_queue_for_callbacks (NULL,
3207 NULL,
3208 NULL,
3209 NULL,
3210 handlers,
3211 &decrypted_error_cb,
3212 t);
3213 t->mst = GNUNET_MST_create (&handle_decrypted,
3214 t);
3215 return t;
3216}
3217
3218
3219/**
3220 * Add a @a connection to the @a tunnel.
3221 *
3222 * @param t a tunnel
3223 * @param cid connection identifier to use for the connection
3224 * @param options options for the connection
3225 * @param path path to use for the connection
3226 * @return #GNUNET_OK on success,
3227 * #GNUNET_SYSERR on failure (duplicate connection)
3228 */
3229int
3230GCT_add_inbound_connection (struct CadetTunnel *t,
3231 const struct
3232 GNUNET_CADET_ConnectionTunnelIdentifier *cid,
3233 struct CadetPeerPath *path)
3234{
3235 struct CadetTConnection *ct;
3236
3237 ct = GNUNET_new (struct CadetTConnection);
3238 ct->created = GNUNET_TIME_absolute_get ();
3239 ct->t = t;
3240 ct->cc = GCC_create_inbound (t->destination,
3241 path,
3242 ct,
3243 cid,
3244 &connection_ready_cb,
3245 ct);
3246 if (NULL == ct->cc)
3247 {
3248 LOG (GNUNET_ERROR_TYPE_DEBUG,
3249 "%s refused inbound %s (duplicate)\n",
3250 GCT_2s (t),
3251 GCC_2s (ct->cc));
3252 GNUNET_free (ct);
3253 return GNUNET_SYSERR;
3254 }
3255 /* FIXME: schedule job to kill connection (and path?) if it takes
3256 too long to get ready! (And track performance data on how long
3257 other connections took with the tunnel!)
3258 => Note: to be done within 'connection'-logic! */
3259 GNUNET_CONTAINER_DLL_insert (t->connection_busy_head,
3260 t->connection_busy_tail,
3261 ct);
3262 t->num_busy_connections++;
3263 LOG (GNUNET_ERROR_TYPE_DEBUG,
3264 "%s has new %s\n",
3265 GCT_2s (t),
3266 GCC_2s (ct->cc));
3267 return GNUNET_OK;
3268}
3269
3270
3271/**
3272 * Handle encrypted message.
3273 *
3274 * @param ct connection/tunnel combo that received encrypted message
3275 * @param msg the encrypted message to decrypt
3276 */
3277void
3278GCT_handle_encrypted (struct CadetTConnection *ct,
3279 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
3280{
3281 struct CadetTunnel *t = ct->t;
3282 uint16_t size = ntohs (msg->header.size);
3283 char cbuf[size] GNUNET_ALIGN;
3284 ssize_t decrypted_size;
3285
3286 LOG (GNUNET_ERROR_TYPE_DEBUG,
3287 "%s received %u bytes of encrypted data in state %d\n",
3288 GCT_2s (t),
3289 (unsigned int) size,
3290 t->estate);
3291
3292 switch (t->estate)
3293 {
3294 case CADET_TUNNEL_KEY_UNINITIALIZED:
3295 case CADET_TUNNEL_KEY_AX_RECV:
3296 /* We did not even SEND our KX, how can the other peer
3297 send us encrypted data? Must have been that we went
3298 down and the other peer still things we are up.
3299 Let's send it KX back. */
3300 GNUNET_STATISTICS_update (stats,
3301 "# received encrypted without any KX",
3302 1,
3303 GNUNET_NO);
3304 if (NULL != t->kx_task)
3305 {
3306 GNUNET_SCHEDULER_cancel (t->kx_task);
3307 t->kx_task = NULL;
3308 }
3309 send_kx (t,
3310 ct,
3311 &t->ax);
3312 return;
3313
3314 case CADET_TUNNEL_KEY_AX_SENT_AND_RECV:
3315 /* We send KX, and other peer send KX to us at the same time.
3316 Neither KX is AUTH'ed, so let's try KX_AUTH this time. */
3317 GNUNET_STATISTICS_update (stats,
3318 "# received encrypted without KX_AUTH",
3319 1,
3320 GNUNET_NO);
3321 if (NULL != t->kx_task)
3322 {
3323 GNUNET_SCHEDULER_cancel (t->kx_task);
3324 t->kx_task = NULL;
3325 }
3326 send_kx_auth (t,
3327 ct,
3328 &t->ax,
3329 GNUNET_YES);
3330 return;
3331
3332 case CADET_TUNNEL_KEY_AX_SENT:
3333 /* We did not get the KX of the other peer, but that
3334 might have been lost. Send our KX again immediately. */
3335 GNUNET_STATISTICS_update (stats,
3336 "# received encrypted without KX",
3337 1,
3338 GNUNET_NO);
3339 if (NULL != t->kx_task)
3340 {
3341 GNUNET_SCHEDULER_cancel (t->kx_task);
3342 t->kx_task = NULL;
3343 }
3344 send_kx (t,
3345 ct,
3346 &t->ax);
3347 return;
3348
3349 case CADET_TUNNEL_KEY_AX_AUTH_SENT:
3350 /* Great, first payload, we might graduate to OK! */
3351 case CADET_TUNNEL_KEY_OK:
3352 /* We are up and running, all good. */
3353 break;
3354 }
3355
3356 decrypted_size = -1;
3357 if (CADET_TUNNEL_KEY_OK == t->estate)
3358 {
3359 /* We have well-established key material available,
3360 try that. (This is the common case.) */
3361 decrypted_size = t_ax_decrypt_and_validate (&t->ax,
3362 cbuf,
3363 msg,
3364 size);
3365 }
3366
3367 if ((-1 == decrypted_size) &&
3368 (NULL != t->unverified_ax))
3369 {
3370 /* We have un-authenticated KX material available. We should try
3371 this as a back-up option, in case the sender crashed and
3372 switched keys. */
3373 decrypted_size = t_ax_decrypt_and_validate (t->unverified_ax,
3374 cbuf,
3375 msg,
3376 size);
3377 if (-1 != decrypted_size)
3378 {
3379 /* It worked! Treat this as authentication of the AX data! */
3380 cleanup_ax (&t->ax);
3381 t->ax = *t->unverified_ax;
3382 GNUNET_free (t->unverified_ax);
3383 t->unverified_ax = NULL;
3384 }
3385 if (CADET_TUNNEL_KEY_AX_AUTH_SENT == t->estate)
3386 {
3387 /* First time it worked, move tunnel into production! */
3388 GCT_change_estate (t,
3389 CADET_TUNNEL_KEY_OK);
3390 if (NULL != t->send_task)
3391 GNUNET_SCHEDULER_cancel (t->send_task);
3392 t->send_task = GNUNET_SCHEDULER_add_now (&trigger_transmissions,
3393 t);
3394 }
3395 }
3396 if (NULL != t->unverified_ax)
3397 {
3398 /* We had unverified KX material that was useless; so increment
3399 counter and eventually move to ignore it. Note that we even do
3400 this increment if we successfully decrypted with the old KX
3401 material and thus didn't even both with the new one. This is
3402 the ideal case, as a malicious injection of bogus KX data
3403 basically only causes us to increment a counter a few times. */t->unverified_attempts++;
3404 LOG (GNUNET_ERROR_TYPE_DEBUG,
3405 "Failed to decrypt message with unverified KX data %u times\n",
3406 t->unverified_attempts);
3407 if (t->unverified_attempts > MAX_UNVERIFIED_ATTEMPTS)
3408 {
3409 cleanup_ax (t->unverified_ax);
3410 GNUNET_free (t->unverified_ax);
3411 t->unverified_ax = NULL;
3412 }
3413 }
3414
3415 if (-1 == decrypted_size)
3416 {
3417 /* Decryption failed for good, complain. */
3418 LOG (GNUNET_ERROR_TYPE_WARNING,
3419 "%s failed to decrypt and validate encrypted data, retrying KX\n",
3420 GCT_2s (t));
3421 GNUNET_STATISTICS_update (stats,
3422 "# unable to decrypt",
3423 1,
3424 GNUNET_NO);
3425 if (NULL != t->kx_task)
3426 {
3427 GNUNET_SCHEDULER_cancel (t->kx_task);
3428 t->kx_task = NULL;
3429 }
3430 send_kx (t,
3431 ct,
3432 &t->ax);
3433 return;
3434 }
3435 GNUNET_STATISTICS_update (stats,
3436 "# decrypted bytes",
3437 decrypted_size,
3438 GNUNET_NO);
3439
3440 /* The MST will ultimately call #handle_decrypted() on each message. */
3441 t->current_ct = ct;
3442 GNUNET_break_op (GNUNET_OK ==
3443 GNUNET_MST_from_buffer (t->mst,
3444 cbuf,
3445 decrypted_size,
3446 GNUNET_YES,
3447 GNUNET_NO));
3448 t->current_ct = NULL;
3449}
3450
3451
3452/**
3453 * Sends an already built message on a tunnel, encrypting it and
3454 * choosing the best connection if not provided.
3455 *
3456 * @param message Message to send. Function modifies it.
3457 * @param t Tunnel on which this message is transmitted.
3458 * @param cont Continuation to call once message is really sent.
3459 * @param cont_cls Closure for @c cont.
3460 * @param The ID of the channel we are using for sending.
3461 * @return Handle to cancel message
3462 */
3463struct CadetTunnelQueueEntry *
3464GCT_send (struct CadetTunnel *t,
3465 const struct GNUNET_MessageHeader *message,
3466 GCT_SendContinuation cont,
3467 void *cont_cls,
3468 struct GNUNET_CADET_ChannelTunnelNumber *ctn)
3469{
3470 struct CadetTunnelQueueEntry *tq;
3471 uint16_t payload_size;
3472 struct GNUNET_MQ_Envelope *env;
3473 struct GNUNET_CADET_TunnelEncryptedMessage *ax_msg;
3474 struct CadetChannel *ch;
3475
3476 if (NULL != ctn)
3477 {
3478 ch = lookup_channel (t,
3479 *ctn);
3480 if ((NULL != ch) && GCCH_is_type_to_drop (ch, message))
3481 {
3482 GNUNET_break (0);
3483 return NULL;
3484 }
3485 }
3486
3487 if (CADET_TUNNEL_KEY_OK != t->estate)
3488 {
3489 GNUNET_break (0);
3490 return NULL;
3491 }
3492 payload_size = ntohs (message->size);
3493 LOG (GNUNET_ERROR_TYPE_DEBUG,
3494 "Encrypting %u bytes for %s\n",
3495 (unsigned int) payload_size,
3496 GCT_2s (t));
3497 env = GNUNET_MQ_msg_extra (ax_msg,
3498 payload_size,
3499 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED);
3500 t_ax_encrypt (&t->ax,
3501 &ax_msg[1],
3502 message,
3503 payload_size);
3504 GNUNET_STATISTICS_update (stats,
3505 "# encrypted bytes",
3506 payload_size,
3507 GNUNET_NO);
3508 ax_msg->ax_header.Ns = htonl (t->ax.Ns++);
3509 ax_msg->ax_header.PNs = htonl (t->ax.PNs);
3510 /* FIXME: we should do this once, not once per message;
3511 this is a point multiplication, and DHRs does not
3512 change all the time. */
3513 GNUNET_CRYPTO_ecdhe_key_get_public (&t->ax.DHRs,
3514 &ax_msg->ax_header.DHRs);
3515 t_h_encrypt (&t->ax,
3516 ax_msg);
3517 t_hmac (&ax_msg->ax_header,
3518 sizeof(struct GNUNET_CADET_AxHeader) + payload_size,
3519 0,
3520 &t->ax.HKs,
3521 &ax_msg->hmac);
3522
3523 tq = GNUNET_malloc (sizeof(*tq));
3524 tq->t = t;
3525 tq->env = env;
3526 tq->cid = &ax_msg->cid; /* will initialize 'ax_msg->cid' once we know the connection */
3527 tq->cont = cont;
3528 tq->cont_cls = cont_cls;
3529 GNUNET_CONTAINER_DLL_insert_tail (t->tq_head,
3530 t->tq_tail,
3531 tq);
3532 if (NULL != t->send_task)
3533 GNUNET_SCHEDULER_cancel (t->send_task);
3534 t->send_task
3535 = GNUNET_SCHEDULER_add_now (&trigger_transmissions,
3536 t);
3537 return tq;
3538}
3539
3540
3541/**
3542 * Cancel a previously sent message while it's in the queue.
3543 *
3544 * ONLY can be called before the continuation given to the send
3545 * function is called. Once the continuation is called, the message is
3546 * no longer in the queue!
3547 *
3548 * @param tq Handle to the queue entry to cancel.
3549 */
3550void
3551GCT_send_cancel (struct CadetTunnelQueueEntry *tq)
3552{
3553 struct CadetTunnel *t = tq->t;
3554
3555 GNUNET_CONTAINER_DLL_remove (t->tq_head,
3556 t->tq_tail,
3557 tq);
3558 GNUNET_MQ_discard (tq->env);
3559 GNUNET_free (tq);
3560}
3561
3562
3563/**
3564 * Iterate over all connections of a tunnel.
3565 *
3566 * @param t Tunnel whose connections to iterate.
3567 * @param iter Iterator.
3568 * @param iter_cls Closure for @c iter.
3569 */
3570void
3571GCT_iterate_connections (struct CadetTunnel *t,
3572 GCT_ConnectionIterator iter,
3573 void *iter_cls)
3574{
3575 struct CadetTConnection *n;
3576
3577 for (struct CadetTConnection *ct = t->connection_ready_head;
3578 NULL != ct;
3579 ct = n)
3580 {
3581 n = ct->next;
3582 iter (iter_cls,
3583 ct);
3584 }
3585 for (struct CadetTConnection *ct = t->connection_busy_head;
3586 NULL != ct;
3587 ct = n)
3588 {
3589 n = ct->next;
3590 iter (iter_cls,
3591 ct);
3592 }
3593}
3594
3595
3596/**
3597 * Closure for #iterate_channels_cb.
3598 */
3599struct ChanIterCls
3600{
3601 /**
3602 * Function to call.
3603 */
3604 GCT_ChannelIterator iter;
3605
3606 /**
3607 * Closure for @e iter.
3608 */
3609 void *iter_cls;
3610};
3611
3612
3613/**
3614 * Helper function for #GCT_iterate_channels.
3615 *
3616 * @param cls the `struct ChanIterCls`
3617 * @param key unused
3618 * @param value a `struct CadetChannel`
3619 * @return #GNUNET_OK
3620 */
3621static int
3622iterate_channels_cb (void *cls,
3623 uint32_t key,
3624 void *value)
3625{
3626 struct ChanIterCls *ctx = cls;
3627 struct CadetChannel *ch = value;
3628
3629 ctx->iter (ctx->iter_cls,
3630 ch);
3631 return GNUNET_OK;
3632}
3633
3634
3635/**
3636 * Iterate over all channels of a tunnel.
3637 *
3638 * @param t Tunnel whose channels to iterate.
3639 * @param iter Iterator.
3640 * @param iter_cls Closure for @c iter.
3641 */
3642void
3643GCT_iterate_channels (struct CadetTunnel *t,
3644 GCT_ChannelIterator iter,
3645 void *iter_cls)
3646{
3647 struct ChanIterCls ctx;
3648
3649 ctx.iter = iter;
3650 ctx.iter_cls = iter_cls;
3651 GNUNET_CONTAINER_multihashmap32_iterate (t->channels,
3652 &iterate_channels_cb,
3653 &ctx);
3654}
3655
3656
3657/**
3658 * Call #GCCH_debug() on a channel.
3659 *
3660 * @param cls points to the log level to use
3661 * @param key unused
3662 * @param value the `struct CadetChannel` to dump
3663 * @return #GNUNET_OK (continue iteration)
3664 */
3665static int
3666debug_channel (void *cls,
3667 uint32_t key,
3668 void *value)
3669{
3670 const enum GNUNET_ErrorType *level = cls;
3671 struct CadetChannel *ch = value;
3672
3673 GCCH_debug (ch, *level);
3674 return GNUNET_OK;
3675}
3676
3677
3678#define LOG2(level, ...) GNUNET_log_from_nocheck (level, "cadet-tun", \
3679 __VA_ARGS__)
3680
3681
3682/**
3683 * Log all possible info about the tunnel state.
3684 *
3685 * @param t Tunnel to debug.
3686 * @param level Debug level to use.
3687 */
3688void
3689GCT_debug (const struct CadetTunnel *t,
3690 enum GNUNET_ErrorType level)
3691{
3692#if ! defined(GNUNET_CULL_LOGGING)
3693 struct CadetTConnection *iter_c;
3694 int do_log;
3695
3696 do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
3697 "cadet-tun",
3698 __FILE__, __FUNCTION__, __LINE__);
3699 if (0 == do_log)
3700 return;
3701
3702 LOG2 (level,
3703 "TTT TUNNEL TOWARDS %s in estate %s tq_len: %u #cons: %u\n",
3704 GCT_2s (t),
3705 estate2s (t->estate),
3706 t->tq_len,
3707 GCT_count_any_connections (t));
3708 LOG2 (level,
3709 "TTT channels:\n");
3710 GNUNET_CONTAINER_multihashmap32_iterate (t->channels,
3711 &debug_channel,
3712 &level);
3713 LOG2 (level,
3714 "TTT connections:\n");
3715 for (iter_c = t->connection_ready_head; NULL != iter_c; iter_c = iter_c->next)
3716 GCC_debug (iter_c->cc,
3717 level);
3718 for (iter_c = t->connection_busy_head; NULL != iter_c; iter_c = iter_c->next)
3719 GCC_debug (iter_c->cc,
3720 level);
3721
3722 LOG2 (level,
3723 "TTT TUNNEL END\n");
3724#endif
3725}
3726
3727
3728/* end of gnunet-service-cadet_tunnels.c */
diff --git a/src/cadet/gnunet-service-cadet_tunnels.h b/src/cadet/gnunet-service-cadet_tunnels.h
deleted file mode 100644
index aea131542..000000000
--- a/src/cadet/gnunet-service-cadet_tunnels.h
+++ /dev/null
@@ -1,388 +0,0 @@
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 cls our tunnel
164 * @param path 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 * Return the number of channels using a tunnel.
256 *
257 * @param t tunnel to count obtain the number of channels for
258 * @return number of channels using the tunnel
259 */
260unsigned int
261GCT_count_channels (struct CadetTunnel *t);
262
263
264/**
265 * Return the number of connections available for a tunnel.
266 *
267 * @param t tunnel to count obtain the number of connections for
268 * @return number of connections available for the tunnel
269 */
270unsigned int
271GCT_count_any_connections (const struct CadetTunnel *t);
272
273
274/**
275 * Iterator over connections.
276 *
277 * @param cls closure
278 * @param ct one of the connections
279 */
280typedef void
281(*GCT_ConnectionIterator) (void *cls,
282 struct CadetTConnection *ct);
283
284
285/**
286 * Iterate over all connections of a tunnel.
287 *
288 * @param t Tunnel whose connections to iterate.
289 * @param iter Iterator.
290 * @param iter_cls Closure for @c iter.
291 */
292void
293GCT_iterate_connections (struct CadetTunnel *t,
294 GCT_ConnectionIterator iter,
295 void *iter_cls);
296
297
298/**
299 * Iterator over channels.
300 *
301 * @param cls closure
302 * @param ch one of the channels
303 */
304typedef void
305(*GCT_ChannelIterator) (void *cls,
306 struct CadetChannel *ch);
307
308
309/**
310 * Iterate over all channels of a tunnel.
311 *
312 * @param t Tunnel whose channels to iterate.
313 * @param iter Iterator.
314 * @param iter_cls Closure for @c iter.
315 */
316void
317GCT_iterate_channels (struct CadetTunnel *t,
318 GCT_ChannelIterator iter,
319 void *iter_cls);
320
321
322/**
323 * Get the encryption state of a tunnel.
324 *
325 * @param t Tunnel.
326 *
327 * @return Tunnel's encryption state.
328 */
329enum CadetTunnelEState
330GCT_get_estate (struct CadetTunnel *t);
331
332/**
333 * Change the tunnel encryption state.
334 * If the encryption state changes to OK, stop the rekey task.
335 *
336 * @param t Tunnel whose encryption state to change, or NULL.
337 * @param state New encryption state.
338 */
339void
340GCT_change_estate (struct CadetTunnel *t,
341 enum CadetTunnelEState state);
342
343/**
344 * Handle KX message.
345 *
346 * @param ct connection/tunnel combo that received encrypted message
347 * @param msg the key exchange message
348 */
349void
350GCT_handle_kx (struct CadetTConnection *ct,
351 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg);
352
353
354/**
355 * Handle KX_AUTH message.
356 *
357 * @param ct connection/tunnel combo that received encrypted message
358 * @param msg the key exchange message
359 */
360void
361GCT_handle_kx_auth (struct CadetTConnection *ct,
362 const struct
363 GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg);
364
365
366/**
367 * Handle encrypted message.
368 *
369 * @param ct connection/tunnel combo that received encrypted message
370 * @param msg the encrypted message to decrypt
371 */
372void
373GCT_handle_encrypted (struct CadetTConnection *ct,
374 const struct GNUNET_CADET_TunnelEncryptedMessage *msg);
375
376
377/**
378 * Log all possible info about the tunnel state.
379 *
380 * @param t Tunnel to debug.
381 * @param level Debug level to use.
382 */
383void
384GCT_debug (const struct CadetTunnel *t,
385 enum GNUNET_ErrorType level);
386
387
388#endif
diff --git a/src/cadet/loopcheck.sh b/src/cadet/loopcheck.sh
deleted file mode 100755
index 9b867e95b..000000000
--- a/src/cadet/loopcheck.sh
+++ /dev/null
@@ -1,57 +0,0 @@
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/cadet/profiler.conf b/src/cadet/profiler.conf
deleted file mode 100644
index 7ce283870..000000000
--- a/src/cadet/profiler.conf
+++ /dev/null
@@ -1,19 +0,0 @@
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/cadet/run_profiler.sh b/src/cadet/run_profiler.sh
deleted file mode 100755
index 4273dcd27..000000000
--- a/src/cadet/run_profiler.sh
+++ /dev/null
@@ -1,25 +0,0 @@
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/cadet/small.dat b/src/cadet/small.dat
deleted file mode 100644
index c3805ee80..000000000
--- a/src/cadet/small.dat
+++ /dev/null
@@ -1,21 +0,0 @@
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/cadet/test_cadet.c b/src/cadet/test_cadet.c
deleted file mode 100644
index bdf2ac986..000000000
--- a/src/cadet/test_cadet.c
+++ /dev/null
@@ -1,1605 +0,0 @@
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/test_cadet.c
22 * @author Bart Polot
23 * @author Christian Grothoff
24 * @brief Test for the cadet service using mq API.
25 */
26#include <stdio.h>
27#include "platform.h"
28#include "cadet.h"
29#include "cadet_test_lib.h"
30#include "gnunet_cadet_service.h"
31#include "gnunet_statistics_service.h"
32#include <gauger.h>
33
34
35/**
36 * Ugly workaround to unify data handlers on incoming and outgoing channels.
37 */
38struct CadetTestChannelWrapper
39{
40 /**
41 * Channel pointer.
42 */
43 struct GNUNET_CADET_Channel *ch;
44};
45
46/**
47 * How many messages to send by default.
48 */
49#define TOTAL_PACKETS 500 /* Cannot exceed 64k! */
50
51/**
52 * How long until we give up on connecting the peers?
53 */
54#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120)
55
56/**
57 * Time to wait by default for stuff that should be rather fast.
58 */
59#define SHORT_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 20)
60
61/**
62 * How fast do we send messages?
63 */
64#define SEND_INTERVAL GNUNET_TIME_relative_multiply ( \
65 GNUNET_TIME_UNIT_MILLISECONDS, 10)
66
67/**
68 * DIFFERENT TESTS TO RUN
69 */
70#define SETUP 0
71#define FORWARD 1
72#define KEEPALIVE 2
73#define SPEED 3
74#define SPEED_ACK 4
75#define SPEED_REL 8
76#define P2P_SIGNAL 10
77#define REOPEN 11
78#define DESTROY 12
79
80/**
81 * Active peer listing operation.
82 */
83static struct GNUNET_CADET_PeersLister *plo;
84
85/*
86 * Task called to check for existing tunnel and depending on that reopen channel
87 */
88static struct GNUNET_SCHEDULER_Task *get_peers_task;
89
90/**
91 * Which test are we running?
92 */
93static int test;
94
95/**
96 * String with test name
97 */
98static char *test_name;
99
100/**
101 * Flag to send traffic leaf->root in speed tests to test BCK_ACK logic.
102 */
103static int test_backwards = GNUNET_NO;
104
105/**
106 * How many packets to send.
107 */
108static unsigned int total_packets;
109
110/**
111 * Time to wait for fast operations.
112 */
113static struct GNUNET_TIME_Relative short_time;
114
115/**
116 * How many events have happened
117 */
118static int ok;
119
120/**
121 * Number of events expected to conclude the test successfully.
122 */
123static int ok_goal;
124
125/**
126 * Size of each test packet's payload
127 */
128static size_t size_payload = sizeof(uint32_t);
129
130/**
131 * Operation to get peer ids.
132 */
133static struct GNUNET_TESTBED_Operation *t_op[2];
134
135/**
136 * Peer ids.
137 */
138static struct GNUNET_PeerIdentity *testpeer_id[2];
139
140/**
141 * Peer ids.
142 */
143static struct GNUNET_CONFIGURATION_Handle *p_cfg[2];
144
145/**
146 * Port ID
147 */
148static struct GNUNET_HashCode port;
149
150/**
151 * Peer ids counter.
152 */
153static unsigned int peerinfo_task_cnt;
154
155/**
156 * Is the setup initialized?
157 */
158static int initialized;
159
160/**
161 * Number of payload packes sent.
162 */
163static int data_sent;
164
165/**
166 * Number of payload packets received.
167 */
168static int data_received;
169
170/**
171 * Number of payload packed acknowledgements sent.
172 */
173static int ack_sent;
174
175/**
176 * Number of payload packed explicitly (app level) acknowledged.
177 */
178static int ack_received;
179
180/**
181 * Total number of peers asked to run.
182 */
183static unsigned long long peers_requested;
184
185/**
186 * Number of currently running peers (should be same as @c peers_requested).
187 */
188static unsigned long long peers_running;
189
190/**
191 * Test context (to shut down).
192 */
193struct GNUNET_CADET_TEST_Context *test_ctx;
194
195/**
196 * Task called to disconnect peers.
197 */
198static struct GNUNET_SCHEDULER_Task *disconnect_task;
199
200/**
201 * Task called to reconnect peers.
202 */
203static struct GNUNET_SCHEDULER_Task *reconnect_task;
204
205/**
206 * Task To perform tests
207 */
208static struct GNUNET_SCHEDULER_Task *test_task;
209
210/**
211 * Task runnining #send_next_msg().
212 */
213static struct GNUNET_SCHEDULER_Task *send_next_msg_task;
214
215/**
216 * Channel handle for the root peer
217 */
218static struct GNUNET_CADET_Channel *outgoing_ch;
219
220/**
221 * Channel handle for the dest peer
222 */
223static struct GNUNET_CADET_Channel *incoming_ch;
224
225/**
226 * Time we started the data transmission (after channel has been established
227 * and initialized).
228 */
229static struct GNUNET_TIME_Absolute start_time;
230
231/**
232 * Peers handle.
233 */
234static struct GNUNET_TESTBED_Peer **testbed_peers;
235
236
237struct GNUNET_CADET_Handle **cadets_running;
238
239/**
240 * Statistics operation handle.
241 */
242static struct GNUNET_TESTBED_Operation *stats_op;
243
244/**
245 * Keepalives sent.
246 */
247static unsigned int ka_sent;
248
249/**
250 * Keepalives received.
251 */
252static unsigned int ka_received;
253
254/**
255 * How many messages were dropped by CADET because of full buffers?
256 */
257static unsigned int msg_dropped;
258
259/**
260 * Drop the next cadet message of a given type..
261 *
262 * @param mq message queue
263 * @param ccn client channel number.
264 * @param type of cadet message to be dropped.
265 */
266void
267GNUNET_CADET_drop_message (struct GNUNET_MQ_Handle *mq,
268 struct GNUNET_CADET_ClientChannelNumber ccn,
269 uint16_t type);
270
271/******************************************************************************/
272
273
274/******************************************************************************/
275
276
277/**
278 * Get the channel considered as the "target" or "receiver", depending on
279 * the test type and size.
280 *
281 * @return Channel handle of the target client, either 0 (for backward tests)
282 * or the last peer in the line (for other tests).
283 */
284static struct GNUNET_CADET_Channel *
285get_target_channel ()
286{
287 if ((SPEED == test) && (GNUNET_YES == test_backwards))
288 return outgoing_ch;
289 else
290 return incoming_ch;
291}
292
293
294/**
295 * Show the results of the test (banwidth achieved) and log them to GAUGER
296 */
297static void
298show_end_data (void)
299{
300 static struct GNUNET_TIME_Absolute end_time;
301 static struct GNUNET_TIME_Relative total_time;
302
303 end_time = GNUNET_TIME_absolute_get ();
304 total_time = GNUNET_TIME_absolute_get_difference (start_time, end_time);
305 fprintf (stderr,
306 "\nResults of test \"%s\"\n",
307 test_name);
308 fprintf (stderr,
309 "Test time %s\n",
310 GNUNET_STRINGS_relative_time_to_string (total_time, GNUNET_YES));
311 fprintf (stderr,
312 "Test bandwidth: %f kb/s\n",
313 4 * total_packets * 1.0 / (total_time.rel_value_us / 1000)); // 4bytes * ms
314 fprintf (stderr,
315 "Test throughput: %f packets/s\n\n",
316 total_packets * 1000.0 / (total_time.rel_value_us / 1000)); // packets * ms
317 GAUGER ("CADET",
318 test_name,
319 total_packets * 1000.0 / (total_time.rel_value_us / 1000),
320 "packets/s");
321}
322
323
324/**
325 * Disconnect from cadet services af all peers, call shutdown.
326 *
327 * @param cls Closure (line number from which termination was requested).
328 * @param tc Task Context.
329 */
330static void
331disconnect_cadet_peers (void *cls)
332{
333 long line = (long) cls;
334
335 disconnect_task = NULL;
336 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
337 "disconnecting cadet service of peers, called from line %ld\n",
338 line);
339 for (unsigned int i = 0; i < 2; i++)
340 {
341 GNUNET_TESTBED_operation_done (t_op[i]);
342 }
343 if (NULL != outgoing_ch)
344 {
345 GNUNET_CADET_channel_destroy (outgoing_ch);
346 outgoing_ch = NULL;
347 }
348 if (NULL != incoming_ch)
349 {
350 GNUNET_CADET_channel_destroy (incoming_ch);
351 incoming_ch = NULL;
352 }
353 GNUNET_CADET_TEST_cleanup (test_ctx);
354 GNUNET_SCHEDULER_shutdown ();
355}
356
357
358/**
359 * Shut down peergroup, clean up.
360 *
361 * @param cls Closure (unused).
362 * @param tc Task Context.
363 */
364static void
365shutdown_task (void *cls)
366{
367 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
368 "Ending test.\n");
369 if (NULL != send_next_msg_task)
370 {
371 GNUNET_SCHEDULER_cancel (send_next_msg_task);
372 send_next_msg_task = NULL;
373 }
374 if (NULL != test_task)
375 {
376 GNUNET_SCHEDULER_cancel (test_task);
377 test_task = NULL;
378 }
379 if (NULL != disconnect_task)
380 {
381 GNUNET_SCHEDULER_cancel (disconnect_task);
382 disconnect_task =
383 GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers,
384 (void *) __LINE__);
385 }
386}
387
388
389/**
390 * Stats callback. Finish the stats testbed operation and when all stats have
391 * been iterated, shutdown the test.
392 *
393 * @param cls Closure (line number from which termination was requested).
394 * @param op the operation that has been finished
395 * @param emsg error message in case the operation has failed; will be NULL if
396 * operation has executed successfully.
397 */
398static void
399stats_cont (void *cls,
400 struct GNUNET_TESTBED_Operation *op,
401 const char *emsg)
402{
403 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
404 "KA sent: %u, KA received: %u\n",
405 ka_sent,
406 ka_received);
407 if (((KEEPALIVE == test) || (REOPEN == test)) &&
408 ((ka_sent < 2) || (ka_sent > ka_received + 1)))
409 {
410 GNUNET_break (0);
411 ok--;
412 }
413 GNUNET_TESTBED_operation_done (stats_op);
414
415 if (NULL != disconnect_task)
416 GNUNET_SCHEDULER_cancel (disconnect_task);
417 disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers,
418 cls);
419}
420
421
422/**
423 * Process statistic values.
424 *
425 * @param cls closure (line number, unused)
426 * @param peer the peer the statistic belong to
427 * @param subsystem name of subsystem that created the statistic
428 * @param name the name of the datum
429 * @param value the current value
430 * @param is_persistent #GNUNET_YES if the value is persistent, #GNUNET_NO if not
431 * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
432 */
433static int
434stats_iterator (void *cls,
435 const struct GNUNET_TESTBED_Peer *peer,
436 const char *subsystem,
437 const char *name,
438 uint64_t value,
439 int is_persistent)
440{
441 static const char *s_sent = "# keepalives sent";
442 static const char *s_recv = "# keepalives received";
443 static const char *rdrops = "# messages dropped due to full buffer";
444 static const char *cdrops = "# messages dropped due to slow client";
445 uint32_t i;
446
447 i = GNUNET_TESTBED_get_index (peer);
448 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "STATS PEER %u - %s [%s]: %llu\n", i,
449 subsystem, name, (unsigned long long) value);
450 if ((0 == strncmp (s_sent, name, strlen (s_sent))) && (0 == i))
451 ka_sent = value;
452 if ((0 == strncmp (s_recv, name, strlen (s_recv))) && (peers_requested - 1 ==
453 i) )
454 ka_received = value;
455 if (0 == strncmp (rdrops, name, strlen (rdrops)))
456 msg_dropped += value;
457 if (0 == strncmp (cdrops, name, strlen (cdrops)))
458 msg_dropped += value;
459
460 return GNUNET_OK;
461}
462
463
464/**
465 * Task to gather all statistics.
466 *
467 * @param cls Closure (line from which the task was scheduled).
468 */
469static void
470gather_stats_and_exit (void *cls)
471{
472 long l = (long) cls;
473
474 disconnect_task = NULL;
475 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
476 "gathering statistics from line %ld\n",
477 l);
478 if (NULL != outgoing_ch)
479 {
480 GNUNET_CADET_channel_destroy (outgoing_ch);
481 outgoing_ch = NULL;
482 }
483 stats_op = GNUNET_TESTBED_get_statistics (peers_running,
484 testbed_peers,
485 "cadet",
486 NULL,
487 &stats_iterator,
488 stats_cont,
489 cls);
490}
491
492
493/**
494 * Send a message on the channel with the appropriate size and payload.
495 *
496 * Update the appropriate *_sent counter.
497 *
498 * @param channel Channel to send the message on.
499 */
500static void
501send_test_message (struct GNUNET_CADET_Channel *channel);
502
503/**
504 * Check if payload is sane (size contains payload).
505 *
506 * @param cls should match #ch
507 * @param message The actual message.
508 * @return #GNUNET_OK to keep the channel open,
509 * #GNUNET_SYSERR to close it (signal serious error).
510 */
511static int
512check_data (void *cls,
513 const struct GNUNET_MessageHeader *message);
514
515/**
516 * Function is called whenever a message is received.
517 *
518 * @param cls closure (set from GNUNET_CADET_connect(), peer number)
519 * @param message the actual message
520 */
521static void
522handle_data (void *cls,
523 const struct GNUNET_MessageHeader *message);
524
525/**
526 * Function called whenever an MQ-channel is destroyed, unless the destruction
527 * was requested by #GNUNET_CADET_channel_destroy.
528 * It must NOT call #GNUNET_CADET_channel_destroy on the channel.
529 *
530 * It should clean up any associated state, including cancelling any pending
531 * transmission on this channel.
532 *
533 * @param cls Channel closure (channel wrapper).
534 * @param channel Connection to the other end (henceforth invalid).
535 */
536static void
537disconnect_handler (void *cls,
538 const struct GNUNET_CADET_Channel *channel);
539
540static struct GNUNET_PeerIdentity *
541get_from_p_ids ()
542{
543 if (0 < GNUNET_memcmp (testpeer_id[0], testpeer_id[1]))
544 {
545 return testpeer_id[1];
546 }
547 else
548 {
549 return testpeer_id[0];
550 }
551}
552
553
554static struct GNUNET_CADET_Handle *
555get_from_cadets ()
556{
557
558 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "1\n");
559 if (0 < GNUNET_memcmp (testpeer_id[0], testpeer_id[1]))
560 {
561 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "standard peer\n");
562 return cadets_running[0];
563 }
564 else
565 {
566 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "the other peer\n");
567 return cadets_running[peers_running - 1];
568 }
569
570}
571
572
573static unsigned int
574get_peer_nr (int outgoing)
575{
576 if (0 < GNUNET_memcmp (testpeer_id[0], testpeer_id[1]))
577 {
578 return GNUNET_YES == outgoing ? 0 : peers_running - 1;
579 }
580 else
581 {
582 return GNUNET_YES == outgoing ? peers_running - 1 : 0;
583 }
584}
585
586
587/**
588 * Task to reconnect to other peer.
589 *
590 * @param cls Closure (line from which the task was scheduled).
591 */
592static void
593reconnect_op (void *cls)
594{
595 struct GNUNET_MQ_MessageHandler handlers[] = {
596 GNUNET_MQ_hd_var_size (data,
597 GNUNET_MESSAGE_TYPE_DUMMY,
598 struct GNUNET_MessageHeader,
599 NULL),
600 GNUNET_MQ_handler_end ()
601 };
602 long l = (long) cls;
603 struct CadetTestChannelWrapper *ch;
604 static struct GNUNET_PeerIdentity *p_id;
605 static struct GNUNET_CADET_Handle *h1;
606
607 reconnect_task = NULL;
608 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
609 "reconnecting from line %ld\n",
610 l);
611 if (NULL != outgoing_ch)
612 {
613 GNUNET_CADET_channel_destroy (outgoing_ch);
614 outgoing_ch = NULL;
615 }
616 ch = GNUNET_new (struct CadetTestChannelWrapper);
617
618 p_id = get_from_p_ids ();
619 h1 = get_from_cadets ();
620
621 outgoing_ch = GNUNET_CADET_channel_create (h1,
622 ch,
623 p_id,
624 &port,
625 NULL,
626 &disconnect_handler,
627 handlers);
628 ch->ch = outgoing_ch;
629 send_test_message (outgoing_ch);
630}
631
632
633void
634reopen_channel ()
635{
636 struct CadetTestChannelWrapper *ch;
637 static struct GNUNET_CADET_Handle *h1;
638 static struct GNUNET_PeerIdentity *p_id;
639 struct GNUNET_MQ_MessageHandler handlers[] = {
640 GNUNET_MQ_hd_var_size (data,
641 GNUNET_MESSAGE_TYPE_DUMMY,
642 struct GNUNET_MessageHeader,
643 NULL),
644 GNUNET_MQ_handler_end ()
645 };
646
647 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "creating channel again\n");
648 p_id = get_from_p_ids ();
649 h1 = get_from_cadets ();
650
651 ch = GNUNET_new (struct CadetTestChannelWrapper);
652 outgoing_ch = GNUNET_CADET_channel_create (h1,
653 ch,
654 p_id,
655 &port,
656 NULL,
657 &disconnect_handler,
658 handlers);
659 ch->ch = outgoing_ch;
660 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
661 "Sending second test data (after destroying the channel) on channel %p...\n",
662 outgoing_ch);
663 send_test_message (outgoing_ch);
664}
665
666
667static void
668peers_callback (void *cls, const struct GNUNET_CADET_PeerListEntry *ple);
669
670/**
671 * We ask the monitoring api for all the peers.
672 */
673static void
674get_peers (void *cls)
675{
676
677 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
678 "requesting peers info!\n");
679 plo = GNUNET_CADET_list_peers (p_cfg[get_peer_nr (GNUNET_YES)],
680 &peers_callback, NULL);
681
682}
683
684
685/**
686 * Method called to retrieve information about all peers in CADET, called
687 * once per peer.
688 *
689 * After last peer has been reported, an additional call with NULL is done.
690 *
691 * We check the peer we are interested in, if we have a tunnel. If not, we
692 * reopen the channel
693 *
694 * @param cls Closure.
695 * @param ple information about peer, or NULL on "EOF".
696 */
697static void
698peers_callback (void *cls, const struct GNUNET_CADET_PeerListEntry *ple)
699{
700
701 const struct GNUNET_PeerIdentity *p_id;
702 const struct GNUNET_PeerIdentity *peer;
703
704
705 peer = &ple->peer;
706
707 if (NULL == ple)
708 {
709 plo = NULL;
710 return;
711 }
712 p_id = get_from_p_ids ();
713
714 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
715 "ple->peer %s\n",
716 GNUNET_i2s_full (&ple->peer));
717 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
718 "p_id %s\n",
719 GNUNET_i2s_full (p_id));
720
721 if ((0 == GNUNET_memcmp (&ple->peer, p_id)) && ple->have_tunnel)
722 {
723
724 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
725 "schedule get_peers again?\n");
726 get_peers_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
727 &get_peers,
728 NULL);
729
730 }
731 else if (0 == GNUNET_memcmp (&ple->peer, p_id) )
732 {
733
734 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
735 "reopen channel\n");
736
737 reopen_channel ();
738
739 }
740}
741
742
743/**
744 * Function called whenever an MQ-channel is destroyed, unless the destruction
745 * was requested by #GNUNET_CADET_channel_destroy.
746 * It must NOT call #GNUNET_CADET_channel_destroy on the channel.
747 *
748 * It should clean up any associated state, including cancelling any pending
749 * transmission on this channel.
750 *
751 * @param cls Channel closure (channel wrapper).
752 * @param channel Connection to the other end (henceforth invalid).
753 */
754static void
755disconnect_handler (void *cls,
756 const struct GNUNET_CADET_Channel *channel)
757{
758 struct CadetTestChannelWrapper *ch_w = cls;
759
760 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
761 "Channel disconnected at ok=%d\n",
762 ok);
763 GNUNET_assert (ch_w->ch == channel);
764
765 if ((DESTROY == test) && (3 == ok))
766 {
767 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
768 "Reopen channel task!\n");
769 if (NULL == get_peers_task)
770 {
771 get_peers_task = GNUNET_SCHEDULER_add_now (&get_peers,
772 NULL);
773 }
774 return;
775 }
776
777 if (channel == incoming_ch)
778 {
779 ok++;
780 incoming_ch = NULL;
781 }
782 else if (outgoing_ch == channel)
783 {
784 if (P2P_SIGNAL == test)
785 {
786 ok++;
787 }
788 outgoing_ch = NULL;
789 }
790 else
791 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
792 "Unknown channel! %p\n",
793 channel);
794 if ((NULL != disconnect_task) && (REOPEN != test))
795 {
796 GNUNET_SCHEDULER_cancel (disconnect_task);
797 disconnect_task =
798 GNUNET_SCHEDULER_add_now (&gather_stats_and_exit,
799 (void *) __LINE__);
800 }
801 else if ((NULL != reconnect_task) && (REOPEN == test))
802 {
803 GNUNET_SCHEDULER_cancel (reconnect_task);
804 reconnect_task =
805 GNUNET_SCHEDULER_add_now (&reconnect_op,
806 (void *) __LINE__);
807 }
808 GNUNET_free (ch_w);
809}
810
811
812/**
813 * Abort test: schedule disconnect and shutdown immediately
814 *
815 * @param line Line in the code the abort is requested from (__LINE__).
816 */
817static void
818abort_test (long line)
819{
820 if (NULL != disconnect_task)
821 {
822 GNUNET_SCHEDULER_cancel (disconnect_task);
823 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
824 "Aborting test from %ld\n",
825 line);
826 disconnect_task =
827 GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers,
828 (void *) line);
829 }
830}
831
832
833/**
834 * Send a message on the channel with the appropriate size and payload.
835 *
836 * Update the appropriate *_sent counter.
837 *
838 * @param channel Channel to send the message on.
839 */
840static void
841send_test_message (struct GNUNET_CADET_Channel *channel)
842{
843 struct GNUNET_MQ_Envelope *env;
844 struct GNUNET_MessageHeader *msg;
845 uint32_t *data;
846 int payload;
847 int size;
848
849 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
850 "Sending test message on channel %u\n",
851 channel->ccn.channel_of_client);
852 size = size_payload;
853 if (GNUNET_NO == initialized)
854 {
855 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending INITIALIZER\n");
856 size += 1000;
857 payload = data_sent;
858 if (SPEED_ACK == test) // FIXME unify SPEED_ACK with an initializer
859 data_sent++;
860 }
861 else if ((SPEED == test) || (SPEED_ACK == test))
862 {
863 if (get_target_channel () == channel)
864 {
865 payload = ack_sent;
866 size += ack_sent;
867 ack_sent++;
868 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
869 "Sending ACK %u [%d bytes]\n",
870 payload, size);
871 }
872 else
873 {
874 payload = data_sent;
875 size += data_sent;
876 data_sent++;
877 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
878 "Sending DATA %u [%d bytes]\n",
879 data_sent, size);
880 }
881 }
882 else if (FORWARD == test)
883 {
884 payload = ack_sent;
885 }
886 else if (P2P_SIGNAL == test)
887 {
888 payload = data_sent;
889 }
890 else if (REOPEN == test)
891 {
892 payload = data_sent;
893 data_sent++;
894 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
895 "Sending DATA %u [%d bytes]\n",
896 data_sent, size);
897 }
898 else if (DESTROY == test)
899 {
900 payload = data_sent;
901 }
902 else
903 {
904 GNUNET_assert (0);
905 }
906 env = GNUNET_MQ_msg_extra (msg, size, GNUNET_MESSAGE_TYPE_DUMMY);
907
908 data = (uint32_t *) &msg[1];
909 *data = htonl (payload);
910 GNUNET_MQ_send (GNUNET_CADET_get_mq (channel), env);
911}
912
913
914/**
915 * Task to request a new data transmission in a SPEED test, without waiting
916 * for previous messages to be sent/arrrive.
917 *
918 * @param cls Closure (unused).
919 */
920static void
921send_next_msg (void *cls)
922{
923 struct GNUNET_CADET_Channel *channel;
924
925 send_next_msg_task = NULL;
926 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
927 "Sending next message: %d\n",
928 data_sent);
929
930 channel = GNUNET_YES == test_backwards ? incoming_ch : outgoing_ch;
931 GNUNET_assert (NULL != channel);
932 GNUNET_assert (SPEED == test);
933 send_test_message (channel);
934 if (data_sent < total_packets)
935 {
936 /* SPEED test: Send all messages as soon as possible */
937 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
938 "Scheduling message %d\n",
939 data_sent + 1);
940 send_next_msg_task =
941 GNUNET_SCHEDULER_add_delayed (SEND_INTERVAL,
942 &send_next_msg,
943 NULL);
944 }
945}
946
947
948/**
949 * Every few messages cancel the timeout task and re-schedule it again, to
950 * avoid timing out when traffic keeps coming.
951 *
952 * @param line Code line number to log if a timeout occurs.
953 */
954static void
955reschedule_timeout_task (long line)
956{
957 if ((ok % 10) == 0)
958 {
959 if (NULL != disconnect_task)
960 {
961 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
962 "reschedule timeout every 10 messages\n");
963 GNUNET_SCHEDULER_cancel (disconnect_task);
964 disconnect_task = GNUNET_SCHEDULER_add_delayed (short_time,
965 &gather_stats_and_exit,
966 (void *) line);
967 }
968 }
969}
970
971
972/**
973 * Check if payload is sane (size contains payload).
974 *
975 * @param cls should match #ch
976 * @param message The actual message.
977 * @return #GNUNET_OK to keep the channel open,
978 * #GNUNET_SYSERR to close it (signal serious error).
979 */
980static int
981check_data (void *cls,
982 const struct GNUNET_MessageHeader *message)
983{
984 return GNUNET_OK; /* all is well-formed */
985}
986
987
988/**
989 * Function is called whenever a message is received.
990 *
991 * @param cls closure (set from GNUNET_CADET_connect(), peer number)
992 * @param message the actual message
993 */
994static void
995handle_data (void *cls,
996 const struct GNUNET_MessageHeader *message)
997{
998 struct CadetTestChannelWrapper *ch = cls;
999 struct GNUNET_CADET_Channel *channel = ch->ch;
1000 uint32_t *data;
1001 uint32_t payload;
1002 int *counter;
1003
1004 ok++;
1005 GNUNET_CADET_receive_done (channel);
1006 counter = get_target_channel () == channel ? &data_received : &ack_received;
1007
1008 reschedule_timeout_task ((long) __LINE__);
1009
1010 if (channel == outgoing_ch)
1011 {
1012 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1013 "Root client got a message.\n");
1014 }
1015 else if (channel == incoming_ch)
1016 {
1017 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1018 "Leaf client got a message.\n");
1019 }
1020 else
1021 {
1022 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1023 "Unknown channel %p.\n",
1024 channel);
1025 GNUNET_assert (0);
1026 }
1027
1028 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1029 "handle_data ok: (%d/%d)\n",
1030 ok,
1031 ok_goal);
1032 data = (uint32_t *) &message[1];
1033 payload = ntohl (*data);
1034 if (payload == *counter)
1035 {
1036 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1037 " payload as expected: %u\n",
1038 payload);
1039 }
1040 else
1041 {
1042 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1043 " payload %u, expected: %u\n",
1044 payload, *counter);
1045 }
1046
1047 if (DESTROY == test)
1048 {
1049 if (2 == ok)
1050 {
1051 ok++;
1052 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1053 "dropping message ok: (%d/%d)\n",
1054 ok,
1055 ok_goal);
1056 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1057 "TEST ID 0: %s\n",
1058 GNUNET_i2s (testpeer_id[0]));
1059 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1060 "TEST ID 1: %s\n",
1061 GNUNET_i2s (testpeer_id[1]));
1062
1063 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "dropping message\n");
1064 GNUNET_CADET_drop_message (GNUNET_CADET_get_mq (outgoing_ch),
1065 outgoing_ch->ccn,
1066 GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY);
1067 if (NULL != outgoing_ch)
1068 {
1069 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1070 "Destroying channel %p...\n",
1071 outgoing_ch);
1072 GNUNET_CADET_channel_destroy (outgoing_ch);
1073 outgoing_ch = NULL;
1074 }
1075 }
1076 else if (5 == ok)
1077 {
1078 ok++;
1079 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1080 "destroy test finished ok: (%d/%d)\n",
1081 ok,
1082 ok_goal);
1083 disconnect_task =
1084 GNUNET_SCHEDULER_add_now (&gather_stats_and_exit,
1085 (void *) __LINE__);
1086 // End of DESTROY test.
1087 }
1088 }
1089
1090 if (GNUNET_NO == initialized)
1091 {
1092 initialized = GNUNET_YES;
1093 start_time = GNUNET_TIME_absolute_get ();
1094 if (SPEED == test)
1095 {
1096 GNUNET_assert (incoming_ch == channel);
1097 send_next_msg_task = GNUNET_SCHEDULER_add_now (&send_next_msg,
1098 NULL);
1099 return;
1100 }
1101 }
1102
1103 (*counter)++;
1104 if (get_target_channel () == channel) /* Got "data" */
1105 {
1106 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " received data %u\n", data_received);
1107 if ((DESTROY != test) && ((SPEED != test) || ( (ok_goal - 2) == ok)) )
1108 {
1109 /* Send ACK */
1110 send_test_message (channel);
1111 return;
1112 }
1113 else
1114 {
1115 if (data_received < total_packets)
1116 return;
1117 }
1118 }
1119 else /* Got "ack" */
1120 {
1121 if ((SPEED_ACK == test) || (SPEED == test) )
1122 {
1123 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " received ack %u\n", ack_received);
1124 /* Send more data */
1125 send_test_message (channel);
1126 if ((ack_received < total_packets) && (SPEED != test) )
1127 return;
1128 if ((ok == 2) && (SPEED == test) )
1129 return;
1130 show_end_data ();
1131 }
1132 if (test == P2P_SIGNAL)
1133 {
1134 GNUNET_CADET_channel_destroy (incoming_ch);
1135 incoming_ch = NULL;
1136 }
1137 else
1138 {
1139 GNUNET_CADET_channel_destroy (outgoing_ch);
1140 outgoing_ch = NULL;
1141 }
1142 }
1143}
1144
1145
1146/**
1147 * Method called whenever a peer connects to a port in MQ-based CADET.
1148 *
1149 * @param cls Closure from #GNUNET_CADET_open_port (peer # as long).
1150 * @param channel New handle to the channel.
1151 * @param source Peer that started this channel.
1152 * @return Closure for the incoming @a channel. It's given to:
1153 * - The #GNUNET_CADET_DisconnectEventHandler (given to
1154 * #GNUNET_CADET_open_port) when the channel dies.
1155 * - Each the #GNUNET_MQ_MessageCallback handlers for each message
1156 * received on the @a channel.
1157 */
1158static void *
1159connect_handler (void *cls,
1160 struct GNUNET_CADET_Channel *channel,
1161 const struct GNUNET_PeerIdentity *source)
1162{
1163 struct CadetTestChannelWrapper *ch;
1164 long peer = (long) cls;
1165
1166 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1167 "Incoming channel from %s to %ld: %p\n",
1168 GNUNET_i2s (source),
1169 peer,
1170 channel);
1171 ok++;
1172 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1173 "connect_handler ok: (%d/%d)\n",
1174 ok,
1175 ok_goal);
1176
1177 if (peer == get_peer_nr (GNUNET_NO))
1178 {
1179 if ((DESTROY != test) && (NULL != incoming_ch))
1180 {
1181 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1182 "Duplicate incoming channel for client %lu\n",
1183 (long) cls);
1184 GNUNET_assert (0);
1185 }
1186 incoming_ch = channel;
1187 }
1188 else
1189 {
1190 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1191 "Incoming channel for unexpected peer #%lu\n",
1192 (long) cls);
1193 GNUNET_assert (0);
1194 }
1195 if ((NULL != disconnect_task) && (REOPEN != test) && (DESTROY != test))
1196 {
1197 GNUNET_SCHEDULER_cancel (disconnect_task);
1198 disconnect_task = GNUNET_SCHEDULER_add_delayed (short_time,
1199 &gather_stats_and_exit,
1200 (void *) __LINE__);
1201 }
1202 else if ((NULL != disconnect_task) && (REOPEN == test))
1203 {
1204 GNUNET_SCHEDULER_cancel (disconnect_task);
1205 disconnect_task = GNUNET_SCHEDULER_add_delayed (
1206 GNUNET_TIME_relative_multiply (short_time, 2),
1207 &gather_stats_and_exit,
1208 (void *) __LINE__);
1209 }
1210
1211 if ((NULL != reconnect_task) && (REOPEN == test))
1212 {
1213 GNUNET_SCHEDULER_cancel (reconnect_task);
1214 reconnect_task = GNUNET_SCHEDULER_add_delayed (short_time,
1215 &reconnect_op,
1216 (void *) __LINE__);
1217 }
1218
1219
1220 /* TODO: cannot return channel as-is, in order to unify the data handlers */
1221 ch = GNUNET_new (struct CadetTestChannelWrapper);
1222 ch->ch = channel;
1223
1224 return ch;
1225}
1226
1227
1228/**
1229 * START THE TESTCASE ITSELF, AS WE ARE CONNECTED TO THE CADET SERVICES.
1230 *
1231 * Testcase continues when the root receives confirmation of connected peers,
1232 * on callback function ch.
1233 *
1234 * @param cls Closure (unused).
1235 */
1236static void
1237start_test (void *cls)
1238{
1239 struct GNUNET_MQ_MessageHandler handlers[] = {
1240 GNUNET_MQ_hd_var_size (data,
1241 GNUNET_MESSAGE_TYPE_DUMMY,
1242 struct GNUNET_MessageHeader,
1243 NULL),
1244 GNUNET_MQ_handler_end ()
1245 };
1246 struct CadetTestChannelWrapper *ch;
1247 static struct GNUNET_CADET_Handle *h1;
1248 static struct GNUNET_PeerIdentity *p_id;
1249
1250 test_task = NULL;
1251 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "start_test: %s\n", test_name);
1252 if (NULL != disconnect_task)
1253 {
1254 GNUNET_SCHEDULER_cancel (disconnect_task);
1255 disconnect_task = NULL;
1256 }
1257
1258 if (SPEED_REL == test)
1259 {
1260 test = SPEED;
1261 }
1262
1263 p_id = get_from_p_ids ();
1264 h1 = get_from_cadets ();
1265
1266 ch = GNUNET_new (struct CadetTestChannelWrapper);
1267 outgoing_ch = GNUNET_CADET_channel_create (h1,
1268 ch,
1269 p_id,
1270 &port,
1271 NULL,
1272 &disconnect_handler,
1273 handlers);
1274 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "channel created\n");
1275
1276 ch->ch = outgoing_ch;
1277
1278 if (DESTROY != test)
1279 disconnect_task = GNUNET_SCHEDULER_add_delayed (short_time,
1280 &gather_stats_and_exit,
1281 (void *) __LINE__);
1282 if (KEEPALIVE == test)
1283 return; /* Don't send any data. */
1284
1285 data_received = 0;
1286 data_sent = 0;
1287 ack_received = 0;
1288 ack_sent = 0;
1289 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1290 "Sending data initializer on channel %p...\n",
1291 outgoing_ch);
1292 send_test_message (outgoing_ch);
1293 if (REOPEN == test)
1294 {
1295 reconnect_task = GNUNET_SCHEDULER_add_delayed (short_time,
1296 &reconnect_op,
1297 (void *) __LINE__);
1298 GNUNET_SCHEDULER_cancel (disconnect_task);
1299 disconnect_task = GNUNET_SCHEDULER_add_delayed (
1300 GNUNET_TIME_relative_multiply (short_time, 2),
1301 &gather_stats_and_exit,
1302 (void *) __LINE__);
1303 }
1304}
1305
1306
1307/**
1308 * Callback to be called when the requested peer information is available
1309 *
1310 * @param cls the closure from GNUNET_TESTBED_peer_getinformation()
1311 * @param op the operation this callback corresponds to
1312 * @param pinfo the result; will be NULL if the operation has failed
1313 * @param emsg error message if the operation has failed;
1314 * NULL if the operation is successful
1315 */
1316static void
1317pi_cb (void *cls,
1318 struct GNUNET_TESTBED_Operation *op,
1319 const struct GNUNET_TESTBED_PeerInformation *pinfo,
1320 const char *emsg)
1321{
1322 long i = (long) cls;
1323
1324 if ((NULL == pinfo) ||
1325 (NULL != emsg))
1326 {
1327 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1328 "pi_cb: %s\n",
1329 emsg);
1330 abort_test (__LINE__);
1331 return;
1332 }
1333
1334 if (GNUNET_TESTBED_PIT_IDENTITY == pinfo->pit)
1335 {
1336 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1337 "ID callback for %ld\n",
1338 i);
1339 testpeer_id[i] = pinfo->result.id;
1340 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1341 "id: %s\n",
1342 GNUNET_i2s (testpeer_id[i]));
1343 }
1344 else if (GNUNET_TESTBED_PIT_CONFIGURATION == pinfo->pit)
1345 {
1346 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1347 "CFG callback for %ld\n",
1348 i);
1349 p_cfg[i] = pinfo->result.cfg;
1350 }
1351 else
1352 {
1353 GNUNET_break (0);
1354 }
1355
1356 peerinfo_task_cnt++;
1357 if (peerinfo_task_cnt < 4)
1358 return;
1359 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1360 "Got all peer information, starting test\n");
1361 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1362 "TEST ID 0: %s\n",
1363 GNUNET_i2s (testpeer_id[0]));
1364 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1365 "TEST ID 1: %s\n",
1366 GNUNET_i2s (testpeer_id[1]));
1367 test_task = GNUNET_SCHEDULER_add_now (&start_test, NULL);
1368}
1369
1370
1371/**
1372 * test main: start test when all peers are connected
1373 *
1374 * @param cls Closure.
1375 * @param ctx Argument to give to GNUNET_CADET_TEST_cleanup on test end.
1376 * @param num_peers Number of peers that are running.
1377 * @param peers Array of peers.
1378 * @param cadets Handle to each of the CADETs of the peers.
1379 */
1380static void
1381tmain (void *cls,
1382 struct GNUNET_CADET_TEST_Context *ctx,
1383 unsigned int num_peers,
1384 struct GNUNET_TESTBED_Peer **peers,
1385 struct GNUNET_CADET_Handle **cadets)
1386{
1387 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test main\n");
1388 ok = 0;
1389 test_ctx = ctx;
1390 peers_running = num_peers;
1391 GNUNET_assert (peers_running == peers_requested);
1392 testbed_peers = peers;
1393 cadets_running = cadets;
1394
1395 disconnect_task = GNUNET_SCHEDULER_add_delayed (short_time,
1396 &disconnect_cadet_peers,
1397 (void *) __LINE__);
1398 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
1399 NULL);
1400 t_op[0] = GNUNET_TESTBED_peer_get_information (peers[0],
1401 GNUNET_TESTBED_PIT_IDENTITY,
1402 &pi_cb,
1403 (void *) 0L);
1404 t_op[1] = GNUNET_TESTBED_peer_get_information (peers[num_peers - 1],
1405 GNUNET_TESTBED_PIT_IDENTITY,
1406 &pi_cb,
1407 (void *) 1L);
1408 t_op[0] = GNUNET_TESTBED_peer_get_information (peers[0],
1409 GNUNET_TESTBED_PIT_CONFIGURATION,
1410 &pi_cb,
1411 (void *) 0L);
1412 t_op[1] = GNUNET_TESTBED_peer_get_information (peers[num_peers - 1],
1413 GNUNET_TESTBED_PIT_CONFIGURATION,
1414 &pi_cb,
1415 (void *) 1L);
1416 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "requested peer ids\n");
1417}
1418
1419
1420/**
1421 * Main: start test
1422 */
1423int
1424main (int argc, char *argv[])
1425{
1426 static const struct GNUNET_HashCode *ports[2];
1427 struct GNUNET_MQ_MessageHandler handlers[] = {
1428 GNUNET_MQ_hd_var_size (data,
1429 GNUNET_MESSAGE_TYPE_DUMMY,
1430 struct GNUNET_MessageHeader,
1431 NULL),
1432 GNUNET_MQ_handler_end ()
1433 };
1434 const char *config_file;
1435 char port_id[] = "test port";
1436 struct GNUNET_GETOPT_CommandLineOption options[] = {
1437 GNUNET_GETOPT_option_relative_time ('t',
1438 "time",
1439 "short_time",
1440 gettext_noop ("set short timeout"),
1441 &short_time),
1442 GNUNET_GETOPT_option_uint ('m',
1443 "messages",
1444 "NUM_MESSAGES",
1445 gettext_noop ("set number of messages to send"),
1446 &total_packets),
1447
1448 GNUNET_GETOPT_OPTION_END
1449 };
1450
1451
1452 initialized = GNUNET_NO;
1453 GNUNET_log_setup ("test", "DEBUG", NULL);
1454
1455 total_packets = TOTAL_PACKETS;
1456 short_time = SHORT_TIME;
1457 if (-1 == GNUNET_GETOPT_run (argv[0], options, argc, argv))
1458 {
1459 fprintf (stderr, "test failed: problem with CLI parameters\n");
1460 exit (1);
1461 }
1462
1463 config_file = "test_cadet.conf";
1464 GNUNET_CRYPTO_hash (port_id, sizeof(port_id), &port);
1465
1466 /* Find out requested size */
1467 if (strstr (argv[0], "_2_") != NULL)
1468 {
1469 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "DIRECT CONNECTIONs\n");
1470 peers_requested = 2;
1471 }
1472 else if (strstr (argv[0], "_5_") != NULL)
1473 {
1474 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "5 PEER LINE\n");
1475 peers_requested = 5;
1476 }
1477 else if (strstr (argv[0], "_6_") != NULL)
1478 {
1479 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "6 PEER LINE\n");
1480 peers_requested = 6;
1481 }
1482 else
1483 {
1484 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "SIZE UNKNOWN, USING 2\n");
1485 peers_requested = 2;
1486 }
1487
1488 /* Find out requested test */
1489 if (strstr (argv[0], "_forward") != NULL)
1490 {
1491 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "FORWARD\n");
1492 test = FORWARD;
1493 test_name = "unicast";
1494 ok_goal = 4;
1495 }
1496 else if (strstr (argv[0], "_signal") != NULL)
1497 {
1498 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SIGNAL\n");
1499 test = P2P_SIGNAL;
1500 test_name = "signal";
1501 ok_goal = 4;
1502 }
1503 else if (strstr (argv[0], "_speed_ack") != NULL)
1504 {
1505 /* Test is supposed to generate the following callbacks:
1506 * 1 incoming channel (@dest)
1507 * total_packets received data packet (@dest)
1508 * total_packets received data packet (@orig)
1509 * 1 received channel destroy (@dest) FIXME #5818
1510 */ok_goal = total_packets * 2 + 2;
1511 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED_ACK\n");
1512 test = SPEED_ACK;
1513 test_name = "speed ack";
1514 }
1515 else if (strstr (argv[0], "_speed") != NULL)
1516 {
1517 /* Test is supposed to generate the following callbacks:
1518 * 1 incoming channel (@dest)
1519 * 1 initial packet (@dest)
1520 * total_packets received data packet (@dest)
1521 * 1 received data packet (@orig)
1522 * 1 received channel destroy (@dest) FIXME #5818
1523 */ok_goal = total_packets + 4;
1524 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED\n");
1525 if (strstr (argv[0], "_reliable") != NULL)
1526 {
1527 test = SPEED_REL;
1528 test_name = "speed reliable";
1529 config_file = "test_cadet_drop.conf";
1530 }
1531 else
1532 {
1533 test = SPEED;
1534 test_name = "speed";
1535 }
1536 }
1537 else if (strstr (argv[0], "_keepalive") != NULL)
1538 {
1539 test = KEEPALIVE;
1540 test_name = "keepalive";
1541 /* Test is supposed to generate the following callbacks:
1542 * 1 incoming channel (@dest)
1543 * [wait]
1544 * 1 received channel destroy (@dest) FIXME #5818
1545 */ok_goal = 1;
1546 }
1547 else if (strstr (argv[0], "_reopen") != NULL)
1548 {
1549 test = REOPEN;
1550 test_name = "reopen";
1551 ///* Test is supposed to generate the following callbacks:
1552 // * 1 incoming channel (@dest)
1553 // * [wait]
1554 // * 1 received channel destroy (@dest) FIXME #5818
1555 // */
1556 ok_goal = 6;
1557 }
1558 else if (strstr (argv[0], "_destroy") != NULL)
1559 {
1560 test = DESTROY;
1561 test_name = "destroy";
1562 ok_goal = 6;
1563 short_time = GNUNET_TIME_relative_multiply (short_time, 5);
1564 }
1565 else
1566 {
1567 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "UNKNOWN\n");
1568 test = SETUP;
1569 ok_goal = 0;
1570 }
1571
1572 if (strstr (argv[0], "backwards") != NULL)
1573 {
1574 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "BACKWARDS (LEAF TO ROOT)\n");
1575 test_backwards = GNUNET_YES;
1576 GNUNET_asprintf (&test_name, "backwards %s", test_name);
1577 }
1578
1579 peerinfo_task_cnt = 0;
1580 ports[0] = &port;
1581 ports[1] = NULL;
1582 GNUNET_CADET_TEST_ruN ("test_cadet_small",
1583 config_file,
1584 peers_requested,
1585 &tmain,
1586 NULL, /* tmain cls */
1587 &connect_handler,
1588 NULL,
1589 &disconnect_handler,
1590 handlers,
1591 ports);
1592 if (NULL != strstr (argv[0], "_reliable"))
1593 msg_dropped = 0; /* dropped should be retransmitted */
1594
1595 if (ok_goal > ok - msg_dropped)
1596 {
1597 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "FAILED! (%d/%d)\n", ok, ok_goal);
1598 return 1;
1599 }
1600 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "success\n");
1601 return 0;
1602}
1603
1604
1605/* end of test_cadet.c */
diff --git a/src/cadet/test_cadet.conf b/src/cadet/test_cadet.conf
deleted file mode 100644
index 79c86bb59..000000000
--- a/src/cadet/test_cadet.conf
+++ /dev/null
@@ -1,109 +0,0 @@
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/cadet/test_cadet_drop.conf b/src/cadet/test_cadet_drop.conf
deleted file mode 100644
index c9bcf603b..000000000
--- a/src/cadet/test_cadet_drop.conf
+++ /dev/null
@@ -1,4 +0,0 @@
1@INLINE@ test_cadet.conf
2
3[cadet]
4DROP_PERCENT = 1
diff --git a/src/cadet/test_cadet_flow.c b/src/cadet/test_cadet_flow.c
deleted file mode 100644
index 9f5a45986..000000000
--- a/src/cadet/test_cadet_flow.c
+++ /dev/null
@@ -1,891 +0,0 @@
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/test_cadet_flow.c
22 * @author Bart Polot
23 * @author Christian Grothoff
24 * @brief Test for flow control of CADET service
25 */
26#include <stdio.h>
27#include "platform.h"
28#include "cadet_test_lib.h"
29#include "gnunet_cadet_service.h"
30#include "gnunet_statistics_service.h"
31#include <gauger.h>
32
33
34/**
35 * Ugly workaround to unify data handlers on incoming and outgoing channels.
36 */
37struct CadetTestChannelWrapper
38{
39 /**
40 * Channel pointer.
41 */
42 struct GNUNET_CADET_Channel *ch;
43};
44
45/**
46 * How many messages to send by default.
47 */
48#define TOTAL_PACKETS_DEFAULT 500
49
50/**
51 * How long until we give up on connecting the peers?
52 */
53#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120)
54
55/**
56 * Time to wait by default for stuff that should be rather fast.
57 */
58#define SHORT_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 20)
59
60/**
61 * How fast do we send messages?
62 */
63#define SEND_INTERVAL GNUNET_TIME_relative_multiply ( \
64 GNUNET_TIME_UNIT_MILLISECONDS, 10)
65
66
67/**
68 * How many packets to send.
69 */
70static unsigned int total_packets = TOTAL_PACKETS_DEFAULT;
71
72/**
73 * Time to wait for fast operations.
74 */
75static struct GNUNET_TIME_Relative short_time;
76
77/**
78 * Size of each test packet's payload
79 */
80static size_t size_payload = sizeof(uint32_t);
81
82/**
83 * Operation to get peer ids.
84 */
85static struct GNUNET_TESTBED_Operation *t_op[2];
86
87/**
88 * Peer ids.
89 */
90static struct GNUNET_PeerIdentity *p_id[2];
91
92/**
93 * Port ID
94 */
95static struct GNUNET_HashCode port;
96
97/**
98 * Peer ids counter.
99 */
100static unsigned int p_ids;
101
102/**
103 * Is the setup initialized?
104 */
105static int initialized;
106
107/**
108 * Number of payload packes sent.
109 */
110static int data_sent;
111
112/**
113 * Number of payload packets received.
114 */
115static int data_received;
116
117/**
118 * Number of payload packed acknowledgements sent.
119 */
120static int ack_sent;
121
122/**
123 * Number of payload packed explicitly (app level) acknowledged.
124 */
125static int ack_received;
126
127/**
128 * Total number of peers asked to run.
129 */
130static unsigned int peers_requested = 2;
131
132/**
133 * Number of currently running peers (should be same as @c peers_requested).
134 */
135static unsigned int peers_running;
136
137/**
138 * Test context (to shut down).
139 */
140struct GNUNET_CADET_TEST_Context *test_ctx;
141
142/**
143 * Task called to disconnect peers.
144 */
145static struct GNUNET_SCHEDULER_Task *disconnect_task;
146
147/**
148 * Task To perform tests
149 */
150static struct GNUNET_SCHEDULER_Task *test_task;
151
152/**
153 * Task runnining #send_next_msg().
154 */
155static struct GNUNET_SCHEDULER_Task *send_next_msg_task;
156
157/**
158 * Cadet handle for the root peer
159 */
160static struct GNUNET_CADET_Handle *h1;
161
162/**
163 * Cadet handle for the first leaf peer
164 */
165static struct GNUNET_CADET_Handle *h2;
166
167/**
168 * Channel handle for the root peer
169 */
170static struct GNUNET_CADET_Channel *outgoing_ch;
171
172/**
173 * Channel handle for the dest peer
174 */
175static struct GNUNET_CADET_Channel *incoming_ch;
176
177/**
178 * Time we started the data transmission (after channel has been established
179 * and initialized).
180 */
181static struct GNUNET_TIME_Absolute start_time;
182
183/**
184 * Peers handle.
185 */
186static struct GNUNET_TESTBED_Peer **testbed_peers;
187
188/**
189 * Statistics operation handle.
190 */
191static struct GNUNET_TESTBED_Operation *stats_op;
192
193/**
194 * Keepalives sent.
195 */
196static unsigned int ka_sent;
197
198/**
199 * Keepalives received.
200 */
201static unsigned int ka_received;
202
203/**
204 * How many messages were dropped by CADET because of full buffers?
205 */
206static unsigned int msg_dropped;
207
208
209/**
210 * Show the results of the test (banwidth achieved) and log them to GAUGER
211 */
212static void
213show_end_data (void)
214{
215 static struct GNUNET_TIME_Absolute end_time;
216 static struct GNUNET_TIME_Relative total_time;
217
218 end_time = GNUNET_TIME_absolute_get ();
219 total_time = GNUNET_TIME_absolute_get_difference (start_time, end_time);
220 fprintf (stderr,
221 "\nResults of test \"%s\"\n",
222 test_name);
223 fprintf (stderr,
224 "Test time %s\n",
225 GNUNET_STRINGS_relative_time_to_string (total_time, GNUNET_YES));
226 fprintf (stderr,
227 "Test bandwidth: %f kb/s\n",
228 4 * total_packets * 1.0 / (total_time.rel_value_us / 1000)); // 4bytes * ms
229 fprintf (stderr,
230 "Test throughput: %f packets/s\n\n",
231 total_packets * 1000.0 / (total_time.rel_value_us / 1000)); // packets * ms
232 GAUGER ("CADET",
233 test_name,
234 total_packets * 1000.0 / (total_time.rel_value_us / 1000),
235 "packets/s");
236}
237
238
239/**
240 * Shut down peergroup, clean up.
241 *
242 * @param cls Closure (unused).
243 * @param tc Task Context.
244 */
245static void
246shutdown_task (void *cls)
247{
248 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
249 "Ending test.\n");
250 if (NULL != send_next_msg_task)
251 {
252 GNUNET_SCHEDULER_cancel (send_next_msg_task);
253 send_next_msg_task = NULL;
254 }
255 if (NULL != test_task)
256 {
257 GNUNET_SCHEDULER_cancel (test_task);
258 test_task = NULL;
259 }
260 for (unsigned int i = 0; i < 2; i++)
261 GNUNET_TESTBED_operation_done (t_op[i]);
262 if (NULL != outgoing_ch)
263 {
264 GNUNET_CADET_channel_destroy (outgoing_ch);
265 outgoing_ch = NULL;
266 }
267 if (NULL != incoming_ch)
268 {
269 GNUNET_CADET_channel_destroy (incoming_ch);
270 incoming_ch = NULL;
271 }
272 GNUNET_CADET_TEST_cleanup (test_ctx);
273}
274
275
276/**
277 * Stats callback. Finish the stats testbed operation and when all stats have
278 * been iterated, shutdown the test.
279 *
280 * @param cls Closure (line number from which termination was requested).
281 * @param op the operation that has been finished
282 * @param emsg error message in case the operation has failed; will be NULL if
283 * operation has executed successfully.
284 */
285static void
286stats_cont (void *cls,
287 struct GNUNET_TESTBED_Operation *op,
288 const char *emsg)
289{
290 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
291 "KA sent: %u, KA received: %u\n",
292 ka_sent,
293 ka_received);
294 if ((KEEPALIVE == test) && ((ka_sent < 2) || (ka_sent > ka_received + 1)))
295 {
296 GNUNET_break (0);
297 ok--;
298 }
299 GNUNET_TESTBED_operation_done (stats_op);
300
301 if (NULL != disconnect_task)
302 GNUNET_SCHEDULER_cancel (disconnect_task);
303 disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers,
304 cls);
305}
306
307
308/**
309 * Process statistic values.
310 *
311 * @param cls closure (line number, unused)
312 * @param peer the peer the statistic belong to
313 * @param subsystem name of subsystem that created the statistic
314 * @param name the name of the datum
315 * @param value the current value
316 * @param is_persistent #GNUNET_YES if the value is persistent, #GNUNET_NO if not
317 * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
318 */
319static int
320stats_iterator (void *cls,
321 const struct GNUNET_TESTBED_Peer *peer,
322 const char *subsystem,
323 const char *name,
324 uint64_t value,
325 int is_persistent)
326{
327 static const char *s_sent = "# keepalives sent";
328 static const char *s_recv = "# keepalives received";
329 static const char *rdrops = "# messages dropped due to full buffer";
330 static const char *cdrops = "# messages dropped due to slow client";
331 uint32_t i;
332
333 i = GNUNET_TESTBED_get_index (peer);
334 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "STATS PEER %u - %s [%s]: %llu\n", i,
335 subsystem, name, (unsigned long long) value);
336 if ((0 == strncmp (s_sent, name, strlen (s_sent))) && (0 == i))
337 ka_sent = value;
338 if ((0 == strncmp (s_recv, name, strlen (s_recv))) && (peers_requested - 1 ==
339 i) )
340 ka_received = value;
341 if (0 == strncmp (rdrops, name, strlen (rdrops)))
342 msg_dropped += value;
343 if (0 == strncmp (cdrops, name, strlen (cdrops)))
344 msg_dropped += value;
345
346 return GNUNET_OK;
347}
348
349
350/**
351 * Task to gather all statistics.
352 *
353 * @param cls Closure (line from which the task was scheduled).
354 */
355static void
356gather_stats_and_exit (void *cls)
357{
358 long l = (long) cls;
359
360 disconnect_task = NULL;
361 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
362 "gathering statistics from line %ld\n",
363 l);
364 if (NULL != outgoing_ch)
365 {
366 GNUNET_CADET_channel_destroy (outgoing_ch);
367 outgoing_ch = NULL;
368 }
369 stats_op = GNUNET_TESTBED_get_statistics (peers_running,
370 testbed_peers,
371 "cadet",
372 NULL,
373 &stats_iterator,
374 stats_cont,
375 cls);
376}
377
378
379/**
380 * Abort test: schedule disconnect and shutdown immediately
381 *
382 * @param line Line in the code the abort is requested from (__LINE__).
383 */
384static void
385abort_test (long line)
386{
387 if (NULL != disconnect_task)
388 {
389 GNUNET_SCHEDULER_cancel (disconnect_task);
390 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
391 "Aborting test from %ld\n",
392 line);
393 disconnect_task =
394 GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers,
395 (void *) line);
396 }
397}
398
399
400/**
401 * Send a message on the channel with the appropriate size and payload.
402 *
403 * Update the appropriate *_sent counter.
404 *
405 * @param channel Channel to send the message on.
406 */
407static void
408send_test_message (struct GNUNET_CADET_Channel *channel)
409{
410 struct GNUNET_MQ_Envelope *env;
411 struct GNUNET_MessageHeader *msg;
412 uint32_t *data;
413 int payload;
414 int size;
415
416 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
417 "Sending test message on channel %p\n",
418 channel);
419 size = size_payload;
420 if (GNUNET_NO == initialized)
421 {
422 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending INITIALIZER\n");
423 size += 1000;
424 payload = data_sent;
425 if (SPEED_ACK == test) // FIXME unify SPEED_ACK with an initializer
426 data_sent++;
427 }
428 else if ((SPEED == test) || (SPEED_ACK == test))
429 {
430 if (get_target_channel () == channel)
431 {
432 payload = ack_sent;
433 size += ack_sent;
434 ack_sent++;
435 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
436 "Sending ACK %u [%d bytes]\n",
437 payload, size);
438 }
439 else
440 {
441 payload = data_sent;
442 size += data_sent;
443 data_sent++;
444 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
445 "Sending DATA %u [%d bytes]\n",
446 data_sent, size);
447 }
448 }
449 else if (FORWARD == test)
450 {
451 payload = ack_sent;
452 }
453 else if (P2P_SIGNAL == test)
454 {
455 payload = data_sent;
456 }
457 else
458 {
459 GNUNET_assert (0);
460 }
461 env = GNUNET_MQ_msg_extra (msg, size, GNUNET_MESSAGE_TYPE_DUMMY);
462
463 data = (uint32_t *) &msg[1];
464 *data = htonl (payload);
465 GNUNET_MQ_send (GNUNET_CADET_get_mq (channel), env);
466}
467
468
469/**
470 * Task to request a new data transmission in a SPEED test, without waiting
471 * for previous messages to be sent/arrrive.
472 *
473 * @param cls Closure (unused).
474 */
475static void
476send_next_msg (void *cls)
477{
478 struct GNUNET_CADET_Channel *channel;
479
480 send_next_msg_task = NULL;
481 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
482 "Sending next message: %d\n",
483 data_sent);
484
485 channel = GNUNET_YES == test_backwards ? incoming_ch : outgoing_ch;
486 GNUNET_assert (NULL != channel);
487 GNUNET_assert (SPEED == test);
488 send_test_message (channel);
489 if (data_sent < total_packets)
490 {
491 /* SPEED test: Send all messages as soon as possible */
492 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
493 "Scheduling message %d\n",
494 data_sent + 1);
495 send_next_msg_task =
496 GNUNET_SCHEDULER_add_delayed (SEND_INTERVAL,
497 &send_next_msg,
498 NULL);
499 }
500}
501
502
503/**
504 * Check if payload is sane (size contains payload).
505 *
506 * @param cls should match #ch
507 * @param message The actual message.
508 * @return #GNUNET_OK to keep the channel open,
509 * #GNUNET_SYSERR to close it (signal serious error).
510 */
511static int
512check_data (void *cls,
513 const struct GNUNET_MessageHeader *message)
514{
515 return GNUNET_OK; /* all is well-formed */
516}
517
518
519/**
520 * Function is called whenever a message is received.
521 *
522 * @param cls closure (set from GNUNET_CADET_connect(), peer number)
523 * @param message the actual message
524 */
525static void
526handle_data (void *cls,
527 const struct GNUNET_MessageHeader *message)
528{
529 struct CadetTestChannelWrapper *ch = cls;
530 struct GNUNET_CADET_Channel *channel = ch->ch;
531 uint32_t *data;
532 uint32_t payload;
533 int *counter;
534
535 GNUNET_CADET_receive_done (channel);
536 counter = get_target_channel () == channel ? &data_received : &ack_received;
537 if (channel == outgoing_ch)
538 {
539 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
540 "Root client got a message.\n");
541 }
542 else if (channel == incoming_ch)
543 {
544 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
545 "Leaf client got a message.\n");
546 }
547 else
548 {
549 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
550 "Unknown channel %p.\n",
551 channel);
552 GNUNET_assert (0);
553 }
554
555 data = (uint32_t *) &message[1];
556 payload = ntohl (*data);
557 if (payload == *counter)
558 {
559 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
560 "Payload as expected: %u\n",
561 payload);
562 }
563 else
564 {
565 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
566 "Received payload %u, expected: %u\n",
567 payload, *counter);
568 }
569 (*counter)++;
570 if (get_target_channel () == channel) /* Got "data" */
571 {
572 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
573 " received data %u\n",
574 data_received);
575 if (data_received < total_packets)
576 return;
577 }
578 else /* Got "ack" */
579 {
580 if ((SPEED_ACK == test) || (SPEED == test) )
581 {
582 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " received ack %u\n", ack_received);
583 /* Send more data */
584 send_test_message (channel);
585 if ((ack_received < total_packets) && (SPEED != test) )
586 return;
587 if ((ok == 2) && (SPEED == test) )
588 return;
589 show_end_data ();
590 }
591 if (test == P2P_SIGNAL)
592 {
593 GNUNET_CADET_channel_destroy (incoming_ch);
594 incoming_ch = NULL;
595 }
596 else
597 {
598 GNUNET_CADET_channel_destroy (outgoing_ch);
599 outgoing_ch = NULL;
600 }
601 }
602}
603
604
605/**
606 * Method called whenever a peer connects to a port in MQ-based CADET.
607 *
608 * @param cls Closure from #GNUNET_CADET_open_port (peer # as long).
609 * @param channel New handle to the channel.
610 * @param source Peer that started this channel.
611 * @return Closure for the incoming @a channel. It's given to:
612 * - The #GNUNET_CADET_DisconnectEventHandler (given to
613 * #GNUNET_CADET_open_port) when the channel dies.
614 * - Each the #GNUNET_MQ_MessageCallback handlers for each message
615 * received on the @a channel.
616 */
617static void *
618connect_handler (void *cls,
619 struct GNUNET_CADET_Channel *channel,
620 const struct GNUNET_PeerIdentity *source)
621{
622 struct CadetTestChannelWrapper *ch;
623 long peer = (long) cls;
624
625 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
626 "Incoming channel from %s to %ld: %p\n",
627 GNUNET_i2s (source),
628 peer,
629 channel);
630 if (peer == peers_requested - 1)
631 {
632 if (NULL != incoming_ch)
633 {
634 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
635 "Duplicate incoming channel for client %lu\n",
636 (long) cls);
637 GNUNET_assert (0);
638 }
639 incoming_ch = channel;
640 }
641 else
642 {
643 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
644 "Incoming channel for unexpected peer #%lu\n",
645 (long) cls);
646 GNUNET_assert (0);
647 }
648 ch = GNUNET_new (struct CadetTestChannelWrapper);
649 ch->ch = channel;
650
651 return ch;
652}
653
654
655/**
656 * Function called whenever an MQ-channel is destroyed, even if the destruction
657 * was requested by #GNUNET_CADET_channel_destroy.
658 * It must NOT call #GNUNET_CADET_channel_destroy on the channel.
659 *
660 * It should clean up any associated state, including cancelling any pending
661 * transmission on this channel.
662 *
663 * @param cls Channel closure (channel wrapper).
664 * @param channel Connection to the other end (henceforth invalid).
665 */
666static void
667disconnect_handler (void *cls,
668 const struct GNUNET_CADET_Channel *channel)
669{
670 struct CadetTestChannelWrapper *ch_w = cls;
671
672 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
673 "Channel disconnected at %d\n",
674 ok);
675 GNUNET_assert (ch_w->ch == channel);
676 if (channel == incoming_ch)
677 incoming_ch = NULL;
678 else if (outgoing_ch == channel)
679 outgoing_ch = NULL;
680 else
681 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
682 "Disconnect on unknown channel %p\n",
683 channel);
684 if (NULL != disconnect_task)
685 GNUNET_SCHEDULER_cancel (disconnect_task);
686 disconnect_task = GNUNET_SCHEDULER_add_now (&gather_stats_and_exit,
687 (void *) __LINE__);
688 GNUNET_free (ch_w);
689}
690
691
692/**
693 * Start the testcase, we know the peers and have handles to CADET.
694 *
695 * Testcase continues when the root receives confirmation of connected peers,
696 * on callback function ch.
697 *
698 * @param cls Closure (unused).
699 */
700static void
701start_test (void *cls)
702{
703 struct GNUNET_MQ_MessageHandler handlers[] = {
704 GNUNET_MQ_hd_var_size (data,
705 GNUNET_MESSAGE_TYPE_DUMMY,
706 struct GNUNET_MessageHeader,
707 NULL),
708 GNUNET_MQ_handler_end ()
709 };
710 struct CadetTestChannelWrapper *ch;
711 enum GNUNET_CADET_ChannelOption flags;
712
713 test_task = NULL;
714 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
715 "In start_test\n");
716 start_time = GNUNET_TIME_absolute_get ();
717 ch = GNUNET_new (struct CadetTestChannelWrapper);
718 outgoing_ch = GNUNET_CADET_channel_create (h1,
719 ch,
720 p_id[1],
721 &port,
722 flags,
723 NULL,
724 &disconnect_handler,
725 handlers);
726 ch->ch = outgoing_ch;
727 GNUNET_assert (NULL == disconnect_task);
728 disconnect_task
729 = GNUNET_SCHEDULER_add_delayed (short_time,
730 &gather_stats_and_exit,
731 (void *) __LINE__);
732 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
733 "Sending data initializer on channel %p...\n",
734 outgoing_ch);
735 send_test_message (outgoing_ch);
736}
737
738
739/**
740 * Callback to be called when the requested peer information is available
741 *
742 * @param cls the closure from GNUNET_TESTBED_peer_get_information()
743 * @param op the operation this callback corresponds to
744 * @param pinfo the result; will be NULL if the operation has failed
745 * @param emsg error message if the operation has failed;
746 * NULL if the operation is successful
747 */
748static void
749pi_cb (void *cls,
750 struct GNUNET_TESTBED_Operation *op,
751 const struct GNUNET_TESTBED_PeerInformation *pinfo,
752 const char *emsg)
753{
754 long i = (long) cls;
755
756 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
757 "ID callback for %ld\n",
758 i);
759 if ((NULL == pinfo) ||
760 (NULL != emsg))
761 {
762 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
763 "pi_cb: %s\n",
764 emsg);
765 abort_test (__LINE__);
766 return;
767 }
768 p_id[i] = pinfo->result.id;
769 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
770 "id: %s\n",
771 GNUNET_i2s (p_id[i]));
772 p_ids++;
773 if (p_ids < 2)
774 return;
775 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
776 "Got all IDs, starting test\n");
777 test_task = GNUNET_SCHEDULER_add_now (&start_test,
778 NULL);
779}
780
781
782/**
783 * test main: start test when all peers are connected
784 *
785 * @param cls Closure.
786 * @param ctx Argument to give to GNUNET_CADET_TEST_cleanup on test end.
787 * @param num_peers Number of peers that are running.
788 * @param peers Array of peers.
789 * @param cadets Handle to each of the CADETs of the peers.
790 */
791static void
792tmain (void *cls,
793 struct GNUNET_CADET_TEST_Context *ctx,
794 unsigned int num_peers,
795 struct GNUNET_TESTBED_Peer **peers,
796 struct GNUNET_CADET_Handle **cadets)
797{
798 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
799 "test main\n");
800 test_ctx = ctx;
801 peers_running = num_peers;
802 GNUNET_assert (peers_running == peers_requested);
803 testbed_peers = peers;
804 h1 = cadets[0];
805 h2 = cadets[num_peers - 1];
806 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
807 NULL);
808 p_ids = 0;
809 t_op[0] = GNUNET_TESTBED_peer_get_information (peers[0],
810 GNUNET_TESTBED_PIT_IDENTITY,
811 &pi_cb,
812 (void *) 0L);
813 t_op[1] = GNUNET_TESTBED_peer_get_information (peers[num_peers - 1],
814 GNUNET_TESTBED_PIT_IDENTITY,
815 &pi_cb,
816 (void *) 1L);
817 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
818 "requested peer ids\n");
819}
820
821
822/**
823 * Main: start test
824 */
825int
826main (int argc,
827 char *argv[])
828{
829 static const struct GNUNET_HashCode *ports[2];
830 struct GNUNET_MQ_MessageHandler handlers[] = {
831 GNUNET_MQ_hd_var_size (data,
832 GNUNET_MESSAGE_TYPE_DUMMY,
833 struct GNUNET_MessageHeader,
834 NULL),
835 GNUNET_MQ_handler_end ()
836 };
837 const char *config_file = "test_cadet.conf";
838 char port_id[] = "test port";
839 struct GNUNET_GETOPT_CommandLineOption options[] = {
840 GNUNET_GETOPT_option_relative_time ('t',
841 "time",
842 "short_time",
843 gettext_noop ("set short timeout"),
844 &short_time),
845 GNUNET_GETOPT_option_uint ('m',
846 "messages",
847 "NUM_MESSAGES",
848 gettext_noop ("set number of messages to send"),
849 &total_packets),
850 GNUNET_GETOPT_option_uint ('p',
851 "peers",
852 "NUM_PEERS",
853 gettext_noop ("number of peers to launch"),
854 &peers_requested),
855 GNUNET_GETOPT_OPTION_END
856 };
857
858 GNUNET_log_setup ("test-cadet-flow",
859 "DEBUG",
860 NULL);
861 total_packets = TOTAL_PACKETS;
862 short_time = SHORT_TIME;
863 if (-1 == GNUNET_GETOPT_run (argv[0],
864 options,
865 argc,
866 argv))
867 {
868 fprintf (stderr,
869 "test failed: problem with CLI parameters\n");
870 return 1;
871 }
872 GNUNET_CRYPTO_hash (port_id,
873 sizeof(port_id),
874 &port);
875 ports[0] = &port;
876 ports[1] = NULL;
877 GNUNET_CADET_TEST_ruN ("test_cadet_flow",
878 config_file,
879 peers_requested,
880 &tmain,
881 NULL, /* tmain cls */
882 &connect_handler,
883 NULL,
884 &disconnect_handler,
885 handlers,
886 ports);
887 return 0;
888}
889
890
891/* end of test_cadet_flow.c */
diff --git a/src/cadet/test_cadet_local_mq.c b/src/cadet/test_cadet_local_mq.c
deleted file mode 100644
index 6f75dfd1f..000000000
--- a/src/cadet/test_cadet_local_mq.c
+++ /dev/null
@@ -1,338 +0,0 @@
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/cadet/valgrind-cadet.supp b/src/cadet/valgrind-cadet.supp
deleted file mode 100644
index fecd5185b..000000000
--- a/src/cadet/valgrind-cadet.supp
+++ /dev/null
@@ -1,116 +0,0 @@
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