aboutsummaryrefslogtreecommitdiff
path: root/src/cadet
diff options
context:
space:
mode:
Diffstat (limited to 'src/cadet')
-rw-r--r--src/cadet/.gitignore27
-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.c1073
-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.c267
-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.c1374
-rw-r--r--src/cadet/gnunet-service-cadet.h328
-rw-r--r--src/cadet/gnunet-service-cadet_channel.c2008
-rw-r--r--src/cadet/gnunet-service-cadet_channel.h306
-rw-r--r--src/cadet/gnunet-service-cadet_connection.c1079
-rw-r--r--src/cadet/gnunet-service-cadet_connection.h363
-rw-r--r--src/cadet/gnunet-service-cadet_core.c1337
-rw-r--r--src/cadet/gnunet-service-cadet_core.h69
-rw-r--r--src/cadet/gnunet-service-cadet_dht.c331
-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.c771
-rw-r--r--src/cadet/gnunet-service-cadet_paths.h183
-rw-r--r--src/cadet/gnunet-service-cadet_peer.c1566
-rw-r--r--src/cadet/gnunet-service-cadet_peer.h433
-rw-r--r--src/cadet/gnunet-service-cadet_tunnels.c3677
-rw-r--r--src/cadet/gnunet-service-cadet_tunnels.h391
-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, 23907 deletions
diff --git a/src/cadet/.gitignore b/src/cadet/.gitignore
deleted file mode 100644
index e72d81bd8..000000000
--- a/src/cadet/.gitignore
+++ /dev/null
@@ -1,27 +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
27test_cadet_2_destroy
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 00c3d2e48..000000000
--- a/src/cadet/cadet_api.c
+++ /dev/null
@@ -1,1073 +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
801void
802GNUNET_CADET_close_port (struct GNUNET_CADET_Port *p)
803{
804 GNUNET_assert (
805 GNUNET_YES ==
806 GNUNET_CONTAINER_multihashmap_remove (p->cadet->ports, &p->id, p));
807 if (NULL != p->cadet->mq)
808 {
809 struct GNUNET_CADET_PortMessage *msg;
810 struct GNUNET_MQ_Envelope *env;
811
812 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE);
813 msg->port = p->id;
814 GNUNET_MQ_send (p->cadet->mq, env);
815 }
816 GNUNET_free (p->handlers);
817 GNUNET_free (p);
818}
819
820
821/**
822 * Destroy an existing channel.
823 *
824 * The existing end callback for the channel will NOT be called.
825 * Any pending outgoing messages will be sent but no incoming messages will be
826 * accepted and no data callbacks will be called.
827 *
828 * @param channel Channel handle, becomes invalid after this call.
829 */
830void
831GNUNET_CADET_channel_destroy (struct GNUNET_CADET_Channel *channel)
832{
833 struct GNUNET_CADET_Handle *h = channel->cadet;
834 struct GNUNET_CADET_LocalChannelDestroyMessage *msg;
835 struct GNUNET_MQ_Envelope *env;
836
837 if (NULL != h->mq)
838 {
839 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY);
840 msg->ccn = channel->ccn;
841 GNUNET_MQ_send (h->mq, env);
842 }
843 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
844 "Destroying channel due to GNUNET_CADET_channel_destroy()\n");
845 channel->disconnects = NULL;
846 destroy_channel (channel);
847}
848
849
850const union GNUNET_CADET_ChannelInfo *
851GNUNET_CADET_channel_get_info (struct GNUNET_CADET_Channel *channel,
852 enum GNUNET_CADET_ChannelInfoOption option,
853 ...)
854{
855 switch (option)
856 {
857 case GNUNET_CADET_OPTION_PEER:
858 return (const union GNUNET_CADET_ChannelInfo *) &channel->peer;
859
860 default:
861 GNUNET_break (0);
862 return NULL;
863 }
864}
865
866
867/**
868 * Send an ack on the channel to confirm the processing of a message.
869 *
870 * @param ch Channel on which to send the ACK.
871 */
872void
873GNUNET_CADET_receive_done (struct GNUNET_CADET_Channel *channel)
874{
875 struct GNUNET_CADET_LocalAck *msg;
876 struct GNUNET_MQ_Envelope *env;
877
878 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK);
879 LOG (GNUNET_ERROR_TYPE_DEBUG,
880 "Sending ACK on channel %X\n",
881 ntohl (channel->ccn.channel_of_client));
882 msg->ccn = channel->ccn;
883 GNUNET_MQ_send (channel->cadet->mq, env);
884}
885
886
887/**
888 * Connect to the MQ-based cadet service.
889 *
890 * @param cfg Configuration to use.
891 *
892 * @return Handle to the cadet service NULL on error.
893 */
894struct GNUNET_CADET_Handle *
895GNUNET_CADET_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
896{
897 struct GNUNET_CADET_Handle *h;
898
899 LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_CADET_connect()\n");
900 h = GNUNET_new (struct GNUNET_CADET_Handle);
901 h->cfg = cfg;
902 h->ports = GNUNET_CONTAINER_multihashmap_create (4, GNUNET_YES);
903 h->channels = GNUNET_CONTAINER_multihashmap32_create (4);
904 reconnect (h);
905 if (NULL == h->mq)
906 {
907 GNUNET_break (0);
908 GNUNET_CADET_disconnect (h);
909 return NULL;
910 }
911 h->next_ccn.channel_of_client = htonl (GNUNET_CADET_LOCAL_CHANNEL_ID_CLI);
912 return h;
913}
914
915
916/**
917 * Function to return link to AGPL source upon request.
918 *
919 * @param cls closure with the identification of the client
920 * @param msg AGPL request
921 */
922static void
923return_agpl (void *cls, const struct GNUNET_MessageHeader *msg)
924{
925 struct GNUNET_SERVICE_Client *client = cls;
926 struct GNUNET_MQ_Handle *mq;
927 struct GNUNET_MQ_Envelope *env;
928 struct GNUNET_MessageHeader *res;
929 size_t slen;
930 const struct GNUNET_OS_ProjectData *pd = GNUNET_OS_project_data_get ();
931
932 (void) msg;
933 slen = strlen (pd->agpl_url) + 1;
934 env = GNUNET_MQ_msg_extra (res, GNUNET_MESSAGE_TYPE_RESPONSE_AGPL, slen);
935 memcpy (&res[1], GNUNET_AGPL_URL, slen);
936 mq = GNUNET_SERVICE_client_get_mq (client);
937 GNUNET_MQ_send (mq, env);
938 GNUNET_SERVICE_client_continue (client);
939}
940
941
942/**
943 * Open a port to receive incoming MQ-based channels.
944 *
945 * @param h CADET handle.
946 * @param port Hash identifying the port.
947 * @param connects Function called when an incoming channel is connected.
948 * @param connects_cls Closure for the @a connects handler.
949 * @param window_changes Function called when the transmit window size changes.
950 * @param disconnects Function called when a channel is disconnected.
951 * @param handlers Callbacks for messages we care about, NULL-terminated.
952 * @return Port handle, NULL if port is in use
953 */
954struct GNUNET_CADET_Port *
955GNUNET_CADET_open_port (struct GNUNET_CADET_Handle *h,
956 const struct GNUNET_HashCode *port,
957 GNUNET_CADET_ConnectEventHandler connects,
958 void *connects_cls,
959 GNUNET_CADET_WindowSizeEventHandler window_changes,
960 GNUNET_CADET_DisconnectEventHandler disconnects,
961 const struct GNUNET_MQ_MessageHandler *handlers)
962{
963 struct GNUNET_CADET_Port *p;
964 const struct GNUNET_OS_ProjectData *pd = GNUNET_OS_project_data_get ();
965
966 GNUNET_assert (NULL != connects);
967 GNUNET_assert (NULL != disconnects);
968 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
969 "Listening to CADET port %s\n",
970 GNUNET_h2s (port));
971
972 p = GNUNET_new (struct GNUNET_CADET_Port);
973 p->cadet = h;
974 p->id = *port;
975 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (
976 h->ports,
977 &p->id,
978 p,
979 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
980 {
981 GNUNET_free (p);
982 return NULL;
983 }
984 p->connects = connects;
985 p->cls = connects_cls;
986 p->window_changes = window_changes;
987 p->disconnects = disconnects;
988 p->handlers = (NULL == pd->agpl_url)
989 ? GNUNET_MQ_copy_handlers (handlers)
990 : GNUNET_MQ_copy_handlers2 (handlers, &return_agpl, NULL);
991
992 GNUNET_assert (GNUNET_OK == open_port_cb (h, &p->id, p));
993 return p;
994}
995
996
997/**
998 * Create a new channel towards a remote peer.
999 *
1000 * If the destination peer closes the channel after accepting it,
1001 * @a disconnects will be called for this channel (unless
1002 * #GNUNET_CADET_channel_destroy() was called on this end first).
1003 *
1004 * @param h CADET handle.
1005 * @param channel_cls Closure for the channel. It's given to:
1006 * - The disconnect handler @a disconnects
1007 * - Each message type callback in @a handlers
1008 * @param destination Peer identity the channel should go to.
1009 * @param port Identification of the destination port.
1010 * @param window_changes Function called when the transmit window size changes.
1011 * @param disconnects Function called when the channel is disconnected.
1012 * @param handlers Callbacks for messages we care about, NULL-terminated.
1013 * @return Handle to the channel.
1014 */
1015struct GNUNET_CADET_Channel *
1016GNUNET_CADET_channel_create (struct GNUNET_CADET_Handle *h,
1017 void *channel_cls,
1018 const struct GNUNET_PeerIdentity *destination,
1019 const struct GNUNET_HashCode *port,
1020 GNUNET_CADET_WindowSizeEventHandler window_changes,
1021 GNUNET_CADET_DisconnectEventHandler disconnects,
1022 const struct GNUNET_MQ_MessageHandler *handlers)
1023{
1024 struct GNUNET_CADET_Channel *ch;
1025 struct GNUNET_CADET_LocalChannelCreateMessage *msg;
1026 struct GNUNET_MQ_Envelope *env;
1027
1028 GNUNET_assert (NULL != disconnects);
1029 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1030 "Creating channel to peer %s at port %s\n",
1031 GNUNET_i2s (destination),
1032 GNUNET_h2s (port));
1033 ch = create_channel (h, NULL);
1034 ch->ctx = channel_cls;
1035 ch->peer = *destination;
1036 ch->window_changes = window_changes;
1037 ch->disconnects = disconnects;
1038
1039 /* Create MQ for channel */
1040 ch->mq = GNUNET_MQ_queue_for_callbacks (&cadet_mq_send_impl,
1041 &cadet_mq_destroy_impl,
1042 &cadet_mq_cancel_impl,
1043 ch,
1044 handlers,
1045 &cadet_mq_error_handler,
1046 ch);
1047 GNUNET_MQ_set_handlers_closure (ch->mq, channel_cls);
1048
1049 /* Request channel creation to service */
1050 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE);
1051 msg->ccn = ch->ccn;
1052 msg->port = *port;
1053 msg->peer = *destination;
1054 GNUNET_MQ_send (h->mq, env);
1055 return ch;
1056}
1057
1058
1059/**
1060 * Obtain the message queue for a connected peer.
1061 *
1062 * @param channel The channel handle from which to get the MQ.
1063 *
1064 * @return NULL if @a channel is not yet connected.
1065 */
1066struct GNUNET_MQ_Handle *
1067GNUNET_CADET_get_mq (const struct GNUNET_CADET_Channel *channel)
1068{
1069 return channel->mq;
1070}
1071
1072
1073/* 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 f32a5e20b..000000000
--- a/src/cadet/cadet_api_get_path.c
+++ /dev/null
@@ -1,267 +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
219struct GNUNET_CADET_GetPath *
220GNUNET_CADET_get_path (const struct GNUNET_CONFIGURATION_Handle *cfg,
221 const struct GNUNET_PeerIdentity *id,
222 GNUNET_CADET_PathCB callback,
223 void *callback_cls)
224{
225 struct GNUNET_CADET_GetPath *gp;
226
227 if (NULL == callback)
228 {
229 GNUNET_break (0);
230 return NULL;
231 }
232 gp = GNUNET_new (struct GNUNET_CADET_GetPath);
233 gp->path_cb = callback;
234 gp->path_cb_cls = callback_cls;
235 gp->cfg = cfg;
236 gp->id = *id;
237 reconnect (gp);
238 if (NULL == gp->mq)
239 {
240 GNUNET_free (gp);
241 return NULL;
242 }
243 return gp;
244}
245
246
247/**
248 * Cancel @a gp operation.
249 *
250 * @param gp operation to cancel
251 * @return closure from #GNUNET_CADET_get_path().
252 */
253void *
254GNUNET_CADET_get_path_cancel (struct GNUNET_CADET_GetPath *gp)
255{
256 void *ret = gp->path_cb_cls;
257
258 if (NULL != gp->mq)
259 GNUNET_MQ_destroy (gp->mq);
260 if (NULL != gp->reconnect_task)
261 GNUNET_SCHEDULER_cancel (gp->reconnect_task);
262 GNUNET_free (gp);
263 return ret;
264}
265
266
267/* end of cadet_api_get_path.c */
diff --git a/src/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 dd1f05807..000000000
--- a/src/cadet/gnunet-service-cadet.c
+++ /dev/null
@@ -1,1374 +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
1100void
1101GSC_drop_loose_channel (const struct GNUNET_HashCode *h_port,
1102 struct CadetChannel *ch)
1103{
1104 GNUNET_assert (GNUNET_YES ==
1105 GNUNET_CONTAINER_multihashmap_remove (loose_channels,
1106 h_port,
1107 ch));
1108}
1109
1110
1111/**
1112 * Iterator for deleting each channel whose client endpoint disconnected.
1113 *
1114 * @param cls Closure (client that has disconnected).
1115 * @param key The local channel id in host byte order
1116 * @param value The value stored at the key (channel to destroy).
1117 * @return #GNUNET_OK, keep iterating.
1118 */
1119static int
1120channel_destroy_iterator (void *cls,
1121 uint32_t key,
1122 void *value)
1123{
1124 struct CadetClient *c = cls;
1125 struct GNUNET_CADET_ClientChannelNumber ccn;
1126 struct CadetChannel *ch = value;
1127
1128 LOG (GNUNET_ERROR_TYPE_DEBUG,
1129 "Destroying %s, due to %s disconnecting.\n",
1130 GCCH_2s (ch),
1131 GSC_2s (c));
1132 ccn.channel_of_client = htonl (key);
1133 GNUNET_assert (GNUNET_YES ==
1134 GNUNET_CONTAINER_multihashmap32_remove (c->channels,
1135 key,
1136 ch));
1137 GCCH_channel_local_destroy (ch,
1138 c,
1139 ccn);
1140 return GNUNET_OK;
1141}
1142
1143
1144/**
1145 * Remove client's ports from the global hashmap on disconnect.
1146 *
1147 * @param cls the `struct CadetClient`
1148 * @param port the port.
1149 * @param value the `struct OpenPort` to remove
1150 * @return #GNUNET_OK, keep iterating.
1151 */
1152static int
1153client_release_ports (void *cls,
1154 const struct GNUNET_HashCode *port,
1155 void *value)
1156{
1157 struct CadetClient *c = cls;
1158 struct OpenPort *op = value;
1159
1160 GNUNET_assert (c == op->c);
1161 LOG (GNUNET_ERROR_TYPE_DEBUG,
1162 "Closing port %s due to %s disconnect.\n",
1163 GNUNET_h2s (port),
1164 GSC_2s (c));
1165 GNUNET_assert (GNUNET_YES ==
1166 GNUNET_CONTAINER_multihashmap_remove (open_ports,
1167 &op->h_port,
1168 op));
1169 GNUNET_assert (GNUNET_YES ==
1170 GNUNET_CONTAINER_multihashmap_remove (c->ports,
1171 port,
1172 op));
1173 GNUNET_free (op);
1174 return GNUNET_OK;
1175}
1176
1177
1178/**
1179 * Callback called when a client disconnected from the service
1180 *
1181 * @param cls closure for the service
1182 * @param client the client that disconnected
1183 * @param internal_cls should be equal to @a c
1184 */
1185static void
1186client_disconnect_cb (void *cls,
1187 struct GNUNET_SERVICE_Client *client,
1188 void *internal_cls)
1189{
1190 struct CadetClient *c = internal_cls;
1191
1192 GNUNET_assert (c->client == client);
1193 LOG (GNUNET_ERROR_TYPE_DEBUG,
1194 "%s is disconnecting.\n",
1195 GSC_2s (c));
1196 if (NULL != c->channels)
1197 {
1198 GNUNET_CONTAINER_multihashmap32_iterate (c->channels,
1199 &channel_destroy_iterator,
1200 c);
1201 GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap32_size (c->channels));
1202 GNUNET_CONTAINER_multihashmap32_destroy (c->channels);
1203 }
1204 if (NULL != c->ports)
1205 {
1206 GNUNET_CONTAINER_multihashmap_iterate (c->ports,
1207 &client_release_ports,
1208 c);
1209 GNUNET_CONTAINER_multihashmap_destroy (c->ports);
1210 }
1211 GNUNET_CONTAINER_DLL_remove (clients_head,
1212 clients_tail,
1213 c);
1214 GNUNET_STATISTICS_update (stats,
1215 "# clients",
1216 -1,
1217 GNUNET_NO);
1218 GNUNET_free (c);
1219 if ((NULL == clients_head) &&
1220 (GNUNET_YES == shutting_down))
1221 shutdown_rest ();
1222}
1223
1224
1225/**
1226 * Setup CADET internals.
1227 *
1228 * @param cls closure
1229 * @param server the initialized server
1230 * @param c configuration to use
1231 */
1232static void
1233run (void *cls,
1234 const struct GNUNET_CONFIGURATION_Handle *c,
1235 struct GNUNET_SERVICE_Handle *service)
1236{
1237 cfg = c;
1238 if (GNUNET_OK !=
1239 GNUNET_CONFIGURATION_get_value_number (c,
1240 "CADET",
1241 "RATCHET_MESSAGES",
1242 &ratchet_messages))
1243 {
1244 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
1245 "CADET",
1246 "RATCHET_MESSAGES",
1247 "needs to be a number");
1248 ratchet_messages = 64;
1249 }
1250 if (GNUNET_OK !=
1251 GNUNET_CONFIGURATION_get_value_time (c,
1252 "CADET",
1253 "RATCHET_TIME",
1254 &ratchet_time))
1255 {
1256 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
1257 "CADET",
1258 "RATCHET_TIME",
1259 "need delay value");
1260 ratchet_time = GNUNET_TIME_UNIT_HOURS;
1261 }
1262 if (GNUNET_OK !=
1263 GNUNET_CONFIGURATION_get_value_time (c,
1264 "CADET",
1265 "REFRESH_CONNECTION_TIME",
1266 &keepalive_period))
1267 {
1268 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
1269 "CADET",
1270 "REFRESH_CONNECTION_TIME",
1271 "need delay value");
1272 keepalive_period = GNUNET_TIME_UNIT_MINUTES;
1273 }
1274 if (GNUNET_OK !=
1275 GNUNET_CONFIGURATION_get_value_number (c,
1276 "CADET",
1277 "DROP_PERCENT",
1278 &drop_percent))
1279 {
1280 drop_percent = 0;
1281 }
1282 else
1283 {
1284 LOG (GNUNET_ERROR_TYPE_WARNING, "**************************************\n");
1285 LOG (GNUNET_ERROR_TYPE_WARNING, "Cadet is running with DROP enabled.\n");
1286 LOG (GNUNET_ERROR_TYPE_WARNING, "This is NOT a good idea!\n");
1287 LOG (GNUNET_ERROR_TYPE_WARNING, "Remove DROP_PERCENT from config file.\n");
1288 LOG (GNUNET_ERROR_TYPE_WARNING, "**************************************\n");
1289 }
1290 my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (c);
1291 if (NULL == my_private_key)
1292 {
1293 GNUNET_break (0);
1294 GNUNET_SCHEDULER_shutdown ();
1295 return;
1296 }
1297 GNUNET_CRYPTO_eddsa_key_get_public (my_private_key,
1298 &my_full_id.public_key);
1299 stats = GNUNET_STATISTICS_create ("cadet",
1300 c);
1301 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
1302 NULL);
1303 ats_ch = GNUNET_ATS_connectivity_init (c);
1304 /* FIXME: optimize code to allow GNUNET_YES here! */
1305 open_ports = GNUNET_CONTAINER_multihashmap_create (16,
1306 GNUNET_NO);
1307 loose_channels = GNUNET_CONTAINER_multihashmap_create (16,
1308 GNUNET_NO);
1309 peers = GNUNET_CONTAINER_multipeermap_create (16,
1310 GNUNET_YES);
1311 connections = GNUNET_CONTAINER_multishortmap_create (256,
1312 GNUNET_YES);
1313 GCH_init (c);
1314 GCD_init (c);
1315 GCO_init (c);
1316 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1317 "CADET started for peer %s\n",
1318 GNUNET_i2s (&my_full_id));
1319}
1320
1321
1322/**
1323 * Define "main" method using service macro.
1324 */
1325GNUNET_SERVICE_MAIN
1326 ("cadet",
1327 GNUNET_SERVICE_OPTION_NONE,
1328 &run,
1329 &client_connect_cb,
1330 &client_disconnect_cb,
1331 NULL,
1332 GNUNET_MQ_hd_fixed_size (port_open,
1333 GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN,
1334 struct GNUNET_CADET_PortMessage,
1335 NULL),
1336 GNUNET_MQ_hd_fixed_size (port_close,
1337 GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE,
1338 struct GNUNET_CADET_PortMessage,
1339 NULL),
1340 GNUNET_MQ_hd_fixed_size (channel_create,
1341 GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE,
1342 struct GNUNET_CADET_LocalChannelCreateMessage,
1343 NULL),
1344 GNUNET_MQ_hd_fixed_size (channel_destroy,
1345 GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY,
1346 struct GNUNET_CADET_LocalChannelDestroyMessage,
1347 NULL),
1348 GNUNET_MQ_hd_var_size (local_data,
1349 GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA,
1350 struct GNUNET_CADET_LocalData,
1351 NULL),
1352 GNUNET_MQ_hd_fixed_size (local_ack,
1353 GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK,
1354 struct GNUNET_CADET_LocalAck,
1355 NULL),
1356 GNUNET_MQ_hd_fixed_size (get_peers,
1357 GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_PEERS,
1358 struct GNUNET_MessageHeader,
1359 NULL),
1360 GNUNET_MQ_hd_fixed_size (show_path,
1361 GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_PATH,
1362 struct GNUNET_CADET_RequestPathInfoMessage,
1363 NULL),
1364 GNUNET_MQ_hd_fixed_size (info_tunnels,
1365 GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_TUNNELS,
1366 struct GNUNET_MessageHeader,
1367 NULL),
1368 GNUNET_MQ_hd_fixed_size (drop_message,
1369 GNUNET_MESSAGE_TYPE_CADET_DROP_CADET_MESSAGE,
1370 struct GNUNET_CADET_RequestDropCadetMessage,
1371 NULL),
1372 GNUNET_MQ_handler_end ());
1373
1374/* 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 f742ba4a7..000000000
--- a/src/cadet/gnunet-service-cadet_channel.c
+++ /dev/null
@@ -1,2008 +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
391void
392GCCH_assign_type_to_drop (struct CadetChannel *ch, const struct
393 GNUNET_CADET_RequestDropCadetMessage *message)
394{
395
396 ch->type = message->type;
397
398}
399
400
401/**
402 * Check if type of message is the one to drop.
403 * @param ch CadetChannel to check for message type to drop.
404 * @param message GNUNET_MessageHeader to compare the type with.
405 */
406int
407GCCH_is_type_to_drop (struct CadetChannel *ch, const struct
408 GNUNET_MessageHeader *message)
409{
410
411 if (ch->type == message->type)
412 {
413 ch->type = 0;
414 return GNUNET_YES;
415 }
416 else
417 return GNUNET_NO;
418}
419
420
421/**
422 * Get the static string for identification of the channel.
423 *
424 * @param ch Channel.
425 *
426 * @return Static string with the channel IDs.
427 */
428const char *
429GCCH_2s (const struct CadetChannel *ch)
430{
431 static char buf[128];
432
433 GNUNET_snprintf (buf,
434 sizeof(buf),
435 "Channel %s:%s ctn:%X(%X/%X)",
436 (GNUNET_YES == ch->is_loopback)
437 ? "loopback"
438 : GNUNET_i2s (GCP_get_id (GCT_get_destination (ch->t))),
439 GNUNET_h2s (&ch->port),
440 ch->ctn.cn,
441 (NULL == ch->owner)
442 ? 0
443 : ntohl (ch->owner->ccn.channel_of_client),
444 (NULL == ch->dest)
445 ? 0
446 : ntohl (ch->dest->ccn.channel_of_client));
447 return buf;
448}
449
450
451/**
452 * Hash the @a port and @a initiator and @a listener to
453 * calculate the "challenge" @a h_port we send to the other
454 * peer on #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN.
455 *
456 * @param[out] h_port set to the hash of @a port, @a initiator and @a listener
457 * @param port cadet port, as seen by CADET clients
458 * @param listener peer that is listining on @a port
459 */
460void
461GCCH_hash_port (struct GNUNET_HashCode *h_port,
462 const struct GNUNET_HashCode *port,
463 const struct GNUNET_PeerIdentity *listener)
464{
465 struct GNUNET_HashContext *hc;
466
467 hc = GNUNET_CRYPTO_hash_context_start ();
468 GNUNET_CRYPTO_hash_context_read (hc, port, sizeof(*port));
469 GNUNET_CRYPTO_hash_context_read (hc, listener, sizeof(*listener));
470 GNUNET_CRYPTO_hash_context_finish (hc, h_port);
471 LOG (GNUNET_ERROR_TYPE_DEBUG,
472 "Calculated port hash %s\n",
473 GNUNET_h2s (h_port));
474}
475
476
477/**
478 * Get the channel's public ID.
479 *
480 * @param ch Channel.
481 *
482 * @return ID used to identify the channel with the remote peer.
483 */
484struct GNUNET_CADET_ChannelTunnelNumber
485GCCH_get_id (const struct CadetChannel *ch)
486{
487 return ch->ctn;
488}
489
490
491/**
492 * Release memory associated with @a ccc
493 *
494 * @param ccc data structure to clean up
495 */
496static void
497free_channel_client (struct CadetChannelClient *ccc)
498{
499 struct CadetOutOfOrderMessage *com;
500
501 while (NULL != (com = ccc->head_recv))
502 {
503 GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, com);
504 ccc->num_recv--;
505 GNUNET_MQ_discard (com->env);
506 GNUNET_free (com);
507 }
508 GNUNET_free (ccc);
509}
510
511
512/**
513 * Destroy the given channel.
514 *
515 * @param ch channel to destroy
516 */
517static void
518channel_destroy (struct CadetChannel *ch)
519{
520 struct CadetReliableMessage *crm;
521
522 while (NULL != (crm = ch->head_sent))
523 {
524 GNUNET_assert (ch == crm->ch);
525 if (NULL != crm->qe)
526 {
527 GCT_send_cancel (crm->qe);
528 crm->qe = NULL;
529 }
530 GNUNET_CONTAINER_DLL_remove (ch->head_sent, ch->tail_sent, crm);
531 GNUNET_free (crm->data_message);
532 GNUNET_free (crm);
533 }
534 if (CADET_CHANNEL_LOOSE == ch->state)
535 {
536 GSC_drop_loose_channel (&ch->h_port, ch);
537 }
538 if (NULL != ch->owner)
539 {
540 free_channel_client (ch->owner);
541 ch->owner = NULL;
542 }
543 if (NULL != ch->dest)
544 {
545 free_channel_client (ch->dest);
546 ch->dest = NULL;
547 }
548 if (NULL != ch->last_control_qe)
549 {
550 GCT_send_cancel (ch->last_control_qe);
551 ch->last_control_qe = NULL;
552 }
553 if (NULL != ch->retry_data_task)
554 {
555 GNUNET_SCHEDULER_cancel (ch->retry_data_task);
556 ch->retry_data_task = NULL;
557 }
558 if (NULL != ch->retry_control_task)
559 {
560 GNUNET_SCHEDULER_cancel (ch->retry_control_task);
561 ch->retry_control_task = NULL;
562 }
563 if (GNUNET_NO == ch->is_loopback)
564 {
565 GCT_remove_channel (ch->t, ch, ch->ctn);
566 ch->t = NULL;
567 }
568 GNUNET_free (ch);
569}
570
571
572/**
573 * Send a channel create message.
574 *
575 * @param cls Channel for which to send.
576 */
577static void
578send_channel_open (void *cls);
579
580
581/**
582 * Function called once the tunnel confirms that we sent the
583 * create message. Delays for a bit until we retry.
584 *
585 * @param cls our `struct CadetChannel`.
586 * @param cid identifier of the connection within the tunnel, NULL
587 * if transmission failed
588 */
589static void
590channel_open_sent_cb (void *cls,
591 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
592{
593 struct CadetChannel *ch = cls;
594
595 GNUNET_assert (NULL != ch->last_control_qe);
596 ch->last_control_qe = NULL;
597 ch->retry_time = GNUNET_TIME_STD_BACKOFF (ch->retry_time);
598 LOG (GNUNET_ERROR_TYPE_DEBUG,
599 "Sent CADET_CHANNEL_OPEN on %s, retrying in %s\n",
600 GCCH_2s (ch),
601 GNUNET_STRINGS_relative_time_to_string (ch->retry_time, GNUNET_YES));
602 ch->retry_control_task =
603 GNUNET_SCHEDULER_add_delayed (ch->retry_time, &send_channel_open, ch);
604}
605
606
607/**
608 * Send a channel open message.
609 *
610 * @param cls Channel for which to send.
611 */
612static void
613send_channel_open (void *cls)
614{
615 struct CadetChannel *ch = cls;
616 struct GNUNET_CADET_ChannelOpenMessage msgcc;
617
618 ch->retry_control_task = NULL;
619 LOG (GNUNET_ERROR_TYPE_DEBUG,
620 "Sending CHANNEL_OPEN message for %s\n",
621 GCCH_2s (ch));
622 msgcc.header.size = htons (sizeof(msgcc));
623 msgcc.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN);
624 // TODO This will be removed in a major release, because this will be a protocol breaking change. We set the deprecated "reliable" bit here that was removed.
625 msgcc.opt = 2;
626 msgcc.h_port = ch->h_port;
627 msgcc.ctn = ch->ctn;
628 ch->state = CADET_CHANNEL_OPEN_SENT;
629 if (NULL != ch->last_control_qe)
630 GCT_send_cancel (ch->last_control_qe);
631 ch->last_control_qe =
632 GCT_send (ch->t, &msgcc.header, &channel_open_sent_cb, ch, &msgcc.ctn);
633 GNUNET_assert (NULL == ch->retry_control_task);
634}
635
636
637/**
638 * Function called once and only once after a channel was bound
639 * to its tunnel via #GCT_add_channel() is ready for transmission.
640 * Note that this is only the case for channels that this peer
641 * initiates, as for incoming channels we assume that they are
642 * ready for transmission immediately upon receiving the open
643 * message. Used to bootstrap the #GCT_send() process.
644 *
645 * @param ch the channel for which the tunnel is now ready
646 */
647void
648GCCH_tunnel_up (struct CadetChannel *ch)
649{
650 GNUNET_assert (NULL == ch->retry_control_task);
651 LOG (GNUNET_ERROR_TYPE_DEBUG,
652 "Tunnel up, sending CHANNEL_OPEN on %s now\n",
653 GCCH_2s (ch));
654 ch->retry_control_task = GNUNET_SCHEDULER_add_now (&send_channel_open, ch);
655}
656
657
658struct CadetChannel *
659GCCH_channel_local_new (struct CadetClient *owner,
660 struct GNUNET_CADET_ClientChannelNumber ccn,
661 struct CadetPeer *destination,
662 const struct GNUNET_HashCode *port,
663 uint32_t options)
664{
665 struct CadetChannel *ch;
666 struct CadetChannelClient *ccco;
667
668 ccco = GNUNET_new (struct CadetChannelClient);
669 ccco->c = owner;
670 ccco->ccn = ccn;
671 ccco->client_ready = GNUNET_YES;
672
673 ch = GNUNET_new (struct CadetChannel);
674 ch->mid_recv.mid = htonl (1); /* The OPEN_ACK counts as message 0! */
675 ch->nobuffer = GNUNET_NO;
676 ch->reliable = GNUNET_YES;
677 ch->out_of_order = GNUNET_NO;
678 ch->max_pending_messages =
679 (ch->nobuffer) ? 1 : 4; /* FIXME: 4!? Do not hardcode! */
680 ch->owner = ccco;
681 ch->port = *port;
682 GCCH_hash_port (&ch->h_port, port, GCP_get_id (destination));
683 if (0 == GNUNET_memcmp (&my_full_id, GCP_get_id (destination)))
684 {
685 struct OpenPort *op;
686
687 ch->is_loopback = GNUNET_YES;
688 op = GNUNET_CONTAINER_multihashmap_get (open_ports, &ch->h_port);
689 if (NULL == op)
690 {
691 /* port closed, wait for it to possibly open */
692 ch->state = CADET_CHANNEL_LOOSE;
693 (void) GNUNET_CONTAINER_multihashmap_put (
694 loose_channels,
695 &ch->h_port,
696 ch,
697 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
698 LOG (GNUNET_ERROR_TYPE_DEBUG,
699 "Created loose incoming loopback channel to port %s\n",
700 GNUNET_h2s (&ch->port));
701 }
702 else
703 {
704 GCCH_bind (ch, op->c, &op->port);
705 }
706 }
707 else
708 {
709 ch->t = GCP_get_tunnel (destination, GNUNET_YES);
710 ch->retry_time = CADET_INITIAL_RETRANSMIT_TIME;
711 ch->ctn = GCT_add_channel (ch->t, ch);
712 }
713 GNUNET_STATISTICS_update (stats, "# channels", 1, GNUNET_NO);
714 LOG (GNUNET_ERROR_TYPE_DEBUG,
715 "Created channel to port %s at peer %s for %s using %s\n",
716 GNUNET_h2s (port),
717 GCP_2s (destination),
718 GSC_2s (owner),
719 (GNUNET_YES == ch->is_loopback) ? "loopback" : GCT_2s (ch->t));
720 return ch;
721}
722
723
724/**
725 * We had an incoming channel to a port that is closed.
726 * It has not been opened for a while, drop it.
727 *
728 * @param cls the channel to drop
729 */
730static void
731timeout_closed_cb (void *cls)
732{
733 struct CadetChannel *ch = cls;
734
735 ch->retry_control_task = NULL;
736 LOG (GNUNET_ERROR_TYPE_DEBUG,
737 "Closing incoming channel to port %s from peer %s due to timeout\n",
738 GNUNET_h2s (&ch->port),
739 GCP_2s (GCT_get_destination (ch->t)));
740 channel_destroy (ch);
741}
742
743
744struct CadetChannel *
745GCCH_channel_incoming_new (struct CadetTunnel *t,
746 struct GNUNET_CADET_ChannelTunnelNumber ctn,
747 const struct GNUNET_HashCode *h_port,
748 uint32_t options)
749{
750 struct CadetChannel *ch;
751 struct OpenPort *op;
752
753 ch = GNUNET_new (struct CadetChannel);
754 ch->h_port = *h_port;
755 ch->t = t;
756 ch->ctn = ctn;
757 ch->retry_time = CADET_INITIAL_RETRANSMIT_TIME;
758 ch->nobuffer = GNUNET_NO;
759 ch->reliable = GNUNET_YES;
760 ch->out_of_order = GNUNET_NO;
761 ch->max_pending_messages =
762 (ch->nobuffer) ? 1 : 4; /* FIXME: 4!? Do not hardcode! */
763 GNUNET_STATISTICS_update (stats, "# channels", 1, GNUNET_NO);
764
765 op = GNUNET_CONTAINER_multihashmap_get (open_ports, h_port);
766 if (NULL == op)
767 {
768 /* port closed, wait for it to possibly open */
769 ch->state = CADET_CHANNEL_LOOSE;
770 (void) GNUNET_CONTAINER_multihashmap_put (
771 loose_channels,
772 &ch->h_port,
773 ch,
774 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
775 GNUNET_assert (NULL == ch->retry_control_task);
776 ch->retry_control_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT_CLOSED_PORT,
777 &timeout_closed_cb,
778 ch);
779 LOG (GNUNET_ERROR_TYPE_DEBUG,
780 "Created loose incoming channel to port %s from peer %s\n",
781 GNUNET_h2s (&ch->port),
782 GCP_2s (GCT_get_destination (ch->t)));
783 }
784 else
785 {
786 GCCH_bind (ch, op->c, &op->port);
787 }
788 GNUNET_STATISTICS_update (stats, "# channels", 1, GNUNET_NO);
789 return ch;
790}
791
792
793/**
794 * Function called once the tunnel confirms that we sent the
795 * ACK message. Just remembers it was sent, we do not expect
796 * ACKs for ACKs ;-).
797 *
798 * @param cls our `struct CadetChannel`.
799 * @param cid identifier of the connection within the tunnel, NULL
800 * if transmission failed
801 */
802static void
803send_ack_cb (void *cls,
804 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
805{
806 struct CadetChannel *ch = cls;
807
808 GNUNET_assert (NULL != ch->last_control_qe);
809 ch->last_control_qe = NULL;
810}
811
812
813/**
814 * Compute and send the current #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK to the other peer.
815 *
816 * @param ch channel to send the #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK for
817 */
818static void
819send_channel_data_ack (struct CadetChannel *ch)
820{
821 struct GNUNET_CADET_ChannelDataAckMessage msg;
822
823 if (GNUNET_NO == ch->reliable)
824 return; /* no ACKs */
825 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK);
826 msg.header.size = htons (sizeof(msg));
827 msg.ctn = ch->ctn;
828 msg.mid.mid = htonl (ntohl (ch->mid_recv.mid));
829 msg.futures = GNUNET_htonll (ch->mid_futures);
830 LOG (GNUNET_ERROR_TYPE_DEBUG,
831 "Sending DATA_ACK %u:%llX via %s\n",
832 (unsigned int) ntohl (msg.mid.mid),
833 (unsigned long long) ch->mid_futures,
834 GCCH_2s (ch));
835 if (NULL != ch->last_control_qe)
836 GCT_send_cancel (ch->last_control_qe);
837 ch->last_control_qe = GCT_send (ch->t, &msg.header, &send_ack_cb, ch,
838 &msg.ctn);
839}
840
841
842/**
843 * Send our initial #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK to the client confirming that the
844 * connection is up.
845 *
846 * @param cls the `struct CadetChannel`
847 */
848static void
849send_open_ack (void *cls)
850{
851 struct CadetChannel *ch = cls;
852 struct GNUNET_CADET_ChannelOpenAckMessage msg;
853
854 ch->retry_control_task = NULL;
855 LOG (GNUNET_ERROR_TYPE_DEBUG,
856 "Sending CHANNEL_OPEN_ACK on %s\n",
857 GCCH_2s (ch));
858 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK);
859 msg.header.size = htons (sizeof(msg));
860 msg.reserved = htonl (0);
861 msg.ctn = ch->ctn;
862 msg.port = ch->port;
863 if (NULL != ch->last_control_qe)
864 GCT_send_cancel (ch->last_control_qe);
865 ch->last_control_qe = GCT_send (ch->t, &msg.header, &send_ack_cb, ch,
866 &msg.ctn);
867}
868
869
870/**
871 * We got a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN message again for
872 * this channel. If the binding was successful, (re)transmit the
873 * #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK.
874 *
875 * @param ch channel that got the duplicate open
876 * @param cti identifier of the connection that delivered the message
877 */
878void
879GCCH_handle_duplicate_open (
880 struct CadetChannel *ch,
881 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti)
882{
883 if (NULL == ch->dest)
884 {
885 LOG (GNUNET_ERROR_TYPE_DEBUG,
886 "Ignoring duplicate CHANNEL_OPEN on %s: port is closed\n",
887 GCCH_2s (ch));
888 return;
889 }
890 if (NULL != ch->retry_control_task)
891 {
892 LOG (GNUNET_ERROR_TYPE_DEBUG,
893 "Ignoring duplicate CHANNEL_OPEN on %s: control message is pending\n",
894 GCCH_2s (ch));
895 return;
896 }
897 LOG (GNUNET_ERROR_TYPE_DEBUG,
898 "Retransmitting CHANNEL_OPEN_ACK on %s\n",
899 GCCH_2s (ch));
900 ch->retry_control_task = GNUNET_SCHEDULER_add_now (&send_open_ack, ch);
901}
902
903
904/**
905 * Send a #GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK to the client to solicit more messages.
906 *
907 * @param ch channel the ack is for
908 * @param to_owner #GNUNET_YES to send to owner,
909 * #GNUNET_NO to send to dest
910 */
911static void
912send_ack_to_client (struct CadetChannel *ch, int to_owner)
913{
914 struct GNUNET_MQ_Envelope *env;
915 struct GNUNET_CADET_LocalAck *ack;
916 struct CadetChannelClient *ccc;
917
918 ccc = (GNUNET_YES == to_owner) ? ch->owner : ch->dest;
919 if (NULL == ccc)
920 {
921 /* This can happen if we are just getting ACKs after
922 our local client already disconnected. */
923 GNUNET_assert (GNUNET_YES == ch->destroy);
924 return;
925 }
926 env = GNUNET_MQ_msg (ack, GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK);
927 ack->ccn = ccc->ccn;
928 LOG (GNUNET_ERROR_TYPE_DEBUG,
929 "Sending CADET_LOCAL_ACK to %s (%s) at ccn %X (%u/%u pending)\n",
930 GSC_2s (ccc->c),
931 (GNUNET_YES == to_owner) ? "owner" : "dest",
932 ntohl (ack->ccn.channel_of_client),
933 ch->pending_messages,
934 ch->max_pending_messages);
935 GSC_send_to_client (ccc->c, env);
936}
937
938
939void
940GCCH_bind (struct CadetChannel *ch,
941 struct CadetClient *c,
942 const struct GNUNET_HashCode *port)
943{
944 uint32_t options;
945 struct CadetChannelClient *cccd;
946
947 LOG (GNUNET_ERROR_TYPE_DEBUG,
948 "Binding %s from %s to port %s of %s\n",
949 GCCH_2s (ch),
950 GCT_2s (ch->t),
951 GNUNET_h2s (&ch->port),
952 GSC_2s (c));
953 if (NULL != ch->retry_control_task)
954 {
955 /* there might be a timeout task here */
956 GNUNET_SCHEDULER_cancel (ch->retry_control_task);
957 ch->retry_control_task = NULL;
958 }
959 options = 0;
960 cccd = GNUNET_new (struct CadetChannelClient);
961 GNUNET_assert (NULL == ch->dest);
962 ch->dest = cccd;
963 ch->port = *port;
964 cccd->c = c;
965 cccd->client_ready = GNUNET_YES;
966 cccd->ccn = GSC_bind (c,
967 ch,
968 (GNUNET_YES == ch->is_loopback)
969 ? GCP_get (&my_full_id, GNUNET_YES)
970 : GCT_get_destination (ch->t),
971 port,
972 options);
973 GNUNET_assert (ntohl (cccd->ccn.channel_of_client) <
974 GNUNET_CADET_LOCAL_CHANNEL_ID_CLI);
975 ch->mid_recv.mid = htonl (1); /* The OPEN counts as message 0! */
976 if (GNUNET_YES == ch->is_loopback)
977 {
978 ch->state = CADET_CHANNEL_OPEN_SENT;
979 GCCH_handle_channel_open_ack (ch, NULL, port);
980 }
981 else
982 {
983 /* notify other peer that we accepted the connection */
984 ch->state = CADET_CHANNEL_READY;
985 ch->retry_control_task = GNUNET_SCHEDULER_add_now (&send_open_ack, ch);
986 }
987 /* give client it's initial supply of ACKs */
988 GNUNET_assert (ntohl (cccd->ccn.channel_of_client) <
989 GNUNET_CADET_LOCAL_CHANNEL_ID_CLI);
990 for (unsigned int i = 0; i < ch->max_pending_messages; i++)
991 send_ack_to_client (ch, GNUNET_NO);
992}
993
994
995/**
996 * One of our clients has disconnected, tell the other one that we
997 * are finished. Done asynchronously to avoid concurrent modification
998 * issues if this is the same client.
999 *
1000 * @param cls the `struct CadetChannel` where one of the ends is now dead
1001 */
1002static void
1003signal_remote_destroy_cb (void *cls)
1004{
1005 struct CadetChannel *ch = cls;
1006 struct CadetChannelClient *ccc;
1007
1008 /* Find which end is left... */
1009 ch->retry_control_task = NULL;
1010 ccc = (NULL != ch->owner) ? ch->owner : ch->dest;
1011 GSC_handle_remote_channel_destroy (ccc->c, ccc->ccn, ch);
1012 channel_destroy (ch);
1013}
1014
1015
1016/**
1017 * Destroy locally created channel. Called by the local client, so no
1018 * need to tell the client.
1019 *
1020 * @param ch channel to destroy
1021 * @param c client that caused the destruction
1022 * @param ccn client number of the client @a c
1023 */
1024void
1025GCCH_channel_local_destroy (struct CadetChannel *ch,
1026 struct CadetClient *c,
1027 struct GNUNET_CADET_ClientChannelNumber ccn)
1028{
1029 LOG (GNUNET_ERROR_TYPE_DEBUG,
1030 "%s asks for destruction of %s\n",
1031 GSC_2s (c),
1032 GCCH_2s (ch));
1033 GNUNET_assert (NULL != c);
1034 if ((NULL != ch->owner) && (c == ch->owner->c) &&
1035 (ccn.channel_of_client == ch->owner->ccn.channel_of_client))
1036 {
1037 free_channel_client (ch->owner);
1038 ch->owner = NULL;
1039 }
1040 else if ((NULL != ch->dest) && (c == ch->dest->c) &&
1041 (ccn.channel_of_client == ch->dest->ccn.channel_of_client))
1042 {
1043 free_channel_client (ch->dest);
1044 ch->dest = NULL;
1045 }
1046 else
1047 {
1048 GNUNET_assert (0);
1049 }
1050
1051 if (GNUNET_YES == ch->destroy)
1052 {
1053 /* other end already destroyed, with the local client gone, no need
1054 to finish transmissions, just destroy immediately. */
1055 channel_destroy (ch);
1056 return;
1057 }
1058 if ((NULL != ch->head_sent) && ((NULL != ch->owner) || (NULL != ch->dest)))
1059 {
1060 /* Wait for other end to destroy us as well,
1061 and otherwise allow send queue to be transmitted first */
1062 ch->destroy = GNUNET_YES;
1063 return;
1064 }
1065 if ((GNUNET_YES == ch->is_loopback) &&
1066 ((NULL != ch->owner) || (NULL != ch->dest)))
1067 {
1068 if (NULL != ch->retry_control_task)
1069 GNUNET_SCHEDULER_cancel (ch->retry_control_task);
1070 ch->retry_control_task =
1071 GNUNET_SCHEDULER_add_now (&signal_remote_destroy_cb, ch);
1072 return;
1073 }
1074 if (GNUNET_NO == ch->is_loopback)
1075 {
1076 /* If the we ever sent the CHANNEL_CREATE, we need to send a destroy message. */
1077 switch (ch->state)
1078 {
1079 case CADET_CHANNEL_NEW:
1080 /* We gave up on a channel that we created as a client to a remote
1081 target, but that never went anywhere. Nothing to do here. */
1082 break;
1083
1084 case CADET_CHANNEL_LOOSE:
1085 break;
1086
1087 default:
1088 GCT_send_channel_destroy (ch->t, ch->ctn);
1089 }
1090 }
1091 /* Nothing left to do, just finish destruction */
1092 channel_destroy (ch);
1093}
1094
1095
1096void
1097GCCH_handle_channel_open_ack (
1098 struct CadetChannel *ch,
1099 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti,
1100 const struct GNUNET_HashCode *port)
1101{
1102 switch (ch->state)
1103 {
1104 case CADET_CHANNEL_NEW:
1105 /* this should be impossible */
1106 GNUNET_break (0);
1107 break;
1108
1109 case CADET_CHANNEL_LOOSE:
1110 /* This makes no sense. */
1111 GNUNET_break_op (0);
1112 break;
1113
1114 case CADET_CHANNEL_OPEN_SENT:
1115 if (NULL == ch->owner)
1116 {
1117 /* We're not the owner, wrong direction! */
1118 GNUNET_break_op (0);
1119 return;
1120 }
1121 if (0 != GNUNET_memcmp (&ch->port, port))
1122 {
1123 /* Other peer failed to provide the right port,
1124 refuse connection. */
1125 GNUNET_break_op (0);
1126 return;
1127 }
1128 LOG (GNUNET_ERROR_TYPE_DEBUG,
1129 "Received CHANNEL_OPEN_ACK for waiting %s, entering READY state\n",
1130 GCCH_2s (ch));
1131 if (NULL != ch->retry_control_task) /* can be NULL if ch->is_loopback */
1132 {
1133 GNUNET_SCHEDULER_cancel (ch->retry_control_task);
1134 ch->retry_control_task = NULL;
1135 }
1136 ch->state = CADET_CHANNEL_READY;
1137 /* On first connect, send client as many ACKs as we allow messages
1138 to be buffered! */
1139 for (unsigned int i = 0; i < ch->max_pending_messages; i++)
1140 send_ack_to_client (ch, GNUNET_YES);
1141 break;
1142
1143 case CADET_CHANNEL_READY:
1144 /* duplicate ACK, maybe we retried the CREATE. Ignore. */
1145 LOG (GNUNET_ERROR_TYPE_DEBUG,
1146 "Received duplicate channel OPEN_ACK for %s\n",
1147 GCCH_2s (ch));
1148 GNUNET_STATISTICS_update (stats, "# duplicate CREATE_ACKs", 1, GNUNET_NO);
1149 break;
1150 }
1151}
1152
1153
1154/**
1155 * Test if element @a e1 comes before element @a e2.
1156 *
1157 * @param cls closure, to a flag where we indicate duplicate packets
1158 * @param m1 a message of to sort
1159 * @param m2 another message to sort
1160 * @return #GNUNET_YES if @e1 < @e2, otherwise #GNUNET_NO
1161 */
1162static int
1163is_before (void *cls,
1164 struct CadetOutOfOrderMessage *m1,
1165 struct CadetOutOfOrderMessage *m2)
1166{
1167 int *duplicate = cls;
1168 uint32_t v1 = ntohl (m1->mid.mid);
1169 uint32_t v2 = ntohl (m2->mid.mid);
1170 uint32_t delta;
1171
1172 delta = v2 - v1;
1173 if (0 == delta)
1174 *duplicate = GNUNET_YES;
1175 if (delta > (uint32_t) INT_MAX)
1176 {
1177 /* in overflow range, we can safely assume we wrapped around */
1178 return GNUNET_NO;
1179 }
1180 else
1181 {
1182 /* result is small, thus v2 > v1, thus m1 < m2 */
1183 return GNUNET_YES;
1184 }
1185}
1186
1187
1188void
1189GCCH_handle_channel_plaintext_data (
1190 struct CadetChannel *ch,
1191 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti,
1192 const struct GNUNET_CADET_ChannelAppDataMessage *msg)
1193{
1194 struct GNUNET_MQ_Envelope *env;
1195 struct GNUNET_CADET_LocalData *ld;
1196 struct CadetChannelClient *ccc;
1197 size_t payload_size;
1198 struct CadetOutOfOrderMessage *com;
1199 int duplicate;
1200 uint32_t mid_min;
1201 uint32_t mid_max;
1202 uint32_t mid_msg;
1203 uint32_t delta;
1204
1205 GNUNET_assert (GNUNET_NO == ch->is_loopback);
1206 if ((NULL == ch->owner) && (NULL == ch->dest))
1207 {
1208 /* This client is gone, but we still have messages to send to
1209 the other end (which is why @a ch is not yet dead). However,
1210 we cannot pass messages to our client anymore. */
1211 LOG (GNUNET_ERROR_TYPE_DEBUG,
1212 "Dropping incoming payload on %s as this end is already closed\n",
1213 GCCH_2s (ch));
1214 /* send back DESTROY notification to stop further retransmissions! */
1215 if (GNUNET_YES == ch->destroy)
1216 GCT_send_channel_destroy (ch->t, ch->ctn);
1217 return;
1218 }
1219 payload_size = ntohs (msg->header.size) - sizeof(*msg);
1220 env = GNUNET_MQ_msg_extra (ld,
1221 payload_size,
1222 GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA);
1223 ld->ccn = (NULL == ch->dest) ? ch->owner->ccn : ch->dest->ccn;
1224 GNUNET_memcpy (&ld[1], &msg[1], payload_size);
1225 ccc = (NULL != ch->owner) ? ch->owner : ch->dest;
1226 if (GNUNET_YES == ccc->client_ready)
1227 {
1228 /*
1229 * We ad-hoc send the message if
1230 * - The channel is out-of-order
1231 * - The channel is reliable and MID matches next expected MID
1232 * - The channel is unreliable and MID is before lowest seen MID
1233 */if ((GNUNET_YES == ch->out_of_order) ||
1234 ((msg->mid.mid == ch->mid_recv.mid) && (GNUNET_YES == ch->reliable)) ||
1235 ((GNUNET_NO == ch->reliable) &&
1236 (ntohl (msg->mid.mid) >= ntohl (ch->mid_recv.mid)) &&
1237 ((NULL == ccc->head_recv) ||
1238 (ntohl (msg->mid.mid) < ntohl (ccc->head_recv->mid.mid)))))
1239 {
1240 LOG (GNUNET_ERROR_TYPE_DEBUG,
1241 "Giving %u bytes of payload with MID %u from %s to client %s\n",
1242 (unsigned int) payload_size,
1243 ntohl (msg->mid.mid),
1244 GCCH_2s (ch),
1245 GSC_2s (ccc->c));
1246 ccc->client_ready = GNUNET_NO;
1247 GSC_send_to_client (ccc->c, env);
1248 if (GNUNET_NO == ch->out_of_order)
1249 ch->mid_recv.mid = htonl (1 + ntohl (msg->mid.mid));
1250 else
1251 ch->mid_recv.mid = htonl (1 + ntohl (ch->mid_recv.mid));
1252 ch->mid_futures >>= 1;
1253 if ((GNUNET_YES == ch->out_of_order) && (GNUNET_NO == ch->reliable))
1254 {
1255 /* possibly shift by more if we skipped messages */
1256 uint64_t delta = htonl (msg->mid.mid) - 1 - ntohl (ch->mid_recv.mid);
1257
1258 if (delta > 63)
1259 ch->mid_futures = 0;
1260 else
1261 ch->mid_futures >>= delta;
1262 ch->mid_recv.mid = htonl (1 + ntohl (msg->mid.mid));
1263 }
1264 send_channel_data_ack (ch);
1265 return;
1266 }
1267 }
1268
1269 if (GNUNET_YES == ch->reliable)
1270 {
1271 /* check if message ought to be dropped because it is ancient/too distant/duplicate */
1272 mid_min = ntohl (ch->mid_recv.mid);
1273 mid_max = mid_min + ch->max_pending_messages;
1274 mid_msg = ntohl (msg->mid.mid);
1275 if (((uint32_t) (mid_msg - mid_min) > ch->max_pending_messages) ||
1276 ((uint32_t) (mid_max - mid_msg) > ch->max_pending_messages))
1277 {
1278 LOG (GNUNET_ERROR_TYPE_DEBUG,
1279 "%s at %u drops ancient or far-future message %u\n",
1280 GCCH_2s (ch),
1281 (unsigned int) mid_min,
1282 ntohl (msg->mid.mid));
1283
1284 GNUNET_STATISTICS_update (stats,
1285 "# duplicate DATA (ancient or future)",
1286 1,
1287 GNUNET_NO);
1288 GNUNET_MQ_discard (env);
1289 send_channel_data_ack (ch);
1290 return;
1291 }
1292 /* mark bit for future ACKs */
1293 delta = mid_msg - mid_min - 1; /* overflow/underflow are OK here */
1294 if (delta < 64)
1295 {
1296 if (0 != (ch->mid_futures & (1LLU << delta)))
1297 {
1298 /* Duplicate within the queue, drop also */
1299 LOG (GNUNET_ERROR_TYPE_DEBUG,
1300 "Duplicate payload of %u bytes on %s (mid %u) dropped\n",
1301 (unsigned int) payload_size,
1302 GCCH_2s (ch),
1303 ntohl (msg->mid.mid));
1304 GNUNET_STATISTICS_update (stats, "# duplicate DATA", 1, GNUNET_NO);
1305 GNUNET_MQ_discard (env);
1306 send_channel_data_ack (ch);
1307 return;
1308 }
1309 ch->mid_futures |= (1LLU << delta);
1310 LOG (GNUNET_ERROR_TYPE_DEBUG,
1311 "Marked bit %llX for mid %u (base: %u); now: %llX\n",
1312 (1LLU << delta),
1313 mid_msg,
1314 mid_min,
1315 (unsigned long long) ch->mid_futures);
1316 }
1317 }
1318 else /* ! ch->reliable */
1319 {
1320 struct CadetOutOfOrderMessage *next_msg;
1321
1322 /**
1323 * We always send if possible in this case.
1324 * It is guaranteed that the queued MID < received MID
1325 **/
1326 if ((NULL != ccc->head_recv) && (GNUNET_YES == ccc->client_ready))
1327 {
1328 next_msg = ccc->head_recv;
1329 LOG (GNUNET_ERROR_TYPE_DEBUG,
1330 "Giving queued MID %u from %s to client %s\n",
1331 ntohl (next_msg->mid.mid),
1332 GCCH_2s (ch),
1333 GSC_2s (ccc->c));
1334 ccc->client_ready = GNUNET_NO;
1335 GSC_send_to_client (ccc->c, next_msg->env);
1336 ch->mid_recv.mid = htonl (1 + ntohl (next_msg->mid.mid));
1337 ch->mid_futures >>= 1;
1338 send_channel_data_ack (ch);
1339 GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, next_msg);
1340 ccc->num_recv--;
1341 /* Do not process duplicate MID */
1342 if (msg->mid.mid == next_msg->mid.mid) /* Duplicate */
1343 {
1344 /* Duplicate within the queue, drop */
1345 LOG (GNUNET_ERROR_TYPE_DEBUG,
1346 "Message on %s (mid %u) dropped, duplicate\n",
1347 GCCH_2s (ch),
1348 ntohl (msg->mid.mid));
1349 GNUNET_free (next_msg);
1350 GNUNET_MQ_discard (env);
1351 return;
1352 }
1353 GNUNET_free (next_msg);
1354 }
1355
1356 if (ntohl (msg->mid.mid) < ntohl (ch->mid_recv.mid)) /* Old */
1357 {
1358 /* Duplicate within the queue, drop */
1359 LOG (GNUNET_ERROR_TYPE_DEBUG,
1360 "Message on %s (mid %u) dropped, old.\n",
1361 GCCH_2s (ch),
1362 ntohl (msg->mid.mid));
1363 GNUNET_MQ_discard (env);
1364 return;
1365 }
1366
1367 /* Channel is unreliable, so we do not ACK. But we also cannot
1368 allow buffering everything, so check if we have space... */
1369 if (ccc->num_recv >= ch->max_pending_messages)
1370 {
1371 struct CadetOutOfOrderMessage *drop;
1372
1373 /* Yep, need to drop. Drop the oldest message in
1374 the buffer. */
1375 LOG (GNUNET_ERROR_TYPE_DEBUG,
1376 "Queue full due slow client on %s, dropping oldest message\n",
1377 GCCH_2s (ch));
1378 GNUNET_STATISTICS_update (stats,
1379 "# messages dropped due to slow client",
1380 1,
1381 GNUNET_NO);
1382 drop = ccc->head_recv;
1383 GNUNET_assert (NULL != drop);
1384 GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, drop);
1385 ccc->num_recv--;
1386 GNUNET_MQ_discard (drop->env);
1387 GNUNET_free (drop);
1388 }
1389 }
1390
1391 /* Insert message into sorted out-of-order queue */
1392 com = GNUNET_new (struct CadetOutOfOrderMessage);
1393 com->mid = msg->mid;
1394 com->env = env;
1395 duplicate = GNUNET_NO;
1396 GNUNET_CONTAINER_DLL_insert_sorted (struct CadetOutOfOrderMessage,
1397 is_before,
1398 &duplicate,
1399 ccc->head_recv,
1400 ccc->tail_recv,
1401 com);
1402 ccc->num_recv++;
1403 if (GNUNET_YES == duplicate)
1404 {
1405 /* Duplicate within the queue, drop also (this is not covered by
1406 the case above if "delta" >= 64, which could be the case if
1407 max_pending_messages is also >= 64 or if our client is unready
1408 and we are seeing retransmissions of the message our client is
1409 blocked on. */LOG (GNUNET_ERROR_TYPE_DEBUG,
1410 "Duplicate payload of %u bytes on %s (mid %u) dropped\n",
1411 (unsigned int) payload_size,
1412 GCCH_2s (ch),
1413 ntohl (msg->mid.mid));
1414 GNUNET_STATISTICS_update (stats, "# duplicate DATA", 1, GNUNET_NO);
1415 GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, com);
1416 ccc->num_recv--;
1417 GNUNET_MQ_discard (com->env);
1418 GNUNET_free (com);
1419 send_channel_data_ack (ch);
1420 return;
1421 }
1422 LOG (GNUNET_ERROR_TYPE_DEBUG,
1423 "Queued %s payload of %u bytes on %s-%X(%p) (mid %u, need %u first)\n",
1424 (GNUNET_YES == ccc->client_ready) ? "out-of-order" : "client-not-ready",
1425 (unsigned int) payload_size,
1426 GCCH_2s (ch),
1427 ntohl (ccc->ccn.channel_of_client),
1428 ccc,
1429 ntohl (msg->mid.mid),
1430 ntohl (ch->mid_recv.mid));
1431 /* NOTE: this ACK we _could_ skip, as the packet is out-of-order and
1432 the sender may already be transmitting the previous one. Needs
1433 experimental evaluation to see if/when this ACK helps or
1434 hurts. (We might even want another option.) */
1435 send_channel_data_ack (ch);
1436}
1437
1438
1439/**
1440 * Function called once the tunnel has sent one of our messages.
1441 * If the message is unreliable, simply frees the `crm`. If the
1442 * message was reliable, calculate retransmission time and
1443 * wait for ACK (or retransmit).
1444 *
1445 * @param cls the `struct CadetReliableMessage` that was sent
1446 * @param cid identifier of the connection within the tunnel, NULL
1447 * if transmission failed
1448 */
1449static void
1450data_sent_cb (void *cls,
1451 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid);
1452
1453
1454/**
1455 * We need to retry a transmission, the last one took too long to
1456 * be acknowledged.
1457 *
1458 * @param cls the `struct CadetChannel` where we need to retransmit
1459 */
1460static void
1461retry_transmission (void *cls)
1462{
1463 struct CadetChannel *ch = cls;
1464 struct CadetReliableMessage *crm = ch->head_sent;
1465
1466 ch->retry_data_task = NULL;
1467 GNUNET_assert (NULL == crm->qe);
1468 LOG (GNUNET_ERROR_TYPE_DEBUG,
1469 "Retrying transmission on %s of message %u\n",
1470 GCCH_2s (ch),
1471 (unsigned int) ntohl (crm->data_message->mid.mid));
1472 crm->qe = GCT_send (ch->t, &crm->data_message->header, &data_sent_cb, crm,
1473 &crm->data_message->ctn);
1474 GNUNET_assert (NULL == ch->retry_data_task);
1475}
1476
1477
1478/**
1479 * We got an PLAINTEXT_DATA_ACK for a message in our queue, remove it from
1480 * the queue and tell our client that it can send more.
1481 *
1482 * @param ch the channel that got the PLAINTEXT_DATA_ACK
1483 * @param cti identifier of the connection that delivered the message
1484 * @param crm the message that got acknowledged
1485 */
1486static void
1487handle_matching_ack (struct CadetChannel *ch,
1488 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti,
1489 struct CadetReliableMessage *crm)
1490{
1491 GNUNET_CONTAINER_DLL_remove (ch->head_sent, ch->tail_sent, crm);
1492 ch->pending_messages--;
1493 GNUNET_assert (ch->pending_messages < ch->max_pending_messages);
1494 LOG (GNUNET_ERROR_TYPE_DEBUG,
1495 "Received DATA_ACK on %s for message %u (%u ACKs pending)\n",
1496 GCCH_2s (ch),
1497 (unsigned int) ntohl (crm->data_message->mid.mid),
1498 ch->pending_messages);
1499 if (NULL != crm->qe)
1500 {
1501 GCT_send_cancel (crm->qe);
1502 crm->qe = NULL;
1503 }
1504 if ((1 == crm->num_transmissions) && (NULL != cti))
1505 {
1506 GCC_ack_observed (cti);
1507 if (0 == GNUNET_memcmp (cti, &crm->connection_taken))
1508 {
1509 GCC_latency_observed (cti,
1510 GNUNET_TIME_absolute_get_duration (
1511 crm->first_transmission_time));
1512 }
1513 }
1514 GNUNET_free (crm->data_message);
1515 GNUNET_free (crm);
1516 send_ack_to_client (ch, (NULL == ch->owner) ? GNUNET_NO : GNUNET_YES);
1517}
1518
1519
1520/**
1521 * We got an acknowledgement for payload data for a channel.
1522 * Possibly resume transmissions.
1523 *
1524 * @param ch channel that got the ack
1525 * @param cti identifier of the connection that delivered the message
1526 * @param ack details about what was received
1527 */
1528void
1529GCCH_handle_channel_plaintext_data_ack (
1530 struct CadetChannel *ch,
1531 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti,
1532 const struct GNUNET_CADET_ChannelDataAckMessage *ack)
1533{
1534 struct CadetReliableMessage *crm;
1535 struct CadetReliableMessage *crmn;
1536 int found;
1537 uint32_t mid_base;
1538 uint64_t mid_mask;
1539 unsigned int delta;
1540
1541 GNUNET_break (GNUNET_NO == ch->is_loopback);
1542 if (GNUNET_NO == ch->reliable)
1543 {
1544 /* not expecting ACKs on unreliable channel, odd */
1545 GNUNET_break_op (0);
1546 return;
1547 }
1548 /* mid_base is the MID of the next message that the
1549 other peer expects (i.e. that is missing!), everything
1550 LOWER (but excluding mid_base itself) was received. */
1551 mid_base = ntohl (ack->mid.mid);
1552 mid_mask = GNUNET_htonll (ack->futures);
1553 found = GNUNET_NO;
1554 for (crm = ch->head_sent; NULL != crm; crm = crmn)
1555 {
1556 crmn = crm->next;
1557 delta = (unsigned int) (ntohl (crm->data_message->mid.mid) - mid_base);
1558 if (delta >= UINT_MAX - ch->max_pending_messages)
1559 {
1560 /* overflow, means crm was a bit in the past, so this ACK counts for it. */
1561 LOG (GNUNET_ERROR_TYPE_DEBUG,
1562 "Got DATA_ACK with base %u satisfying past message %u on %s\n",
1563 (unsigned int) mid_base,
1564 ntohl (crm->data_message->mid.mid),
1565 GCCH_2s (ch));
1566 handle_matching_ack (ch, cti, crm);
1567 found = GNUNET_YES;
1568 continue;
1569 }
1570 delta--;
1571 if (delta >= 64)
1572 continue;
1573 LOG (GNUNET_ERROR_TYPE_DEBUG,
1574 "Testing bit %llX for mid %u (base: %u)\n",
1575 (1LLU << delta),
1576 ntohl (crm->data_message->mid.mid),
1577 mid_base);
1578 if (0 != (mid_mask & (1LLU << delta)))
1579 {
1580 LOG (GNUNET_ERROR_TYPE_DEBUG,
1581 "Got DATA_ACK with mask for %u on %s\n",
1582 ntohl (crm->data_message->mid.mid),
1583 GCCH_2s (ch));
1584 handle_matching_ack (ch, cti, crm);
1585 found = GNUNET_YES;
1586 }
1587 }
1588 if (GNUNET_NO == found)
1589 {
1590 /* ACK for message we already dropped, might have been a
1591 duplicate ACK? Ignore. */
1592 LOG (GNUNET_ERROR_TYPE_DEBUG,
1593 "Duplicate DATA_ACK on %s, ignoring\n",
1594 GCCH_2s (ch));
1595 GNUNET_STATISTICS_update (stats, "# duplicate DATA_ACKs", 1, GNUNET_NO);
1596 return;
1597 }
1598 if (NULL != ch->retry_data_task)
1599 {
1600 GNUNET_SCHEDULER_cancel (ch->retry_data_task);
1601 ch->retry_data_task = NULL;
1602 }
1603 if ((NULL != ch->head_sent) && (NULL == ch->head_sent->qe))
1604 ch->retry_data_task = GNUNET_SCHEDULER_add_at (ch->head_sent->next_retry,
1605 &retry_transmission,
1606 ch);
1607}
1608
1609
1610void
1611GCCH_handle_remote_destroy (
1612 struct CadetChannel *ch,
1613 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti)
1614{
1615 struct CadetChannelClient *ccc;
1616
1617 GNUNET_assert (GNUNET_NO == ch->is_loopback);
1618 LOG (GNUNET_ERROR_TYPE_DEBUG,
1619 "Received remote channel DESTROY for %s\n",
1620 GCCH_2s (ch));
1621 if (GNUNET_YES == ch->destroy)
1622 {
1623 /* Local client already gone, this is instant-death. */
1624 channel_destroy (ch);
1625 return;
1626 }
1627 ccc = (NULL != ch->owner) ? ch->owner : ch->dest;
1628 if ((NULL != ccc) && (NULL != ccc->head_recv))
1629 {
1630 LOG (GNUNET_ERROR_TYPE_WARNING,
1631 "Lost end of transmission due to remote shutdown on %s\n",
1632 GCCH_2s (ch));
1633 /* FIXME: change API to notify client about truncated transmission! */
1634 }
1635 ch->destroy = GNUNET_YES;
1636 if (NULL != ccc)
1637 GSC_handle_remote_channel_destroy (ccc->c, ccc->ccn, ch);
1638 channel_destroy (ch);
1639}
1640
1641
1642/**
1643 * Test if element @a e1 comes before element @a e2.
1644 *
1645 * @param cls closure, to a flag where we indicate duplicate packets
1646 * @param crm1 an element of to sort
1647 * @param crm2 another element to sort
1648 * @return #GNUNET_YES if @e1 < @e2, otherwise #GNUNET_NO
1649 */
1650static int
1651cmp_crm_by_next_retry (void *cls,
1652 struct CadetReliableMessage *crm1,
1653 struct CadetReliableMessage *crm2)
1654{
1655 if (crm1->next_retry.abs_value_us < crm2->next_retry.abs_value_us)
1656 return GNUNET_YES;
1657 return GNUNET_NO;
1658}
1659
1660
1661/**
1662 * Function called once the tunnel has sent one of our messages.
1663 * If the message is unreliable, simply frees the `crm`. If the
1664 * message was reliable, calculate retransmission time and
1665 * wait for ACK (or retransmit).
1666 *
1667 * @param cls the `struct CadetReliableMessage` that was sent
1668 * @param cid identifier of the connection within the tunnel, NULL
1669 * if transmission failed
1670 */
1671static void
1672data_sent_cb (void *cls,
1673 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
1674{
1675 struct CadetReliableMessage *crm = cls;
1676 struct CadetChannel *ch = crm->ch;
1677
1678 GNUNET_assert (GNUNET_NO == ch->is_loopback);
1679 GNUNET_assert (NULL != crm->qe);
1680 crm->qe = NULL;
1681 GNUNET_CONTAINER_DLL_remove (ch->head_sent, ch->tail_sent, crm);
1682 if (GNUNET_NO == ch->reliable)
1683 {
1684 GNUNET_free (crm->data_message);
1685 GNUNET_free (crm);
1686 ch->pending_messages--;
1687 send_ack_to_client (ch, (NULL == ch->owner) ? GNUNET_NO : GNUNET_YES);
1688 return;
1689 }
1690 if (NULL == cid)
1691 {
1692 /* There was an error sending. */
1693 crm->num_transmissions = GNUNET_SYSERR;
1694 }
1695 else if (GNUNET_SYSERR != crm->num_transmissions)
1696 {
1697 /* Increment transmission counter, and possibly store @a cid
1698 if this was the first transmission. */
1699 crm->num_transmissions++;
1700 if (1 == crm->num_transmissions)
1701 {
1702 crm->first_transmission_time = GNUNET_TIME_absolute_get ();
1703 crm->connection_taken = *cid;
1704 GCC_ack_expected (cid);
1705 }
1706 }
1707 if ((0 == crm->retry_delay.rel_value_us) && (NULL != cid))
1708 {
1709 struct CadetConnection *cc = GCC_lookup (cid);
1710
1711 if (NULL != cc)
1712 crm->retry_delay = GCC_get_metrics (cc)->aged_latency;
1713 else
1714 crm->retry_delay = ch->retry_time;
1715 }
1716 crm->retry_delay = GNUNET_TIME_STD_BACKOFF (crm->retry_delay);
1717 crm->retry_delay = GNUNET_TIME_relative_max (crm->retry_delay, MIN_RTT_DELAY);
1718 crm->next_retry = GNUNET_TIME_relative_to_absolute (crm->retry_delay);
1719
1720 GNUNET_CONTAINER_DLL_insert_sorted (struct CadetReliableMessage,
1721 cmp_crm_by_next_retry,
1722 NULL,
1723 ch->head_sent,
1724 ch->tail_sent,
1725 crm);
1726 LOG (GNUNET_ERROR_TYPE_DEBUG,
1727 "Message %u sent, next transmission on %s in %s\n",
1728 (unsigned int) ntohl (crm->data_message->mid.mid),
1729 GCCH_2s (ch),
1730 GNUNET_STRINGS_relative_time_to_string (
1731 GNUNET_TIME_absolute_get_remaining (
1732 ch->head_sent->next_retry),
1733 GNUNET_YES));
1734 if (NULL == ch->head_sent->qe)
1735 {
1736 if (NULL != ch->retry_data_task)
1737 GNUNET_SCHEDULER_cancel (ch->retry_data_task);
1738 ch->retry_data_task = GNUNET_SCHEDULER_add_at (ch->head_sent->next_retry,
1739 &retry_transmission,
1740 ch);
1741 }
1742}
1743
1744
1745/**
1746 * Handle data given by a client.
1747 *
1748 * Check whether the client is allowed to send in this tunnel, save if
1749 * channel is reliable and send an ACK to the client if there is still
1750 * buffer space in the tunnel.
1751 *
1752 * @param ch Channel.
1753 * @param sender_ccn ccn of the sender
1754 * @param buf payload to transmit.
1755 * @param buf_len number of bytes in @a buf
1756 * @return #GNUNET_OK if everything goes well,
1757 * #GNUNET_SYSERR in case of an error.
1758 */
1759int
1760GCCH_handle_local_data (struct CadetChannel *ch,
1761 struct GNUNET_CADET_ClientChannelNumber sender_ccn,
1762 const char *buf,
1763 size_t buf_len)
1764{
1765 struct CadetReliableMessage *crm;
1766
1767 if (ch->pending_messages >= ch->max_pending_messages)
1768 {
1769 GNUNET_break (0); /* Fails: #5370 */
1770 return GNUNET_SYSERR;
1771 }
1772 if (GNUNET_YES == ch->destroy)
1773 {
1774 /* we are going down, drop messages */
1775 return GNUNET_OK;
1776 }
1777 ch->pending_messages++;
1778
1779 if (GNUNET_YES == ch->is_loopback)
1780 {
1781 struct CadetChannelClient *receiver;
1782 struct GNUNET_MQ_Envelope *env;
1783 struct GNUNET_CADET_LocalData *ld;
1784 int ack_to_owner;
1785
1786 env =
1787 GNUNET_MQ_msg_extra (ld, buf_len, GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA);
1788 if ((NULL != ch->owner) &&
1789 (sender_ccn.channel_of_client == ch->owner->ccn.channel_of_client))
1790 {
1791 receiver = ch->dest;
1792 ack_to_owner = GNUNET_YES;
1793 }
1794 else if ((NULL != ch->dest) &&
1795 (sender_ccn.channel_of_client == ch->dest->ccn.channel_of_client))
1796 {
1797 receiver = ch->owner;
1798 ack_to_owner = GNUNET_NO;
1799 }
1800 else
1801 {
1802 GNUNET_free (env);
1803 GNUNET_break (0);
1804 return GNUNET_SYSERR;
1805 }
1806 GNUNET_assert (NULL != receiver);
1807 ld->ccn = receiver->ccn;
1808 GNUNET_memcpy (&ld[1], buf, buf_len);
1809 if (GNUNET_YES == receiver->client_ready)
1810 {
1811 ch->pending_messages--;
1812 GSC_send_to_client (receiver->c, env);
1813 send_ack_to_client (ch, ack_to_owner);
1814 }
1815 else
1816 {
1817 struct CadetOutOfOrderMessage *oom;
1818
1819 oom = GNUNET_new (struct CadetOutOfOrderMessage);
1820 oom->env = env;
1821 GNUNET_CONTAINER_DLL_insert_tail (receiver->head_recv,
1822 receiver->tail_recv,
1823 oom);
1824 receiver->num_recv++;
1825 }
1826 return GNUNET_OK;
1827 }
1828
1829 /* Everything is correct, send the message. */
1830 crm = GNUNET_malloc (sizeof(*crm));
1831 crm->ch = ch;
1832 crm->data_message = GNUNET_malloc (
1833 sizeof(struct GNUNET_CADET_ChannelAppDataMessage) + buf_len);
1834 crm->data_message->header.size =
1835 htons (sizeof(struct GNUNET_CADET_ChannelAppDataMessage) + buf_len);
1836 crm->data_message->header.type =
1837 htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA);
1838 ch->mid_send.mid = htonl (ntohl (ch->mid_send.mid) + 1);
1839 crm->data_message->mid = ch->mid_send;
1840 crm->data_message->ctn = ch->ctn;
1841 GNUNET_memcpy (&crm->data_message[1], buf, buf_len);
1842 GNUNET_CONTAINER_DLL_insert_tail (ch->head_sent, ch->tail_sent, crm);
1843 LOG (GNUNET_ERROR_TYPE_DEBUG,
1844 "Sending message %u from local client to %s with %lu bytes\n",
1845 ntohl (crm->data_message->mid.mid),
1846 GCCH_2s (ch),
1847 (unsigned long) buf_len);
1848 if (NULL != ch->retry_data_task)
1849 {
1850 GNUNET_SCHEDULER_cancel (ch->retry_data_task);
1851 ch->retry_data_task = NULL;
1852 }
1853 crm->qe = GCT_send (ch->t, &crm->data_message->header, &data_sent_cb, crm,
1854 &crm->data_message->ctn);
1855 GNUNET_assert (NULL == ch->retry_data_task);
1856 return GNUNET_OK;
1857}
1858
1859
1860void
1861GCCH_handle_local_ack (struct CadetChannel *ch,
1862 struct GNUNET_CADET_ClientChannelNumber client_ccn)
1863{
1864 struct CadetChannelClient *ccc;
1865 struct CadetOutOfOrderMessage *com;
1866
1867 if ((NULL != ch->owner) &&
1868 (ch->owner->ccn.channel_of_client == client_ccn.channel_of_client))
1869 ccc = ch->owner;
1870 else if ((NULL != ch->dest) &&
1871 (ch->dest->ccn.channel_of_client == client_ccn.channel_of_client))
1872 ccc = ch->dest;
1873 else
1874 GNUNET_assert (0);
1875 ccc->client_ready = GNUNET_YES;
1876 com = ccc->head_recv;
1877 if (NULL == com)
1878 {
1879 LOG (GNUNET_ERROR_TYPE_DEBUG,
1880 "Got LOCAL_ACK, %s-%X ready to receive more data, but none pending on %s-%X(%p)!\n",
1881 GSC_2s (ccc->c),
1882 ntohl (client_ccn.channel_of_client),
1883 GCCH_2s (ch),
1884 ntohl (ccc->ccn.channel_of_client),
1885 ccc);
1886 return; /* none pending */
1887 }
1888 if (GNUNET_YES == ch->is_loopback)
1889 {
1890 int to_owner;
1891
1892 /* Messages are always in-order, just send */
1893 GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, com);
1894 ccc->num_recv--;
1895 GSC_send_to_client (ccc->c, com->env);
1896 /* Notify sender that we can receive more */
1897 if ((NULL != ch->owner) &&
1898 (ccc->ccn.channel_of_client == ch->owner->ccn.channel_of_client))
1899 {
1900 to_owner = GNUNET_NO;
1901 }
1902 else
1903 {
1904 GNUNET_assert ((NULL != ch->dest) && (ccc->ccn.channel_of_client ==
1905 ch->dest->ccn.channel_of_client));
1906 to_owner = GNUNET_YES;
1907 }
1908 send_ack_to_client (ch, to_owner);
1909 GNUNET_free (com);
1910 return;
1911 }
1912
1913 if ((com->mid.mid != ch->mid_recv.mid) && (GNUNET_NO == ch->out_of_order) &&
1914 (GNUNET_YES == ch->reliable))
1915 {
1916 LOG (GNUNET_ERROR_TYPE_DEBUG,
1917 "Got LOCAL_ACK, %s-%X ready to receive more data (but next one is out-of-order %u vs. %u)!\n",
1918 GSC_2s (ccc->c),
1919 ntohl (ccc->ccn.channel_of_client),
1920 ntohl (com->mid.mid),
1921 ntohl (ch->mid_recv.mid));
1922 return; /* missing next one in-order */
1923 }
1924
1925 LOG (GNUNET_ERROR_TYPE_DEBUG,
1926 "Got LOCAL_ACK, giving payload message %u to %s-%X on %s\n",
1927 ntohl (com->mid.mid),
1928 GSC_2s (ccc->c),
1929 ntohl (ccc->ccn.channel_of_client),
1930 GCCH_2s (ch));
1931
1932 /* all good, pass next message to client */
1933 GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, com);
1934 ccc->num_recv--;
1935 /* FIXME: if unreliable, this is not aggressive
1936 enough, as it would be OK to have lost some! */
1937
1938 ch->mid_recv.mid = htonl (1 + ntohl (com->mid.mid));
1939 ch->mid_futures >>= 1; /* equivalent to division by 2 */
1940 ccc->client_ready = GNUNET_NO;
1941 GSC_send_to_client (ccc->c, com->env);
1942 GNUNET_free (com);
1943 send_channel_data_ack (ch);
1944 if (NULL != ccc->head_recv)
1945 return;
1946 if (GNUNET_NO == ch->destroy)
1947 return;
1948 GCT_send_channel_destroy (ch->t, ch->ctn);
1949 channel_destroy (ch);
1950}
1951
1952
1953#define LOG2(level, ...) \
1954 GNUNET_log_from_nocheck (level, "cadet-chn", __VA_ARGS__)
1955
1956
1957/**
1958 * Log channel info.
1959 *
1960 * @param ch Channel.
1961 * @param level Debug level to use.
1962 */
1963void
1964GCCH_debug (struct CadetChannel *ch, enum GNUNET_ErrorType level)
1965{
1966#if ! defined(GNUNET_CULL_LOGGING)
1967 int do_log;
1968
1969 do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
1970 "cadet-chn",
1971 __FILE__,
1972 __FUNCTION__,
1973 __LINE__);
1974 if (0 == do_log)
1975 return;
1976
1977 if (NULL == ch)
1978 {
1979 LOG2 (level, "CHN *** DEBUG NULL CHANNEL ***\n");
1980 return;
1981 }
1982 LOG2 (level, "CHN %s:%X (%p)\n", GCT_2s (ch->t), ch->ctn.cn, ch);
1983 if (NULL != ch->owner)
1984 {
1985 LOG2 (level,
1986 "CHN origin %s ready %s local-id: %u\n",
1987 GSC_2s (ch->owner->c),
1988 ch->owner->client_ready ? "YES" : "NO",
1989 ntohl (ch->owner->ccn.channel_of_client));
1990 }
1991 if (NULL != ch->dest)
1992 {
1993 LOG2 (level,
1994 "CHN destination %s ready %s local-id: %u\n",
1995 GSC_2s (ch->dest->c),
1996 ch->dest->client_ready ? "YES" : "NO",
1997 ntohl (ch->dest->ccn.channel_of_client));
1998 }
1999 LOG2 (level,
2000 "CHN Message IDs recv: %d (%llX), send: %d\n",
2001 ntohl (ch->mid_recv.mid),
2002 (unsigned long long) ch->mid_futures,
2003 ntohl (ch->mid_send.mid));
2004#endif
2005}
2006
2007
2008/* end of gnunet-service-cadet_channel.c */
diff --git a/src/cadet/gnunet-service-cadet_channel.h b/src/cadet/gnunet-service-cadet_channel.h
deleted file mode 100644
index b09de883f..000000000
--- a/src/cadet/gnunet-service-cadet_channel.h
+++ /dev/null
@@ -1,306 +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 * Assign type of message to drop.
71 * @param ch CadetChannel to assign type to drop.
72 * @param message GNUNET_CADET_RequestDropCadetMessage to get the type from.
73 */
74void
75GCCH_assign_type_to_drop (struct CadetChannel *ch, const struct
76 GNUNET_CADET_RequestDropCadetMessage *message);
77
78/**
79 * Get the static string for identification of the channel.
80 *
81 * @param ch Channel.
82 *
83 * @return Static string with the channel IDs.
84 */
85const char *
86GCCH_2s (const struct CadetChannel *ch);
87
88
89/**
90 * Log channel info.
91 *
92 * @param ch Channel.
93 * @param level Debug level to use.
94 */
95void
96GCCH_debug (struct CadetChannel *ch,
97 enum GNUNET_ErrorType level);
98
99
100/**
101 * Get the channel's public ID.
102 *
103 * @param ch Channel.
104 *
105 * @return ID used to identify the channel with the remote peer.
106 */
107struct GNUNET_CADET_ChannelTunnelNumber
108GCCH_get_id (const struct CadetChannel *ch);
109
110
111/**
112 * Create a new channel.
113 *
114 * @param owner local client owning the channel
115 * @param owner_id local chid of this channel at the @a owner
116 * @param destination peer to which we should build the channel
117 * @param port desired port at @a destination
118 * @param options options for the channel
119 * @return handle to the new channel
120 */
121struct CadetChannel *
122GCCH_channel_local_new (struct CadetClient *owner,
123 struct GNUNET_CADET_ClientChannelNumber owner_id,
124 struct CadetPeer *destination,
125 const struct GNUNET_HashCode *port,
126 uint32_t options);
127
128
129/**
130 * A client is bound to the port that we have a channel
131 * open to. Send the acknowledgement for the connection
132 * request and establish the link with the client.
133 *
134 * @param ch open incoming channel
135 * @param c client listening on the respective @a port
136 * @param port port number @a c is listening on
137 */
138void
139GCCH_bind (struct CadetChannel *ch,
140 struct CadetClient *c,
141 const struct GNUNET_HashCode *port);
142
143
144/**
145 * Destroy locally created channel. Called by the
146 * local client, so no need to tell the client.
147 *
148 * @param ch channel to destroy
149 * @param c client that caused the destruction
150 * @param ccn client number of the client @a c
151 */
152void
153GCCH_channel_local_destroy (struct CadetChannel *ch,
154 struct CadetClient *c,
155 struct GNUNET_CADET_ClientChannelNumber ccn);
156
157
158/**
159 * Function called once and only once after a channel was bound
160 * to its tunnel via #GCT_add_channel() is ready for transmission.
161 * Note that this is only the case for channels that this peer
162 * initiates, as for incoming channels we assume that they are
163 * ready for transmission immediately upon receiving the open
164 * message. Used to bootstrap the #GCT_send() process.
165 *
166 * @param ch the channel for which the tunnel is now ready
167 */
168void
169GCCH_tunnel_up (struct CadetChannel *ch);
170
171
172/**
173 * Create a new channel based on a request coming in over the network.
174 *
175 * @param t tunnel to the remote peer
176 * @param chid identifier of this channel in the tunnel
177 * @param h_port hash of desired local port
178 * @param options options for the channel
179 * @return handle to the new channel
180 */
181struct CadetChannel *
182GCCH_channel_incoming_new (struct CadetTunnel *t,
183 struct GNUNET_CADET_ChannelTunnelNumber chid,
184 const struct GNUNET_HashCode *h_port,
185 uint32_t options);
186
187
188/**
189 * We got a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN message again for
190 * this channel. If the binding was successful, (re)transmit the
191 * #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK.
192 *
193 * @param ch channel that got the duplicate open
194 * @param cti identifier of the connection that delivered the message
195 */
196void
197GCCH_handle_duplicate_open (struct CadetChannel *ch,
198 const struct
199 GNUNET_CADET_ConnectionTunnelIdentifier *cti);
200
201
202/**
203 * We got payload data for a channel. Pass it on to the client
204 * and send an ACK to the other end (once flow control allows it!)
205 *
206 * @param ch channel that got data
207 * @param cti identifier of the connection that delivered the message
208 * @param msg message that was received
209 */
210void
211GCCH_handle_channel_plaintext_data (struct CadetChannel *ch,
212 const struct
213 GNUNET_CADET_ConnectionTunnelIdentifier *cti,
214 const struct
215 GNUNET_CADET_ChannelAppDataMessage *msg);
216
217
218/**
219 * We got an acknowledgement for payload data for a channel.
220 * Possibly resume transmissions.
221 *
222 * @param ch channel that got the ack
223 * @param cti identifier of the connection that delivered the message
224 * @param ack details about what was received
225 */
226void
227GCCH_handle_channel_plaintext_data_ack (struct CadetChannel *ch,
228 const struct
229 GNUNET_CADET_ConnectionTunnelIdentifier
230 *cti,
231 const struct
232 GNUNET_CADET_ChannelDataAckMessage *ack);
233
234
235/**
236 * We got an acknowledgement for the creation of the channel
237 * (the port is open on the other side). Verify that the
238 * other end really has the right port, and begin transmissions.
239 *
240 * @param ch channel to destroy
241 * @param cti identifier of the connection that delivered the message,
242 * NULL if the ACK was inferred because we got payload or are on loopback
243 * @param port port number (needed to verify receiver knows the port)
244 */
245void
246GCCH_handle_channel_open_ack (struct CadetChannel *ch,
247 const struct
248 GNUNET_CADET_ConnectionTunnelIdentifier *cti,
249 const struct GNUNET_HashCode *port);
250
251
252/**
253 * Destroy channel, based on the other peer closing the
254 * connection. Also needs to remove this channel from
255 * the tunnel.
256 *
257 * FIXME: need to make it possible to defer destruction until we have
258 * received all messages up to the destroy, and right now the destroy
259 * message (and this API) fails to give is the information we need!
260 *
261 * FIXME: also need to know if the other peer got a destroy from
262 * us before!
263 *
264 * @param ch channel to destroy
265 * @param cti identifier of the connection that delivered the message,
266 * NULL if we are simulating receiving a destroy due to shutdown
267 */
268void
269GCCH_handle_remote_destroy (struct CadetChannel *ch,
270 const struct
271 GNUNET_CADET_ConnectionTunnelIdentifier *cti);
272
273
274/**
275 * Handle data given by a client.
276 *
277 * Check whether the client is allowed to send in this tunnel, save if
278 * channel is reliable and send an ACK to the client if there is still
279 * buffer space in the tunnel.
280 *
281 * @param ch Channel.
282 * @param sender_ccn ccn of the sender
283 * @param buf payload to transmit.
284 * @param buf_len number of bytes in @a buf
285 * @return #GNUNET_OK if everything goes well,
286 * #GNUNET_SYSERR in case of an error.
287 */
288int
289GCCH_handle_local_data (struct CadetChannel *ch,
290 struct GNUNET_CADET_ClientChannelNumber sender_ccn,
291 const char *buf,
292 size_t buf_len);
293
294
295/**
296 * Handle ACK from client on local channel. Means the client is ready
297 * for more data, see if we have any for it.
298 *
299 * @param ch channel to destroy
300 * @param client_ccn ccn of the client sending the ack
301 */
302void
303GCCH_handle_local_ack (struct CadetChannel *ch,
304 struct GNUNET_CADET_ClientChannelNumber client_ccn);
305
306#endif
diff --git a/src/cadet/gnunet-service-cadet_connection.c b/src/cadet/gnunet-service-cadet_connection.c
deleted file mode 100644
index 66b67aa64..000000000
--- a/src/cadet/gnunet-service-cadet_connection.c
+++ /dev/null
@@ -1,1079 +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
452void
453GCC_latency_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
454 struct GNUNET_TIME_Relative latency)
455{
456 struct CadetConnection *cc;
457 double weight;
458 double result;
459
460 cc = GCC_lookup (cid);
461 if (NULL == cc)
462 return; /* whopise, connection already down? */
463 GNUNET_STATISTICS_update (stats, "# latencies observed", 1, GNUNET_NO);
464 cc->latency_datapoints++;
465 if (cc->latency_datapoints >= 7)
466 weight = 7.0;
467 else
468 weight = cc->latency_datapoints;
469 /* Compute weighted average, giving at MOST weight 7 to the
470 existing values, or less if that value is based on fewer than 7
471 measurements. */
472 result = (weight * cc->metrics.aged_latency.rel_value_us)
473 + 1.0 * latency.rel_value_us;
474 result /= (weight + 1.0);
475 cc->metrics.aged_latency.rel_value_us = (uint64_t) result;
476}
477
478
479void
480GCC_handle_connection_create_ack (struct CadetConnection *cc)
481{
482 LOG (GNUNET_ERROR_TYPE_DEBUG,
483 "Received CADET_CONNECTION_CREATE_ACK for %s in state %d (%s)\n",
484 GCC_2s (cc),
485 cc->state,
486 (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy");
487 if (CADET_CONNECTION_READY == cc->state)
488 return; /* Duplicate ACK, ignore */
489 if (NULL != cc->task)
490 {
491 GNUNET_SCHEDULER_cancel (cc->task);
492 cc->task = NULL;
493 }
494 cc->metrics.age = GNUNET_TIME_absolute_get ();
495 update_state (cc, CADET_CONNECTION_READY, cc->mqm_ready);
496 if ((NULL == cc->keepalive_qe) && (GNUNET_YES == cc->mqm_ready) &&
497 (NULL == cc->task))
498 cc->task =
499 GNUNET_SCHEDULER_add_delayed (keepalive_period, &send_keepalive, cc);
500}
501
502
503/**
504 * Handle KX message.
505 *
506 * @param cc connection that received encrypted message
507 * @param msg the key exchange message
508 */
509void
510GCC_handle_kx (struct CadetConnection *cc,
511 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
512{
513 LOG (GNUNET_ERROR_TYPE_DEBUG,
514 "Received KX message with ephermal %s on CC %s in state %d\n",
515 GNUNET_e2s (&msg->ephemeral_key),
516 GNUNET_sh2s (&cc->cid.connection_of_tunnel),
517 cc->state);
518 if (CADET_CONNECTION_SENT == cc->state)
519 {
520 /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine,
521 clearly something is working, so pretend we got an ACK. */
522 LOG (GNUNET_ERROR_TYPE_DEBUG,
523 "Faking connection CADET_CONNECTION_CREATE_ACK for %s due to KX\n",
524 GCC_2s (cc));
525 GCC_handle_connection_create_ack (cc);
526 }
527 GCT_handle_kx (cc->ct, msg);
528}
529
530
531/**
532 * Handle KX_AUTH message.
533 *
534 * @param cc connection that received encrypted message
535 * @param msg the key exchange message
536 */
537void
538GCC_handle_kx_auth (struct CadetConnection *cc,
539 const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg)
540{
541 LOG (GNUNET_ERROR_TYPE_DEBUG,
542 "Received KX AUTH message with ephermal %s on CC %s in state %d\n",
543 GNUNET_e2s (&msg->kx.ephemeral_key),
544 GNUNET_sh2s (&cc->cid.connection_of_tunnel),
545 cc->state);
546 if (CADET_CONNECTION_SENT == cc->state)
547 {
548 /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine,
549 clearly something is working, so pretend we got an ACK. */
550 LOG (GNUNET_ERROR_TYPE_DEBUG,
551 "Faking connection CADET_CONNECTION_CREATE_ACK for %s due to KX\n",
552 GCC_2s (cc));
553 GCC_handle_connection_create_ack (cc);
554 }
555 GCT_handle_kx_auth (cc->ct, msg);
556}
557
558
559/**
560 * Handle encrypted message.
561 *
562 * @param cc connection that received encrypted message
563 * @param msg the encrypted message to decrypt
564 */
565void
566GCC_handle_encrypted (struct CadetConnection *cc,
567 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
568{
569 if (CADET_CONNECTION_SENT == cc->state)
570 {
571 /* We didn't get the CREATE_ACK, but instead got payload. That's fine,
572 clearly something is working, so pretend we got an ACK. */
573 LOG (GNUNET_ERROR_TYPE_DEBUG,
574 "Faking connection ACK for %s due to ENCRYPTED payload\n",
575 GCC_2s (cc));
576 GCC_handle_connection_create_ack (cc);
577 }
578 cc->metrics.last_use = GNUNET_TIME_absolute_get ();
579 GCT_handle_encrypted (cc->ct, msg);
580}
581
582
583/**
584 * Set the signature for a monotime value on a GNUNET_CADET_ConnectionCreateMessage.
585 *
586 * @param msg The GNUNET_CADET_ConnectionCreateMessage.
587 */
588void
589set_monotime_sig (struct GNUNET_CADET_ConnectionCreateMessage *msg)
590{
591
592 struct CadetConnectionCreatePS cp = { .purpose.purpose = htonl (
593 GNUNET_SIGNATURE_PURPOSE_CADET_CONNECTION_INITIATOR),
594 .purpose.size = htonl (sizeof(cp)),
595 .monotonic_time = msg->monotime};
596
597 GNUNET_CRYPTO_eddsa_sign (my_private_key, &cp,
598 &msg->monotime_sig);
599
600}
601
602
603/**
604 * Send a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE message to the
605 * first hop.
606 *
607 * @param cls the `struct CadetConnection` to initiate
608 */
609static void
610send_create (void *cls)
611{
612 struct CadetConnection *cc = cls;
613 struct GNUNET_CADET_ConnectionCreateMessage *create_msg;
614 struct GNUNET_PeerIdentity *pids;
615 struct GNUNET_MQ_Envelope *env;
616 struct CadetTunnel *t;
617
618 cc->task = NULL;
619 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
620 env =
621 GNUNET_MQ_msg_extra (create_msg,
622 (2 + cc->off) * sizeof(struct GNUNET_PeerIdentity),
623 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE);
624 // TODO This will be removed in a major release, because this will be a protocol breaking change. We set the deprecated 'reliable' bit here that was removed.
625 create_msg->options = 2;
626 create_msg->cid = cc->cid;
627
628 // check for tunnel state and set signed monotime (xrs,t3ss)
629 t = GCP_get_tunnel (cc->destination, GNUNET_YES);
630 if ((NULL != t) && (GCT_get_estate (t) == CADET_TUNNEL_KEY_UNINITIALIZED) &&
631 (GCT_alice_or_betty (GCP_get_id (cc->destination)) == GNUNET_NO))
632 {
633 create_msg->has_monotime = GNUNET_YES;
634 create_msg->monotime = GNUNET_TIME_absolute_hton (
635 GNUNET_TIME_absolute_get_monotonic (cfg));
636 set_monotime_sig (create_msg);
637 }
638
639 pids = (struct GNUNET_PeerIdentity *) &create_msg[1];
640 pids[0] = my_full_id;
641 for (unsigned int i = 0; i <= cc->off; i++)
642 pids[i + 1] = *GCP_get_id (GCPP_get_peer_at_offset (cc->path, i));
643 LOG (GNUNET_ERROR_TYPE_DEBUG,
644 "Sending CADET_CONNECTION_CREATE message for %s with %u hops\n",
645 GCC_2s (cc),
646 cc->off + 2);
647 cc->env = env;
648 cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay);
649 cc->create_at = GNUNET_TIME_relative_to_absolute (cc->retry_delay);
650 update_state (cc, CADET_CONNECTION_SENT, GNUNET_NO);
651 GCP_send (cc->mq_man, env);
652}
653
654
655/**
656 * Send a CREATE_ACK message towards the origin.
657 *
658 * @param cls the `struct CadetConnection` to initiate
659 */
660static void
661send_create_ack (void *cls)
662{
663 struct CadetConnection *cc = cls;
664 struct GNUNET_CADET_ConnectionCreateAckMessage *ack_msg;
665 struct GNUNET_MQ_Envelope *env;
666
667 cc->task = NULL;
668 LOG (GNUNET_ERROR_TYPE_DEBUG,
669 "Sending CONNECTION_CREATE_ACK message for %s\n",
670 GCC_2s (cc));
671 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
672 env =
673 GNUNET_MQ_msg (ack_msg, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK);
674 ack_msg->cid = cc->cid;
675 cc->env = env;
676 cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay);
677 cc->create_ack_at = GNUNET_TIME_relative_to_absolute (cc->retry_delay);
678 if (CADET_CONNECTION_CREATE_RECEIVED == cc->state)
679 update_state (cc, CADET_CONNECTION_READY, GNUNET_NO);
680 if (CADET_CONNECTION_READY == cc->state)
681 cc->task =
682 GNUNET_SCHEDULER_add_delayed (keepalive_period, &send_keepalive, cc);
683 GCP_send (cc->mq_man, env);
684}
685
686
687/**
688 * We got a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE for a
689 * connection that we already have. Either our ACK got lost
690 * or something is fishy. Consider retransmitting the ACK.
691 *
692 * @param cc connection that got the duplicate CREATE
693 */
694void
695GCC_handle_duplicate_create (struct CadetConnection *cc)
696{
697 if (GNUNET_YES == cc->mqm_ready)
698 {
699 LOG (GNUNET_ERROR_TYPE_DEBUG,
700 "Got duplicate CREATE for %s, scheduling another ACK (%s)\n",
701 GCC_2s (cc),
702 (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy");
703 /* Revert back to the state of having only received the 'CREATE',
704 and immediately proceed to send the CREATE_ACK. */
705 update_state (cc, CADET_CONNECTION_CREATE_RECEIVED, cc->mqm_ready);
706 if (NULL != cc->task)
707 GNUNET_SCHEDULER_cancel (cc->task);
708 cc->task =
709 GNUNET_SCHEDULER_add_at (cc->create_ack_at, &send_create_ack, cc);
710 }
711 else
712 {
713 /* We are currently sending something else back, which
714 can only be an ACK or payload, either of which would
715 do. So actually no need to do anything. */
716 LOG (GNUNET_ERROR_TYPE_DEBUG,
717 "Got duplicate CREATE for %s. MQ is busy, not queueing another ACK\n",
718 GCC_2s (cc));
719 }
720}
721
722
723/**
724 * There has been a change in the message queue existence for our
725 * peer at the first hop. Adjust accordingly.
726 *
727 * @param cls the `struct CadetConnection`
728 * @param available #GNUNET_YES if sending is now possible,
729 * #GNUNET_NO if sending is no longer possible
730 * #GNUNET_SYSERR if sending is no longer possible
731 * and the last envelope was discarded
732 */
733static void
734manage_first_hop_mq (void *cls, int available)
735{
736 struct CadetConnection *cc = cls;
737
738 if (GNUNET_YES != available)
739 {
740 /* Connection is down, for now... */
741 LOG (GNUNET_ERROR_TYPE_DEBUG, "Core MQ for %s went down\n", GCC_2s (cc));
742 update_state (cc, CADET_CONNECTION_NEW, GNUNET_NO);
743 cc->retry_delay = INITIAL_CONNECTION_CREATE_RETRY_DELAY;
744 if (NULL != cc->task)
745 {
746 GNUNET_SCHEDULER_cancel (cc->task);
747 cc->task = NULL;
748 }
749 return;
750 }
751
752 update_state (cc, cc->state, GNUNET_YES);
753 LOG (GNUNET_ERROR_TYPE_DEBUG,
754 "Core MQ for %s became available in state %d\n",
755 GCC_2s (cc),
756 cc->state);
757 switch (cc->state)
758 {
759 case CADET_CONNECTION_NEW:
760 /* Transmit immediately */
761 cc->task = GNUNET_SCHEDULER_add_at (cc->create_at, &send_create, cc);
762 break;
763
764 case CADET_CONNECTION_SENDING_CREATE:
765 /* Should not be possible to be called in this state. */
766 GNUNET_assert (0);
767 break;
768
769 case CADET_CONNECTION_SENT:
770 /* Retry a bit later... */
771 cc->task = GNUNET_SCHEDULER_add_at (cc->create_at, &send_create, cc);
772 break;
773
774 case CADET_CONNECTION_CREATE_RECEIVED:
775 /* We got the 'CREATE' (incoming connection), should send the CREATE_ACK */
776 cc->metrics.age = GNUNET_TIME_absolute_get ();
777 cc->task =
778 GNUNET_SCHEDULER_add_at (cc->create_ack_at, &send_create_ack, cc);
779 break;
780
781 case CADET_CONNECTION_READY:
782 if ((NULL == cc->keepalive_qe) && (GNUNET_YES == cc->mqm_ready) &&
783 (NULL == cc->task))
784 {
785 LOG (GNUNET_ERROR_TYPE_DEBUG,
786 "Scheduling keepalive for %s in %s\n",
787 GCC_2s (cc),
788 GNUNET_STRINGS_relative_time_to_string (keepalive_period,
789 GNUNET_YES));
790 cc->task =
791 GNUNET_SCHEDULER_add_delayed (keepalive_period, &send_keepalive, cc);
792 }
793 break;
794 }
795}
796
797
798/**
799 * Create a connection to @a destination via @a path and notify @a cb
800 * whenever we are ready for more data. Shared logic independent of
801 * who is initiating the connection.
802 *
803 * @param destination where to go
804 * @param path which path to take (may not be the full path)
805 * @param off offset of @a destination on @a path
806 * @param ct which tunnel uses this connection
807 * @param init_state initial state for the connection
808 * @param ready_cb function to call when ready to transmit
809 * @param ready_cb_cls closure for @a cb
810 * @return handle to the connection
811 */
812static struct CadetConnection *
813connection_create (struct CadetPeer *destination,
814 struct CadetPeerPath *path,
815 unsigned int off,
816 struct CadetTConnection *ct,
817 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
818 enum CadetConnectionState init_state,
819 GCC_ReadyCallback ready_cb,
820 void *ready_cb_cls)
821{
822 struct CadetConnection *cc;
823 struct CadetPeer *first_hop;
824
825 cc = GNUNET_new (struct CadetConnection);
826 cc->state = init_state;
827 cc->ct = ct;
828 cc->destination = destination; /* xrs,t3ss,lurchi*/
829 cc->cid = *cid;
830 cc->retry_delay =
831 GNUNET_TIME_relative_multiply (INITIAL_CONNECTION_CREATE_RETRY_DELAY, off);
832 GNUNET_assert (GNUNET_OK ==
833 GNUNET_CONTAINER_multishortmap_put (
834 connections,
835 &GCC_get_id (cc)->connection_of_tunnel,
836 cc,
837 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
838 cc->ready_cb = ready_cb;
839 cc->ready_cb_cls = ready_cb_cls;
840 cc->path = path;
841 cc->off = off;
842 LOG (GNUNET_ERROR_TYPE_DEBUG,
843 "Creating %s using path %s (offset: %u)\n",
844 GCC_2s (cc),
845 GCPP_2s (path),
846 off);
847 GCPP_add_connection (path, off, cc);
848 for (unsigned int i = 0; i < off; i++)
849 GCP_add_connection (GCPP_get_peer_at_offset (path, i), cc);
850 first_hop = GCPP_get_peer_at_offset (path, 0);
851 cc->mq_man = GCP_request_mq (first_hop, &manage_first_hop_mq, cc);
852 return cc;
853}
854
855
856/**
857 * Create a connection to @a destination via @a path and
858 * notify @a cb whenever we are ready for more data. This
859 * is an inbound tunnel, so we must use the existing @a cid
860 *
861 * @param destination where to go
862 * @param path which path to take (may not be the full path)
863 * @param ct which tunnel uses this connection
864 * @param ready_cb function to call when ready to transmit
865 * @param ready_cb_cls closure for @a cb
866 * @return handle to the connection, NULL if we already have
867 * a connection that takes precedence on @a path
868 */
869struct CadetConnection *
870GCC_create_inbound (struct CadetPeer *destination,
871 struct CadetPeerPath *path,
872 struct CadetTConnection *ct,
873 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
874 GCC_ReadyCallback ready_cb,
875 void *ready_cb_cls)
876{
877 struct CadetConnection *cc;
878 unsigned int off;
879
880 off = GCPP_find_peer (path, destination);
881 GNUNET_assert (UINT_MAX != off);
882 cc = GCPP_get_connection (path, destination, off);
883 if (NULL != cc)
884 {
885 int cmp;
886
887 cmp = GNUNET_memcmp (cid, &cc->cid);
888 if (0 == cmp)
889 {
890 /* Two peers picked the SAME random connection identifier at the
891 same time for the same path? Must be malicious. Drop
892 connection (existing and inbound), even if it is the only
893 one. */
894 GNUNET_break_op (0);
895 GCT_connection_lost (cc->ct);
896 GCC_destroy_without_tunnel (cc);
897 return NULL;
898 }
899 if (0 < cmp)
900 {
901 /* drop existing */
902 LOG (GNUNET_ERROR_TYPE_DEBUG,
903 "Got two connections on %s, dropping my existing %s\n",
904 GCPP_2s (path),
905 GCC_2s (cc));
906 GCT_connection_lost (cc->ct);
907 GCC_destroy_without_tunnel (cc);
908 }
909 else
910 {
911 /* keep existing */
912 LOG (GNUNET_ERROR_TYPE_DEBUG,
913 "Got two connections on %s, keeping my existing %s\n",
914 GCPP_2s (path),
915 GCC_2s (cc));
916 return NULL;
917 }
918 }
919
920 return connection_create (destination,
921 path,
922 off,
923 ct,
924 cid,
925 CADET_CONNECTION_CREATE_RECEIVED,
926 ready_cb,
927 ready_cb_cls);
928}
929
930
931struct CadetConnection *
932GCC_create (struct CadetPeer *destination,
933 struct CadetPeerPath *path,
934 unsigned int off,
935 struct CadetTConnection *ct,
936 GCC_ReadyCallback ready_cb,
937 void *ready_cb_cls)
938{
939 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
940
941 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, &cid, sizeof(cid));
942 return connection_create (destination,
943 path,
944 off,
945 ct,
946 &cid,
947 CADET_CONNECTION_NEW,
948 ready_cb,
949 ready_cb_cls);
950}
951
952
953/**
954 * Transmit message @a msg via connection @a cc. Must only be called
955 * (once) after the connection has signalled that it is ready via the
956 * `ready_cb`. Clients can also use #GCC_is_ready() to check if the
957 * connection is right now ready for transmission.
958 *
959 * @param cc connection identification
960 * @param env envelope with message to transmit; must NOT
961 * yet have a #GNUNET_MQ_notify_sent() callback attached to it
962 */
963void
964GCC_transmit (struct CadetConnection *cc, struct GNUNET_MQ_Envelope *env)
965{
966 LOG (GNUNET_ERROR_TYPE_DEBUG,
967 "Scheduling message for transmission on %s\n",
968 GCC_2s (cc));
969 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
970 GNUNET_assert (CADET_CONNECTION_READY == cc->state);
971 cc->metrics.last_use = GNUNET_TIME_absolute_get ();
972 cc->mqm_ready = GNUNET_NO;
973 if (NULL != cc->task)
974 {
975 GNUNET_SCHEDULER_cancel (cc->task);
976 cc->task = NULL;
977 }
978 GCP_send (cc->mq_man, env);
979}
980
981
982/**
983 * Obtain the path used by this connection.
984 *
985 * @param cc connection
986 * @param off[out] set to the length of the path we use
987 * @return path to @a cc
988 */
989struct CadetPeerPath *
990GCC_get_path (struct CadetConnection *cc, unsigned int *off)
991{
992 *off = cc->off;
993 return cc->path;
994}
995
996
997/**
998 * Obtain unique ID for the connection.
999 *
1000 * @param cc connection.
1001 * @return unique number of the connection
1002 */
1003const struct GNUNET_CADET_ConnectionTunnelIdentifier *
1004GCC_get_id (struct CadetConnection *cc)
1005{
1006 return &cc->cid;
1007}
1008
1009
1010/**
1011 * Get a (static) string for a connection.
1012 *
1013 * @param cc Connection.
1014 */
1015const char *
1016GCC_2s (const struct CadetConnection *cc)
1017{
1018 static char buf[128];
1019
1020 if (NULL == cc)
1021 return "Connection(NULL)";
1022
1023 if (NULL != cc->ct)
1024 {
1025 GNUNET_snprintf (buf,
1026 sizeof(buf),
1027 "Connection %s (%s)",
1028 GNUNET_sh2s (&cc->cid.connection_of_tunnel),
1029 GCT_2s (cc->ct->t));
1030 return buf;
1031 }
1032 GNUNET_snprintf (buf,
1033 sizeof(buf),
1034 "Connection %s",
1035 GNUNET_sh2s (&cc->cid.connection_of_tunnel));
1036 return buf;
1037}
1038
1039
1040#define LOG2(level, ...) \
1041 GNUNET_log_from_nocheck (level, "cadet-con", __VA_ARGS__)
1042
1043
1044/**
1045 * Log connection info.
1046 *
1047 * @param cc connection
1048 * @param level Debug level to use.
1049 */
1050void
1051GCC_debug (struct CadetConnection *cc, enum GNUNET_ErrorType level)
1052{
1053#if ! defined(GNUNET_CULL_LOGGING)
1054 int do_log;
1055
1056 do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
1057 "cadet-con",
1058 __FILE__,
1059 __FUNCTION__,
1060 __LINE__);
1061 if (0 == do_log)
1062 return;
1063 if (NULL == cc)
1064 {
1065 LOG2 (level, "Connection (NULL)\n");
1066 return;
1067 }
1068 LOG2 (level,
1069 "%s to %s via path %s in state %d is %s\n",
1070 GCC_2s (cc),
1071 GCP_2s (cc->destination),
1072 GCPP_2s (cc->path),
1073 cc->state,
1074 (GNUNET_YES == cc->mqm_ready) ? "ready" : "busy");
1075#endif
1076}
1077
1078
1079/* end of gnunet-service-cadet_connection.c */
diff --git a/src/cadet/gnunet-service-cadet_connection.h b/src/cadet/gnunet-service-cadet_connection.h
deleted file mode 100644
index 53c0c1541..000000000
--- a/src/cadet/gnunet-service-cadet_connection.h
+++ /dev/null
@@ -1,363 +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 #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK was received for
146 * this connection, implying that the end-to-end connection is up.
147 * Process it.
148 *
149 * @param cc the connection that got the ACK.
150 */
151void
152GCC_handle_connection_create_ack (struct CadetConnection *cc);
153
154
155/**
156 * We got a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE for a
157 * connection that we already have. Either our ACK got lost
158 * or something is fishy. Consider retransmitting the ACK.
159 *
160 * @param cc connection that got the duplicate CREATE
161 */
162void
163GCC_handle_duplicate_create (struct CadetConnection *cc);
164
165
166/**
167 * Handle KX message.
168 *
169 * @param cc connection that received encrypted message
170 * @param msg the key exchange message
171 */
172void
173GCC_handle_kx (struct CadetConnection *cc,
174 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg);
175
176
177/**
178 * Handle KX_AUTH message.
179 *
180 * @param cc connection that received encrypted message
181 * @param msg the key exchange message
182 */
183void
184GCC_handle_kx_auth (struct CadetConnection *cc,
185 const struct
186 GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg);
187
188/**
189 * Purpose for the signature of a monotime.
190 */
191struct CadetConnectionCreatePS
192{
193
194 /**
195 * Purpose is #GNUNET_SIGNATURE_PURPOSE_CADET_CONNECTION_INITIATOR
196 */
197 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
198
199 /**
200 * Time at the initiator when generating the signature.
201 *
202 * Note that the receiver MUST IGNORE the absolute time, and only interpret
203 * the value as a mononic time and reject "older" values than the last one
204 * observed. This is necessary as we do not want to require synchronized
205 * clocks and may not have a bidirectional communication channel.
206 *
207 * Even with this, there is no real guarantee against replay achieved here,
208 * unless the latest timestamp is persisted. Persistence should be
209 * provided via PEERSTORE if possible.
210 */
211 struct GNUNET_TIME_AbsoluteNBO monotonic_time;
212
213};
214
215/**
216 * Performance metrics for a connection.
217 */
218struct CadetConnectionMetrics
219{
220 /**
221 * Our current best estimate of the latency, based on a weighted
222 * average of at least @a latency_datapoints values.
223 */
224 struct GNUNET_TIME_Relative aged_latency;
225
226 /**
227 * When was this connection first established? (by us sending or
228 * receiving the CREATE_ACK for the first time)
229 */
230 struct GNUNET_TIME_Absolute age;
231
232 /**
233 * When was this connection last used? (by us sending or
234 * receiving a PAYLOAD message on it)
235 */
236 struct GNUNET_TIME_Absolute last_use;
237
238 /**
239 * How many packets that ought to generate an ACK did we send via
240 * this connection?
241 */
242 unsigned long long num_acked_transmissions;
243
244 /**
245 * Number of packets that were sent via this connection did actually
246 * receive an ACK? (Note: ACKs may be transmitted and lost via
247 * other connections, so this value should only be interpreted
248 * relative to @e num_acked_transmissions and in relation to other
249 * connections.)
250 */
251 unsigned long long num_successes;
252};
253
254
255/**
256 * Obtain performance @a metrics from @a cc.
257 *
258 * @param cc connection to query
259 * @return the metrics
260 */
261const struct CadetConnectionMetrics *
262GCC_get_metrics (struct CadetConnection *cc);
263
264
265/**
266 * Handle encrypted message.
267 *
268 * @param cc connection that received encrypted message
269 * @param msg the encrypted message to decrypt
270 */
271void
272GCC_handle_encrypted (struct CadetConnection *cc,
273 const struct GNUNET_CADET_TunnelEncryptedMessage *msg);
274
275
276/**
277 * We sent a message for which we expect to receive an ACK via
278 * the connection identified by @a cti.
279 *
280 * @param cid connection identifier where we expect an ACK
281 */
282void
283GCC_ack_expected (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid);
284
285
286/**
287 * We observed an ACK for a message that was originally sent via
288 * the connection identified by @a cti.
289 *
290 * @param cid connection identifier where we got an ACK for a message
291 * that was originally sent via this connection (the ACK
292 * may have gotten back to us via a different connection).
293 */
294void
295GCC_ack_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid);
296
297
298/**
299 * We observed some the given @a latency on the connection
300 * identified by @a cti. (The same connection was taken
301 * in both directions.)
302 *
303 * @param cti connection identifier where we measured latency
304 * @param latency the observed latency
305 */
306void
307GCC_latency_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti,
308 struct GNUNET_TIME_Relative latency);
309
310
311/**
312 * Return the tunnel associated with this connection.
313 *
314 * @param cc connection to query
315 * @return corresponding entry in the tunnel's connection list
316 */
317struct CadetTConnection *
318GCC_get_ct (struct CadetConnection *cc);
319
320
321/**
322 * Obtain the path used by this connection.
323 *
324 * @param cc connection
325 * @param off[out] set to offset in this path where the connection @a cc ends
326 * @return path to @a cc
327 */
328struct CadetPeerPath *
329GCC_get_path (struct CadetConnection *cc,
330 unsigned int *off);
331
332
333/**
334 * Obtain unique ID for the connection.
335 *
336 * @param cc connection.
337 * @return unique number of the connection
338 */
339const struct GNUNET_CADET_ConnectionTunnelIdentifier *
340GCC_get_id (struct CadetConnection *cc);
341
342
343/**
344 * Get a (static) string for a connection.
345 *
346 * @param cc Connection.
347 */
348const char *
349GCC_2s (const struct CadetConnection *cc);
350
351
352/**
353 * Log connection info.
354 *
355 * @param cc connection
356 * @param level Debug level to use.
357 */
358void
359GCC_debug (struct CadetConnection *cc,
360 enum GNUNET_ErrorType level);
361
362
363#endif
diff --git a/src/cadet/gnunet-service-cadet_core.c b/src/cadet/gnunet-service-cadet_core.c
deleted file mode 100644
index bff7632da..000000000
--- a/src/cadet/gnunet-service-cadet_core.c
+++ /dev/null
@@ -1,1337 +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
142struct CadetRoute
143{
144 /**
145 * Information about the next hop on this route.
146 */
147 struct RouteDirection next;
148
149 /**
150 * Information about the previous hop on this route.
151 */
152 struct RouteDirection prev;
153
154 /**
155 * Unique identifier for the connection that uses this route.
156 */
157 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
158
159 /**
160 * When was this route last in use?
161 */
162 struct GNUNET_TIME_Absolute last_use;
163
164 /**
165 * Position of this route in the #route_heap.
166 */
167 struct GNUNET_CONTAINER_HeapNode *hn;
168};
169
170
171/**
172 * Handle to the CORE service.
173 */
174static struct GNUNET_CORE_Handle *core;
175
176/**
177 * Routes on which this peer is an intermediate.
178 */
179static struct GNUNET_CONTAINER_MultiShortmap *routes;
180
181/**
182 * Heap of routes, MIN-sorted by last activity.
183 */
184static struct GNUNET_CONTAINER_Heap *route_heap;
185
186/**
187 * Rung zero (always pointed to by #rung_head).
188 */
189static struct Rung rung_zero;
190
191/**
192 * DLL of rungs, with the head always point to a rung of
193 * route directions with no messages in the queue.
194 */
195static struct Rung *rung_head = &rung_zero;
196
197/**
198 * Tail of the #rung_head DLL.
199 */
200static struct Rung *rung_tail = &rung_zero;
201
202/**
203 * Maximum number of concurrent routes this peer will support.
204 */
205static unsigned long long max_routes;
206
207/**
208 * Maximum number of envelopes we will buffer at this peer.
209 */
210static unsigned long long max_buffers;
211
212/**
213 * Current number of envelopes we have buffered at this peer.
214 */
215static unsigned long long cur_buffers;
216
217/**
218 * Task to timeout routes.
219 */
220static struct GNUNET_SCHEDULER_Task *timeout_task;
221
222/**
223 * Get the route corresponding to a hash.
224 *
225 * @param cid hash generated from the connection identifier
226 */
227static struct CadetRoute *
228get_route (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
229{
230 return GNUNET_CONTAINER_multishortmap_get (routes,
231 &cid->connection_of_tunnel);
232}
233
234
235/**
236 * Lower the rung in which @a dir is by 1.
237 *
238 * @param dir direction to lower in rung.
239 */
240static void
241lower_rung (struct RouteDirection *dir)
242{
243 struct Rung *rung = dir->rung;
244 struct Rung *prev;
245
246 GNUNET_CONTAINER_DLL_remove (rung->rd_head, rung->rd_tail, dir);
247 prev = rung->prev;
248 GNUNET_assert (NULL != prev);
249 if (prev->rung_off != rung->rung_off - 1)
250 {
251 prev = GNUNET_new (struct Rung);
252 prev->rung_off = rung->rung_off - 1;
253 GNUNET_CONTAINER_DLL_insert_after (rung_head, rung_tail, rung->prev, prev);
254 }
255 GNUNET_assert (NULL != prev);
256 GNUNET_CONTAINER_DLL_insert (prev->rd_head, prev->rd_tail, dir);
257 dir->rung = prev;
258}
259
260
261/**
262 * Discard the buffer @a env from the route direction @a dir and
263 * move @a dir down a rung.
264 *
265 * @param dir direction that contains the @a env in the buffer
266 * @param env envelope to discard
267 */
268static void
269discard_buffer (struct RouteDirection *dir, struct GNUNET_MQ_Envelope *env)
270{
271 GNUNET_MQ_dll_remove (&dir->env_head, &dir->env_tail, env);
272 cur_buffers--;
273 GNUNET_MQ_discard (env);
274 lower_rung (dir);
275 GNUNET_STATISTICS_set (stats, "# buffer use", cur_buffers, GNUNET_NO);
276}
277
278
279/**
280 * Discard all messages from the highest rung, to make space.
281 */
282static void
283discard_all_from_rung_tail ()
284{
285 struct Rung *tail = rung_tail;
286 struct RouteDirection *dir;
287
288 while (NULL != (dir = tail->rd_head))
289 {
290 LOG (GNUNET_ERROR_TYPE_DEBUG,
291 "Queue full due new message on connection %s, dropping old message\n",
292 GNUNET_sh2s (&dir->my_route->cid.connection_of_tunnel));
293 GNUNET_STATISTICS_update (stats,
294 "# messages dropped due to full buffer",
295 1,
296 GNUNET_NO);
297 discard_buffer (dir, dir->env_head);
298 }
299 GNUNET_CONTAINER_DLL_remove (rung_head, rung_tail, tail);
300 GNUNET_free (tail);
301}
302
303
304/**
305 * We message @a msg from @a prev. Find its route by @a cid and
306 * forward to the next hop. Drop and signal broken route if we do not
307 * have a route.
308 *
309 * @param prev previous hop (sender)
310 * @param cid connection identifier, tells us which route to use
311 * @param msg the message to forward
312 */
313static void
314route_message (struct CadetPeer *prev,
315 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
316 const struct GNUNET_MessageHeader *msg,
317 const enum GNUNET_MQ_PriorityPreferences priority)
318{
319 struct CadetRoute *route;
320 struct RouteDirection *dir;
321 struct Rung *rung;
322 struct Rung *nxt;
323 struct GNUNET_MQ_Envelope *env;
324
325 route = get_route (cid);
326 if (NULL == route)
327 {
328 struct GNUNET_MQ_Envelope *env;
329 struct GNUNET_CADET_ConnectionBrokenMessage *bm;
330
331 LOG (GNUNET_ERROR_TYPE_DEBUG,
332 "Failed to route message of type %u from %s on connection %s: no route\n",
333 ntohs (msg->type),
334 GCP_2s (prev),
335 GNUNET_sh2s (&cid->connection_of_tunnel));
336 switch (ntohs (msg->type))
337 {
338 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY:
339 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN:
340 /* No need to respond to these! */
341 return;
342 }
343 env = GNUNET_MQ_msg (bm, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
344 bm->cid = *cid;
345 bm->peer1 = my_full_id;
346 GCP_send_ooo (prev, env);
347 return;
348 }
349 route->last_use = GNUNET_TIME_absolute_get ();
350 GNUNET_CONTAINER_heap_update_cost (route->hn, route->last_use.abs_value_us);
351 dir = (prev == route->prev.hop) ? &route->next : &route->prev;
352 if (GNUNET_YES == dir->is_ready)
353 {
354 LOG (GNUNET_ERROR_TYPE_DEBUG,
355 "Routing message of type %u from %s to %s on connection %s\n",
356 ntohs (msg->type),
357 GCP_2s (prev),
358 GNUNET_i2s (GCP_get_id (dir->hop)),
359 GNUNET_sh2s (&cid->connection_of_tunnel));
360 dir->is_ready = GNUNET_NO;
361 GCP_send (dir->mqm, GNUNET_MQ_msg_copy (msg));
362 return;
363 }
364 /* Check if low latency is required and if the previous message was
365 unreliable; if so, make sure we only queue one message per
366 direction (no buffering). */
367 if ((0 != (priority & GNUNET_MQ_PREF_LOW_LATENCY)) &&
368 (NULL != dir->env_head) &&
369 (0 ==
370 (GNUNET_MQ_env_get_options (dir->env_head) & GNUNET_MQ_PREF_UNRELIABLE)))
371 discard_buffer (dir, dir->env_head);
372 /* Check for duplicates */
373 for (const struct GNUNET_MQ_Envelope *env = dir->env_head; NULL != env;
374 env = GNUNET_MQ_env_next (env))
375 {
376 const struct GNUNET_MessageHeader *hdr = GNUNET_MQ_env_get_msg (env);
377
378 if ((hdr->size == msg->size) && (0 == memcmp (hdr, msg, ntohs (msg->size))))
379 {
380 LOG (GNUNET_ERROR_TYPE_DEBUG,
381 "Received duplicate of message already in buffer, dropping\n");
382 GNUNET_STATISTICS_update (stats,
383 "# messages dropped due to duplicate in buffer",
384 1,
385 GNUNET_NO);
386 return;
387 }
388 }
389
390 rung = dir->rung;
391 if (cur_buffers == max_buffers)
392 {
393 /* Need to make room. */
394 if (NULL != rung->next)
395 {
396 /* Easy case, drop messages from route directions in highest rung */
397 discard_all_from_rung_tail ();
398 }
399 else
400 {
401 /* We are in the highest rung, drop our own! */
402 LOG (GNUNET_ERROR_TYPE_DEBUG,
403 "Queue full due new message on connection %s, dropping old message\n",
404 GNUNET_sh2s (&dir->my_route->cid.connection_of_tunnel));
405 GNUNET_STATISTICS_update (stats,
406 "# messages dropped due to full buffer",
407 1,
408 GNUNET_NO);
409 discard_buffer (dir, dir->env_head);
410 rung = dir->rung;
411 }
412 }
413 /* remove 'dir' from current rung */
414 GNUNET_CONTAINER_DLL_remove (rung->rd_head, rung->rd_tail, dir);
415 /* make 'nxt' point to the next higher rung, create if necessary */
416 nxt = rung->next;
417 if ((NULL == nxt) || (rung->rung_off + 1 != nxt->rung_off))
418 {
419 nxt = GNUNET_new (struct Rung);
420 nxt->rung_off = rung->rung_off + 1;
421 GNUNET_CONTAINER_DLL_insert_after (rung_head, rung_tail, rung, nxt);
422 }
423 /* insert 'dir' into next higher rung */
424 GNUNET_CONTAINER_DLL_insert (nxt->rd_head, nxt->rd_tail, dir);
425 dir->rung = nxt;
426
427 /* add message into 'dir' buffer */
428 LOG (GNUNET_ERROR_TYPE_DEBUG,
429 "Queueing new message of type %u from %s to %s on connection %s\n",
430 ntohs (msg->type),
431 GCP_2s (prev),
432 GNUNET_i2s (GCP_get_id (dir->hop)),
433 GNUNET_sh2s (&cid->connection_of_tunnel));
434 env = GNUNET_MQ_msg_copy (msg);
435 GNUNET_MQ_env_set_options (env, priority);
436 if ((0 != (priority & GNUNET_MQ_PREF_LOW_LATENCY)) &&
437 (0 != (priority & GNUNET_MQ_PREF_OUT_OF_ORDER)) &&
438 (NULL != dir->env_head) &&
439 (0 == (GNUNET_MQ_env_get_options (dir->env_head)
440 & GNUNET_MQ_PREF_LOW_LATENCY)))
441 GNUNET_MQ_dll_insert_head (&dir->env_head, &dir->env_tail, env);
442 else
443 GNUNET_MQ_dll_insert_tail (&dir->env_head, &dir->env_tail, env);
444 cur_buffers++;
445 GNUNET_STATISTICS_set (stats, "# buffer use", cur_buffers, GNUNET_NO);
446 /* Clean up 'rung' if now empty (and not head) */
447 if ((NULL == rung->rd_head) && (rung != rung_head))
448 {
449 GNUNET_CONTAINER_DLL_remove (rung_head, rung_tail, rung);
450 GNUNET_free (rung);
451 }
452}
453
454
455/**
456 * Check if the create_connection message has the appropriate size.
457 *
458 * @param cls Closure (unused).
459 * @param msg Message to check.
460 *
461 * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
462 */
463static int
464check_connection_create (void *cls,
465 const struct GNUNET_CADET_ConnectionCreateMessage *msg)
466{
467 uint16_t size = ntohs (msg->header.size) - sizeof(*msg);
468
469 if (0 != (size % sizeof(struct GNUNET_PeerIdentity)))
470 {
471 GNUNET_break_op (0);
472 return GNUNET_NO;
473 }
474 return GNUNET_YES;
475}
476
477
478/**
479 * Free internal data of a route direction.
480 *
481 * @param dir direction to destroy (do NOT free memory of 'dir' itself)
482 */
483static void
484destroy_direction (struct RouteDirection *dir)
485{
486 struct GNUNET_MQ_Envelope *env;
487
488 while (NULL != (env = dir->env_head))
489 {
490 GNUNET_STATISTICS_update (stats,
491 "# messages dropped due to route destruction",
492 1,
493 GNUNET_NO);
494 discard_buffer (dir, env);
495 }
496 if (NULL != dir->mqm)
497 {
498 GCP_request_mq_cancel (dir->mqm, NULL);
499 dir->mqm = NULL;
500 }
501 GNUNET_CONTAINER_DLL_remove (rung_head->rd_head, rung_head->rd_tail, dir);
502}
503
504
505/**
506 * Destroy our state for @a route.
507 *
508 * @param route route to destroy
509 */
510static void
511destroy_route (struct CadetRoute *route)
512{
513 LOG (GNUNET_ERROR_TYPE_DEBUG,
514 "Destroying route from %s to %s of connection %s\n",
515 GNUNET_i2s (GCP_get_id (route->prev.hop)),
516 GNUNET_i2s2 (GCP_get_id (route->next.hop)),
517 GNUNET_sh2s (&route->cid.connection_of_tunnel));
518 GNUNET_assert (route == GNUNET_CONTAINER_heap_remove_node (route->hn));
519 GNUNET_assert (
520 GNUNET_YES ==
521 GNUNET_CONTAINER_multishortmap_remove (routes,
522 &route->cid.connection_of_tunnel,
523 route));
524 GNUNET_STATISTICS_set (stats,
525 "# routes",
526 GNUNET_CONTAINER_multishortmap_size (routes),
527 GNUNET_NO);
528 destroy_direction (&route->prev);
529 destroy_direction (&route->next);
530 GNUNET_free (route);
531}
532
533
534/**
535 * Send message that a route is broken between @a peer1 and @a peer2.
536 *
537 * @param target where to send the message
538 * @param cid connection identifier to use
539 * @param peer1 one of the peers where a link is broken
540 * @param peer2 another one of the peers where a link is broken
541 */
542static void
543send_broken (struct RouteDirection *target,
544 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
545 const struct GNUNET_PeerIdentity *peer1,
546 const struct GNUNET_PeerIdentity *peer2)
547{
548 struct GNUNET_MQ_Envelope *env;
549 struct GNUNET_CADET_ConnectionBrokenMessage *bm;
550
551 if (NULL == target->mqm)
552 return; /* Can't send notification, connection is down! */
553 LOG (GNUNET_ERROR_TYPE_DEBUG,
554 "Notifying %s about BROKEN route at %s-%s of connection %s\n",
555 GCP_2s (target->hop),
556 GNUNET_i2s (peer1),
557 GNUNET_i2s2 (peer2),
558 GNUNET_sh2s (&cid->connection_of_tunnel));
559
560 env = GNUNET_MQ_msg (bm, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
561 bm->cid = *cid;
562 if (NULL != peer1)
563 bm->peer1 = *peer1;
564 if (NULL != peer2)
565 bm->peer2 = *peer2;
566 GCP_request_mq_cancel (target->mqm, env);
567 target->mqm = NULL;
568}
569
570
571/**
572 * Function called to check if any routes have timed out, and if
573 * so, to clean them up. Finally, schedules itself again at the
574 * earliest time where there might be more work.
575 *
576 * @param cls NULL
577 */
578static void
579timeout_cb (void *cls)
580{
581 struct CadetRoute *r;
582 struct GNUNET_TIME_Relative linger;
583 struct GNUNET_TIME_Absolute exp;
584
585 timeout_task = NULL;
586 linger = GNUNET_TIME_relative_multiply (keepalive_period, 3);
587 while (NULL != (r = GNUNET_CONTAINER_heap_peek (route_heap)))
588 {
589 exp = GNUNET_TIME_absolute_add (r->last_use, linger);
590 if (0 != GNUNET_TIME_absolute_get_remaining (exp).rel_value_us)
591 {
592 /* Route not yet timed out, wait until it does. */
593 timeout_task = GNUNET_SCHEDULER_add_at (exp, &timeout_cb, NULL);
594 return;
595 }
596 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
597 "Sending BROKEN due to timeout (%s was last use, %s linger)\n",
598 GNUNET_STRINGS_absolute_time_to_string (r->last_use),
599 GNUNET_STRINGS_relative_time_to_string (linger, GNUNET_YES));
600 send_broken (&r->prev, &r->cid, NULL, NULL);
601 send_broken (&r->next, &r->cid, NULL, NULL);
602 destroy_route (r);
603 }
604 /* No more routes left, so no need for a #timeout_task */
605}
606
607
608/**
609 * Function called when the message queue to the previous hop
610 * becomes available/unavailable. We expect this function to
611 * be called immediately when we register, and then again
612 * later if the connection ever goes down.
613 *
614 * @param cls the `struct RouteDirection`
615 * @param available #GNUNET_YES if sending is now possible,
616 * #GNUNET_NO if sending is no longer possible
617 * #GNUNET_SYSERR if sending is no longer possible
618 * and the last envelope was discarded
619 */
620static void
621dir_ready_cb (void *cls, int ready)
622{
623 struct RouteDirection *dir = cls;
624 struct CadetRoute *route = dir->my_route;
625 struct RouteDirection *odir;
626
627 if (GNUNET_YES == ready)
628 {
629 struct GNUNET_MQ_Envelope *env;
630
631 dir->is_ready = GNUNET_YES;
632 if (NULL != (env = dir->env_head))
633 {
634 GNUNET_MQ_dll_remove (&dir->env_head, &dir->env_tail, env);
635 cur_buffers--;
636 GNUNET_STATISTICS_set (stats, "# buffer use", cur_buffers, GNUNET_NO);
637 lower_rung (dir);
638 dir->is_ready = GNUNET_NO;
639 GCP_send (dir->mqm, env);
640 }
641 return;
642 }
643 odir = (dir == &route->next) ? &route->prev : &route->next;
644 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending BROKEN due to MQ going down\n");
645 send_broken (&route->next, &route->cid, GCP_get_id (odir->hop), &my_full_id);
646 destroy_route (route);
647}
648
649
650/**
651 * Initialize one of the directions of a route.
652 *
653 * @param route route the direction belongs to
654 * @param dir direction to initialize
655 * @param hop next hop on in the @a dir
656 */
657static void
658dir_init (struct RouteDirection *dir,
659 struct CadetRoute *route,
660 struct CadetPeer *hop)
661{
662 dir->hop = hop;
663 dir->my_route = route;
664 dir->mqm = GCP_request_mq (hop, &dir_ready_cb, dir);
665 GNUNET_CONTAINER_DLL_insert (rung_head->rd_head, rung_head->rd_tail, dir);
666 dir->rung = rung_head;
667 GNUNET_assert (GNUNET_YES == dir->is_ready);
668}
669
670
671/**
672 * We could not create the desired route. Send a
673 * #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN
674 * message to @a target.
675 *
676 * @param target who should receive the message
677 * @param cid identifier of the connection/route that failed
678 * @param failure_at neighbour with which we failed to route,
679 * or NULL.
680 */
681static void
682send_broken_without_mqm (
683 struct CadetPeer *target,
684 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
685 const struct GNUNET_PeerIdentity *failure_at)
686{
687 struct GNUNET_MQ_Envelope *env;
688 struct GNUNET_CADET_ConnectionBrokenMessage *bm;
689
690 env = GNUNET_MQ_msg (bm, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
691 bm->cid = *cid;
692 bm->peer1 = my_full_id;
693 if (NULL != failure_at)
694 bm->peer2 = *failure_at;
695 GCP_send_ooo (target, env);
696}
697
698
699/**
700 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE
701 *
702 * @param cls Closure (CadetPeer for neighbor that sent the message).
703 * @param msg Message itself.
704 */
705static void
706handle_connection_create (
707 void *cls,
708 const struct GNUNET_CADET_ConnectionCreateMessage *msg)
709{
710 struct CadetPeer *sender = cls;
711 struct CadetPeer *next;
712 const struct GNUNET_PeerIdentity *pids =
713 (const struct GNUNET_PeerIdentity *) &msg[1];
714 struct CadetRoute *route;
715 uint16_t size = ntohs (msg->header.size) - sizeof(*msg);
716 unsigned int path_length;
717 unsigned int off;
718 struct CadetTunnel *t;
719
720 path_length = size / sizeof(struct GNUNET_PeerIdentity);
721 if (0 == path_length)
722 {
723 LOG (GNUNET_ERROR_TYPE_DEBUG,
724 "Dropping CADET_CONNECTION_CREATE with empty path\n");
725 GNUNET_break_op (0);
726 return;
727 }
728 LOG (GNUNET_ERROR_TYPE_DEBUG,
729 "Handling CADET_CONNECTION_CREATE from %s for CID %s with %u hops\n",
730 GCP_2s (sender),
731 GNUNET_sh2s (&msg->cid.connection_of_tunnel),
732 path_length);
733 /* Check for loops */
734 {
735 struct GNUNET_CONTAINER_MultiPeerMap *map;
736
737 map = GNUNET_CONTAINER_multipeermap_create (path_length * 2, GNUNET_YES);
738 GNUNET_assert (NULL != map);
739 for (unsigned int i = 0; i < path_length; i++)
740 {
741 LOG (GNUNET_ERROR_TYPE_DEBUG,
742 "CADET_CONNECTION_CREATE has peer %s at offset %u\n",
743 GNUNET_i2s (&pids[i]),
744 i);
745 if (GNUNET_SYSERR == GNUNET_CONTAINER_multipeermap_put (
746 map,
747 &pids[i],
748 NULL,
749 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
750 {
751 /* bogus request */
752 GNUNET_CONTAINER_multipeermap_destroy (map);
753 LOG (GNUNET_ERROR_TYPE_DEBUG,
754 "Dropping CADET_CONNECTION_CREATE with cyclic path\n");
755 GNUNET_break_op (0);
756 return;
757 }
758 }
759 GNUNET_CONTAINER_multipeermap_destroy (map);
760 }
761 /* Initiator is at offset 0, find us */
762 for (off = 1; off < path_length; off++)
763 if (0 == GNUNET_memcmp (&my_full_id, &pids[off]))
764 break;
765 if (off == path_length)
766 {
767 LOG (GNUNET_ERROR_TYPE_DEBUG,
768 "Dropping CADET_CONNECTION_CREATE without us in the path\n");
769 GNUNET_break_op (0);
770 return;
771 }
772 /* Check previous hop */
773 if (sender != GCP_get (&pids[off - 1], GNUNET_NO))
774 {
775 LOG (GNUNET_ERROR_TYPE_DEBUG,
776 "Dropping CADET_CONNECTION_CREATE without sender at previous hop in the path\n");
777 GNUNET_break_op (0);
778 return;
779 }
780 if (NULL != (route = get_route (&msg->cid)))
781 {
782 /* Duplicate CREATE, pass it on, previous one might have been lost! */
783
784 LOG (GNUNET_ERROR_TYPE_DEBUG,
785 "Passing on duplicate CADET_CONNECTION_CREATE message on connection %s\n",
786 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
787 route_message (sender,
788 &msg->cid,
789 &msg->header,
790 GNUNET_MQ_PRIO_CRITICAL_CONTROL
791 | GNUNET_MQ_PREF_LOW_LATENCY);
792 return;
793 }
794 if (off == path_length - 1)
795 {
796 /* We are the destination, create connection */
797 struct CadetConnection *cc;
798 struct CadetPeerPath *path;
799 struct CadetPeer *origin;
800
801 cc = GCC_lookup (&msg->cid);
802 if (NULL != cc)
803 {
804 LOG (GNUNET_ERROR_TYPE_DEBUG,
805 "Received duplicate CADET_CONNECTION_CREATE message on connection %s\n",
806 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
807 GCC_handle_duplicate_create (cc);
808 return;
809 }
810
811 origin = GCP_get (&pids[0], GNUNET_YES);
812 LOG (GNUNET_ERROR_TYPE_DEBUG,
813 "I am destination for CADET_CONNECTION_CREATE message from %s for connection %s, building inverse path\n",
814 GCP_2s (origin),
815 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
816 path = GCPP_get_path_from_route (path_length - 1, pids);
817 t = GCP_get_tunnel (origin, GNUNET_YES);
818
819 // Check for CADET state in case the other side has lost the tunnel (xrs,t3ss)
820 if ((GNUNET_YES == msg->has_monotime) &&
821 (GNUNET_YES == GCP_check_and_update_monotime (origin, msg->monotime)) &&
822 (GNUNET_OK == GCP_check_monotime_sig (origin, msg)) &&
823 (CADET_TUNNEL_KEY_OK == GCT_get_estate (t)))
824 {
825 GCT_change_estate (t, CADET_TUNNEL_KEY_UNINITIALIZED);
826 }
827
828 if (GNUNET_OK !=
829 GCT_add_inbound_connection (t,
830 &msg->cid,
831 path))
832 {
833 /* Send back BROKEN: duplicate connection on the same path,
834 we will use the other one. */
835 LOG (GNUNET_ERROR_TYPE_DEBUG,
836 "Received CADET_CONNECTION_CREATE from %s for %s, but %s already has a connection. Sending BROKEN\n",
837 GCP_2s (sender),
838 GNUNET_sh2s (&msg->cid.connection_of_tunnel),
839 GCPP_2s (path));
840 send_broken_without_mqm (sender, &msg->cid, NULL);
841 return;
842 }
843 return;
844 }
845 /* We are merely a hop on the way, check if we can support the route */
846 next = GCP_get (&pids[off + 1], GNUNET_NO);
847 if ((NULL == next) || (GNUNET_NO == GCP_has_core_connection (next)))
848 {
849 /* unworkable, send back BROKEN notification */
850 LOG (GNUNET_ERROR_TYPE_DEBUG,
851 "Received CADET_CONNECTION_CREATE from %s for %s. Next hop %s:%u is down. Sending BROKEN\n",
852 GCP_2s (sender),
853 GNUNET_sh2s (&msg->cid.connection_of_tunnel),
854 GNUNET_i2s (&pids[off + 1]),
855 off + 1);
856 send_broken_without_mqm (sender, &msg->cid, &pids[off + 1]);
857 return;
858 }
859 if (max_routes <= GNUNET_CONTAINER_multishortmap_size (routes))
860 {
861 LOG (GNUNET_ERROR_TYPE_DEBUG,
862 "Received CADET_CONNECTION_CREATE from %s for %s. We have reached our route limit. Sending BROKEN\n",
863 GCP_2s (sender),
864 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
865 send_broken_without_mqm (sender, &msg->cid, &pids[off - 1]);
866 return;
867 }
868
869 /* Workable route, create routing entry */
870 LOG (GNUNET_ERROR_TYPE_DEBUG,
871 "Received CADET_CONNECTION_CREATE from %s for %s. Next hop %s:%u is up. Creating route\n",
872 GCP_2s (sender),
873 GNUNET_sh2s (&msg->cid.connection_of_tunnel),
874 GNUNET_i2s (&pids[off + 1]),
875 off + 1);
876 route = GNUNET_new (struct CadetRoute);
877 route->cid = msg->cid;
878 route->last_use = GNUNET_TIME_absolute_get ();
879 dir_init (&route->prev, route, sender);
880 dir_init (&route->next, route, next);
881 GNUNET_assert (GNUNET_OK ==
882 GNUNET_CONTAINER_multishortmap_put (
883 routes,
884 &route->cid.connection_of_tunnel,
885 route,
886 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
887 GNUNET_STATISTICS_set (stats,
888 "# routes",
889 GNUNET_CONTAINER_multishortmap_size (routes),
890 GNUNET_NO);
891 route->hn = GNUNET_CONTAINER_heap_insert (route_heap,
892 route,
893 route->last_use.abs_value_us);
894 if (NULL == timeout_task)
895 timeout_task =
896 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (
897 keepalive_period,
898 3),
899 &timeout_cb,
900 NULL);
901 /* also pass CREATE message along to next hop */
902 route_message (sender,
903 &msg->cid,
904 &msg->header,
905 GNUNET_MQ_PRIO_CRITICAL_CONTROL | GNUNET_MQ_PREF_LOW_LATENCY);
906}
907
908
909/**
910 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK
911 *
912 * @param cls Closure (CadetPeer for neighbor that sent the message).
913 * @param msg Message itself.
914 */
915static void
916handle_connection_create_ack (
917 void *cls,
918 const struct GNUNET_CADET_ConnectionCreateAckMessage *msg)
919{
920 struct CadetPeer *peer = cls;
921 struct CadetConnection *cc;
922
923 /* First, check if ACK belongs to a connection that ends here. */
924 cc = GCC_lookup (&msg->cid);
925 if (NULL != cc)
926 {
927 /* verify ACK came from the right direction */
928 unsigned int len;
929 struct CadetPeerPath *path = GCC_get_path (cc, &len);
930
931 if (peer != GCPP_get_peer_at_offset (path, 0))
932 {
933 /* received ACK from unexpected direction, ignore! */
934 GNUNET_break_op (0);
935 return;
936 }
937 LOG (GNUNET_ERROR_TYPE_DEBUG,
938 "Received CONNECTION_CREATE_ACK for connection %s.\n",
939 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
940 GCC_handle_connection_create_ack (cc);
941 return;
942 }
943
944 /* We're just an intermediary peer, route the message along its path */
945 route_message (peer,
946 &msg->cid,
947 &msg->header,
948 GNUNET_MQ_PRIO_CRITICAL_CONTROL | GNUNET_MQ_PREF_LOW_LATENCY);
949}
950
951
952/**
953 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN
954 *
955 * @param cls Closure (CadetPeer for neighbor that sent the message).
956 * @param msg Message itself.
957 * @deprecated duplicate logic with #handle_destroy(); dedup!
958 */
959static void
960handle_connection_broken (
961 void *cls,
962 const struct GNUNET_CADET_ConnectionBrokenMessage *msg)
963{
964 struct CadetPeer *peer = cls;
965 struct CadetConnection *cc;
966 struct CadetRoute *route;
967
968 /* First, check if message belongs to a connection that ends here. */
969 cc = GCC_lookup (&msg->cid);
970 if (NULL != cc)
971 {
972 /* verify message came from the right direction */
973 unsigned int len;
974 struct CadetPeerPath *path = GCC_get_path (cc, &len);
975
976 if (peer != GCPP_get_peer_at_offset (path, 0))
977 {
978 /* received message from unexpected direction, ignore! */
979 GNUNET_break_op (0);
980 return;
981 }
982 LOG (GNUNET_ERROR_TYPE_DEBUG,
983 "Received CONNECTION_BROKEN for connection %s. Destroying it.\n",
984 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
985 GCC_destroy_without_core (cc);
986
987 /* FIXME: also destroy the path up to the specified link! */
988 return;
989 }
990
991 /* We're just an intermediary peer, route the message along its path */
992 route_message (peer,
993 &msg->cid,
994 &msg->header,
995 GNUNET_MQ_PREF_LOW_LATENCY | GNUNET_MQ_PRIO_CRITICAL_CONTROL);
996 route = get_route (&msg->cid);
997 if (NULL != route)
998 destroy_route (route);
999 /* FIXME: also destroy paths we MAY have up to the specified link! */
1000}
1001
1002
1003/**
1004 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY
1005 *
1006 * @param cls Closure (CadetPeer for neighbor that sent the message).
1007 * @param msg Message itself.
1008 */
1009static void
1010handle_connection_destroy (
1011 void *cls,
1012 const struct GNUNET_CADET_ConnectionDestroyMessage *msg)
1013{
1014 struct CadetPeer *peer = cls;
1015 struct CadetConnection *cc;
1016 struct CadetRoute *route;
1017
1018 /* First, check if message belongs to a connection that ends here. */
1019 cc = GCC_lookup (&msg->cid);
1020 if (NULL != cc)
1021 {
1022 /* verify message came from the right direction */
1023 unsigned int len;
1024 struct CadetPeerPath *path = GCC_get_path (cc, &len);
1025
1026 if (peer != GCPP_get_peer_at_offset (path, 0))
1027 {
1028 /* received message from unexpected direction, ignore! */
1029 GNUNET_break_op (0);
1030 return;
1031 }
1032 LOG (GNUNET_ERROR_TYPE_DEBUG,
1033 "Received CONNECTION_DESTROY for connection %s. Destroying connection.\n",
1034 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
1035
1036 GCC_destroy_without_core (cc);
1037 return;
1038 }
1039
1040 /* We're just an intermediary peer, route the message along its path */
1041 LOG (GNUNET_ERROR_TYPE_DEBUG,
1042 "Received CONNECTION_DESTROY for connection %s. Destroying route.\n",
1043 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
1044 route_message (peer,
1045 &msg->cid,
1046 &msg->header,
1047 GNUNET_MQ_PREF_LOW_LATENCY | GNUNET_MQ_PRIO_CRITICAL_CONTROL);
1048 route = get_route (&msg->cid);
1049 if (NULL != route)
1050 destroy_route (route);
1051}
1052
1053
1054/**
1055 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX
1056 *
1057 * @param cls Closure (CadetPeer for neighbor that sent the message).
1058 * @param msg Message itself.
1059 */
1060static void
1061handle_tunnel_kx (void *cls,
1062 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
1063{
1064 struct CadetPeer *peer = cls;
1065 struct CadetConnection *cc;
1066
1067 /* First, check if message belongs to a connection that ends here. */
1068 LOG (GNUNET_ERROR_TYPE_DEBUG,
1069 "Routing KX with ephemeral %s on CID %s\n",
1070 GNUNET_e2s (&msg->ephemeral_key),
1071 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
1072
1073
1074 cc = GCC_lookup (&msg->cid);
1075 if (NULL != cc)
1076 {
1077 /* verify message came from the right direction */
1078 unsigned int len;
1079 struct CadetPeerPath *path = GCC_get_path (cc, &len);
1080
1081 if (peer != GCPP_get_peer_at_offset (path, 0))
1082 {
1083 /* received message from unexpected direction, ignore! */
1084 GNUNET_break_op (0);
1085 return;
1086 }
1087 GCC_handle_kx (cc, msg);
1088 return;
1089 }
1090
1091 /* We're just an intermediary peer, route the message along its path */
1092 route_message (peer,
1093 &msg->cid,
1094 &msg->header,
1095 GNUNET_MQ_PRIO_CRITICAL_CONTROL | GNUNET_MQ_PREF_LOW_LATENCY);
1096}
1097
1098
1099/**
1100 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX_AUTH
1101 *
1102 * @param cls Closure (CadetPeer for neighbor that sent the message).
1103 * @param msg Message itself.
1104 */
1105static void
1106handle_tunnel_kx_auth (
1107 void *cls,
1108 const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg)
1109{
1110 struct CadetPeer *peer = cls;
1111 struct CadetConnection *cc;
1112
1113 /* First, check if message belongs to a connection that ends here. */
1114 cc = GCC_lookup (&msg->kx.cid);
1115 if (NULL != cc)
1116 {
1117 /* verify message came from the right direction */
1118 unsigned int len;
1119 struct CadetPeerPath *path = GCC_get_path (cc, &len);
1120
1121 if (peer != GCPP_get_peer_at_offset (path, 0))
1122 {
1123 /* received message from unexpected direction, ignore! */
1124 GNUNET_break_op (0);
1125 return;
1126 }
1127 GCC_handle_kx_auth (cc, msg);
1128 return;
1129 }
1130
1131 /* We're just an intermediary peer, route the message along its path */
1132 route_message (peer,
1133 &msg->kx.cid,
1134 &msg->kx.header,
1135 GNUNET_MQ_PRIO_CRITICAL_CONTROL | GNUNET_MQ_PREF_LOW_LATENCY);
1136}
1137
1138
1139/**
1140 * Check if the encrypted message has the appropriate size.
1141 *
1142 * @param cls Closure (unused).
1143 * @param msg Message to check.
1144 *
1145 * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
1146 */
1147static int
1148check_tunnel_encrypted (void *cls,
1149 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
1150{
1151 return GNUNET_YES;
1152}
1153
1154
1155/**
1156 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED.
1157 *
1158 * @param cls Closure (CadetPeer for neighbor that sent the message).
1159 * @param msg Message itself.
1160 */
1161static void
1162handle_tunnel_encrypted (void *cls,
1163 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
1164{
1165 struct CadetPeer *peer = cls;
1166 struct CadetConnection *cc;
1167
1168 /* First, check if message belongs to a connection that ends here. */
1169 cc = GCC_lookup (&msg->cid);
1170 if (NULL != cc)
1171 {
1172 /* verify message came from the right direction */
1173 unsigned int len;
1174 struct CadetPeerPath *path = GCC_get_path (cc, &len);
1175
1176 if (peer != GCPP_get_peer_at_offset (path, 0))
1177 {
1178 /* received message from unexpected direction, ignore! */
1179 GNUNET_break_op (0);
1180 return;
1181 }
1182 GCC_handle_encrypted (cc, msg);
1183 return;
1184 }
1185 /* We're just an intermediary peer, route the message along its path */
1186 route_message (peer, &msg->cid, &msg->header, GNUNET_MQ_PRIO_BEST_EFFORT);
1187}
1188
1189
1190/**
1191 * Function called after #GNUNET_CORE_connect has succeeded (or failed
1192 * for good). Note that the private key of the peer is intentionally
1193 * not exposed here; if you need it, your process should try to read
1194 * the private key file directly (which should work if you are
1195 * authorized...). Implementations of this function must not call
1196 * #GNUNET_CORE_disconnect (other than by scheduling a new task to
1197 * do this later).
1198 *
1199 * @param cls closure
1200 * @param my_identity ID of this peer, NULL if we failed
1201 */
1202static void
1203core_init_cb (void *cls, const struct GNUNET_PeerIdentity *my_identity)
1204{
1205 if (NULL == my_identity)
1206 {
1207 GNUNET_break (0);
1208 return;
1209 }
1210 GNUNET_break (0 == GNUNET_memcmp (my_identity, &my_full_id));
1211}
1212
1213
1214/**
1215 * Method called whenever a given peer connects.
1216 *
1217 * @param cls closure
1218 * @param peer peer identity this notification is about
1219 */
1220static void *
1221core_connect_cb (void *cls,
1222 const struct GNUNET_PeerIdentity *peer,
1223 struct GNUNET_MQ_Handle *mq)
1224{
1225 struct CadetPeer *cp;
1226
1227 LOG (GNUNET_ERROR_TYPE_DEBUG,
1228 "CORE connection to peer %s was established.\n",
1229 GNUNET_i2s (peer));
1230 cp = GCP_get (peer, GNUNET_YES);
1231 GCP_set_mq (cp, mq);
1232 return cp;
1233}
1234
1235
1236/**
1237 * Method called whenever a peer disconnects.
1238 *
1239 * @param cls closure
1240 * @param peer peer identity this notification is about
1241 */
1242static void
1243core_disconnect_cb (void *cls,
1244 const struct GNUNET_PeerIdentity *peer,
1245 void *peer_cls)
1246{
1247 struct CadetPeer *cp = peer_cls;
1248
1249 LOG (GNUNET_ERROR_TYPE_DEBUG,
1250 "CORE connection to peer %s went down.\n",
1251 GNUNET_i2s (peer));
1252 GCP_set_mq (cp, NULL);
1253}
1254
1255
1256/**
1257 * Initialize the CORE subsystem.
1258 *
1259 * @param c Configuration.
1260 */
1261void
1262GCO_init (const struct GNUNET_CONFIGURATION_Handle *c)
1263{
1264 struct GNUNET_MQ_MessageHandler handlers[] =
1265 { GNUNET_MQ_hd_var_size (connection_create,
1266 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE,
1267 struct GNUNET_CADET_ConnectionCreateMessage,
1268 NULL),
1269 GNUNET_MQ_hd_fixed_size (connection_create_ack,
1270 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK,
1271 struct GNUNET_CADET_ConnectionCreateAckMessage,
1272 NULL),
1273 GNUNET_MQ_hd_fixed_size (connection_broken,
1274 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN,
1275 struct GNUNET_CADET_ConnectionBrokenMessage,
1276 NULL),
1277 GNUNET_MQ_hd_fixed_size (connection_destroy,
1278 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY,
1279 struct GNUNET_CADET_ConnectionDestroyMessage,
1280 NULL),
1281 GNUNET_MQ_hd_fixed_size (tunnel_kx,
1282 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX,
1283 struct GNUNET_CADET_TunnelKeyExchangeMessage,
1284 NULL),
1285 GNUNET_MQ_hd_fixed_size (tunnel_kx_auth,
1286 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX_AUTH,
1287 struct GNUNET_CADET_TunnelKeyExchangeAuthMessage,
1288 NULL),
1289 GNUNET_MQ_hd_var_size (tunnel_encrypted,
1290 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED,
1291 struct GNUNET_CADET_TunnelEncryptedMessage,
1292 NULL),
1293 GNUNET_MQ_handler_end () };
1294
1295 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (c,
1296 "CADET",
1297 "MAX_ROUTES",
1298 &max_routes))
1299 max_routes = 5000;
1300 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (c,
1301 "CADET",
1302 "MAX_MSGS_QUEUE",
1303 &max_buffers))
1304 max_buffers = 10000;
1305 routes = GNUNET_CONTAINER_multishortmap_create (1024, GNUNET_NO);
1306 route_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
1307 core = GNUNET_CORE_connect (c,
1308 NULL,
1309 &core_init_cb,
1310 &core_connect_cb,
1311 &core_disconnect_cb,
1312 handlers);
1313}
1314
1315
1316void
1317GCO_shutdown ()
1318{
1319 if (NULL != core)
1320 {
1321 GNUNET_CORE_disconnect (core);
1322 core = NULL;
1323 }
1324 GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (routes));
1325 GNUNET_CONTAINER_multishortmap_destroy (routes);
1326 routes = NULL;
1327 GNUNET_CONTAINER_heap_destroy (route_heap);
1328 route_heap = NULL;
1329 if (NULL != timeout_task)
1330 {
1331 GNUNET_SCHEDULER_cancel (timeout_task);
1332 timeout_task = NULL;
1333 }
1334}
1335
1336
1337/* end of gnunet-cadet-service_core.c */
diff --git a/src/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 82ba326b4..000000000
--- a/src/cadet/gnunet-service-cadet_dht.c
+++ /dev/null
@@ -1,331 +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
58struct GCD_search_handle
59{
60 /**
61 * DHT_GET handle.
62 */
63 struct GNUNET_DHT_GetHandle *dhtget;
64};
65
66
67/**
68 * Handle to use DHT.
69 */
70static struct GNUNET_DHT_Handle *dht_handle;
71
72/**
73 * How often to PUT own ID in the DHT.
74 */
75static struct GNUNET_TIME_Relative id_announce_time;
76
77/**
78 * DHT replication level, see DHT API: #GNUNET_DHT_get_start(), #GNUNET_DHT_put().
79 */
80static unsigned long long dht_replication_level;
81
82/**
83 * Task to periodically announce itself in the network.
84 */
85static struct GNUNET_SCHEDULER_Task *announce_id_task;
86
87/**
88 * Delay for the next ID announce.
89 */
90static struct GNUNET_TIME_Relative announce_delay;
91
92
93/**
94 * Function to process paths received for a new peer addition. The recorded
95 * paths form the initial tunnel, which can be optimized later.
96 * Called on each result obtained for the DHT search.
97 *
98 * @param cls closure
99 * @param exp when will this value expire
100 * @param key key of the result
101 * @param trunc_peer peer preceeding with invalid signature, or NULL
102 * @param get_path path of the get request
103 * @param get_path_length length of @a get_path
104 * @param put_path path of the put request
105 * @param put_path_length length of the @a put_path
106 * @param type type of the result
107 * @param size number of bytes in data
108 * @param data pointer to the result data
109 */
110static void
111dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp,
112 const struct GNUNET_HashCode *key,
113 const struct GNUNET_PeerIdentity *trunc_peer,
114 const struct GNUNET_DHT_PathElement *get_path,
115 unsigned int get_path_length,
116 const struct GNUNET_DHT_PathElement *put_path,
117 unsigned int put_path_length,
118 enum GNUNET_BLOCK_Type type,
119 size_t size,
120 const void *data)
121{
122 const struct GNUNET_HELLO_Message *hello = data;
123
124 (void) trunc_peer;
125 GCPP_try_path_from_dht (get_path,
126 get_path_length,
127 put_path,
128 put_path_length);
129 if ((size >= sizeof(struct GNUNET_HELLO_Message)) &&
130 (ntohs (hello->header.size) == size) &&
131 (size == GNUNET_HELLO_size (hello)))
132 {
133 struct CadetPeer *peer;
134
135 peer = GCP_get (&put_path[0].pred,
136 GNUNET_YES);
137 LOG (GNUNET_ERROR_TYPE_DEBUG,
138 "Got HELLO for %s\n",
139 GCP_2s (peer));
140 GCP_set_hello (peer,
141 hello);
142 }
143}
144
145
146/**
147 * Periodically announce self id in the DHT
148 *
149 * @param cls closure
150 */
151static void
152announce_id (void *cls)
153{
154 struct GNUNET_HashCode phash;
155 const struct GNUNET_HELLO_Message *hello;
156 size_t size;
157 struct GNUNET_TIME_Absolute expiration;
158 struct GNUNET_TIME_Relative next_put;
159
160 hello = GCH_get_mine ();
161 size = (NULL != hello) ? GNUNET_HELLO_size (hello) : 0;
162 if (0 == size)
163 {
164 expiration = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
165 announce_delay);
166 announce_delay = GNUNET_TIME_STD_BACKOFF (announce_delay);
167 }
168 else
169 {
170 expiration = GNUNET_HELLO_get_last_expiration (hello);
171 announce_delay = GNUNET_TIME_UNIT_SECONDS;
172 }
173
174 /* Call again in id_announce_time, unless HELLO expires first,
175 * but wait at least 1s. */
176 next_put
177 = GNUNET_TIME_absolute_get_remaining (expiration);
178 next_put
179 = GNUNET_TIME_relative_min (next_put,
180 id_announce_time);
181 next_put
182 = GNUNET_TIME_relative_max (next_put,
183 GNUNET_TIME_UNIT_SECONDS);
184 announce_id_task
185 = GNUNET_SCHEDULER_add_delayed (next_put,
186 &announce_id,
187 cls);
188 GNUNET_STATISTICS_update (stats,
189 "# DHT announce",
190 1,
191 GNUNET_NO);
192 memset (&phash,
193 0,
194 sizeof(phash));
195 GNUNET_memcpy (&phash,
196 &my_full_id,
197 sizeof(my_full_id));
198 LOG (GNUNET_ERROR_TYPE_DEBUG,
199 "Announcing my HELLO (%lu bytes) in the DHT\n",
200 (unsigned long) size);
201 GNUNET_DHT_put (dht_handle, /* DHT handle */
202 &phash, /* Key to use */
203 dht_replication_level, /* Replication level */
204 GNUNET_DHT_RO_RECORD_ROUTE
205 | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, /* DHT options */
206 GNUNET_BLOCK_TYPE_DHT_HELLO, /* Block type */
207 size, /* Size of the data */
208 (const char *) hello, /* Data itself */
209 expiration, /* Data expiration */
210 NULL, /* Continuation */
211 NULL); /* Continuation closure */
212}
213
214
215void
216GCD_hello_update ()
217{
218 if (NULL == announce_id_task)
219 return; /* too early */
220 GNUNET_SCHEDULER_cancel (announce_id_task);
221 announce_id_task
222 = GNUNET_SCHEDULER_add_delayed (CHANGE_DELAY,
223 &announce_id,
224 NULL);
225}
226
227
228void
229GCD_init (const struct GNUNET_CONFIGURATION_Handle *c)
230{
231 if (GNUNET_OK !=
232 GNUNET_CONFIGURATION_get_value_number (c,
233 "CADET",
234 "DHT_REPLICATION_LEVEL",
235 &dht_replication_level))
236 {
237 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
238 "CADET",
239 "DHT_REPLICATION_LEVEL",
240 "USING DEFAULT");
241 dht_replication_level = 3;
242 }
243
244 if (GNUNET_OK !=
245 GNUNET_CONFIGURATION_get_value_time (c,
246 "CADET",
247 "ID_ANNOUNCE_TIME",
248 &id_announce_time))
249 {
250 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
251 "CADET",
252 "ID_ANNOUNCE_TIME",
253 "MISSING");
254 GNUNET_SCHEDULER_shutdown ();
255 return;
256 }
257
258 dht_handle = GNUNET_DHT_connect (c,
259 64);
260 GNUNET_break (NULL != dht_handle);
261 announce_delay = GNUNET_TIME_UNIT_SECONDS;
262 announce_id_task = GNUNET_SCHEDULER_add_delayed (STARTUP_DELAY,
263 &announce_id,
264 NULL);
265}
266
267
268void
269GCD_shutdown (void)
270{
271 if (NULL != dht_handle)
272 {
273 GNUNET_DHT_disconnect (dht_handle);
274 dht_handle = NULL;
275 }
276 if (NULL != announce_id_task)
277 {
278 GNUNET_SCHEDULER_cancel (announce_id_task);
279 announce_id_task = NULL;
280 }
281}
282
283
284struct GCD_search_handle *
285GCD_search (const struct GNUNET_PeerIdentity *peer_id)
286{
287 struct GNUNET_HashCode phash;
288 struct GCD_search_handle *h;
289
290 GNUNET_STATISTICS_update (stats,
291 "# DHT search",
292 1,
293 GNUNET_NO);
294 memset (&phash,
295 0,
296 sizeof(phash));
297 GNUNET_memcpy (&phash,
298 peer_id,
299 sizeof(*peer_id));
300
301 h = GNUNET_new (struct GCD_search_handle);
302 h->dhtget = GNUNET_DHT_get_start (dht_handle, /* handle */
303 GNUNET_BLOCK_TYPE_DHT_HELLO, /* type */
304 &phash, /* key to search */
305 dht_replication_level, /* replication level */
306 GNUNET_DHT_RO_RECORD_ROUTE
307 | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
308 NULL, /* xquery */
309 0, /* xquery bits */
310 &dht_get_id_handler,
311 h);
312 LOG (GNUNET_ERROR_TYPE_DEBUG,
313 "Starting DHT GET for peer %s (%p)\n",
314 GNUNET_i2s (peer_id),
315 h);
316 return h;
317}
318
319
320void
321GCD_search_stop (struct GCD_search_handle *h)
322{
323 LOG (GNUNET_ERROR_TYPE_DEBUG,
324 "Stopping DHT GET %p\n",
325 h);
326 GNUNET_DHT_get_stop (h->dhtget);
327 GNUNET_free (h);
328}
329
330
331/* 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 83b996e05..000000000
--- a/src/cadet/gnunet-service-cadet_paths.c
+++ /dev/null
@@ -1,771 +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_DHT_PathElement *get_path,
472 unsigned int get_path_length,
473 const struct GNUNET_DHT_PathElement *put_path,
474 unsigned int put_path_length)
475{
476 struct CadetPeer *cpath[get_path_length + put_path_length];
477 struct CheckMatchContext cm_ctx;
478 struct CadetPeerPath *path;
479 unsigned int skip;
480 unsigned int total_len;
481
482 /* precompute 'cpath' so we can avoid doing the lookups lots of times */
483 skip = 0;
484 memset (cpath,
485 0,
486 sizeof(cpath)); /* Just to trigger harder errors later. */
487 total_len = get_path_length + put_path_length;
488 for (unsigned int off = 0; off < total_len; off++)
489 {
490 const struct GNUNET_PeerIdentity *pid;
491
492 pid = (off < get_path_length)
493 ? &get_path[get_path_length - off - 1].pred
494 : &put_path[get_path_length + put_path_length - off - 1].pred;
495 /* Check that I am not in the path */
496 if (0 == GNUNET_memcmp (&my_full_id,
497 pid))
498 {
499 skip = off + 1;
500 continue;
501 }
502 cpath[off - skip] = GCP_get (pid,
503 GNUNET_YES);
504 /* Check that no peer is twice on the path */
505 for (unsigned int i = 0; i < off - skip; i++)
506 {
507 if (cpath[i] == cpath[off - skip])
508 {
509 skip = off - i;
510 break;
511 }
512 }
513 }
514 if (skip >= total_len)
515 {
516 LOG (GNUNET_ERROR_TYPE_DEBUG,
517 "Path discovered from DHT is one big cycle?\n");
518 return;
519 }
520 total_len -= skip;
521
522 /* First figure out if this path is a subset of an existing path, an
523 extension of an existing path, or a new path. */
524 cm_ctx.cpath_length = total_len;
525 cm_ctx.cpath = cpath;
526 cm_ctx.match = NULL;
527 for (int i = total_len - 1; i >= 0; i--)
528 {
529 GCP_iterate_paths_at (cpath[i],
530 (unsigned int) i,
531 &check_match,
532 &cm_ctx);
533 if (NULL != cm_ctx.match)
534 {
535 if (i == total_len - 1)
536 {
537 /* Existing path includes this one, nothing to do! */
538 LOG (GNUNET_ERROR_TYPE_DEBUG,
539 "Path discovered from DHT is already known\n");
540 return;
541 }
542 if (cm_ctx.match->entries_length == i + 1)
543 {
544 /* Existing path ends in the middle of new path, extend it! */
545 LOG (GNUNET_ERROR_TYPE_DEBUG,
546 "Trying to extend existing path %s by additional links discovered from DHT\n",
547 GCPP_2s (cm_ctx.match));
548 extend_path (cm_ctx.match,
549 &cpath[i + 1],
550 total_len - i - 1,
551 GNUNET_NO);
552 return;
553 }
554 }
555 }
556
557 /* No match at all, create completely new path */
558 path = GNUNET_new (struct CadetPeerPath);
559 path->entries_length = total_len;
560 path->entries = GNUNET_new_array (path->entries_length,
561 struct CadetPeerPathEntry *);
562 for (int i = path->entries_length - 1; i >= 0; i--)
563 {
564 struct CadetPeerPathEntry *entry = GNUNET_new (struct CadetPeerPathEntry);
565
566 path->entries[i] = entry;
567 entry->peer = cpath[i];
568 entry->path = path;
569 }
570 for (int i = path->entries_length - 1; i >= 0; i--)
571 {
572 struct CadetPeerPathEntry *entry = path->entries[i];
573
574 GCP_path_entry_add (entry->peer,
575 entry,
576 i);
577 }
578
579 /* Finally, try to attach it */
580 attach_path (path, 0);
581 if (NULL == path->hn)
582 {
583 /* None of the peers on the path care about it. */
584 LOG (GNUNET_ERROR_TYPE_DEBUG,
585 "Path discovered from DHT is not interesting to us\n");
586 GNUNET_assert (0 == path->entries_length);
587 GNUNET_assert (NULL == path->entries);
588 GNUNET_free (path);
589 return;
590 }
591 LOG (GNUNET_ERROR_TYPE_DEBUG,
592 "Created new path %s based on information from DHT\n",
593 GCPP_2s (path));
594}
595
596
597struct CadetPeerPath *
598GCPP_get_path_from_route (unsigned int path_length,
599 const struct GNUNET_PeerIdentity *pids)
600{
601 struct CheckMatchContext cm_ctx;
602 struct CadetPeer *cpath[path_length];
603 struct CadetPeerPath *path;
604
605 /* precompute inverted 'cpath' so we can avoid doing the lookups and
606 have the correct order */
607 for (unsigned int off = 0; off < path_length; off++)
608 cpath[off] = GCP_get (&pids[path_length - 1 - off],
609 GNUNET_YES);
610
611 /* First figure out if this path is a subset of an existing path, an
612 extension of an existing path, or a new path. */
613 cm_ctx.cpath = cpath;
614 cm_ctx.cpath_length = path_length;
615 cm_ctx.match = NULL;
616 for (int i = path_length - 1; i >= 0; i--)
617 {
618 GCP_iterate_paths_at (cpath[i],
619 (unsigned int) i,
620 &check_match,
621 &cm_ctx);
622 if (NULL != cm_ctx.match)
623 {
624 if (i == path_length - 1)
625 {
626 /* Existing path includes this one, return the match! */
627 LOG (GNUNET_ERROR_TYPE_DEBUG,
628 "Returning existing path %s as inverse for incoming connection\n",
629 GCPP_2s (cm_ctx.match));
630 return cm_ctx.match;
631 }
632 if (cm_ctx.match->entries_length == i + 1)
633 {
634 /* Existing path ends in the middle of new path, extend it! */
635 LOG (GNUNET_ERROR_TYPE_DEBUG,
636 "Extending existing path %s to create inverse for incoming connection\n",
637 GCPP_2s (cm_ctx.match));
638 extend_path (cm_ctx.match,
639 &cpath[i + 1],
640 path_length - i - 1,
641 GNUNET_YES);
642 /* Check that extension was successful */
643 GNUNET_assert (cm_ctx.match->entries_length == path_length);
644 return cm_ctx.match;
645 }
646 /* Eh, we found a match but couldn't use it? Something is wrong. */
647 GNUNET_break (0);
648 }
649 }
650
651 /* No match at all, create completely new path */
652 path = GNUNET_new (struct CadetPeerPath);
653 path->entries_length = path_length;
654 path->entries = GNUNET_new_array (path->entries_length,
655 struct CadetPeerPathEntry *);
656 for (int i = path_length - 1; i >= 0; i--)
657 {
658 struct CadetPeerPathEntry *entry = GNUNET_new (struct CadetPeerPathEntry);
659
660 path->entries[i] = entry;
661 entry->peer = cpath[i];
662 entry->path = path;
663 }
664 for (int i = path_length - 1; i >= 0; i--)
665 {
666 struct CadetPeerPathEntry *entry = path->entries[i];
667
668 GCP_path_entry_add (entry->peer,
669 entry,
670 i);
671 }
672 recalculate_path_desirability (path);
673 LOG (GNUNET_ERROR_TYPE_DEBUG,
674 "Created new path %s to create inverse for incoming connection\n",
675 GCPP_2s (path));
676 path->hn = GCP_attach_path (cpath[path_length - 1],
677 path,
678 path_length - 1,
679 GNUNET_YES);
680 return path;
681}
682
683
684/**
685 * Return the length of the path. Excludes one end of the
686 * path, so the loopback path has length 0.
687 *
688 * @param path path to return the length for
689 * @return number of peers on the path
690 */
691unsigned int
692GCPP_get_length (struct CadetPeerPath *path)
693{
694 return path->entries_length;
695}
696
697
698/**
699 * Find peer's offset on path.
700 *
701 * @param path path to search
702 * @param cp peer to look for
703 * @return offset of @a cp on @a path, or UINT_MAX if not found
704 */
705unsigned int
706GCPP_find_peer (struct CadetPeerPath *path,
707 struct CadetPeer *cp)
708{
709 for (unsigned int off = 0;
710 off < path->entries_length;
711 off++)
712 if (cp == GCPP_get_peer_at_offset (path,
713 off))
714 return off;
715 return UINT_MAX;
716}
717
718
719struct CadetPeer *
720GCPP_get_peer_at_offset (struct CadetPeerPath *path,
721 unsigned int off)
722{
723 GNUNET_assert (off < path->entries_length);
724 return path->entries[off]->peer;
725}
726
727
728/**
729 * Convert a path to a human-readable string.
730 *
731 * @param path path to convert
732 * @return string, to be freed by caller (unlike other *_2s APIs!)
733 */
734const char *
735GCPP_2s (struct CadetPeerPath *path)
736{
737 static char buf[2048];
738 size_t off;
739 const unsigned int max_plen = (sizeof(buf) - 16) / 5 - 2; /* 5 characters per entry */
740
741 off = 0;
742 for (unsigned int i = 0;
743 i < path->entries_length;
744 i++)
745 {
746 if ((path->entries_length > max_plen) &&
747 (i == max_plen / 2))
748 off += GNUNET_snprintf (&buf[off],
749 sizeof(buf) - off,
750 "...-");
751 if ((path->entries_length > max_plen) &&
752 (i > max_plen / 2) &&
753 (i < path->entries_length - max_plen / 2))
754 continue;
755 off += GNUNET_snprintf (&buf[off],
756 sizeof(buf) - off,
757 "%s%s",
758 GNUNET_i2s (GCP_get_id (GCPP_get_peer_at_offset (
759 path,
760 i))),
761 (i == path->entries_length - 1) ? "" : "-");
762 }
763 GNUNET_snprintf (&buf[off],
764 sizeof(buf) - off,
765 "(%p)",
766 path);
767 return buf;
768}
769
770
771/* end of gnunet-service-cadet-new_paths.c */
diff --git a/src/cadet/gnunet-service-cadet_paths.h b/src/cadet/gnunet-service-cadet_paths.h
deleted file mode 100644
index defdd0df2..000000000
--- a/src/cadet/gnunet-service-cadet_paths.h
+++ /dev/null
@@ -1,183 +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_dht_service.h"
32#include "gnunet-service-cadet.h"
33
34/**
35 * Create a peer path based on the result of a DHT lookup. If we
36 * already know this path, or one that is longer, simply return NULL.
37 * Otherwise, we try to extend an existing path, or create a new one
38 * if applicable.
39 *
40 * @param get_path path of the get request
41 * @param get_path_length length of @a get_path
42 * @param put_path path of the put request
43 * @param put_path_length length of the @a put_path
44 */
45void
46GCPP_try_path_from_dht (const struct GNUNET_DHT_PathElement *get_path,
47 unsigned int get_path_length,
48 const struct GNUNET_DHT_PathElement *put_path,
49 unsigned int put_path_length);
50
51
52/**
53 * We got an incoming connection, obtain the corresponding path.
54 *
55 * @param path_length number of segments on the @a path
56 * @param path through the network, in reverse order
57 * (we are at the end, at index @a path_length)
58 * @return corresponding path object
59 */
60struct CadetPeerPath *
61GCPP_get_path_from_route (unsigned int path_length,
62 const struct GNUNET_PeerIdentity *pids);
63
64
65/**
66 * Return the length of the path. Excludes one end of the
67 * path, so the loopback path has length 0.
68 *
69 * @param path path to return the length for
70 * @return number of peers on the path
71 */
72unsigned int
73GCPP_get_length (struct CadetPeerPath *path);
74
75
76/**
77 * Return connection to @a destination using @a path, or return
78 * NULL if no such connection exists.
79 *
80 * @param path path to traverse
81 * @param destination destination node to get to, must be on path
82 * @param off offset of @a destination on @a path
83 * @return NULL if we have no existing connection
84 * otherwise connection from us to @a destination via @a path
85 */
86struct CadetConnection *
87GCPP_get_connection (struct CadetPeerPath *path,
88 struct CadetPeer *destination,
89 unsigned int off);
90
91
92/**
93 * Notify @a path that it is used for connection @a cc
94 * which ends at the path's offset @a off.
95 *
96 * @param path the path to remember the @a cc
97 * @param off the offset where the @a cc ends
98 * @param cc the connection to remember
99 */
100void
101GCPP_add_connection (struct CadetPeerPath *path,
102 unsigned int off,
103 struct CadetConnection *cc);
104
105
106/**
107 * Notify @a path that it is no longer used for connection @a cc which
108 * ended at the path's offset @a off.
109 *
110 * @param path the path to forget the @a cc
111 * @param off the offset where the @a cc ended
112 * @param cc the connection to forget
113 */
114void
115GCPP_del_connection (struct CadetPeerPath *path,
116 unsigned int off,
117 struct CadetConnection *cc);
118
119
120/**
121 * Find peer's offset on path.
122 *
123 * @param path path to search
124 * @param cp peer to look for
125 * @return offset of @a cp on @a path, or UINT_MAX if not found
126 */
127unsigned int
128GCPP_find_peer (struct CadetPeerPath *path,
129 struct CadetPeer *cp);
130
131
132/**
133 * Return how much we like keeping the path. This is an aggregate
134 * score based on various factors, including the age of the path
135 * (older == better), and the value of this path to all of its adjacent
136 * peers. For example, long paths that end at a peer that we have no
137 * shorter way to reach are very desirable, while long paths that end
138 * at a peer for which we have a shorter way as well are much less
139 * desirable. Higher values indicate more valuable paths. The
140 * returned value should be used to decide which paths to remember.
141 *
142 * @param path path to return the length for
143 * @return desirability of the path, larger is more desirable
144 */
145GNUNET_CONTAINER_HeapCostType
146GCPP_get_desirability (const struct CadetPeerPath *path);
147
148
149/**
150 * The given peer @a cp used to own this @a path. However, it is no
151 * longer interested in maintaining it, so the path should be
152 * discarded or shortened (in case a previous peer on the path finds
153 * the path desirable).
154 *
155 * @param path the path that is being released
156 */
157void
158GCPP_release (struct CadetPeerPath *path);
159
160
161/**
162 * Obtain the peer at offset @a off in @a path.
163 *
164 * @param path peer path to inspect
165 * @param off offset to return, must be smaller than path length
166 * @return peer at offset @a off
167 */
168struct CadetPeer *
169GCPP_get_peer_at_offset (struct CadetPeerPath *path,
170 unsigned int off);
171
172
173/**
174 * Convert a path to a human-readable string.
175 *
176 * @param path path to convert
177 * @return string, statically allocated
178 */
179const char *
180GCPP_2s (struct CadetPeerPath *p);
181
182
183#endif
diff --git a/src/cadet/gnunet-service-cadet_peer.c b/src/cadet/gnunet-service-cadet_peer.c
deleted file mode 100644
index 99669eb05..000000000
--- a/src/cadet/gnunet-service-cadet_peer.c
+++ /dev/null
@@ -1,1566 +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
263double
264GCP_get_desirability_of_path (struct CadetPeer *cp,
265 unsigned int off)
266{
267 unsigned int num_alts = cp->num_paths;
268 unsigned int off_sum;
269 double avg_sum;
270 double path_delta;
271 double weight_alts;
272
273 GNUNET_assert (num_alts >= 1); /* 'path' should be in there! */
274 GNUNET_assert (0 != cp->path_dll_length);
275
276 /* We maintain 'off_sum' in 'peer' and thereby
277 avoid the SLOW recalculation each time. Kept here
278 just to document what is going on. */
279#if SLOW
280 off_sum = 0;
281 for (unsigned int j = 0; j < cp->path_dll_length; j++)
282 for (struct CadetPeerPathEntry *pe = cp->path_heads[j];
283 NULL != pe;
284 pe = pe->next)
285 off_sum += j;
286 GNUNET_assert (off_sum == cp->off_sum);
287#else
288 off_sum = cp->off_sum;
289#endif
290 avg_sum = off_sum * 1.0 / cp->path_dll_length;
291 path_delta = off - avg_sum;
292 /* path_delta positive: path off of peer above average (bad path for peer),
293 path_delta negative: path off of peer below average (good path for peer) */
294 if (path_delta <= -1.0)
295 weight_alts = -num_alts / path_delta; /* discount alternative paths */
296 else if (path_delta >= 1.0)
297 weight_alts = num_alts * path_delta; /* overcount alternative paths */
298 else
299 weight_alts = num_alts; /* count alternative paths normally */
300
301
302 /* off+1: long paths are generally harder to find and thus count
303 a bit more as they get longer. However, above-average paths
304 still need to count less, hence the squaring of that factor. */
305 return (off + 1.0) / (weight_alts * weight_alts);
306}
307
308
309/**
310 * This peer is no longer be needed, clean it up now.
311 *
312 * @param cls peer to clean up
313 */
314static void
315destroy_peer (void *cls)
316{
317 struct CadetPeer *cp = cls;
318
319 LOG (GNUNET_ERROR_TYPE_DEBUG,
320 "Destroying state about peer %s\n",
321 GCP_2s (cp));
322 cp->destroy_task = NULL;
323 GNUNET_assert (NULL == cp->t);
324 GNUNET_assert (NULL == cp->core_mq);
325 GNUNET_assert (0 == cp->num_paths);
326 for (unsigned int i = 0; i < cp->path_dll_length; i++)
327 GNUNET_assert (NULL == cp->path_heads[i]);
328 GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (cp->connections));
329 GNUNET_assert (GNUNET_YES ==
330 GNUNET_CONTAINER_multipeermap_remove (peers,
331 &cp->pid,
332 cp));
333 GNUNET_free (cp->path_heads);
334 GNUNET_free (cp->path_tails);
335 cp->path_dll_length = 0;
336 if (NULL != cp->search_h)
337 {
338 GCD_search_stop (cp->search_h);
339 cp->search_h = NULL;
340 }
341 /* FIXME: clean up search_delayedXXX! */
342
343 if (NULL != cp->hello_offer)
344 {
345 GNUNET_TRANSPORT_offer_hello_cancel (cp->hello_offer);
346 cp->hello_offer = NULL;
347 }
348 if (NULL != cp->connectivity_suggestion)
349 {
350 GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
351 cp->connectivity_suggestion = NULL;
352 }
353 GNUNET_CONTAINER_multishortmap_destroy (cp->connections);
354 if (NULL != cp->path_heap)
355 {
356 GNUNET_CONTAINER_heap_destroy (cp->path_heap);
357 cp->path_heap = NULL;
358 }
359 if (NULL != cp->heap_cleanup_task)
360 {
361 GNUNET_SCHEDULER_cancel (cp->heap_cleanup_task);
362 cp->heap_cleanup_task = NULL;
363 }
364 GNUNET_free (cp->hello);
365 /* Peer should not be freed if paths exist; if there are no paths,
366 there ought to be no connections, and without connections, no
367 notifications. Thus we can assert that mqm_head is empty at this
368 point. */
369 GNUNET_assert (NULL == cp->mqm_head);
370 GNUNET_assert (NULL == cp->mqm_ready_ptr);
371 GNUNET_free (cp);
372}
373
374
375/**
376 * This peer is now on more "active" duty, activate processes related to it.
377 *
378 * @param cp the more-active peer
379 */
380static void
381consider_peer_activate (struct CadetPeer *cp)
382{
383 uint32_t strength;
384
385 LOG (GNUNET_ERROR_TYPE_DEBUG,
386 "Updating peer %s activation state (%u connections)%s%s\n",
387 GCP_2s (cp),
388 GNUNET_CONTAINER_multishortmap_size (cp->connections),
389 (NULL == cp->t) ? "" : " with tunnel",
390 (NULL == cp->core_mq) ? "" : " with CORE link");
391 if (NULL != cp->destroy_task)
392 {
393 /* It's active, do not destroy! */
394 GNUNET_SCHEDULER_cancel (cp->destroy_task);
395 cp->destroy_task = NULL;
396 }
397 if ((0 == GNUNET_CONTAINER_multishortmap_size (cp->connections)) &&
398 (NULL == cp->t))
399 {
400 /* We're just on a path or directly connected; don't bother too much */
401 if (NULL != cp->connectivity_suggestion)
402 {
403 GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
404 cp->connectivity_suggestion = NULL;
405 }
406 if (NULL != cp->search_h)
407 {
408 GCD_search_stop (cp->search_h);
409 cp->search_h = NULL;
410 }
411 return;
412 }
413 if (NULL == cp->core_mq)
414 {
415 /* Lacks direct connection, try to create one by querying the DHT */
416 if ((NULL == cp->search_h) &&
417 (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths))
418 cp->search_h
419 = GCD_search (&cp->pid);
420 }
421 else
422 {
423 /* Have direct connection, stop DHT search if active */
424 if (NULL != cp->search_h)
425 {
426 GCD_search_stop (cp->search_h);
427 cp->search_h = NULL;
428 }
429 }
430
431 /* If we have a tunnel, our urge for connections is much bigger */
432 strength = (NULL != cp->t) ? 32 : 1;
433 if (NULL != cp->connectivity_suggestion)
434 GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
435 cp->connectivity_suggestion
436 = GNUNET_ATS_connectivity_suggest (ats_ch,
437 &cp->pid,
438 strength);
439}
440
441
442/**
443 * This peer may no longer be needed, consider cleaning it up.
444 *
445 * @param cp peer to clean up
446 */
447static void
448consider_peer_destroy (struct CadetPeer *cp);
449
450
451/**
452 * We really no longere care about a peer, stop hogging memory with paths to it.
453 * Afterwards, see if there is more to be cleaned up about this peer.
454 *
455 * @param cls a `struct CadetPeer`.
456 */
457static void
458drop_paths (void *cls)
459{
460 struct CadetPeer *cp = cls;
461 struct CadetPeerPath *path;
462
463 cp->destroy_task = NULL;
464 while (NULL != (path = GNUNET_CONTAINER_heap_remove_root (cp->path_heap)))
465 GCPP_release (path);
466 consider_peer_destroy (cp);
467}
468
469
470/**
471 * This peer may no longer be needed, consider cleaning it up.
472 *
473 * @param cp peer to clean up
474 */
475static void
476consider_peer_destroy (struct CadetPeer *cp)
477{
478 struct GNUNET_TIME_Relative exp;
479
480 if (NULL != cp->destroy_task)
481 {
482 GNUNET_SCHEDULER_cancel (cp->destroy_task);
483 cp->destroy_task = NULL;
484 }
485 if (NULL != cp->t)
486 return; /* still relevant! */
487 if (NULL != cp->core_mq)
488 return; /* still relevant! */
489 if (0 != GNUNET_CONTAINER_multishortmap_size (cp->connections))
490 return; /* still relevant! */
491 if ((NULL != cp->path_heap) &&
492 (0 < GNUNET_CONTAINER_heap_get_size (cp->path_heap)))
493 {
494 cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PATH_TIMEOUT,
495 &drop_paths,
496 cp);
497 return;
498 }
499 if (0 != cp->num_paths)
500 return; /* still relevant! */
501 if (NULL != cp->hello)
502 {
503 /* relevant only until HELLO expires */
504 exp = GNUNET_TIME_absolute_get_remaining (GNUNET_HELLO_get_last_expiration (
505 cp->hello));
506 cp->destroy_task = GNUNET_SCHEDULER_add_delayed (exp,
507 &destroy_peer,
508 cp);
509 return;
510 }
511 cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PEER_TIMEOUT,
512 &destroy_peer,
513 cp);
514}
515
516
517/**
518 * Set the message queue to @a mq for peer @a cp and notify watchers.
519 *
520 * @param cp peer to modify
521 * @param mq message queue to set (can be NULL)
522 */
523void
524GCP_set_mq (struct CadetPeer *cp,
525 struct GNUNET_MQ_Handle *mq)
526{
527 LOG (GNUNET_ERROR_TYPE_DEBUG,
528 "Message queue for peer %s is now %p\n",
529 GCP_2s (cp),
530 mq);
531 cp->core_mq = mq;
532 for (struct GCP_MessageQueueManager *mqm = cp->mqm_head, *next;
533 NULL != mqm;
534 mqm = next)
535 {
536 /* Save next pointer in case mqm gets freed by the callback */
537 next = mqm->next;
538 if (NULL == mq)
539 {
540 if (NULL != mqm->env)
541 {
542 GNUNET_MQ_discard (mqm->env);
543 mqm->env = NULL;
544 mqm->cb (mqm->cb_cls,
545 GNUNET_SYSERR);
546 }
547 else
548 {
549 mqm->cb (mqm->cb_cls,
550 GNUNET_NO);
551 }
552 }
553 else
554 {
555 GNUNET_assert (NULL == mqm->env);
556 mqm->cb (mqm->cb_cls,
557 GNUNET_YES);
558 }
559 }
560 if ((NULL != mq) ||
561 (NULL != cp->t))
562 consider_peer_activate (cp);
563 else
564 consider_peer_destroy (cp);
565
566 if ((NULL != mq) &&
567 (NULL != cp->t))
568 {
569 /* have a new, direct path to the target, notify tunnel */
570 struct CadetPeerPath *path;
571
572 path = GCPP_get_path_from_route (1,
573 &cp->pid);
574 GCT_consider_path (cp->t,
575 path,
576 0);
577 }
578}
579
580
581/**
582 * Debug function should NEVER return true in production code, useful to
583 * simulate losses for testcases.
584 *
585 * @return #GNUNET_YES or #GNUNET_NO with the decision to drop.
586 */
587static int
588should_I_drop (void)
589{
590 if (0 == drop_percent)
591 return GNUNET_NO;
592 if (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
593 101) < drop_percent)
594 return GNUNET_YES;
595 return GNUNET_NO;
596}
597
598
599/**
600 * Function called when CORE took one of the messages from
601 * a message queue manager and transmitted it.
602 *
603 * @param cls the `struct CadetPeeer` where we made progress
604 */
605static void
606mqm_send_done (void *cls);
607
608
609/**
610 * Transmit current envelope from this @a mqm.
611 *
612 * @param mqm mqm to transmit message for now
613 */
614static void
615mqm_execute (struct GCP_MessageQueueManager *mqm)
616{
617 struct CadetPeer *cp = mqm->cp;
618
619 /* Move ready pointer to the next entry that might be ready. */
620 if ((mqm == cp->mqm_ready_ptr) &&
621 (NULL != mqm->next))
622 cp->mqm_ready_ptr = mqm->next;
623 /* Move entry to the end of the DLL, to be fair. */
624 if (mqm != cp->mqm_tail)
625 {
626 GNUNET_CONTAINER_DLL_remove (cp->mqm_head,
627 cp->mqm_tail,
628 mqm);
629 GNUNET_CONTAINER_DLL_insert_tail (cp->mqm_head,
630 cp->mqm_tail,
631 mqm);
632 }
633 cp->mqm_ready_counter--;
634 if (GNUNET_YES == should_I_drop ())
635 {
636 LOG (GNUNET_ERROR_TYPE_DEBUG,
637 "DROPPING message to peer %s from MQM %p\n",
638 GCP_2s (cp),
639 mqm);
640 GNUNET_MQ_discard (mqm->env);
641 mqm->env = NULL;
642 mqm_send_done (cp);
643 }
644 else
645 {
646 {
647 const struct GNUNET_MessageHeader *mh;
648
649 mh = GNUNET_MQ_env_get_msg (mqm->env);
650 switch (ntohs (mh->type))
651 {
652 case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX:
653 {
654 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg
655 = (const struct GNUNET_CADET_TunnelKeyExchangeMessage *) mh;
656 LOG (GNUNET_ERROR_TYPE_DEBUG,
657 "P2P forwarding KX with ephemeral %s to %s on CID %s\n",
658 GNUNET_e2s (&msg->ephemeral_key),
659 GCP_2s (cp),
660 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
661 }
662 break;
663
664 default:
665 break;
666 }
667 }
668 LOG (GNUNET_ERROR_TYPE_DEBUG,
669 "Sending to peer %s from MQM %p\n",
670 GCP_2s (cp),
671 mqm);
672 GNUNET_MQ_send (cp->core_mq,
673 mqm->env);
674 mqm->env = NULL;
675 }
676 mqm->cb (mqm->cb_cls,
677 GNUNET_YES);
678}
679
680
681/**
682 * Find the next ready message in the queue (starting
683 * the search from the `cp->mqm_ready_ptr`) and if possible
684 * execute the transmission.
685 *
686 * @param cp peer to try to send the next ready message to
687 */
688static void
689send_next_ready (struct CadetPeer *cp)
690{
691 struct GCP_MessageQueueManager *mqm;
692
693 if (0 == cp->mqm_ready_counter)
694 return;
695 while ((NULL != (mqm = cp->mqm_ready_ptr)) &&
696 (NULL == mqm->env))
697 cp->mqm_ready_ptr = mqm->next;
698 if (NULL == mqm)
699 return; /* nothing to do */
700 mqm_execute (mqm);
701}
702
703
704/**
705 * Function called when CORE took one of the messages from
706 * a message queue manager and transmitted it.
707 *
708 * @param cls the `struct CadetPeeer` where we made progress
709 */
710static void
711mqm_send_done (void *cls)
712{
713 struct CadetPeer *cp = cls;
714
715 LOG (GNUNET_ERROR_TYPE_DEBUG,
716 "Sending to peer %s completed\n",
717 GCP_2s (cp));
718 send_next_ready (cp);
719}
720
721
722/**
723 * Send the message in @a env to @a cp.
724 *
725 * @param mqm the message queue manager to use for transmission
726 * @param env envelope with the message to send; must NOT
727 * yet have a #GNUNET_MQ_notify_sent() callback attached to it
728 */
729void
730GCP_send (struct GCP_MessageQueueManager *mqm,
731 struct GNUNET_MQ_Envelope *env)
732{
733 struct CadetPeer *cp = mqm->cp;
734
735 GNUNET_assert (NULL != env);
736 LOG (GNUNET_ERROR_TYPE_DEBUG,
737 "Queueing message to peer %s in MQM %p\n",
738 GCP_2s (cp),
739 mqm);
740 GNUNET_assert (NULL != cp->core_mq);
741 GNUNET_assert (NULL == mqm->env);
742 GNUNET_MQ_notify_sent (env,
743 &mqm_send_done,
744 cp);
745 mqm->env = env;
746 cp->mqm_ready_counter++;
747 if (mqm != cp->mqm_ready_ptr)
748 cp->mqm_ready_ptr = cp->mqm_head;
749 if (1 == cp->mqm_ready_counter)
750 cp->mqm_ready_ptr = mqm;
751 if (0 != GNUNET_MQ_get_length (cp->core_mq))
752 return;
753 send_next_ready (cp);
754}
755
756
757/**
758 * Function called to destroy a peer now.
759 *
760 * @param cls NULL
761 * @param pid identity of the peer (unused)
762 * @param value the `struct CadetPeer` to clean up
763 * @return #GNUNET_OK (continue to iterate)
764 */
765static int
766destroy_iterator_cb (void *cls,
767 const struct GNUNET_PeerIdentity *pid,
768 void *value)
769{
770 struct CadetPeer *cp = value;
771
772 if (NULL != cp->destroy_task)
773 {
774 GNUNET_SCHEDULER_cancel (cp->destroy_task);
775 cp->destroy_task = NULL;
776 }
777 destroy_peer (cp);
778 return GNUNET_OK;
779}
780
781
782/**
783 * Clean up all entries about all peers.
784 * Must only be called after all tunnels, CORE-connections and
785 * connections are down.
786 */
787void
788GCP_destroy_all_peers ()
789{
790 LOG (GNUNET_ERROR_TYPE_DEBUG,
791 "Destroying all peers now\n");
792 GNUNET_CONTAINER_multipeermap_iterate (peers,
793 &destroy_iterator_cb,
794 NULL);
795}
796
797
798/**
799 * Drop all paths owned by this peer, and do not
800 * allow new ones to be added: We are shutting down.
801 *
802 * @param cp peer to drop paths to
803 */
804void
805GCP_drop_owned_paths (struct CadetPeer *cp)
806{
807 struct CadetPeerPath *path;
808
809 LOG (GNUNET_ERROR_TYPE_DEBUG,
810 "Destroying all paths to %s\n",
811 GCP_2s (cp));
812 while (NULL != (path =
813 GNUNET_CONTAINER_heap_remove_root (cp->path_heap)))
814 GCPP_release (path);
815 GNUNET_CONTAINER_heap_destroy (cp->path_heap);
816 cp->path_heap = NULL;
817}
818
819
820/**
821 * Add an entry to the DLL of all of the paths that this peer is on.
822 *
823 * @param cp peer to modify
824 * @param entry an entry on a path
825 * @param off offset of this peer on the path
826 */
827void
828GCP_path_entry_add (struct CadetPeer *cp,
829 struct CadetPeerPathEntry *entry,
830 unsigned int off)
831{
832 GNUNET_assert (cp == GCPP_get_peer_at_offset (entry->path,
833 off));
834 LOG (GNUNET_ERROR_TYPE_DEBUG,
835 "Discovered that peer %s is on path %s at offset %u\n",
836 GCP_2s (cp),
837 GCPP_2s (entry->path),
838 off);
839 if (off >= cp->path_dll_length)
840 {
841 unsigned int len = cp->path_dll_length;
842
843 GNUNET_array_grow (cp->path_heads,
844 len,
845 off + 4);
846 GNUNET_array_grow (cp->path_tails,
847 cp->path_dll_length,
848 off + 4);
849 }
850 GNUNET_CONTAINER_DLL_insert (cp->path_heads[off],
851 cp->path_tails[off],
852 entry);
853 cp->off_sum += off;
854 cp->num_paths++;
855
856 /* If we have a tunnel to this peer, tell the tunnel that there is a
857 new path available. */
858 if (NULL != cp->t)
859 GCT_consider_path (cp->t,
860 entry->path,
861 off);
862
863 if ((NULL != cp->search_h) &&
864 (DESIRED_CONNECTIONS_PER_TUNNEL <= cp->num_paths))
865 {
866 /* Now I have enough paths, stop search */
867 GCD_search_stop (cp->search_h);
868 cp->search_h = NULL;
869 }
870 if (NULL != cp->destroy_task)
871 {
872 /* paths changed, this resets the destroy timeout counter
873 and aborts a destroy task that may no longer be valid
874 to have (as we now have more paths via this peer). */
875 consider_peer_destroy (cp);
876 }
877}
878
879
880/**
881 * Remove an entry from the DLL of all of the paths that this peer is on.
882 *
883 * @param cp peer to modify
884 * @param entry an entry on a path
885 * @param off offset of this peer on the path
886 */
887void
888GCP_path_entry_remove (struct CadetPeer *cp,
889 struct CadetPeerPathEntry *entry,
890 unsigned int off)
891{
892 LOG (GNUNET_ERROR_TYPE_DEBUG,
893 "Removing knowledge about peer %s beging on path %s at offset %u\n",
894 GCP_2s (cp),
895 GCPP_2s (entry->path),
896 off);
897 GNUNET_CONTAINER_DLL_remove (cp->path_heads[off],
898 cp->path_tails[off],
899 entry);
900 GNUNET_assert (0 < cp->num_paths);
901 cp->off_sum -= off;
902 cp->num_paths--;
903 if ((NULL == cp->core_mq) &&
904 (NULL != cp->t) &&
905 (NULL == cp->search_h) &&
906 (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths))
907 cp->search_h
908 = GCD_search (&cp->pid);
909 if (NULL == cp->destroy_task)
910 {
911 /* paths changed, we might now be ready for destruction, check again */
912 consider_peer_destroy (cp);
913 }
914}
915
916
917/**
918 * Prune down the number of paths to this peer, we seem to
919 * have way too many.
920 *
921 * @param cls the `struct CadetPeer` to maintain the path heap for
922 */
923static void
924path_heap_cleanup (void *cls)
925{
926 struct CadetPeer *cp = cls;
927 struct CadetPeerPath *root;
928
929 cp->heap_cleanup_task = NULL;
930 while (GNUNET_CONTAINER_heap_get_size (cp->path_heap) >=
931 2 * DESIRED_CONNECTIONS_PER_TUNNEL)
932 {
933 /* Now we have way too many, drop least desirable UNLESS it is in use!
934 (Note that this intentionally keeps highly desirable, but currently
935 unused paths around in the hope that we might be able to switch, even
936 if the number of paths exceeds the threshold.) */
937 root = GNUNET_CONTAINER_heap_peek (cp->path_heap);
938 GNUNET_assert (NULL != root);
939 if (NULL !=
940 GCPP_get_connection (root,
941 cp,
942 GCPP_get_length (root) - 1))
943 break; /* can't fix */
944 /* Got plenty of paths to this destination, and this is a low-quality
945 one that we don't care about. Allow it to die. */
946 GNUNET_assert (root ==
947 GNUNET_CONTAINER_heap_remove_root (cp->path_heap));
948 GCPP_release (root);
949 }
950}
951
952
953struct GNUNET_CONTAINER_HeapNode *
954GCP_attach_path (struct CadetPeer *cp,
955 struct CadetPeerPath *path,
956 unsigned int off,
957 int force)
958{
959 GNUNET_CONTAINER_HeapCostType desirability;
960 struct CadetPeerPath *root;
961 GNUNET_CONTAINER_HeapCostType root_desirability;
962 struct GNUNET_CONTAINER_HeapNode *hn;
963
964 GNUNET_assert (off == GCPP_get_length (path) - 1);
965 GNUNET_assert (cp == GCPP_get_peer_at_offset (path,
966 off));
967 if (NULL == cp->path_heap)
968 {
969 /* #GCP_drop_owned_paths() was already called, we cannot take new ones! */
970 GNUNET_assert (GNUNET_NO == force);
971 return NULL;
972 }
973 desirability = GCPP_get_desirability (path);
974 if (GNUNET_NO == force)
975 {
976 /* FIXME: desirability is not yet initialized; tricky! */
977 if (GNUNET_NO ==
978 GNUNET_CONTAINER_heap_peek2 (cp->path_heap,
979 (void **) &root,
980 &root_desirability))
981 {
982 root = NULL;
983 root_desirability = 0;
984 }
985
986 if ((DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) &&
987 (desirability < root_desirability))
988 {
989 LOG (GNUNET_ERROR_TYPE_DEBUG,
990 "Decided to not attach path %s to peer %s due to undesirability\n",
991 GCPP_2s (path),
992 GCP_2s (cp));
993 return NULL;
994 }
995 }
996
997 LOG (GNUNET_ERROR_TYPE_DEBUG,
998 "Attaching path %s to peer %s (%s)\n",
999 GCPP_2s (path),
1000 GCP_2s (cp),
1001 (GNUNET_NO == force) ? "desirable" : "forced");
1002
1003 /* Yes, we'd like to add this path, add to our heap */
1004 hn = GNUNET_CONTAINER_heap_insert (cp->path_heap,
1005 path,
1006 desirability);
1007
1008 /* Consider maybe dropping other paths because of the new one */
1009 if ((GNUNET_CONTAINER_heap_get_size (cp->path_heap) >=
1010 2 * DESIRED_CONNECTIONS_PER_TUNNEL) &&
1011 (NULL != cp->heap_cleanup_task))
1012 cp->heap_cleanup_task = GNUNET_SCHEDULER_add_now (&path_heap_cleanup,
1013 cp);
1014 return hn;
1015}
1016
1017
1018/**
1019 * This peer can no longer own @a path as the path
1020 * has been extended and a peer further down the line
1021 * is now the new owner.
1022 *
1023 * @param cp old owner of the @a path
1024 * @param path path where the ownership is lost
1025 * @param hn note in @a cp's path heap that must be deleted
1026 */
1027void
1028GCP_detach_path (struct CadetPeer *cp,
1029 struct CadetPeerPath *path,
1030 struct GNUNET_CONTAINER_HeapNode *hn)
1031{
1032 LOG (GNUNET_ERROR_TYPE_DEBUG,
1033 "Detaching path %s from peer %s\n",
1034 GCPP_2s (path),
1035 GCP_2s (cp));
1036 GNUNET_assert (path ==
1037 GNUNET_CONTAINER_heap_remove_node (hn));
1038}
1039
1040
1041/**
1042 * Add a @a connection to this @a cp.
1043 *
1044 * @param cp peer via which the @a connection goes
1045 * @param cc the connection to add
1046 */
1047void
1048GCP_add_connection (struct CadetPeer *cp,
1049 struct CadetConnection *cc)
1050{
1051 LOG (GNUNET_ERROR_TYPE_DEBUG,
1052 "Adding %s to peer %s\n",
1053 GCC_2s (cc),
1054 GCP_2s (cp));
1055 GNUNET_assert (GNUNET_OK ==
1056 GNUNET_CONTAINER_multishortmap_put (cp->connections,
1057 &GCC_get_id (
1058 cc)->connection_of_tunnel,
1059 cc,
1060 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1061 if (NULL != cp->destroy_task)
1062 {
1063 GNUNET_SCHEDULER_cancel (cp->destroy_task);
1064 cp->destroy_task = NULL;
1065 }
1066}
1067
1068
1069/**
1070 * Remove a @a connection that went via this @a cp.
1071 *
1072 * @param cp peer via which the @a connection went
1073 * @param cc the connection to remove
1074 */
1075void
1076GCP_remove_connection (struct CadetPeer *cp,
1077 struct CadetConnection *cc)
1078{
1079 LOG (GNUNET_ERROR_TYPE_DEBUG,
1080 "Removing connection %s from peer %s\n",
1081 GCC_2s (cc),
1082 GCP_2s (cp));
1083 GNUNET_assert (GNUNET_YES ==
1084 GNUNET_CONTAINER_multishortmap_remove (cp->connections,
1085 &GCC_get_id (
1086 cc)->
1087 connection_of_tunnel,
1088 cc));
1089 consider_peer_destroy (cp);
1090}
1091
1092
1093/**
1094 * Retrieve the CadetPeer structure associated with the
1095 * peer. Optionally create one and insert it in the appropriate
1096 * structures if the peer is not known yet.
1097 *
1098 * @param peer_id Full identity of the peer.
1099 * @param create #GNUNET_YES if a new peer should be created if unknown.
1100 * #GNUNET_NO to return NULL if peer is unknown.
1101 * @return Existing or newly created peer structure.
1102 * NULL if unknown and not requested @a create
1103 */
1104struct CadetPeer *
1105GCP_get (const struct GNUNET_PeerIdentity *peer_id,
1106 int create)
1107{
1108 struct CadetPeer *cp;
1109
1110 cp = GNUNET_CONTAINER_multipeermap_get (peers,
1111 peer_id);
1112 if (NULL != cp)
1113 return cp;
1114 if (GNUNET_NO == create)
1115 return NULL;
1116 cp = GNUNET_new (struct CadetPeer);
1117 cp->pid = *peer_id;
1118 cp->connections = GNUNET_CONTAINER_multishortmap_create (32,
1119 GNUNET_YES);
1120 cp->path_heap = GNUNET_CONTAINER_heap_create (
1121 GNUNET_CONTAINER_HEAP_ORDER_MIN);
1122 GNUNET_assert (GNUNET_YES ==
1123 GNUNET_CONTAINER_multipeermap_put (peers,
1124 &cp->pid,
1125 cp,
1126 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1127 LOG (GNUNET_ERROR_TYPE_DEBUG,
1128 "Creating peer %s\n",
1129 GCP_2s (cp));
1130 return cp;
1131}
1132
1133
1134/**
1135 * Obtain the peer identity for a `struct CadetPeer`.
1136 *
1137 * @param cp our peer handle
1138 * @return the peer identity
1139 */
1140const struct GNUNET_PeerIdentity *
1141GCP_get_id (struct CadetPeer *cp)
1142{
1143 return &cp->pid;
1144}
1145
1146
1147/**
1148 * Iterate over all known peers.
1149 *
1150 * @param iter Iterator.
1151 * @param cls Closure for @c iter.
1152 */
1153void
1154GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter,
1155 void *cls)
1156{
1157 GNUNET_CONTAINER_multipeermap_iterate (peers,
1158 iter,
1159 cls);
1160}
1161
1162
1163/**
1164 * Count the number of known paths toward the peer.
1165 *
1166 * @param cp Peer to get path info.
1167 * @return Number of known paths.
1168 */
1169unsigned int
1170GCP_count_paths (const struct CadetPeer *cp)
1171{
1172 return cp->num_paths;
1173}
1174
1175
1176/**
1177 * Iterate over the paths to a peer.
1178 *
1179 * @param cp Peer to get path info.
1180 * @param callback Function to call for every path.
1181 * @param callback_cls Closure for @a callback.
1182 * @return Number of iterated paths.
1183 */
1184unsigned int
1185GCP_iterate_paths (struct CadetPeer *cp,
1186 GCP_PathIterator callback,
1187 void *callback_cls)
1188{
1189 unsigned int ret = 0;
1190
1191 LOG (GNUNET_ERROR_TYPE_DEBUG,
1192 "Iterating over paths to peer %s%s\n",
1193 GCP_2s (cp),
1194 (NULL == cp->core_mq) ? "" : " including direct link");
1195 if (NULL != cp->core_mq)
1196 {
1197 /* FIXME: this branch seems to duplicate the
1198 i=0 case below (direct link). Leave out!??? -CG */
1199 struct CadetPeerPath *path;
1200
1201 path = GCPP_get_path_from_route (1,
1202 &cp->pid);
1203 ret++;
1204 if (GNUNET_NO ==
1205 callback (callback_cls,
1206 path,
1207 0))
1208 return ret;
1209 }
1210 for (unsigned int i = 0; i < cp->path_dll_length; i++)
1211 {
1212 for (struct CadetPeerPathEntry *pe = cp->path_heads[i];
1213 NULL != pe;
1214 pe = pe->next)
1215 {
1216 ret++;
1217 if (GNUNET_NO ==
1218 callback (callback_cls,
1219 pe->path,
1220 i))
1221 return ret;
1222 }
1223 }
1224 return ret;
1225}
1226
1227
1228/**
1229 * Iterate over the paths to a peer without direct link.
1230 *
1231 * @param cp Peer to get path info.
1232 * @param callback Function to call for every path.
1233 * @param callback_cls Closure for @a callback.
1234 * @return Number of iterated paths.
1235 */
1236unsigned int
1237GCP_iterate_indirect_paths (struct CadetPeer *cp,
1238 GCP_PathIterator callback,
1239 void *callback_cls)
1240{
1241 unsigned int ret = 0;
1242
1243 LOG (GNUNET_ERROR_TYPE_DEBUG,
1244 "Iterating over paths to peer %s without direct link\n",
1245 GCP_2s (cp));
1246 for (unsigned int i = 1; i < cp->path_dll_length; i++)
1247 {
1248 for (struct CadetPeerPathEntry *pe = cp->path_heads[i];
1249 NULL != pe;
1250 pe = pe->next)
1251 {
1252 ret++;
1253 if (GNUNET_NO ==
1254 callback (callback_cls,
1255 pe->path,
1256 i))
1257 return ret;
1258 }
1259 }
1260 return ret;
1261}
1262
1263
1264unsigned int
1265GCP_iterate_paths_at (struct CadetPeer *cp,
1266 unsigned int dist,
1267 GCP_PathIterator callback,
1268 void *callback_cls)
1269{
1270 unsigned int ret = 0;
1271
1272 if (dist >= cp->path_dll_length)
1273 {
1274 LOG (GNUNET_ERROR_TYPE_DEBUG,
1275 "Asked to look for paths at distance %u, but maximum for me is < %u\n",
1276 dist,
1277 cp->path_dll_length);
1278 return 0;
1279 }
1280 for (struct CadetPeerPathEntry *pe = cp->path_heads[dist];
1281 NULL != pe;
1282 pe = pe->next)
1283 {
1284 if (GNUNET_NO ==
1285 callback (callback_cls,
1286 pe->path,
1287 dist))
1288 return ret;
1289 ret++;
1290 }
1291 return ret;
1292}
1293
1294
1295/**
1296 * Get the tunnel towards a peer.
1297 *
1298 * @param cp Peer to get from.
1299 * @param create #GNUNET_YES to create a tunnel if we do not have one
1300 * @return Tunnel towards peer.
1301 */
1302struct CadetTunnel *
1303GCP_get_tunnel (struct CadetPeer *cp,
1304 int create)
1305{
1306 if (NULL == cp)
1307 return NULL;
1308 if ((NULL != cp->t) ||
1309 (GNUNET_NO == create))
1310 return cp->t;
1311 cp->t = GCT_create_tunnel (cp);
1312 consider_peer_activate (cp);
1313 return cp->t;
1314}
1315
1316
1317/**
1318 * Hello offer was passed to the transport service. Mark it
1319 * as done.
1320 *
1321 * @param cls the `struct CadetPeer` where the offer completed
1322 */
1323static void
1324hello_offer_done (void *cls)
1325{
1326 struct CadetPeer *cp = cls;
1327
1328 cp->hello_offer = NULL;
1329}
1330
1331
1332void
1333GCP_set_hello (struct CadetPeer *cp,
1334 const struct GNUNET_HELLO_Message *hello)
1335{
1336 struct GNUNET_HELLO_Message *mrg;
1337
1338 LOG (GNUNET_ERROR_TYPE_DEBUG,
1339 "Got %u byte HELLO for peer %s\n",
1340 (unsigned int) GNUNET_HELLO_size (hello),
1341 GCP_2s (cp));
1342 if (NULL != cp->hello_offer)
1343 {
1344 GNUNET_TRANSPORT_offer_hello_cancel (cp->hello_offer);
1345 cp->hello_offer = NULL;
1346 }
1347 if (NULL != cp->hello)
1348 {
1349 mrg = GNUNET_HELLO_merge (hello,
1350 cp->hello);
1351 GNUNET_free (cp->hello);
1352 cp->hello = mrg;
1353 }
1354 else
1355 {
1356 cp->hello = GNUNET_memdup (hello,
1357 GNUNET_HELLO_size (hello));
1358 }
1359 cp->hello_offer
1360 = GNUNET_TRANSPORT_offer_hello (cfg,
1361 GNUNET_HELLO_get_header (cp->hello),
1362 &hello_offer_done,
1363 cp);
1364 /* New HELLO means cp's destruction time may change... */
1365 consider_peer_destroy (cp);
1366}
1367
1368
1369/**
1370 * The tunnel to the given peer no longer exists, remove it from our
1371 * data structures, and possibly clean up the peer itself.
1372 *
1373 * @param cp the peer affected
1374 * @param t the dead tunnel
1375 */
1376void
1377GCP_drop_tunnel (struct CadetPeer *cp,
1378 struct CadetTunnel *t)
1379{
1380 LOG (GNUNET_ERROR_TYPE_DEBUG,
1381 "Dropping tunnel %s to peer %s\n",
1382 GCT_2s (t),
1383 GCP_2s (cp));
1384 GNUNET_assert (cp->t == t);
1385 cp->t = NULL;
1386 consider_peer_destroy (cp);
1387}
1388
1389
1390/**
1391 * Test if @a cp has a core-level connection
1392 *
1393 * @param cp peer to test
1394 * @return #GNUNET_YES if @a cp has a core-level connection
1395 */
1396int
1397GCP_has_core_connection (struct CadetPeer *cp)
1398{
1399 return (NULL != cp->core_mq) ? GNUNET_YES : GNUNET_NO;
1400}
1401
1402
1403/**
1404 * Start message queue change notifications.
1405 *
1406 * @param cp peer to notify for
1407 * @param cb function to call if mq becomes available or unavailable
1408 * @param cb_cls closure for @a cb
1409 * @return handle to cancel request
1410 */
1411struct GCP_MessageQueueManager *
1412GCP_request_mq (struct CadetPeer *cp,
1413 GCP_MessageQueueNotificationCallback cb,
1414 void *cb_cls)
1415{
1416 struct GCP_MessageQueueManager *mqm;
1417
1418 mqm = GNUNET_new (struct GCP_MessageQueueManager);
1419 mqm->cb = cb;
1420 mqm->cb_cls = cb_cls;
1421 mqm->cp = cp;
1422 GNUNET_CONTAINER_DLL_insert (cp->mqm_head,
1423 cp->mqm_tail,
1424 mqm);
1425 LOG (GNUNET_ERROR_TYPE_DEBUG,
1426 "Creating MQM %p for peer %s\n",
1427 mqm,
1428 GCP_2s (cp));
1429 if (NULL != cp->core_mq)
1430 cb (cb_cls,
1431 GNUNET_YES);
1432 return mqm;
1433}
1434
1435
1436/**
1437 * Stops message queue change notifications.
1438 *
1439 * @param mqm handle matching request to cancel
1440 * @param last_env final message to transmit, or NULL
1441 */
1442void
1443GCP_request_mq_cancel (struct GCP_MessageQueueManager *mqm,
1444 struct GNUNET_MQ_Envelope *last_env)
1445{
1446 struct CadetPeer *cp = mqm->cp;
1447
1448 LOG (GNUNET_ERROR_TYPE_DEBUG,
1449 "Destroying MQM %p for peer %s%s\n",
1450 mqm,
1451 GCP_2s (cp),
1452 (NULL == last_env) ? "" : " with last ditch transmission");
1453 if (NULL != mqm->env)
1454 GNUNET_MQ_discard (mqm->env);
1455 if (NULL != last_env)
1456 {
1457 if (NULL != cp->core_mq)
1458 {
1459 GNUNET_MQ_notify_sent (last_env,
1460 &mqm_send_done,
1461 cp);
1462 GNUNET_MQ_send (cp->core_mq,
1463 last_env);
1464 }
1465 else
1466 {
1467 GNUNET_MQ_discard (last_env);
1468 }
1469 }
1470 if (cp->mqm_ready_ptr == mqm)
1471 cp->mqm_ready_ptr = mqm->next;
1472 GNUNET_CONTAINER_DLL_remove (cp->mqm_head,
1473 cp->mqm_tail,
1474 mqm);
1475 GNUNET_free (mqm);
1476}
1477
1478
1479/**
1480 * Send the message in @a env to @a cp, overriding queueing logic.
1481 * This function should only be used to send error messages outside
1482 * of flow and congestion control, similar to ICMP. Note that
1483 * the envelope may be silently discarded as well.
1484 *
1485 * @param cp peer to send the message to
1486 * @param env envelope with the message to send
1487 */
1488void
1489GCP_send_ooo (struct CadetPeer *cp,
1490 struct GNUNET_MQ_Envelope *env)
1491{
1492 LOG (GNUNET_ERROR_TYPE_DEBUG,
1493 "Sending message to %s out of management\n",
1494 GCP_2s (cp));
1495 if (NULL == cp->core_mq)
1496 {
1497 GNUNET_MQ_discard (env);
1498 return;
1499 }
1500 if (GNUNET_MQ_get_length (cp->core_mq) > MAX_OOO_QUEUE_SIZE)
1501 {
1502 GNUNET_MQ_discard (env);
1503 return;
1504 }
1505 GNUNET_MQ_notify_sent (env,
1506 &mqm_send_done,
1507 cp);
1508 GNUNET_MQ_send (cp->core_mq,
1509 env);
1510}
1511
1512
1513/**
1514 * 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.
1515 *
1516 * @param peer The peer we received a new time value from.
1517 * @param monotime Time value we check against the last time value we received from a peer.
1518 * @return GNUNET_YES if monotime is newer than the last received time value, GNUNET_NO if monotime is not newer.
1519 */
1520int
1521GCP_check_and_update_monotime (struct CadetPeer *peer,
1522 struct GNUNET_TIME_AbsoluteNBO monotime)
1523{
1524
1525 struct GNUNET_TIME_Absolute mt = GNUNET_TIME_absolute_ntoh (monotime);
1526
1527 if (mt.abs_value_us > *(&peer->last_connection_create.abs_value_us))
1528 {
1529 peer->last_connection_create = mt;
1530 return GNUNET_YES;
1531 }
1532 return GNUNET_NO;
1533}
1534
1535
1536/**
1537 * Checking the signature for a monotime of a GNUNET_CADET_ConnectionCreateMessage.
1538 *
1539 * @param peer The peer that signed the monotime value.
1540 * @param msg The GNUNET_CADET_ConnectionCreateMessage with the monotime value.
1541 * @return GNUNET_OK if the signature is good, GNUNET_SYSERR if not.
1542 */
1543int
1544GCP_check_monotime_sig (struct CadetPeer *peer,
1545 const struct GNUNET_CADET_ConnectionCreateMessage *msg)
1546{
1547 struct CadetConnectionCreatePS cp = { .purpose.purpose = htonl (
1548 GNUNET_SIGNATURE_PURPOSE_CADET_CONNECTION_INITIATOR),
1549 .purpose.size = htonl (sizeof(cp)),
1550 .monotonic_time = msg->monotime};
1551
1552 if (GNUNET_OK !=
1553 GNUNET_CRYPTO_eddsa_verify (
1554 GNUNET_SIGNATURE_PURPOSE_CADET_CONNECTION_INITIATOR,
1555 &cp,
1556 &msg->monotime_sig,
1557 &peer->pid.public_key))
1558 {
1559 GNUNET_break_op (0);
1560 return GNUNET_SYSERR;
1561 }
1562 return GNUNET_OK;
1563}
1564
1565
1566/* 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 69436d766..000000000
--- a/src/cadet/gnunet-service-cadet_peer.h
+++ /dev/null
@@ -1,433 +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 * The 'desirability_table.c' program can be used to compute a list of
66 * sample outputs for different scenarios. Basically, we score paths
67 * lower if there are many alternatives, and higher if they are
68 * shorter than average, and very high if they are much shorter than
69 * average and without many alternatives.
70 *
71 * @param cp a peer reachable via a path
72 * @param off offset of @a cp in a path
73 * @return score how useful a path is to reach @a cp,
74 * positive scores mean path is more desirable
75 */
76double
77GCP_get_desirability_of_path (struct CadetPeer *cp,
78 unsigned int off);
79
80
81/**
82 * Obtain the peer identity for a `struct CadetPeer`.
83 *
84 * @param cp our peer handle
85 * @return the peer identity
86 */
87const struct GNUNET_PeerIdentity *
88GCP_get_id (struct CadetPeer *cp);
89
90
91/**
92 * Iterate over all known peers.
93 *
94 * @param iter Iterator.
95 * @param cls Closure for @c iter.
96 */
97void
98GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter,
99 void *cls);
100
101
102/**
103 * Count the number of known paths toward the peer.
104 *
105 * @param cp Peer to get path info.
106 * @return Number of known paths.
107 */
108unsigned int
109GCP_count_paths (const struct CadetPeer *cp);
110
111
112/**
113 * Drop all paths owned by this peer, and do not
114 * allow new ones to be added: We are shutting down.
115 *
116 * @param cp peer to drop paths to
117 */
118void
119GCP_drop_owned_paths (struct CadetPeer *cp);
120
121
122/**
123 * Peer path iterator.
124 *
125 * @param cls Closure.
126 * @param path Path itself
127 * @param off offset of the target peer in @a path
128 * @return #GNUNET_YES if should keep iterating.
129 * #GNUNET_NO otherwise.
130 */
131typedef int
132(*GCP_PathIterator) (void *cls,
133 struct CadetPeerPath *path,
134 unsigned int off);
135
136
137/**
138 * Iterate over the paths to a peer.
139 *
140 * @param cp Peer to get path info.
141 * @param callback Function to call for every path.
142 * @param callback_cls Closure for @a callback.
143 * @return Number of iterated paths.
144 */
145unsigned int
146GCP_iterate_paths (struct CadetPeer *cp,
147 GCP_PathIterator callback,
148 void *callback_cls);
149
150/**
151 * Iterate over the paths to a peer without direct link.
152 *
153 * @param cp Peer to get path info.
154 * @param callback Function to call for every path.
155 * @param callback_cls Closure for @a callback.
156 * @return Number of iterated paths.
157 */
158unsigned int
159GCP_iterate_indirect_paths (struct CadetPeer *cp,
160 GCP_PathIterator callback,
161 void *callback_cls);
162
163
164/**
165 * Iterate over the paths to @a peer where
166 * @a peer is at distance @a dist from us.
167 *
168 * @param cp Peer to get path info.
169 * @param dist desired distance of @a peer to us on the path
170 * @param callback Function to call for every path.
171 * @param callback_cls Closure for @a callback.
172 * @return Number of iterated paths.
173 */
174unsigned int
175GCP_iterate_paths_at (struct CadetPeer *cp,
176 unsigned int dist,
177 GCP_PathIterator callback,
178 void *callback_cls);
179
180
181/**
182 * Remove an entry from the DLL of all of the paths that this peer is on.
183 *
184 * @param cp peer to modify
185 * @param entry an entry on a path
186 * @param off offset of this peer on the path
187 */
188void
189GCP_path_entry_remove (struct CadetPeer *cp,
190 struct CadetPeerPathEntry *entry,
191 unsigned int off);
192
193
194/**
195 * Add an entry to the DLL of all of the paths that this peer is on.
196 *
197 * @param cp peer to modify
198 * @param entry an entry on a path
199 * @param off offset of this peer on the path
200 */
201void
202GCP_path_entry_add (struct CadetPeer *cp,
203 struct CadetPeerPathEntry *entry,
204 unsigned int off);
205
206
207/**
208 * Get the tunnel towards a peer.
209 *
210 * @param cp Peer to get from.
211 * @param create #GNUNET_YES to create a tunnel if we do not have one
212 * @return Tunnel towards peer.
213 */
214struct CadetTunnel *
215GCP_get_tunnel (struct CadetPeer *cp,
216 int create);
217
218
219/**
220 * The tunnel to the given peer no longer exists, remove it from our
221 * data structures, and possibly clean up the peer itself.
222 *
223 * @param cp the peer affected
224 * @param t the dead tunnel
225 */
226void
227GCP_drop_tunnel (struct CadetPeer *cp,
228 struct CadetTunnel *t);
229
230
231/**
232 * Try adding a @a path to this @a cp. If the peer already
233 * has plenty of paths, return NULL.
234 *
235 * @param cp peer to which the @a path leads to
236 * @param path a path looking for an owner; may not be fully initialized yet!
237 * @param off offset of @a cp in @a path
238 * @param force force attaching the path
239 * @return NULL if this peer does not care to become a new owner,
240 * otherwise the node in the peer's path heap for the @a path.
241 */
242struct GNUNET_CONTAINER_HeapNode *
243GCP_attach_path (struct CadetPeer *cp,
244 struct CadetPeerPath *path,
245 unsigned int off,
246 int force);
247
248
249/**
250 * This peer can no longer own @a path as the path
251 * has been extended and a peer further down the line
252 * is now the new owner.
253 *
254 * @param cp old owner of the @a path
255 * @param path path where the ownership is lost
256 * @param hn note in @a cp's path heap that must be deleted
257 */
258void
259GCP_detach_path (struct CadetPeer *cp,
260 struct CadetPeerPath *path,
261 struct GNUNET_CONTAINER_HeapNode *hn);
262
263
264/**
265 * Add a @a connection to this @a cp.
266 *
267 * @param cp peer via which the @a connection goes
268 * @param cc the connection to add
269 */
270void
271GCP_add_connection (struct CadetPeer *cp,
272 struct CadetConnection *cc);
273
274
275/**
276 * Remove a @a connection that went via this @a cp.
277 *
278 * @param cp peer via which the @a connection went
279 * @param cc the connection to remove
280 */
281void
282GCP_remove_connection (struct CadetPeer *cp,
283 struct CadetConnection *cc);
284
285
286/**
287 * We got a HELLO for a @a cp, remember it, and possibly
288 * trigger adequate actions (like trying to connect).
289 *
290 * @param cp the peer we got a HELLO for
291 * @param hello the HELLO to remember
292 */
293void
294GCP_set_hello (struct CadetPeer *cp,
295 const struct GNUNET_HELLO_Message *hello);
296
297
298/**
299 * Clean up all entries about all peers.
300 * Must only be called after all tunnels, CORE-connections and
301 * connections are down.
302 */
303void
304GCP_destroy_all_peers (void);
305
306
307/**
308 * Data structure used to track whom we have to notify about changes
309 * in our ability to transmit to a given peer.
310 *
311 * All queue managers will be given equal chance for sending messages
312 * to @a cp. This construct this guarantees fairness for access to @a
313 * cp among the different message queues. Each connection or route
314 * will have its respective message queue managers for each direction.
315 */
316struct GCP_MessageQueueManager;
317
318
319/**
320 * Function to call with updated message queue object.
321 *
322 * @param cls closure
323 * @param available #GNUNET_YES if sending is now possible,
324 * #GNUNET_NO if sending is no longer possible
325 * #GNUNET_SYSERR if sending is no longer possible
326 * and the last envelope was discarded
327 */
328typedef void
329(*GCP_MessageQueueNotificationCallback)(void *cls,
330 int available);
331
332
333/**
334 * Start message queue change notifications. Will create a new slot
335 * to manage the message queue to the given @a cp.
336 *
337 * @param cp peer to notify for
338 * @param cb function to call if mq becomes available or unavailable
339 * @param cb_cls closure for @a cb
340 * @return handle to cancel request
341 */
342struct GCP_MessageQueueManager *
343GCP_request_mq (struct CadetPeer *cp,
344 GCP_MessageQueueNotificationCallback cb,
345 void *cb_cls);
346
347
348/**
349 * Test if @a cp has a core-level connection
350 *
351 * @param cp peer to test
352 * @return #GNUNET_YES if @a cp has a core-level connection
353 */
354int
355GCP_has_core_connection (struct CadetPeer *cp);
356
357
358/**
359 * Send the message in @a env via a @a mqm. Must only be called at
360 * most once after the respective
361 * #GCP_MessageQueueNotificationCallback was called with `available`
362 * set to #GNUNET_YES, and not after the callback was called with
363 * `available` set to #GNUNET_NO or #GNUNET_SYSERR.
364 *
365 * @param mqm message queue manager for the transmission
366 * @param env envelope with the message to send; must NOT
367 * yet have a #GNUNET_MQ_notify_sent() callback attached to it
368 */
369void
370GCP_send (struct GCP_MessageQueueManager *mqm,
371 struct GNUNET_MQ_Envelope *env);
372
373
374/**
375 * Send the message in @a env to @a cp, overriding queueing logic.
376 * This function should only be used to send error messages outside
377 * of flow and congestion control, similar to ICMP. Note that
378 * the envelope may be silently discarded as well.
379 *
380 * @param cp peer to send the message to
381 * @param env envelope with the message to send
382 */
383void
384GCP_send_ooo (struct CadetPeer *cp,
385 struct GNUNET_MQ_Envelope *env);
386
387
388/**
389 * Stops message queue change notifications and sends a last message.
390 * In practice, this is implemented by sending that @a last_env
391 * message immediately (if any), ignoring queue order.
392 *
393 * @param mqm handle matching request to cancel
394 * @param last_env final message to transmit, or NULL
395 */
396void
397GCP_request_mq_cancel (struct GCP_MessageQueueManager *mqm,
398 struct GNUNET_MQ_Envelope *last_env);
399
400
401/**
402 * Set the message queue to @a mq for peer @a cp and notify watchers.
403 *
404 * @param cp peer to modify
405 * @param mq message queue to set (can be NULL)
406 */
407void
408GCP_set_mq (struct CadetPeer *cp,
409 struct GNUNET_MQ_Handle *mq);
410
411/**
412 * Checking the signature for a monotime of a GNUNET_CADET_ConnectionCreateMessage.
413 *
414 * @param peer The peer that signed the monotime value.
415 * @param msg The GNUNET_CADET_ConnectionCreateMessage with the monotime value.
416 * @return GNUNET_OK if the signature is good, GNUNET_SYSERR if not.
417 */
418int
419GCP_check_monotime_sig (struct CadetPeer *peer, const struct
420 GNUNET_CADET_ConnectionCreateMessage *msg);
421
422/**
423 * Checking if a monotime value is newer than the last monotime value received from a peer. If the time value is newer it will be stored at the peer.
424 *
425 * @param peer The peer we received a new time value from.
426 * @param monotime Time value we check against the last time value we received from a peer.
427 * @return GNUNET_YES if monotime is newer than the last received time value, GNUNET_NO if monotime is not newer.
428 */
429int
430GCP_check_and_update_monotime (struct CadetPeer *peer,
431 struct GNUNET_TIME_AbsoluteNBO monotime);
432
433#endif
diff --git a/src/cadet/gnunet-service-cadet_tunnels.c b/src/cadet/gnunet-service-cadet_tunnels.c
deleted file mode 100644
index 9653fd3ec..000000000
--- a/src/cadet/gnunet-service-cadet_tunnels.c
+++ /dev/null
@@ -1,3677 +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
579unsigned int
580GCT_count_channels (struct CadetTunnel *t)
581{
582 return GNUNET_CONTAINER_multihashmap32_size (t->channels);
583}
584
585
586/**
587 * Lookup a channel by its @a ctn.
588 *
589 * @param t tunnel to look in
590 * @param ctn number of channel to find
591 * @return NULL if channel does not exist
592 */
593struct CadetChannel *
594lookup_channel (struct CadetTunnel *t,
595 struct GNUNET_CADET_ChannelTunnelNumber ctn)
596{
597 return GNUNET_CONTAINER_multihashmap32_get (t->channels,
598 ntohl (ctn.cn));
599}
600
601
602unsigned int
603GCT_count_any_connections (const struct CadetTunnel *t)
604{
605 return t->num_ready_connections + t->num_busy_connections;
606}
607
608
609/**
610 * Find first connection that is ready in the list of
611 * our connections. Picks ready connections round-robin.
612 *
613 * @param t tunnel to search
614 * @return NULL if we have no connection that is ready
615 */
616static struct CadetTConnection *
617get_ready_connection (struct CadetTunnel *t)
618{
619 struct CadetTConnection *hd = t->connection_ready_head;
620
621 GNUNET_assert ((NULL == hd) ||
622 (GNUNET_YES == hd->is_ready));
623 return hd;
624}
625
626
627/**
628 * Get the encryption state of a tunnel.
629 *
630 * @param t Tunnel.
631 *
632 * @return Tunnel's encryption state.
633 */
634enum CadetTunnelEState
635GCT_get_estate (struct CadetTunnel *t)
636{
637 return t->estate;
638}
639
640
641/**
642 * Called when either we have a new connection, or a new message in the
643 * queue, or some existing connection has transmission capacity. Looks
644 * at our message queue and if there is a message, picks a connection
645 * to send it on.
646 *
647 * @param cls the `struct CadetTunnel` to process messages on
648 */
649static void
650trigger_transmissions (void *cls);
651
652
653/* ************************************** start core crypto ***************************** */
654
655
656/**
657 * Create a new Axolotl ephemeral (ratchet) key.
658 *
659 * @param ax key material to update
660 */
661static void
662new_ephemeral (struct CadetTunnelAxolotl *ax)
663{
664 LOG (GNUNET_ERROR_TYPE_DEBUG,
665 "Creating new ephemeral ratchet key (DHRs)\n");
666 GNUNET_CRYPTO_ecdhe_key_create (&ax->DHRs);
667}
668
669
670/**
671 * Calculate HMAC.
672 *
673 * @param plaintext Content to HMAC.
674 * @param size Size of @c plaintext.
675 * @param iv Initialization vector for the message.
676 * @param key Key to use.
677 * @param hmac[out] Destination to store the HMAC.
678 */
679static void
680t_hmac (const void *plaintext,
681 size_t size,
682 uint32_t iv,
683 const struct GNUNET_CRYPTO_SymmetricSessionKey *key,
684 struct GNUNET_ShortHashCode *hmac)
685{
686 static const char ctx[] = "cadet authentication key";
687 struct GNUNET_CRYPTO_AuthKey auth_key;
688 struct GNUNET_HashCode hash;
689
690 GNUNET_CRYPTO_hmac_derive_key (&auth_key,
691 key,
692 &iv, sizeof(iv),
693 key, sizeof(*key),
694 ctx, sizeof(ctx),
695 NULL);
696 /* Two step: GNUNET_ShortHash is only 256 bits,
697 GNUNET_HashCode is 512, so we truncate. */
698 GNUNET_CRYPTO_hmac (&auth_key,
699 plaintext,
700 size,
701 &hash);
702 GNUNET_memcpy (hmac,
703 &hash,
704 sizeof(*hmac));
705}
706
707
708/**
709 * Perform a HMAC.
710 *
711 * @param key Key to use.
712 * @param[out] hash Resulting HMAC.
713 * @param source Source key material (data to HMAC).
714 * @param len Length of @a source.
715 */
716static void
717t_ax_hmac_hash (const struct GNUNET_CRYPTO_SymmetricSessionKey *key,
718 struct GNUNET_HashCode *hash,
719 const void *source,
720 unsigned int len)
721{
722 static const char ctx[] = "axolotl HMAC-HASH";
723 struct GNUNET_CRYPTO_AuthKey auth_key;
724
725 GNUNET_CRYPTO_hmac_derive_key (&auth_key,
726 key,
727 ctx, sizeof(ctx),
728 NULL);
729 GNUNET_CRYPTO_hmac (&auth_key,
730 source,
731 len,
732 hash);
733}
734
735
736/**
737 * Derive a symmetric encryption key from an HMAC-HASH.
738 *
739 * @param key Key to use for the HMAC.
740 * @param[out] out Key to generate.
741 * @param source Source key material (data to HMAC).
742 * @param len Length of @a source.
743 */
744static void
745t_hmac_derive_key (const struct GNUNET_CRYPTO_SymmetricSessionKey *key,
746 struct GNUNET_CRYPTO_SymmetricSessionKey *out,
747 const void *source,
748 unsigned int len)
749{
750 static const char ctx[] = "axolotl derive key";
751 struct GNUNET_HashCode h;
752
753 t_ax_hmac_hash (key,
754 &h,
755 source,
756 len);
757 GNUNET_CRYPTO_kdf (out, sizeof(*out),
758 ctx, sizeof(ctx),
759 &h, sizeof(h),
760 NULL);
761}
762
763
764/**
765 * Encrypt data with the axolotl tunnel key.
766 *
767 * @param ax key material to use.
768 * @param dst Destination with @a size bytes for the encrypted data.
769 * @param src Source of the plaintext. Can overlap with @c dst, must contain @a size bytes
770 * @param size Size of the buffers at @a src and @a dst
771 */
772static void
773t_ax_encrypt (struct CadetTunnelAxolotl *ax,
774 void *dst,
775 const void *src,
776 size_t size)
777{
778 struct GNUNET_CRYPTO_SymmetricSessionKey MK;
779 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
780 size_t out_size;
781
782 ax->ratchet_counter++;
783 if ((GNUNET_YES == ax->ratchet_allowed) &&
784 ((ratchet_messages <= ax->ratchet_counter) ||
785 (0 == GNUNET_TIME_absolute_get_remaining (
786 ax->ratchet_expiration).rel_value_us)))
787 {
788 ax->ratchet_flag = GNUNET_YES;
789 }
790 if (GNUNET_YES == ax->ratchet_flag)
791 {
792 /* Advance ratchet */
793 struct GNUNET_CRYPTO_SymmetricSessionKey keys[3];
794 struct GNUNET_HashCode dh;
795 struct GNUNET_HashCode hmac;
796 static const char ctx[] = "axolotl ratchet";
797
798 new_ephemeral (ax);
799 ax->HKs = ax->NHKs;
800
801 /* RK, NHKs, CKs = KDF( HMAC-HASH(RK, DH(DHRs, DHRr)) ) */
802 GNUNET_CRYPTO_ecc_ecdh (&ax->DHRs,
803 &ax->DHRr,
804 &dh);
805 t_ax_hmac_hash (&ax->RK,
806 &hmac,
807 &dh,
808 sizeof(dh));
809 GNUNET_CRYPTO_kdf (keys, sizeof(keys),
810 ctx, sizeof(ctx),
811 &hmac, sizeof(hmac),
812 NULL);
813 ax->RK = keys[0];
814 ax->NHKs = keys[1];
815 ax->CKs = keys[2];
816
817 ax->PNs = ax->Ns;
818 ax->Ns = 0;
819 ax->ratchet_flag = GNUNET_NO;
820 ax->ratchet_allowed = GNUNET_NO;
821 ax->ratchet_counter = 0;
822 ax->ratchet_expiration
823 = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
824 ratchet_time);
825 }
826
827 t_hmac_derive_key (&ax->CKs,
828 &MK,
829 "0",
830 1);
831 GNUNET_CRYPTO_symmetric_derive_iv (&iv,
832 &MK,
833 NULL, 0,
834 NULL);
835
836 out_size = GNUNET_CRYPTO_symmetric_encrypt (src,
837 size,
838 &MK,
839 &iv,
840 dst);
841 GNUNET_assert (size == out_size);
842 t_hmac_derive_key (&ax->CKs,
843 &ax->CKs,
844 "1",
845 1);
846}
847
848
849/**
850 * Decrypt data with the axolotl tunnel key.
851 *
852 * @param ax key material to use.
853 * @param dst Destination for the decrypted data, must contain @a size bytes.
854 * @param src Source of the ciphertext. Can overlap with @c dst, must contain @a size bytes.
855 * @param size Size of the @a src and @a dst buffers
856 */
857static void
858t_ax_decrypt (struct CadetTunnelAxolotl *ax,
859 void *dst,
860 const void *src,
861 size_t size)
862{
863 struct GNUNET_CRYPTO_SymmetricSessionKey MK;
864 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
865 size_t out_size;
866
867 t_hmac_derive_key (&ax->CKr,
868 &MK,
869 "0",
870 1);
871 GNUNET_CRYPTO_symmetric_derive_iv (&iv,
872 &MK,
873 NULL, 0,
874 NULL);
875 GNUNET_assert (size >= sizeof(struct GNUNET_MessageHeader));
876 out_size = GNUNET_CRYPTO_symmetric_decrypt (src,
877 size,
878 &MK,
879 &iv,
880 dst);
881 GNUNET_assert (out_size == size);
882 t_hmac_derive_key (&ax->CKr,
883 &ax->CKr,
884 "1",
885 1);
886}
887
888
889/**
890 * Encrypt header with the axolotl header key.
891 *
892 * @param ax key material to use.
893 * @param[in|out] msg Message whose header to encrypt.
894 */
895static void
896t_h_encrypt (struct CadetTunnelAxolotl *ax,
897 struct GNUNET_CADET_TunnelEncryptedMessage *msg)
898{
899 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
900 size_t out_size;
901
902 GNUNET_CRYPTO_symmetric_derive_iv (&iv,
903 &ax->HKs,
904 NULL, 0,
905 NULL);
906 out_size = GNUNET_CRYPTO_symmetric_encrypt (&msg->ax_header,
907 sizeof(struct
908 GNUNET_CADET_AxHeader),
909 &ax->HKs,
910 &iv,
911 &msg->ax_header);
912 GNUNET_assert (sizeof(struct GNUNET_CADET_AxHeader) == out_size);
913}
914
915
916/**
917 * Decrypt header with the current axolotl header key.
918 *
919 * @param ax key material to use.
920 * @param src Message whose header to decrypt.
921 * @param dst Where to decrypt header to.
922 */
923static void
924t_h_decrypt (struct CadetTunnelAxolotl *ax,
925 const struct GNUNET_CADET_TunnelEncryptedMessage *src,
926 struct GNUNET_CADET_TunnelEncryptedMessage *dst)
927{
928 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
929 size_t out_size;
930
931 GNUNET_CRYPTO_symmetric_derive_iv (&iv,
932 &ax->HKr,
933 NULL, 0,
934 NULL);
935 out_size = GNUNET_CRYPTO_symmetric_decrypt (&src->ax_header.Ns,
936 sizeof(struct
937 GNUNET_CADET_AxHeader),
938 &ax->HKr,
939 &iv,
940 &dst->ax_header.Ns);
941 GNUNET_assert (sizeof(struct GNUNET_CADET_AxHeader) == out_size);
942}
943
944
945/**
946 * Delete a key from the list of skipped keys.
947 *
948 * @param ax key material to delete @a key from.
949 * @param key Key to delete.
950 */
951static void
952delete_skipped_key (struct CadetTunnelAxolotl *ax,
953 struct CadetTunnelSkippedKey *key)
954{
955 GNUNET_CONTAINER_DLL_remove (ax->skipped_head,
956 ax->skipped_tail,
957 key);
958 GNUNET_free (key);
959 ax->skipped--;
960}
961
962
963/**
964 * Decrypt and verify data with the appropriate tunnel key and verify that the
965 * data has not been altered since it was sent by the remote peer.
966 *
967 * @param ax key material to use.
968 * @param dst Destination for the plaintext.
969 * @param src Source of the message. Can overlap with @c dst.
970 * @param size Size of the message.
971 * @return Size of the decrypted data, -1 if an error was encountered.
972 */
973static ssize_t
974try_old_ax_keys (struct CadetTunnelAxolotl *ax,
975 void *dst,
976 const struct GNUNET_CADET_TunnelEncryptedMessage *src,
977 size_t size)
978{
979 struct CadetTunnelSkippedKey *key;
980 struct GNUNET_ShortHashCode *hmac;
981 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
982 struct GNUNET_CADET_TunnelEncryptedMessage plaintext_header;
983 struct GNUNET_CRYPTO_SymmetricSessionKey *valid_HK;
984 size_t esize;
985 size_t res;
986 size_t len;
987 unsigned int N;
988
989 LOG (GNUNET_ERROR_TYPE_DEBUG,
990 "Trying skipped keys\n");
991 hmac = &plaintext_header.hmac;
992 esize = size - sizeof(struct GNUNET_CADET_TunnelEncryptedMessage);
993
994 /* Find a correct Header Key */
995 valid_HK = NULL;
996 for (key = ax->skipped_head; NULL != key; key = key->next)
997 {
998 t_hmac (&src->ax_header,
999 sizeof(struct GNUNET_CADET_AxHeader) + esize,
1000 0,
1001 &key->HK,
1002 hmac);
1003 if (0 == GNUNET_memcmp (hmac,
1004 &src->hmac))
1005 {
1006 valid_HK = &key->HK;
1007 break;
1008 }
1009 }
1010 if (NULL == key)
1011 return -1;
1012
1013 /* Should've been checked in -cadet_connection.c handle_cadet_encrypted. */
1014 GNUNET_assert (size > sizeof(struct GNUNET_CADET_TunnelEncryptedMessage));
1015 len = size - sizeof(struct GNUNET_CADET_TunnelEncryptedMessage);
1016 GNUNET_assert (len >= sizeof(struct GNUNET_MessageHeader));
1017
1018 /* Decrypt header */
1019 GNUNET_CRYPTO_symmetric_derive_iv (&iv,
1020 &key->HK,
1021 NULL, 0,
1022 NULL);
1023 res = GNUNET_CRYPTO_symmetric_decrypt (&src->ax_header.Ns,
1024 sizeof(struct GNUNET_CADET_AxHeader),
1025 &key->HK,
1026 &iv,
1027 &plaintext_header.ax_header.Ns);
1028 GNUNET_assert (sizeof(struct GNUNET_CADET_AxHeader) == res);
1029
1030 /* Find the correct message key */
1031 N = ntohl (plaintext_header.ax_header.Ns);
1032 while ((NULL != key) &&
1033 (N != key->Kn))
1034 key = key->next;
1035 if ((NULL == key) ||
1036 (0 != GNUNET_memcmp (&key->HK,
1037 valid_HK)))
1038 return -1;
1039
1040 /* Decrypt payload */
1041 GNUNET_CRYPTO_symmetric_derive_iv (&iv,
1042 &key->MK,
1043 NULL,
1044 0,
1045 NULL);
1046 res = GNUNET_CRYPTO_symmetric_decrypt (&src[1],
1047 len,
1048 &key->MK,
1049 &iv,
1050 dst);
1051 delete_skipped_key (ax,
1052 key);
1053 return res;
1054}
1055
1056
1057/**
1058 * Delete a key from the list of skipped keys.
1059 *
1060 * @param ax key material to delete from.
1061 * @param HKr Header Key to use.
1062 */
1063static void
1064store_skipped_key (struct CadetTunnelAxolotl *ax,
1065 const struct GNUNET_CRYPTO_SymmetricSessionKey *HKr)
1066{
1067 struct CadetTunnelSkippedKey *key;
1068
1069 key = GNUNET_new (struct CadetTunnelSkippedKey);
1070 key->timestamp = GNUNET_TIME_absolute_get ();
1071 key->Kn = ax->Nr;
1072 key->HK = ax->HKr;
1073 t_hmac_derive_key (&ax->CKr,
1074 &key->MK,
1075 "0",
1076 1);
1077 t_hmac_derive_key (&ax->CKr,
1078 &ax->CKr,
1079 "1",
1080 1);
1081 GNUNET_CONTAINER_DLL_insert (ax->skipped_head,
1082 ax->skipped_tail,
1083 key);
1084 ax->skipped++;
1085 ax->Nr++;
1086}
1087
1088
1089/**
1090 * Stage skipped AX keys and calculate the message key.
1091 * Stores each HK and MK for skipped messages.
1092 *
1093 * @param ax key material to use
1094 * @param HKr Header key.
1095 * @param Np Received meesage number.
1096 * @return #GNUNET_OK if keys were stored.
1097 * #GNUNET_SYSERR if an error occurred (@a Np not expected).
1098 */
1099static int
1100store_ax_keys (struct CadetTunnelAxolotl *ax,
1101 const struct GNUNET_CRYPTO_SymmetricSessionKey *HKr,
1102 uint32_t Np)
1103{
1104 int gap;
1105
1106 gap = Np - ax->Nr;
1107 LOG (GNUNET_ERROR_TYPE_DEBUG,
1108 "Storing skipped keys [%u, %u)\n",
1109 ax->Nr,
1110 Np);
1111 if (MAX_KEY_GAP < gap)
1112 {
1113 /* Avoid DoS (forcing peer to do more than #MAX_KEY_GAP HMAC operations) */
1114 /* TODO: start new key exchange on return */
1115 GNUNET_break_op (0);
1116 LOG (GNUNET_ERROR_TYPE_WARNING,
1117 "Got message %u, expected %u+\n",
1118 Np,
1119 ax->Nr);
1120 return GNUNET_SYSERR;
1121 }
1122 if (0 > gap)
1123 {
1124 /* Delayed message: don't store keys, flag to try old keys. */
1125 return GNUNET_SYSERR;
1126 }
1127
1128 while (ax->Nr < Np)
1129 store_skipped_key (ax,
1130 HKr);
1131
1132 while (ax->skipped > MAX_SKIPPED_KEYS)
1133 delete_skipped_key (ax,
1134 ax->skipped_tail);
1135 return GNUNET_OK;
1136}
1137
1138
1139/**
1140 * Decrypt and verify data with the appropriate tunnel key and verify that the
1141 * data has not been altered since it was sent by the remote peer.
1142 *
1143 * @param ax key material to use
1144 * @param dst Destination for the plaintext.
1145 * @param src Source of the message. Can overlap with @c dst.
1146 * @param size Size of the message.
1147 * @return Size of the decrypted data, -1 if an error was encountered.
1148 */
1149static ssize_t
1150t_ax_decrypt_and_validate (struct CadetTunnelAxolotl *ax,
1151 void *dst,
1152 const struct
1153 GNUNET_CADET_TunnelEncryptedMessage *src,
1154 size_t size)
1155{
1156 struct GNUNET_ShortHashCode msg_hmac;
1157 struct GNUNET_HashCode hmac;
1158 struct GNUNET_CADET_TunnelEncryptedMessage plaintext_header;
1159 uint32_t Np;
1160 uint32_t PNp;
1161 size_t esize; /* Size of encryped payload */
1162
1163 esize = size - sizeof(struct GNUNET_CADET_TunnelEncryptedMessage);
1164
1165 /* Try current HK */
1166 t_hmac (&src->ax_header,
1167 sizeof(struct GNUNET_CADET_AxHeader) + esize,
1168 0, &ax->HKr,
1169 &msg_hmac);
1170 if (0 != GNUNET_memcmp (&msg_hmac,
1171 &src->hmac))
1172 {
1173 static const char ctx[] = "axolotl ratchet";
1174 struct GNUNET_CRYPTO_SymmetricSessionKey keys[3]; /* RKp, NHKp, CKp */
1175 struct GNUNET_CRYPTO_SymmetricSessionKey HK;
1176 struct GNUNET_HashCode dh;
1177 struct GNUNET_CRYPTO_EcdhePublicKey *DHRp;
1178
1179 /* Try Next HK */
1180 t_hmac (&src->ax_header,
1181 sizeof(struct GNUNET_CADET_AxHeader) + esize,
1182 0,
1183 &ax->NHKr,
1184 &msg_hmac);
1185 if (0 != GNUNET_memcmp (&msg_hmac,
1186 &src->hmac))
1187 {
1188 /* Try the skipped keys, if that fails, we're out of luck. */
1189 return try_old_ax_keys (ax,
1190 dst,
1191 src,
1192 size);
1193 }
1194 HK = ax->HKr;
1195 ax->HKr = ax->NHKr;
1196 t_h_decrypt (ax,
1197 src,
1198 &plaintext_header);
1199 Np = ntohl (plaintext_header.ax_header.Ns);
1200 PNp = ntohl (plaintext_header.ax_header.PNs);
1201 DHRp = &plaintext_header.ax_header.DHRs;
1202 store_ax_keys (ax,
1203 &HK,
1204 PNp);
1205
1206 /* RKp, NHKp, CKp = KDF (HMAC-HASH (RK, DH (DHRp, DHRs))) */
1207 GNUNET_CRYPTO_ecc_ecdh (&ax->DHRs,
1208 DHRp,
1209 &dh);
1210 t_ax_hmac_hash (&ax->RK,
1211 &hmac,
1212 &dh, sizeof(dh));
1213 GNUNET_CRYPTO_kdf (keys, sizeof(keys),
1214 ctx, sizeof(ctx),
1215 &hmac, sizeof(hmac),
1216 NULL);
1217
1218 /* Commit "purported" keys */
1219 ax->RK = keys[0];
1220 ax->NHKr = keys[1];
1221 ax->CKr = keys[2];
1222 ax->DHRr = *DHRp;
1223 ax->Nr = 0;
1224 ax->ratchet_allowed = GNUNET_YES;
1225 }
1226 else
1227 {
1228 t_h_decrypt (ax,
1229 src,
1230 &plaintext_header);
1231 Np = ntohl (plaintext_header.ax_header.Ns);
1232 PNp = ntohl (plaintext_header.ax_header.PNs);
1233 }
1234 if ((Np != ax->Nr) &&
1235 (GNUNET_OK != store_ax_keys (ax,
1236 &ax->HKr,
1237 Np)))
1238 {
1239 /* Try the skipped keys, if that fails, we're out of luck. */
1240 return try_old_ax_keys (ax,
1241 dst,
1242 src,
1243 size);
1244 }
1245
1246 t_ax_decrypt (ax,
1247 dst,
1248 &src[1],
1249 esize);
1250 ax->Nr = Np + 1;
1251 return esize;
1252}
1253
1254
1255/**
1256 * Our tunnel became ready for the first time, notify channels
1257 * that have been waiting.
1258 *
1259 * @param cls our tunnel, not used
1260 * @param key unique ID of the channel, not used
1261 * @param value the `struct CadetChannel` to notify
1262 * @return #GNUNET_OK (continue to iterate)
1263 */
1264static int
1265notify_tunnel_up_cb (void *cls,
1266 uint32_t key,
1267 void *value)
1268{
1269 struct CadetChannel *ch = value;
1270
1271 GCCH_tunnel_up (ch);
1272 return GNUNET_OK;
1273}
1274
1275
1276/**
1277 * Change the tunnel encryption state.
1278 * If the encryption state changes to OK, stop the rekey task.
1279 *
1280 * @param t Tunnel whose encryption state to change, or NULL.
1281 * @param state New encryption state.
1282 */
1283void
1284GCT_change_estate (struct CadetTunnel *t,
1285 enum CadetTunnelEState state)
1286{
1287 enum CadetTunnelEState old = t->estate;
1288
1289 t->estate = state;
1290 LOG (GNUNET_ERROR_TYPE_DEBUG,
1291 "%s estate changed from %s to %s\n",
1292 GCT_2s (t),
1293 estate2s (old),
1294 estate2s (state));
1295
1296 if ((CADET_TUNNEL_KEY_OK != old) &&
1297 (CADET_TUNNEL_KEY_OK == t->estate))
1298 {
1299 if (NULL != t->kx_task)
1300 {
1301 GNUNET_SCHEDULER_cancel (t->kx_task);
1302 t->kx_task = NULL;
1303 }
1304 /* notify all channels that have been waiting */
1305 GNUNET_CONTAINER_multihashmap32_iterate (t->channels,
1306 &notify_tunnel_up_cb,
1307 t);
1308 if (NULL != t->send_task)
1309 GNUNET_SCHEDULER_cancel (t->send_task);
1310 t->send_task = GNUNET_SCHEDULER_add_now (&trigger_transmissions,
1311 t);
1312 }
1313}
1314
1315
1316/**
1317 * Send a KX message.
1318 *
1319 * @param t tunnel on which to send the KX_AUTH
1320 * @param ct Tunnel and connection on which to send the KX_AUTH, NULL if
1321 * we are to find one that is ready.
1322 * @param ax axolotl key context to use
1323 */
1324static void
1325send_kx (struct CadetTunnel *t,
1326 struct CadetTConnection *ct,
1327 struct CadetTunnelAxolotl *ax)
1328{
1329 struct CadetConnection *cc;
1330 struct GNUNET_MQ_Envelope *env;
1331 struct GNUNET_CADET_TunnelKeyExchangeMessage *msg;
1332 enum GNUNET_CADET_KX_Flags flags;
1333
1334 if (GNUNET_YES != GCT_alice_or_betty (GCP_get_id (t->destination)))
1335 return; /* only Alice may send KX */
1336 if ((NULL == ct) ||
1337 (GNUNET_NO == ct->is_ready))
1338 ct = get_ready_connection (t);
1339 if (NULL == ct)
1340 {
1341 LOG (GNUNET_ERROR_TYPE_DEBUG,
1342 "Wanted to send %s in state %s, but no connection is ready, deferring\n",
1343 GCT_2s (t),
1344 estate2s (t->estate));
1345 t->next_kx_attempt = GNUNET_TIME_absolute_get ();
1346 return;
1347 }
1348 cc = ct->cc;
1349 env = GNUNET_MQ_msg (msg,
1350 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX);
1351 flags = GNUNET_CADET_KX_FLAG_FORCE_REPLY; /* always for KX */
1352 msg->flags = htonl (flags);
1353 msg->cid = *GCC_get_id (cc);
1354 GNUNET_CRYPTO_ecdhe_key_get_public (&ax->kx_0,
1355 &msg->ephemeral_key);
1356#if DEBUG_KX
1357 msg->ephemeral_key_XXX = ax->kx_0;
1358 msg->private_key_XXX = *my_private_key;
1359#endif
1360 LOG (GNUNET_ERROR_TYPE_DEBUG,
1361 "Sending KX message to %s with ephemeral %s on CID %s\n",
1362 GCT_2s (t),
1363 GNUNET_e2s (&msg->ephemeral_key),
1364 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
1365 GNUNET_CRYPTO_ecdhe_key_get_public (&ax->DHRs,
1366 &msg->ratchet_key);
1367 mark_connection_unready (ct);
1368 t->kx_retry_delay = GNUNET_TIME_STD_BACKOFF (t->kx_retry_delay);
1369 t->next_kx_attempt = GNUNET_TIME_relative_to_absolute (t->kx_retry_delay);
1370 if (CADET_TUNNEL_KEY_UNINITIALIZED == t->estate)
1371 GCT_change_estate (t,
1372 CADET_TUNNEL_KEY_AX_SENT);
1373 else if (CADET_TUNNEL_KEY_AX_RECV == t->estate)
1374 GCT_change_estate (t,
1375 CADET_TUNNEL_KEY_AX_SENT_AND_RECV);
1376 GCC_transmit (cc,
1377 env);
1378 GNUNET_STATISTICS_update (stats,
1379 "# KX transmitted",
1380 1,
1381 GNUNET_NO);
1382}
1383
1384
1385/**
1386 * Send a KX_AUTH message.
1387 *
1388 * @param t tunnel on which to send the KX_AUTH
1389 * @param ct Tunnel and connection on which to send the KX_AUTH, NULL if
1390 * we are to find one that is ready.
1391 * @param ax axolotl key context to use
1392 * @param force_reply Force the other peer to reply with a KX_AUTH message
1393 * (set if we would like to transmit right now, but cannot)
1394 */
1395static void
1396send_kx_auth (struct CadetTunnel *t,
1397 struct CadetTConnection *ct,
1398 struct CadetTunnelAxolotl *ax,
1399 int force_reply)
1400{
1401 struct CadetConnection *cc;
1402 struct GNUNET_MQ_Envelope *env;
1403 struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg;
1404 enum GNUNET_CADET_KX_Flags flags;
1405
1406 if ((NULL == ct) ||
1407 (GNUNET_NO == ct->is_ready))
1408 ct = get_ready_connection (t);
1409 if (NULL == ct)
1410 {
1411 LOG (GNUNET_ERROR_TYPE_DEBUG,
1412 "Wanted to send KX_AUTH on %s, but no connection is ready, deferring\n",
1413 GCT_2s (t));
1414 t->next_kx_attempt = GNUNET_TIME_absolute_get ();
1415 t->kx_auth_requested = GNUNET_YES; /* queue KX_AUTH independent of estate */
1416 return;
1417 }
1418 t->kx_auth_requested = GNUNET_NO; /* clear flag */
1419 cc = ct->cc;
1420 env = GNUNET_MQ_msg (msg,
1421 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX_AUTH);
1422 flags = GNUNET_CADET_KX_FLAG_NONE;
1423 if (GNUNET_YES == force_reply)
1424 flags |= GNUNET_CADET_KX_FLAG_FORCE_REPLY;
1425 msg->kx.flags = htonl (flags);
1426 msg->kx.cid = *GCC_get_id (cc);
1427 GNUNET_CRYPTO_ecdhe_key_get_public (&ax->kx_0,
1428 &msg->kx.ephemeral_key);
1429 GNUNET_CRYPTO_ecdhe_key_get_public (&ax->DHRs,
1430 &msg->kx.ratchet_key);
1431#if DEBUG_KX
1432 msg->kx.ephemeral_key_XXX = ax->kx_0;
1433 msg->kx.private_key_XXX = *my_private_key;
1434 msg->r_ephemeral_key_XXX = ax->last_ephemeral;
1435#endif
1436 LOG (GNUNET_ERROR_TYPE_DEBUG,
1437 "Sending KX_AUTH message to %s with ephemeral %s on CID %s\n",
1438 GCT_2s (t),
1439 GNUNET_e2s (&msg->kx.ephemeral_key),
1440 GNUNET_sh2s (&msg->kx.cid.connection_of_tunnel));
1441
1442 /* Compute authenticator (this is the main difference to #send_kx()) */
1443 GNUNET_CRYPTO_hash (&ax->RK,
1444 sizeof(ax->RK),
1445 &msg->auth);
1446 /* Compute when to be triggered again; actual job will
1447 be scheduled via #connection_ready_cb() */
1448 t->kx_retry_delay
1449 = GNUNET_TIME_STD_BACKOFF (t->kx_retry_delay);
1450 t->next_kx_attempt
1451 = GNUNET_TIME_relative_to_absolute (t->kx_retry_delay);
1452
1453 /* Send via cc, mark it as unready */
1454 mark_connection_unready (ct);
1455
1456 /* Update state machine, unless we are already OK */
1457 if (CADET_TUNNEL_KEY_OK != t->estate)
1458 GCT_change_estate (t,
1459 CADET_TUNNEL_KEY_AX_AUTH_SENT);
1460 GCC_transmit (cc,
1461 env);
1462 GNUNET_STATISTICS_update (stats,
1463 "# KX_AUTH transmitted",
1464 1,
1465 GNUNET_NO);
1466}
1467
1468
1469/**
1470 * Cleanup state used by @a ax.
1471 *
1472 * @param ax state to free, but not memory of @a ax itself
1473 */
1474static void
1475cleanup_ax (struct CadetTunnelAxolotl *ax)
1476{
1477 while (NULL != ax->skipped_head)
1478 delete_skipped_key (ax,
1479 ax->skipped_head);
1480 GNUNET_assert (0 == ax->skipped);
1481 GNUNET_CRYPTO_ecdhe_key_clear (&ax->kx_0);
1482 GNUNET_CRYPTO_ecdhe_key_clear (&ax->DHRs);
1483}
1484
1485
1486/**
1487 * Update our Axolotl key state based on the KX data we received.
1488 * Computes the new chain keys, and root keys, etc, and also checks
1489 * whether this is a replay of the current chain.
1490 *
1491 * @param[in|out] axolotl chain key state to recompute
1492 * @param pid peer identity of the other peer
1493 * @param ephemeral_key ephemeral public key of the other peer
1494 * @param ratchet_key senders next ephemeral public key
1495 * @return #GNUNET_OK on success, #GNUNET_NO if the resulting
1496 * root key is already in @a ax and thus the KX is useless;
1497 * #GNUNET_SYSERR on hard errors (i.e. @a pid is #my_full_id)
1498 */
1499static int
1500update_ax_by_kx (struct CadetTunnelAxolotl *ax,
1501 const struct GNUNET_PeerIdentity *pid,
1502 const struct GNUNET_CRYPTO_EcdhePublicKey *ephemeral_key,
1503 const struct GNUNET_CRYPTO_EcdhePublicKey *ratchet_key)
1504{
1505 struct GNUNET_HashCode key_material[3];
1506 struct GNUNET_CRYPTO_SymmetricSessionKey keys[5];
1507 const char salt[] = "CADET Axolotl salt";
1508 int am_I_alice;
1509
1510 if (GNUNET_SYSERR == (am_I_alice = GCT_alice_or_betty (pid)))
1511 {
1512 GNUNET_break_op (0);
1513 return GNUNET_SYSERR;
1514 }
1515 if (0 == GNUNET_memcmp (&ax->DHRr,
1516 ratchet_key))
1517 {
1518 GNUNET_STATISTICS_update (stats,
1519 "# Ratchet key already known",
1520 1,
1521 GNUNET_NO);
1522 LOG (GNUNET_ERROR_TYPE_DEBUG,
1523 "Ratchet key already known. Ignoring KX.\n");
1524 return GNUNET_NO;
1525 }
1526
1527 ax->DHRr = *ratchet_key;
1528 ax->last_ephemeral = *ephemeral_key;
1529 /* ECDH A B0 */
1530 if (GNUNET_YES == am_I_alice)
1531 {
1532 GNUNET_CRYPTO_eddsa_ecdh (my_private_key, /* a */
1533 ephemeral_key, /* B0 */
1534 &key_material[0]);
1535 }
1536 else
1537 {
1538 GNUNET_CRYPTO_ecdh_eddsa (&ax->kx_0, /* b0 */
1539 &pid->public_key, /* A */
1540 &key_material[0]);
1541 }
1542 /* ECDH A0 B */
1543 if (GNUNET_YES == am_I_alice)
1544 {
1545 GNUNET_CRYPTO_ecdh_eddsa (&ax->kx_0, /* a0 */
1546 &pid->public_key, /* B */
1547 &key_material[1]);
1548 }
1549 else
1550 {
1551 GNUNET_CRYPTO_eddsa_ecdh (my_private_key, /* b */
1552 ephemeral_key, /* A0 */
1553 &key_material[1]);
1554 }
1555
1556 /* ECDH A0 B0 */
1557 GNUNET_CRYPTO_ecc_ecdh (&ax->kx_0, /* a0 or b0 */
1558 ephemeral_key, /* B0 or A0 */
1559 &key_material[2]);
1560 /* KDF */
1561 GNUNET_CRYPTO_kdf (keys, sizeof(keys),
1562 salt, sizeof(salt),
1563 &key_material, sizeof(key_material),
1564 NULL);
1565
1566 if (0 == memcmp (&ax->RK,
1567 &keys[0],
1568 sizeof(ax->RK)))
1569 {
1570 LOG (GNUNET_ERROR_TYPE_DEBUG,
1571 "Root key already known. Ignoring KX.\n");
1572 GNUNET_STATISTICS_update (stats,
1573 "# Root key already known",
1574 1,
1575 GNUNET_NO);
1576 return GNUNET_NO;
1577 }
1578
1579 ax->RK = keys[0];
1580 if (GNUNET_YES == am_I_alice)
1581 {
1582 ax->HKr = keys[1];
1583 ax->NHKs = keys[2];
1584 ax->NHKr = keys[3];
1585 ax->CKr = keys[4];
1586 ax->ratchet_flag = GNUNET_YES;
1587 }
1588 else
1589 {
1590 ax->HKs = keys[1];
1591 ax->NHKr = keys[2];
1592 ax->NHKs = keys[3];
1593 ax->CKs = keys[4];
1594 ax->ratchet_flag = GNUNET_NO;
1595 ax->ratchet_expiration
1596 = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
1597 ratchet_time);
1598 }
1599 return GNUNET_OK;
1600}
1601
1602
1603/**
1604 * Try to redo the KX or KX_AUTH handshake, if we can.
1605 *
1606 * @param cls the `struct CadetTunnel` to do KX for.
1607 */
1608static void
1609retry_kx (void *cls)
1610{
1611 struct CadetTunnel *t = cls;
1612 struct CadetTunnelAxolotl *ax;
1613
1614 t->kx_task = NULL;
1615 LOG (GNUNET_ERROR_TYPE_DEBUG,
1616 "Trying to make KX progress on %s in state %s\n",
1617 GCT_2s (t),
1618 estate2s (t->estate));
1619 switch (t->estate)
1620 {
1621 case CADET_TUNNEL_KEY_UNINITIALIZED: /* first attempt */
1622 case CADET_TUNNEL_KEY_AX_SENT: /* trying again */
1623 send_kx (t,
1624 NULL,
1625 &t->ax);
1626 break;
1627
1628 case CADET_TUNNEL_KEY_AX_RECV:
1629 case CADET_TUNNEL_KEY_AX_SENT_AND_RECV:
1630 /* We are responding, so only require reply
1631 if WE have a channel waiting. */
1632 if (NULL != t->unverified_ax)
1633 {
1634 /* Send AX_AUTH so we might get this one verified */
1635 ax = t->unverified_ax;
1636 }
1637 else
1638 {
1639 /* How can this be? */
1640 GNUNET_break (0);
1641 ax = &t->ax;
1642 }
1643 send_kx_auth (t,
1644 NULL,
1645 ax,
1646 (0 == GCT_count_channels (t))
1647 ? GNUNET_NO
1648 : GNUNET_YES);
1649 break;
1650
1651 case CADET_TUNNEL_KEY_AX_AUTH_SENT:
1652 /* We are responding, so only require reply
1653 if WE have a channel waiting. */
1654 if (NULL != t->unverified_ax)
1655 {
1656 /* Send AX_AUTH so we might get this one verified */
1657 ax = t->unverified_ax;
1658 }
1659 else
1660 {
1661 /* How can this be? */
1662 GNUNET_break (0);
1663 ax = &t->ax;
1664 }
1665 send_kx_auth (t,
1666 NULL,
1667 ax,
1668 (0 == GCT_count_channels (t))
1669 ? GNUNET_NO
1670 : GNUNET_YES);
1671 break;
1672
1673 case CADET_TUNNEL_KEY_OK:
1674 /* Must have been the *other* peer asking us to
1675 respond with a KX_AUTH. */
1676 if (NULL != t->unverified_ax)
1677 {
1678 /* Sending AX_AUTH in response to AX so we might get this one verified */
1679 ax = t->unverified_ax;
1680 }
1681 else
1682 {
1683 /* Sending AX_AUTH in response to AX_AUTH */
1684 ax = &t->ax;
1685 }
1686 send_kx_auth (t,
1687 NULL,
1688 ax,
1689 GNUNET_NO);
1690 break;
1691 }
1692}
1693
1694
1695void
1696GCT_handle_kx (struct CadetTConnection *ct,
1697 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
1698{
1699 struct CadetTunnel *t = ct->t;
1700 int ret;
1701
1702 GNUNET_STATISTICS_update (stats,
1703 "# KX received",
1704 1,
1705 GNUNET_NO);
1706 if (GNUNET_YES ==
1707 GCT_alice_or_betty (GCP_get_id (t->destination)))
1708 {
1709 /* Betty/Bob is not allowed to send KX! */
1710 GNUNET_break_op (0);
1711 return;
1712 }
1713 LOG (GNUNET_ERROR_TYPE_DEBUG,
1714 "Received KX message from %s with ephemeral %s from %s on connection %s\n",
1715 GCT_2s (t),
1716 GNUNET_e2s (&msg->ephemeral_key),
1717 GNUNET_i2s (GCP_get_id (t->destination)),
1718 GCC_2s (ct->cc));
1719#if 1
1720 if ((0 ==
1721 memcmp (&t->ax.DHRr,
1722 &msg->ratchet_key,
1723 sizeof(msg->ratchet_key))) &&
1724 (0 ==
1725 memcmp (&t->ax.last_ephemeral,
1726 &msg->ephemeral_key,
1727 sizeof(msg->ephemeral_key))))
1728
1729 {
1730 GNUNET_STATISTICS_update (stats,
1731 "# Duplicate KX received",
1732 1,
1733 GNUNET_NO);
1734 send_kx_auth (t,
1735 ct,
1736 &t->ax,
1737 GNUNET_NO);
1738 return;
1739 }
1740#endif
1741 /* We only keep ONE unverified KX around, so if there is an existing one,
1742 clean it up. */
1743 if (NULL != t->unverified_ax)
1744 {
1745 if ((0 ==
1746 memcmp (&t->unverified_ax->DHRr,
1747 &msg->ratchet_key,
1748 sizeof(msg->ratchet_key))) &&
1749 (0 ==
1750 memcmp (&t->unverified_ax->last_ephemeral,
1751 &msg->ephemeral_key,
1752 sizeof(msg->ephemeral_key))))
1753 {
1754 GNUNET_STATISTICS_update (stats,
1755 "# Duplicate unverified KX received",
1756 1,
1757 GNUNET_NO);
1758#if 1
1759 send_kx_auth (t,
1760 ct,
1761 t->unverified_ax,
1762 GNUNET_NO);
1763 return;
1764#endif
1765 }
1766 LOG (GNUNET_ERROR_TYPE_DEBUG,
1767 "Dropping old unverified KX state.\n");
1768 GNUNET_STATISTICS_update (stats,
1769 "# Unverified KX dropped for fresh KX",
1770 1,
1771 GNUNET_NO);
1772 GNUNET_break (NULL == t->unverified_ax->skipped_head);
1773 memset (t->unverified_ax,
1774 0,
1775 sizeof(struct CadetTunnelAxolotl));
1776 }
1777 else
1778 {
1779 LOG (GNUNET_ERROR_TYPE_DEBUG,
1780 "Creating fresh unverified KX for %s\n",
1781 GCT_2s (t));
1782 GNUNET_STATISTICS_update (stats,
1783 "# Fresh KX setup",
1784 1,
1785 GNUNET_NO);
1786 t->unverified_ax = GNUNET_new (struct CadetTunnelAxolotl);
1787 }
1788 /* Set as the 'current' RK/DHRr the one we are currently using,
1789 so that the duplicate-detection logic of
1790 #update_ax_by_kx can work. */
1791 t->unverified_ax->RK = t->ax.RK;
1792 t->unverified_ax->DHRr = t->ax.DHRr;
1793 t->unverified_ax->DHRs = t->ax.DHRs;
1794 t->unverified_ax->kx_0 = t->ax.kx_0;
1795 t->unverified_attempts = 0;
1796
1797 /* Update 'ax' by the new key material */
1798 ret = update_ax_by_kx (t->unverified_ax,
1799 GCP_get_id (t->destination),
1800 &msg->ephemeral_key,
1801 &msg->ratchet_key);
1802 GNUNET_break (GNUNET_SYSERR != ret);
1803 if (GNUNET_OK != ret)
1804 {
1805 GNUNET_STATISTICS_update (stats,
1806 "# Useless KX",
1807 1,
1808 GNUNET_NO);
1809 return; /* duplicate KX, nothing to do */
1810 }
1811 /* move ahead in our state machine */
1812 if (CADET_TUNNEL_KEY_UNINITIALIZED == t->estate)
1813 GCT_change_estate (t,
1814 CADET_TUNNEL_KEY_AX_RECV);
1815 else if (CADET_TUNNEL_KEY_AX_SENT == t->estate)
1816 GCT_change_estate (t,
1817 CADET_TUNNEL_KEY_AX_SENT_AND_RECV);
1818
1819 /* KX is still not done, try again our end. */
1820 if (CADET_TUNNEL_KEY_OK != t->estate)
1821 {
1822 if (NULL != t->kx_task)
1823 GNUNET_SCHEDULER_cancel (t->kx_task);
1824 t->kx_task
1825 = GNUNET_SCHEDULER_add_now (&retry_kx,
1826 t);
1827 }
1828}
1829
1830
1831#if DEBUG_KX
1832static void
1833check_ee (const struct GNUNET_CRYPTO_EcdhePrivateKey *e1,
1834 const struct GNUNET_CRYPTO_EcdhePrivateKey *e2)
1835{
1836 struct GNUNET_CRYPTO_EcdhePublicKey p1;
1837 struct GNUNET_CRYPTO_EcdhePublicKey p2;
1838 struct GNUNET_HashCode hc1;
1839 struct GNUNET_HashCode hc2;
1840
1841 GNUNET_CRYPTO_ecdhe_key_get_public (e1,
1842 &p1);
1843 GNUNET_CRYPTO_ecdhe_key_get_public (e2,
1844 &p2);
1845 GNUNET_assert (GNUNET_OK ==
1846 GNUNET_CRYPTO_ecc_ecdh (e1,
1847 &p2,
1848 &hc1));
1849 GNUNET_assert (GNUNET_OK ==
1850 GNUNET_CRYPTO_ecc_ecdh (e2,
1851 &p1,
1852 &hc2));
1853 GNUNET_break (0 == GNUNET_memcmp (&hc1,
1854 &hc2));
1855}
1856
1857
1858static void
1859check_ed (const struct GNUNET_CRYPTO_EcdhePrivateKey *e1,
1860 const struct GNUNET_CRYPTO_EddsaPrivateKey *e2)
1861{
1862 struct GNUNET_CRYPTO_EcdhePublicKey p1;
1863 struct GNUNET_CRYPTO_EddsaPublicKey p2;
1864 struct GNUNET_HashCode hc1;
1865 struct GNUNET_HashCode hc2;
1866
1867 GNUNET_CRYPTO_ecdhe_key_get_public (e1,
1868 &p1);
1869 GNUNET_CRYPTO_eddsa_key_get_public (e2,
1870 &p2);
1871 GNUNET_assert (GNUNET_OK ==
1872 GNUNET_CRYPTO_ecdh_eddsa (e1,
1873 &p2,
1874 &hc1));
1875 GNUNET_assert (GNUNET_OK ==
1876 GNUNET_CRYPTO_eddsa_ecdh (e2,
1877 &p1,
1878 &hc2));
1879 GNUNET_break (0 == GNUNET_memcmp (&hc1,
1880 &hc2));
1881}
1882
1883
1884static void
1885test_crypto_bug (const struct GNUNET_CRYPTO_EcdhePrivateKey *e1,
1886 const struct GNUNET_CRYPTO_EcdhePrivateKey *e2,
1887 const struct GNUNET_CRYPTO_EddsaPrivateKey *d1,
1888 const struct GNUNET_CRYPTO_EddsaPrivateKey *d2)
1889{
1890 check_ee (e1, e2);
1891 check_ed (e1, d2);
1892 check_ed (e2, d1);
1893}
1894
1895
1896#endif
1897
1898
1899/**
1900 * Handle KX_AUTH message.
1901 *
1902 * @param ct connection/tunnel combo that received encrypted message
1903 * @param msg the key exchange message
1904 */
1905void
1906GCT_handle_kx_auth (struct CadetTConnection *ct,
1907 const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg)
1908{
1909 struct CadetTunnel *t = ct->t;
1910 struct CadetTunnelAxolotl ax_tmp;
1911 struct GNUNET_HashCode kx_auth;
1912 int ret;
1913
1914 GNUNET_STATISTICS_update (stats,
1915 "# KX_AUTH received",
1916 1,
1917 GNUNET_NO);
1918 if ((CADET_TUNNEL_KEY_UNINITIALIZED == t->estate) ||
1919 (CADET_TUNNEL_KEY_AX_RECV == t->estate))
1920 {
1921 /* Confusing, we got a KX_AUTH before we even send our own
1922 KX. This should not happen. We'll send our own KX ASAP anyway,
1923 so let's ignore this here. */
1924 GNUNET_break_op (0);
1925 return;
1926 }
1927 LOG (GNUNET_ERROR_TYPE_DEBUG,
1928 "Handling KX_AUTH message from %s with ephemeral %s\n",
1929 GCT_2s (t),
1930 GNUNET_e2s (&msg->kx.ephemeral_key));
1931 /* We do everything in ax_tmp until we've checked the authentication
1932 so we don't clobber anything we care about by accident. */
1933 ax_tmp = t->ax;
1934
1935 /* Update 'ax' by the new key material */
1936 ret = update_ax_by_kx (&ax_tmp,
1937 GCP_get_id (t->destination),
1938 &msg->kx.ephemeral_key,
1939 &msg->kx.ratchet_key);
1940 if (GNUNET_OK != ret)
1941 {
1942 if (GNUNET_NO == ret)
1943 GNUNET_STATISTICS_update (stats,
1944 "# redundant KX_AUTH received",
1945 1,
1946 GNUNET_NO);
1947 else
1948 GNUNET_break (0); /* connect to self!? */
1949 return;
1950 }
1951 GNUNET_CRYPTO_hash (&ax_tmp.RK,
1952 sizeof(ax_tmp.RK),
1953 &kx_auth);
1954 if (0 != GNUNET_memcmp (&kx_auth,
1955 &msg->auth))
1956 {
1957 /* This KX_AUTH is not using the latest KX/KX_AUTH data
1958 we transmitted to the sender, refuse it, try KX again. */
1959 GNUNET_STATISTICS_update (stats,
1960 "# KX_AUTH not using our last KX received (auth failure)",
1961 1,
1962 GNUNET_NO);
1963 LOG (GNUNET_ERROR_TYPE_WARNING,
1964 "KX AUTH mismatch!\n");
1965#if DEBUG_KX
1966 {
1967 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
1968
1969 GNUNET_CRYPTO_ecdhe_key_get_public (&ax_tmp.kx_0,
1970 &ephemeral_key);
1971 if (0 != GNUNET_memcmp (&ephemeral_key,
1972 &msg->r_ephemeral_key_XXX))
1973 {
1974 LOG (GNUNET_ERROR_TYPE_WARNING,
1975 "My ephemeral is %s!\n",
1976 GNUNET_e2s (&ephemeral_key));
1977 LOG (GNUNET_ERROR_TYPE_WARNING,
1978 "Response is for ephemeral %s!\n",
1979 GNUNET_e2s (&msg->r_ephemeral_key_XXX));
1980 }
1981 else
1982 {
1983 test_crypto_bug (&ax_tmp.kx_0,
1984 &msg->kx.ephemeral_key_XXX,
1985 my_private_key,
1986 &msg->kx.private_key_XXX);
1987 }
1988 }
1989#endif
1990 if (NULL == t->kx_task)
1991 t->kx_task
1992 = GNUNET_SCHEDULER_add_at (t->next_kx_attempt,
1993 &retry_kx,
1994 t);
1995 return;
1996 }
1997 /* Yep, we're good. */
1998 t->ax = ax_tmp;
1999 if (NULL != t->unverified_ax)
2000 {
2001 /* We got some "stale" KX before, drop that. */
2002 cleanup_ax (t->unverified_ax);
2003 GNUNET_free (t->unverified_ax);
2004 t->unverified_ax = NULL;
2005 }
2006
2007 /* move ahead in our state machine */
2008 switch (t->estate)
2009 {
2010 case CADET_TUNNEL_KEY_UNINITIALIZED:
2011 case CADET_TUNNEL_KEY_AX_RECV:
2012 /* Checked above, this is impossible. */
2013 GNUNET_assert (0);
2014 break;
2015
2016 case CADET_TUNNEL_KEY_AX_SENT: /* This is the normal case */
2017 case CADET_TUNNEL_KEY_AX_SENT_AND_RECV: /* both peers started KX */
2018 case CADET_TUNNEL_KEY_AX_AUTH_SENT: /* both peers now did KX_AUTH */
2019 GCT_change_estate (t,
2020 CADET_TUNNEL_KEY_OK);
2021 break;
2022
2023 case CADET_TUNNEL_KEY_OK:
2024 /* Did not expect another KX_AUTH, but so what, still acceptable.
2025 Nothing to do here. */
2026 break;
2027 }
2028 if (0 != (GNUNET_CADET_KX_FLAG_FORCE_REPLY & ntohl (msg->kx.flags)))
2029 {
2030 send_kx_auth (t,
2031 NULL,
2032 &t->ax,
2033 GNUNET_NO);
2034 }
2035}
2036
2037
2038/* ************************************** end core crypto ***************************** */
2039
2040
2041/**
2042 * Compute the next free channel tunnel number for this tunnel.
2043 *
2044 * @param t the tunnel
2045 * @return unused number that can uniquely identify a channel in the tunnel
2046 */
2047static struct GNUNET_CADET_ChannelTunnelNumber
2048get_next_free_ctn (struct CadetTunnel *t)
2049{
2050#define HIGH_BIT 0x8000000
2051 struct GNUNET_CADET_ChannelTunnelNumber ret;
2052 uint32_t ctn;
2053 int cmp;
2054 uint32_t highbit;
2055
2056 cmp = GNUNET_memcmp (&my_full_id,
2057 GCP_get_id (GCT_get_destination (t)));
2058 if (0 < cmp)
2059 highbit = HIGH_BIT;
2060 else if (0 > cmp)
2061 highbit = 0;
2062 else
2063 GNUNET_assert (0); // loopback must never go here!
2064 ctn = ntohl (t->next_ctn.cn);
2065 while (NULL !=
2066 GNUNET_CONTAINER_multihashmap32_get (t->channels,
2067 ctn | highbit))
2068 {
2069 ctn = ((ctn + 1) & (~HIGH_BIT));
2070 }
2071 t->next_ctn.cn = htonl ((ctn + 1) & (~HIGH_BIT));
2072 ret.cn = htonl (ctn | highbit);
2073 return ret;
2074}
2075
2076
2077/**
2078 * Add a channel to a tunnel, and notify channel that we are ready
2079 * for transmission if we are already up. Otherwise that notification
2080 * will be done later in #notify_tunnel_up_cb().
2081 *
2082 * @param t Tunnel.
2083 * @param ch Channel
2084 * @return unique number identifying @a ch within @a t
2085 */
2086struct GNUNET_CADET_ChannelTunnelNumber
2087GCT_add_channel (struct CadetTunnel *t,
2088 struct CadetChannel *ch)
2089{
2090 struct GNUNET_CADET_ChannelTunnelNumber ctn;
2091
2092 ctn = get_next_free_ctn (t);
2093 if (NULL != t->destroy_task)
2094 {
2095 GNUNET_SCHEDULER_cancel (t->destroy_task);
2096 t->destroy_task = NULL;
2097 }
2098 GNUNET_assert (GNUNET_YES ==
2099 GNUNET_CONTAINER_multihashmap32_put (t->channels,
2100 ntohl (ctn.cn),
2101 ch,
2102 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
2103 LOG (GNUNET_ERROR_TYPE_DEBUG,
2104 "Adding %s to %s with state %d\n",
2105 GCCH_2s (ch),
2106 GCT_2s (t),
2107 t->estate);
2108 switch (t->estate)
2109 {
2110 case CADET_TUNNEL_KEY_UNINITIALIZED:
2111 /* waiting for connection to start KX */
2112 break;
2113
2114 case CADET_TUNNEL_KEY_AX_RECV:
2115 case CADET_TUNNEL_KEY_AX_SENT:
2116 case CADET_TUNNEL_KEY_AX_SENT_AND_RECV:
2117 /* we're currently waiting for KX to complete */
2118 break;
2119
2120 case CADET_TUNNEL_KEY_AX_AUTH_SENT:
2121 /* waiting for OTHER peer to send us data,
2122 we might need to prompt more aggressively! */
2123 if (NULL == t->kx_task)
2124 t->kx_task
2125 = GNUNET_SCHEDULER_add_at (t->next_kx_attempt,
2126 &retry_kx,
2127 t);
2128 break;
2129
2130 case CADET_TUNNEL_KEY_OK:
2131 /* We are ready. Tell the new channel that we are up. */
2132 GCCH_tunnel_up (ch);
2133 break;
2134 }
2135 return ctn;
2136}
2137
2138
2139/**
2140 * We lost a connection, remove it from our list and clean up
2141 * the connection object itself.
2142 *
2143 * @param ct binding of connection to tunnel of the connection that was lost.
2144 */
2145void
2146GCT_connection_lost (struct CadetTConnection *ct)
2147{
2148 struct CadetTunnel *t = ct->t;
2149
2150 if (GNUNET_YES == ct->is_ready)
2151 {
2152 GNUNET_CONTAINER_DLL_remove (t->connection_ready_head,
2153 t->connection_ready_tail,
2154 ct);
2155 t->num_ready_connections--;
2156 }
2157 else
2158 {
2159 GNUNET_CONTAINER_DLL_remove (t->connection_busy_head,
2160 t->connection_busy_tail,
2161 ct);
2162 t->num_busy_connections--;
2163 }
2164 GNUNET_free (ct);
2165}
2166
2167
2168/**
2169 * Clean up connection @a ct of a tunnel.
2170 *
2171 * @param cls the `struct CadetTunnel`
2172 * @param ct connection to clean up
2173 */
2174static void
2175destroy_t_connection (void *cls,
2176 struct CadetTConnection *ct)
2177{
2178 struct CadetTunnel *t = cls;
2179 struct CadetConnection *cc = ct->cc;
2180
2181 GNUNET_assert (ct->t == t);
2182 GCT_connection_lost (ct);
2183 GCC_destroy_without_tunnel (cc);
2184}
2185
2186
2187/**
2188 * This tunnel is no longer used, destroy it.
2189 *
2190 * @param cls the idle tunnel
2191 */
2192static void
2193destroy_tunnel (void *cls)
2194{
2195 struct CadetTunnel *t = cls;
2196 struct CadetTunnelQueueEntry *tq;
2197
2198 t->destroy_task = NULL;
2199 LOG (GNUNET_ERROR_TYPE_DEBUG,
2200 "Destroying idle %s\n",
2201 GCT_2s (t));
2202 GNUNET_assert (0 == GCT_count_channels (t));
2203 GCT_iterate_connections (t,
2204 &destroy_t_connection,
2205 t);
2206 GNUNET_assert (NULL == t->connection_ready_head);
2207 GNUNET_assert (NULL == t->connection_busy_head);
2208 while (NULL != (tq = t->tq_head))
2209 {
2210 if (NULL != tq->cont)
2211 tq->cont (tq->cont_cls,
2212 NULL);
2213 GCT_send_cancel (tq);
2214 }
2215 GCP_drop_tunnel (t->destination,
2216 t);
2217 GNUNET_CONTAINER_multihashmap32_destroy (t->channels);
2218 if (NULL != t->maintain_connections_task)
2219 {
2220 GNUNET_SCHEDULER_cancel (t->maintain_connections_task);
2221 t->maintain_connections_task = NULL;
2222 }
2223 if (NULL != t->send_task)
2224 {
2225 GNUNET_SCHEDULER_cancel (t->send_task);
2226 t->send_task = NULL;
2227 }
2228 if (NULL != t->kx_task)
2229 {
2230 GNUNET_SCHEDULER_cancel (t->kx_task);
2231 t->kx_task = NULL;
2232 }
2233 GNUNET_MST_destroy (t->mst);
2234 GNUNET_MQ_destroy (t->mq);
2235 if (NULL != t->unverified_ax)
2236 {
2237 cleanup_ax (t->unverified_ax);
2238 GNUNET_free (t->unverified_ax);
2239 }
2240 cleanup_ax (&t->ax);
2241 GNUNET_assert (NULL == t->destroy_task);
2242 GNUNET_free (t);
2243}
2244
2245
2246/**
2247 * Remove a channel from a tunnel.
2248 *
2249 * @param t Tunnel.
2250 * @param ch Channel
2251 * @param ctn unique number identifying @a ch within @a t
2252 */
2253void
2254GCT_remove_channel (struct CadetTunnel *t,
2255 struct CadetChannel *ch,
2256 struct GNUNET_CADET_ChannelTunnelNumber ctn)
2257{
2258 LOG (GNUNET_ERROR_TYPE_DEBUG,
2259 "Removing %s from %s\n",
2260 GCCH_2s (ch),
2261 GCT_2s (t));
2262 GNUNET_assert (GNUNET_YES ==
2263 GNUNET_CONTAINER_multihashmap32_remove (t->channels,
2264 ntohl (ctn.cn),
2265 ch));
2266 if ((0 ==
2267 GCT_count_channels (t)) &&
2268 (NULL == t->destroy_task))
2269 {
2270 t->destroy_task
2271 = GNUNET_SCHEDULER_add_delayed (IDLE_DESTROY_DELAY,
2272 &destroy_tunnel,
2273 t);
2274 }
2275}
2276
2277
2278/**
2279 * Destroy remaining channels during shutdown.
2280 *
2281 * @param cls the `struct CadetTunnel` of the channel
2282 * @param key key of the channel
2283 * @param value the `struct CadetChannel`
2284 * @return #GNUNET_OK (continue to iterate)
2285 */
2286static int
2287destroy_remaining_channels (void *cls,
2288 uint32_t key,
2289 void *value)
2290{
2291 struct CadetChannel *ch = value;
2292
2293 GCCH_handle_remote_destroy (ch,
2294 NULL);
2295 return GNUNET_OK;
2296}
2297
2298
2299/**
2300 * Destroys the tunnel @a t now, without delay. Used during shutdown.
2301 *
2302 * @param t tunnel to destroy
2303 */
2304void
2305GCT_destroy_tunnel_now (struct CadetTunnel *t)
2306{
2307 GNUNET_assert (GNUNET_YES == shutting_down);
2308 GNUNET_CONTAINER_multihashmap32_iterate (t->channels,
2309 &destroy_remaining_channels,
2310 t);
2311 GNUNET_assert (0 ==
2312 GCT_count_channels (t));
2313 if (NULL != t->destroy_task)
2314 {
2315 GNUNET_SCHEDULER_cancel (t->destroy_task);
2316 t->destroy_task = NULL;
2317 }
2318 destroy_tunnel (t);
2319}
2320
2321
2322/**
2323 * Send normal payload from queue in @a t via connection @a ct.
2324 * Does nothing if our payload queue is empty.
2325 *
2326 * @param t tunnel to send data from
2327 * @param ct connection to use for transmission (is ready)
2328 */
2329static void
2330try_send_normal_payload (struct CadetTunnel *t,
2331 struct CadetTConnection *ct)
2332{
2333 struct CadetTunnelQueueEntry *tq;
2334
2335 GNUNET_assert (GNUNET_YES == ct->is_ready);
2336 tq = t->tq_head;
2337 if (NULL == tq)
2338 {
2339 /* no messages pending right now */
2340 LOG (GNUNET_ERROR_TYPE_DEBUG,
2341 "Not sending payload of %s on ready %s (nothing pending)\n",
2342 GCT_2s (t),
2343 GCC_2s (ct->cc));
2344 return;
2345 }
2346 /* ready to send message 'tq' on tunnel 'ct' */
2347 GNUNET_assert (t == tq->t);
2348 GNUNET_CONTAINER_DLL_remove (t->tq_head,
2349 t->tq_tail,
2350 tq);
2351 if (NULL != tq->cid)
2352 *tq->cid = *GCC_get_id (ct->cc);
2353 mark_connection_unready (ct);
2354 LOG (GNUNET_ERROR_TYPE_DEBUG,
2355 "Sending payload of %s on %s\n",
2356 GCT_2s (t),
2357 GCC_2s (ct->cc));
2358 GCC_transmit (ct->cc,
2359 tq->env);
2360 if (NULL != tq->cont)
2361 tq->cont (tq->cont_cls,
2362 GCC_get_id (ct->cc));
2363 GNUNET_free (tq);
2364}
2365
2366
2367/**
2368 * A connection is @a is_ready for transmission. Looks at our message
2369 * queue and if there is a message, sends it out via the connection.
2370 *
2371 * @param cls the `struct CadetTConnection` that is @a is_ready
2372 * @param is_ready #GNUNET_YES if connection are now ready,
2373 * #GNUNET_NO if connection are no longer ready
2374 */
2375static void
2376connection_ready_cb (void *cls,
2377 int is_ready)
2378{
2379 struct CadetTConnection *ct = cls;
2380 struct CadetTunnel *t = ct->t;
2381
2382 if (GNUNET_NO == is_ready)
2383 {
2384 LOG (GNUNET_ERROR_TYPE_DEBUG,
2385 "%s no longer ready for %s\n",
2386 GCC_2s (ct->cc),
2387 GCT_2s (t));
2388 mark_connection_unready (ct);
2389 return;
2390 }
2391 GNUNET_assert (GNUNET_NO == ct->is_ready);
2392 GNUNET_CONTAINER_DLL_remove (t->connection_busy_head,
2393 t->connection_busy_tail,
2394 ct);
2395 GNUNET_assert (0 < t->num_busy_connections);
2396 t->num_busy_connections--;
2397 ct->is_ready = GNUNET_YES;
2398 GNUNET_CONTAINER_DLL_insert_tail (t->connection_ready_head,
2399 t->connection_ready_tail,
2400 ct);
2401 t->num_ready_connections++;
2402
2403 LOG (GNUNET_ERROR_TYPE_DEBUG,
2404 "%s now ready for %s in state %s\n",
2405 GCC_2s (ct->cc),
2406 GCT_2s (t),
2407 estate2s (t->estate));
2408 switch (t->estate)
2409 {
2410 case CADET_TUNNEL_KEY_UNINITIALIZED:
2411 LOG (GNUNET_ERROR_TYPE_DEBUG,
2412 "Do not begin KX for %s if WE have no channels waiting. Retrying after %llu\n",
2413 GCT_2s (t),
2414 (unsigned long long) GNUNET_TIME_absolute_get_remaining (
2415 t->next_kx_attempt).rel_value_us);
2416 /* Do not begin KX if WE have no channels waiting! */
2417 if (0 != GNUNET_TIME_absolute_get_remaining (
2418 t->next_kx_attempt).rel_value_us)
2419 return; /* wait for timeout before retrying */
2420 /* We are uninitialized, just transmit immediately,
2421 without undue delay. */
2422
2423 LOG (GNUNET_ERROR_TYPE_DEBUG,
2424 "Why for %s \n",
2425 GCT_2s (t));
2426
2427 if (NULL != t->kx_task)
2428 {
2429 GNUNET_SCHEDULER_cancel (t->kx_task);
2430 t->kx_task = NULL;
2431 }
2432 send_kx (t,
2433 ct,
2434 &t->ax);
2435 if ((0 ==
2436 GCT_count_channels (t)) &&
2437 (NULL == t->destroy_task))
2438 {
2439 t->destroy_task
2440 = GNUNET_SCHEDULER_add_delayed (IDLE_DESTROY_DELAY,
2441 &destroy_tunnel,
2442 t);
2443 }
2444 break;
2445
2446 case CADET_TUNNEL_KEY_AX_RECV:
2447 case CADET_TUNNEL_KEY_AX_SENT:
2448 case CADET_TUNNEL_KEY_AX_SENT_AND_RECV:
2449 case CADET_TUNNEL_KEY_AX_AUTH_SENT:
2450 /* we're currently waiting for KX to complete, schedule job */
2451 if (NULL == t->kx_task)
2452 t->kx_task
2453 = GNUNET_SCHEDULER_add_at (t->next_kx_attempt,
2454 &retry_kx,
2455 t);
2456 break;
2457
2458 case CADET_TUNNEL_KEY_OK:
2459 if (GNUNET_YES == t->kx_auth_requested)
2460 {
2461 if (0 != GNUNET_TIME_absolute_get_remaining (
2462 t->next_kx_attempt).rel_value_us)
2463 return; /* wait for timeout */
2464 if (NULL != t->kx_task)
2465 {
2466 GNUNET_SCHEDULER_cancel (t->kx_task);
2467 t->kx_task = NULL;
2468 }
2469 send_kx_auth (t,
2470 ct,
2471 &t->ax,
2472 GNUNET_NO);
2473 return;
2474 }
2475 try_send_normal_payload (t,
2476 ct);
2477 break;
2478 }
2479}
2480
2481
2482/**
2483 * Called when either we have a new connection, or a new message in the
2484 * queue, or some existing connection has transmission capacity. Looks
2485 * at our message queue and if there is a message, picks a connection
2486 * to send it on.
2487 *
2488 * @param cls the `struct CadetTunnel` to process messages on
2489 */
2490static void
2491trigger_transmissions (void *cls)
2492{
2493 struct CadetTunnel *t = cls;
2494 struct CadetTConnection *ct;
2495
2496 t->send_task = NULL;
2497 if (NULL == t->tq_head)
2498 return; /* no messages pending right now */
2499 ct = get_ready_connection (t);
2500 if (NULL == ct)
2501 return; /* no connections ready */
2502 try_send_normal_payload (t,
2503 ct);
2504}
2505
2506
2507/**
2508 * Closure for #evaluate_connection. Used to assemble summary information
2509 * about the existing connections so we can evaluate a new path.
2510 */
2511struct EvaluationSummary
2512{
2513 /**
2514 * Minimum length of any of our connections, `UINT_MAX` if we have none.
2515 */
2516 unsigned int min_length;
2517
2518 /**
2519 * Maximum length of any of our connections, 0 if we have none.
2520 */
2521 unsigned int max_length;
2522
2523 /**
2524 * Minimum desirability of any of our connections, UINT64_MAX if we have none.
2525 */
2526 GNUNET_CONTAINER_HeapCostType min_desire;
2527
2528 /**
2529 * Maximum desirability of any of our connections, 0 if we have none.
2530 */
2531 GNUNET_CONTAINER_HeapCostType max_desire;
2532
2533 /**
2534 * Path we are comparing against for #evaluate_connection, can be NULL.
2535 */
2536 struct CadetPeerPath *path;
2537
2538 /**
2539 * Connection deemed the "worst" so far encountered by #evaluate_connection,
2540 * NULL if we did not yet encounter any connections.
2541 */
2542 struct CadetTConnection *worst;
2543
2544 /**
2545 * Numeric score of @e worst, only set if @e worst is non-NULL.
2546 */
2547 double worst_score;
2548
2549 /**
2550 * Set to #GNUNET_YES if we have a connection over @e path already.
2551 */
2552 int duplicate;
2553};
2554
2555
2556/**
2557 * Evaluate a connection, updating our summary information in @a cls about
2558 * what kinds of connections we have.
2559 *
2560 * @param cls the `struct EvaluationSummary *` to update
2561 * @param ct a connection to include in the summary
2562 */
2563static void
2564evaluate_connection (void *cls,
2565 struct CadetTConnection *ct)
2566{
2567 struct EvaluationSummary *es = cls;
2568 struct CadetConnection *cc = ct->cc;
2569 unsigned int ct_length;
2570 struct CadetPeerPath *ps;
2571 const struct CadetConnectionMetrics *metrics;
2572 GNUNET_CONTAINER_HeapCostType ct_desirability;
2573 struct GNUNET_TIME_Relative uptime;
2574 struct GNUNET_TIME_Relative last_use;
2575 double score;
2576 double success_rate;
2577
2578 ps = GCC_get_path (cc,
2579 &ct_length);
2580 LOG (GNUNET_ERROR_TYPE_DEBUG,
2581 "Evaluating path %s of existing %s\n",
2582 GCPP_2s (ps),
2583 GCC_2s (cc));
2584 if (ps == es->path)
2585 {
2586 LOG (GNUNET_ERROR_TYPE_DEBUG,
2587 "Ignoring duplicate path %s.\n",
2588 GCPP_2s (es->path));
2589 es->duplicate = GNUNET_YES;
2590 return;
2591 }
2592 if (NULL != es->path)
2593 {
2594 int duplicate = GNUNET_YES;
2595
2596 for (unsigned int i = 0; i < ct_length; i++)
2597 {
2598 GNUNET_assert (GCPP_get_length (es->path) > i);
2599 if (GCPP_get_peer_at_offset (es->path,
2600 i) !=
2601 GCPP_get_peer_at_offset (ps,
2602 i))
2603 {
2604 duplicate = GNUNET_NO;
2605 break;
2606 }
2607 }
2608 if (GNUNET_YES == duplicate)
2609 {
2610 LOG (GNUNET_ERROR_TYPE_DEBUG,
2611 "Ignoring overlapping path %s.\n",
2612 GCPP_2s (es->path));
2613 es->duplicate = GNUNET_YES;
2614 return;
2615 }
2616 else
2617 {
2618 LOG (GNUNET_ERROR_TYPE_DEBUG,
2619 "Known path %s differs from proposed path\n",
2620 GCPP_2s (ps));
2621 }
2622 }
2623
2624 ct_desirability = GCPP_get_desirability (ps);
2625 metrics = GCC_get_metrics (cc);
2626 uptime = GNUNET_TIME_absolute_get_duration (metrics->age);
2627 last_use = GNUNET_TIME_absolute_get_duration (metrics->last_use);
2628 /* We add 1.0 here to avoid division by zero. */
2629 success_rate = (metrics->num_acked_transmissions + 1.0)
2630 / (metrics->num_successes + 1.0);
2631 score
2632 = ct_desirability
2633 + 100.0 / (1.0 + ct_length) /* longer paths = better */
2634 + sqrt (uptime.rel_value_us / 60000000LL) /* larger uptime = better */
2635 - last_use.rel_value_us / 1000L; /* longer idle = worse */
2636 score *= success_rate; /* weigh overall by success rate */
2637
2638 if ((NULL == es->worst) ||
2639 (score < es->worst_score))
2640 {
2641 es->worst = ct;
2642 es->worst_score = score;
2643 }
2644 es->min_length = GNUNET_MIN (es->min_length,
2645 ct_length);
2646 es->max_length = GNUNET_MAX (es->max_length,
2647 ct_length);
2648 es->min_desire = GNUNET_MIN (es->min_desire,
2649 ct_desirability);
2650 es->max_desire = GNUNET_MAX (es->max_desire,
2651 ct_desirability);
2652}
2653
2654
2655/**
2656 * Consider using the path @a p for the tunnel @a t.
2657 * The tunnel destination is at offset @a off in path @a p.
2658 *
2659 * @param cls our tunnel
2660 * @param path a path to our destination
2661 * @param off offset of the destination on path @a path
2662 * @return #GNUNET_YES (should keep iterating)
2663 */
2664static int
2665consider_path_cb (void *cls,
2666 struct CadetPeerPath *path,
2667 unsigned int off)
2668{
2669 struct CadetTunnel *t = cls;
2670 struct EvaluationSummary es;
2671 struct CadetTConnection *ct;
2672
2673 GNUNET_assert (off < GCPP_get_length (path));
2674 GNUNET_assert (GCPP_get_peer_at_offset (path,
2675 off) == t->destination);
2676 es.min_length = UINT_MAX;
2677 es.max_length = 0;
2678 es.max_desire = 0;
2679 es.min_desire = UINT64_MAX;
2680 es.path = path;
2681 es.duplicate = GNUNET_NO;
2682 es.worst = NULL;
2683
2684 /* Compute evaluation summary over existing connections. */
2685 LOG (GNUNET_ERROR_TYPE_DEBUG,
2686 "Evaluating proposed path %s for target %s\n",
2687 GCPP_2s (path),
2688 GCT_2s (t));
2689 /* FIXME: suspect this does not ACTUALLY iterate
2690 over all existing paths, otherwise dup detection
2691 should work!!! */
2692 GCT_iterate_connections (t,
2693 &evaluate_connection,
2694 &es);
2695 if (GNUNET_YES == es.duplicate)
2696 return GNUNET_YES;
2697
2698 /* FIXME: not sure we should really just count
2699 'num_connections' here, as they may all have
2700 consistently failed to connect. */
2701
2702 /* We iterate by increasing path length; if we have enough paths and
2703 this one is more than twice as long than what we are currently
2704 using, then ignore all of these super-long ones! */
2705 if ((GCT_count_any_connections (t) > DESIRED_CONNECTIONS_PER_TUNNEL) &&
2706 (es.min_length * 2 < off) &&
2707 (es.max_length < off))
2708 {
2709 LOG (GNUNET_ERROR_TYPE_DEBUG,
2710 "Ignoring paths of length %u, they are way too long.\n",
2711 es.min_length * 2);
2712 return GNUNET_NO;
2713 }
2714 /* If we have enough paths and this one looks no better, ignore it. */
2715 if ((GCT_count_any_connections (t) >= DESIRED_CONNECTIONS_PER_TUNNEL) &&
2716 (es.min_length < GCPP_get_length (path)) &&
2717 (es.min_desire > GCPP_get_desirability (path)) &&
2718 (es.max_length < off))
2719 {
2720 LOG (GNUNET_ERROR_TYPE_DEBUG,
2721 "Ignoring path (%u/%llu) to %s, got something better already.\n",
2722 GCPP_get_length (path),
2723 (unsigned long long) GCPP_get_desirability (path),
2724 GCP_2s (t->destination));
2725 return GNUNET_YES;
2726 }
2727
2728 /* Path is interesting (better by some metric, or we don't have
2729 enough paths yet). */
2730 ct = GNUNET_new (struct CadetTConnection);
2731 ct->created = GNUNET_TIME_absolute_get ();
2732 ct->t = t;
2733 ct->cc = GCC_create (t->destination,
2734 path,
2735 off,
2736 ct,
2737 &connection_ready_cb,
2738 ct);
2739
2740 /* FIXME: schedule job to kill connection (and path?) if it takes
2741 too long to get ready! (And track performance data on how long
2742 other connections took with the tunnel!)
2743 => Note: to be done within 'connection'-logic! */
2744 GNUNET_CONTAINER_DLL_insert (t->connection_busy_head,
2745 t->connection_busy_tail,
2746 ct);
2747 t->num_busy_connections++;
2748 LOG (GNUNET_ERROR_TYPE_DEBUG,
2749 "Found interesting path %s for %s, created %s\n",
2750 GCPP_2s (path),
2751 GCT_2s (t),
2752 GCC_2s (ct->cc));
2753 return GNUNET_YES;
2754}
2755
2756
2757/**
2758 * Function called to maintain the connections underlying our tunnel.
2759 * Tries to maintain (incl. tear down) connections for the tunnel, and
2760 * if there is a significant change, may trigger transmissions.
2761 *
2762 * Basically, needs to check if there are connections that perform
2763 * badly, and if so eventually kill them and trigger a replacement.
2764 * The strategy is to open one more connection than
2765 * #DESIRED_CONNECTIONS_PER_TUNNEL, and then periodically kick out the
2766 * least-performing one, and then inquire for new ones.
2767 *
2768 * @param cls the `struct CadetTunnel`
2769 */
2770static void
2771maintain_connections_cb (void *cls)
2772{
2773 struct CadetTunnel *t = cls;
2774 struct GNUNET_TIME_Relative delay;
2775 struct EvaluationSummary es;
2776
2777 t->maintain_connections_task = NULL;
2778 LOG (GNUNET_ERROR_TYPE_DEBUG,
2779 "Performing connection maintenance for %s.\n",
2780 GCT_2s (t));
2781
2782 es.min_length = UINT_MAX;
2783 es.max_length = 0;
2784 es.max_desire = 0;
2785 es.min_desire = UINT64_MAX;
2786 es.path = NULL;
2787 es.worst = NULL;
2788 es.duplicate = GNUNET_NO;
2789 GCT_iterate_connections (t,
2790 &evaluate_connection,
2791 &es);
2792 if ((NULL != es.worst) &&
2793 (GCT_count_any_connections (t) > DESIRED_CONNECTIONS_PER_TUNNEL))
2794 {
2795 /* Clear out worst-performing connection 'es.worst'. */
2796 destroy_t_connection (t,
2797 es.worst);
2798 }
2799
2800 /* Consider additional paths */
2801 (void) GCP_iterate_paths (t->destination,
2802 &consider_path_cb,
2803 t);
2804
2805 /* FIXME: calculate when to try again based on how well we are doing;
2806 in particular, if we have to few connections, we might be able
2807 to do without this (as PATHS should tell us whenever a new path
2808 is available instantly; however, need to make sure this job is
2809 restarted after that happens).
2810 Furthermore, if the paths we do know are in a reasonably narrow
2811 quality band and are plentyful, we might also consider us stabilized
2812 and then reduce the frequency accordingly. */delay = GNUNET_TIME_UNIT_MINUTES;
2813 t->maintain_connections_task
2814 = GNUNET_SCHEDULER_add_delayed (delay,
2815 &maintain_connections_cb,
2816 t);
2817}
2818
2819
2820void
2821GCT_consider_path (struct CadetTunnel *t,
2822 struct CadetPeerPath *p,
2823 unsigned int off)
2824{
2825 LOG (GNUNET_ERROR_TYPE_DEBUG,
2826 "Considering %s for %s (offset %u)\n",
2827 GCPP_2s (p),
2828 GCT_2s (t),
2829 off);
2830 (void) consider_path_cb (t,
2831 p,
2832 off);
2833}
2834
2835
2836/**
2837 * We got a keepalive. Track in statistics.
2838 *
2839 * @param cls the `struct CadetTunnel` for which we decrypted the message
2840 * @param msg the message we received on the tunnel
2841 */
2842static void
2843handle_plaintext_keepalive (void *cls,
2844 const struct GNUNET_MessageHeader *msg)
2845{
2846 struct CadetTunnel *t = cls;
2847
2848 LOG (GNUNET_ERROR_TYPE_DEBUG,
2849 "Received KEEPALIVE on %s\n",
2850 GCT_2s (t));
2851 GNUNET_STATISTICS_update (stats,
2852 "# keepalives received",
2853 1,
2854 GNUNET_NO);
2855}
2856
2857
2858/**
2859 * Check that @a msg is well-formed.
2860 *
2861 * @param cls the `struct CadetTunnel` for which we decrypted the message
2862 * @param msg the message we received on the tunnel
2863 * @return #GNUNET_OK (any variable-size payload goes)
2864 */
2865static int
2866check_plaintext_data (void *cls,
2867 const struct GNUNET_CADET_ChannelAppDataMessage *msg)
2868{
2869 return GNUNET_OK;
2870}
2871
2872
2873/**
2874 * We received payload data for a channel. Locate the channel
2875 * and process the data, or return an error if the channel is unknown.
2876 *
2877 * @param cls the `struct CadetTunnel` for which we decrypted the message
2878 * @param msg the message we received on the tunnel
2879 */
2880static void
2881handle_plaintext_data (void *cls,
2882 const struct GNUNET_CADET_ChannelAppDataMessage *msg)
2883{
2884 struct CadetTunnel *t = cls;
2885 struct CadetChannel *ch;
2886
2887 ch = lookup_channel (t,
2888 msg->ctn);
2889 if (NULL == ch)
2890 {
2891 /* We don't know about such a channel, might have been destroyed on our
2892 end in the meantime, or never existed. Send back a DESTROY. */
2893 LOG (GNUNET_ERROR_TYPE_DEBUG,
2894 "Received %u bytes of application data for unknown channel %u, sending DESTROY\n",
2895 (unsigned int) (ntohs (msg->header.size) - sizeof(*msg)),
2896 ntohl (msg->ctn.cn));
2897 GCT_send_channel_destroy (t,
2898 msg->ctn);
2899 return;
2900 }
2901 GCCH_handle_channel_plaintext_data (ch,
2902 GCC_get_id (t->current_ct->cc),
2903 msg);
2904}
2905
2906
2907/**
2908 * We received an acknowledgement for data we sent on a channel.
2909 * Locate the channel and process it, or return an error if the
2910 * channel is unknown.
2911 *
2912 * @param cls the `struct CadetTunnel` for which we decrypted the message
2913 * @param ack the message we received on the tunnel
2914 */
2915static void
2916handle_plaintext_data_ack (void *cls,
2917 const struct GNUNET_CADET_ChannelDataAckMessage *ack)
2918{
2919 struct CadetTunnel *t = cls;
2920 struct CadetChannel *ch;
2921
2922 ch = lookup_channel (t,
2923 ack->ctn);
2924 if (NULL == ch)
2925 {
2926 /* We don't know about such a channel, might have been destroyed on our
2927 end in the meantime, or never existed. Send back a DESTROY. */
2928 LOG (GNUNET_ERROR_TYPE_DEBUG,
2929 "Received DATA_ACK for unknown channel %u, sending DESTROY\n",
2930 ntohl (ack->ctn.cn));
2931 GCT_send_channel_destroy (t,
2932 ack->ctn);
2933 return;
2934 }
2935 GCCH_handle_channel_plaintext_data_ack (ch,
2936 GCC_get_id (t->current_ct->cc),
2937 ack);
2938}
2939
2940
2941/**
2942 * We have received a request to open a channel to a port from
2943 * another peer. Creates the incoming channel.
2944 *
2945 * @param cls the `struct CadetTunnel` for which we decrypted the message
2946 * @param copen the message we received on the tunnel
2947 */
2948static void
2949handle_plaintext_channel_open (void *cls,
2950 const struct
2951 GNUNET_CADET_ChannelOpenMessage *copen)
2952{
2953 struct CadetTunnel *t = cls;
2954 struct CadetChannel *ch;
2955
2956 ch = GNUNET_CONTAINER_multihashmap32_get (t->channels,
2957 ntohl (copen->ctn.cn));
2958 if (NULL != ch)
2959 {
2960 LOG (GNUNET_ERROR_TYPE_DEBUG,
2961 "Received duplicate channel CHANNEL_OPEN on h_port %s from %s (%s), resending ACK\n",
2962 GNUNET_h2s (&copen->h_port),
2963 GCT_2s (t),
2964 GCCH_2s (ch));
2965 GCCH_handle_duplicate_open (ch,
2966 GCC_get_id (t->current_ct->cc));
2967 return;
2968 }
2969 LOG (GNUNET_ERROR_TYPE_DEBUG,
2970 "Received CHANNEL_OPEN on h_port %s from %s\n",
2971 GNUNET_h2s (&copen->h_port),
2972 GCT_2s (t));
2973 ch = GCCH_channel_incoming_new (t,
2974 copen->ctn,
2975 &copen->h_port,
2976 ntohl (copen->opt));
2977 if (NULL != t->destroy_task)
2978 {
2979 GNUNET_SCHEDULER_cancel (t->destroy_task);
2980 t->destroy_task = NULL;
2981 }
2982 GNUNET_assert (GNUNET_OK ==
2983 GNUNET_CONTAINER_multihashmap32_put (t->channels,
2984 ntohl (copen->ctn.cn),
2985 ch,
2986 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
2987}
2988
2989
2990/**
2991 * Send a DESTROY message via the tunnel.
2992 *
2993 * @param t the tunnel to transmit over
2994 * @param ctn ID of the channel to destroy
2995 */
2996void
2997GCT_send_channel_destroy (struct CadetTunnel *t,
2998 struct GNUNET_CADET_ChannelTunnelNumber ctn)
2999{
3000 struct GNUNET_CADET_ChannelDestroyMessage msg;
3001
3002 LOG (GNUNET_ERROR_TYPE_DEBUG,
3003 "Sending DESTROY message for channel ID %u\n",
3004 ntohl (ctn.cn));
3005 msg.header.size = htons (sizeof(msg));
3006 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY);
3007 msg.reserved = htonl (0);
3008 msg.ctn = ctn;
3009 GCT_send (t,
3010 &msg.header,
3011 NULL,
3012 NULL,
3013 &ctn);
3014}
3015
3016
3017/**
3018 * We have received confirmation from the target peer that the
3019 * given channel could be established (the port is open).
3020 * Tell the client.
3021 *
3022 * @param cls the `struct CadetTunnel` for which we decrypted the message
3023 * @param cm the message we received on the tunnel
3024 */
3025static void
3026handle_plaintext_channel_open_ack (void *cls,
3027 const struct
3028 GNUNET_CADET_ChannelOpenAckMessage *cm)
3029{
3030 struct CadetTunnel *t = cls;
3031 struct CadetChannel *ch;
3032
3033 ch = lookup_channel (t,
3034 cm->ctn);
3035 if (NULL == ch)
3036 {
3037 /* We don't know about such a channel, might have been destroyed on our
3038 end in the meantime, or never existed. Send back a DESTROY. */
3039 LOG (GNUNET_ERROR_TYPE_DEBUG,
3040 "Received channel OPEN_ACK for unknown channel %u, sending DESTROY\n",
3041 ntohl (cm->ctn.cn));
3042 GCT_send_channel_destroy (t,
3043 cm->ctn);
3044 return;
3045 }
3046 LOG (GNUNET_ERROR_TYPE_DEBUG,
3047 "Received channel OPEN_ACK on channel %s from %s\n",
3048 GCCH_2s (ch),
3049 GCT_2s (t));
3050 GCCH_handle_channel_open_ack (ch,
3051 GCC_get_id (t->current_ct->cc),
3052 &cm->port);
3053}
3054
3055
3056/**
3057 * We received a message saying that a channel should be destroyed.
3058 * Pass it on to the correct channel.
3059 *
3060 * @param cls the `struct CadetTunnel` for which we decrypted the message
3061 * @param cm the message we received on the tunnel
3062 */
3063static void
3064handle_plaintext_channel_destroy (void *cls,
3065 const struct
3066 GNUNET_CADET_ChannelDestroyMessage *cm)
3067{
3068 struct CadetTunnel *t = cls;
3069 struct CadetChannel *ch;
3070
3071 ch = lookup_channel (t,
3072 cm->ctn);
3073 if (NULL == ch)
3074 {
3075 /* We don't know about such a channel, might have been destroyed on our
3076 end in the meantime, or never existed. */
3077 LOG (GNUNET_ERROR_TYPE_DEBUG,
3078 "Received channel DESTROY for unknown channel %u. Ignoring.\n",
3079 ntohl (cm->ctn.cn));
3080 return;
3081 }
3082 LOG (GNUNET_ERROR_TYPE_DEBUG,
3083 "Received channel DESTROY on %s from %s\n",
3084 GCCH_2s (ch),
3085 GCT_2s (t));
3086 GCCH_handle_remote_destroy (ch,
3087 GCC_get_id (t->current_ct->cc));
3088}
3089
3090
3091/**
3092 * Handles a message we decrypted, by injecting it into
3093 * our message queue (which will do the dispatching).
3094 *
3095 * @param cls the `struct CadetTunnel` that got the message
3096 * @param msg the message
3097 * @return #GNUNET_OK on success (always)
3098 * #GNUNET_NO to stop further processing (no error)
3099 * #GNUNET_SYSERR to stop further processing with error
3100 */
3101static int
3102handle_decrypted (void *cls,
3103 const struct GNUNET_MessageHeader *msg)
3104{
3105 struct CadetTunnel *t = cls;
3106
3107 GNUNET_assert (NULL != t->current_ct);
3108 GNUNET_MQ_inject_message (t->mq,
3109 msg);
3110 return GNUNET_OK;
3111}
3112
3113
3114/**
3115 * Function called if we had an error processing
3116 * an incoming decrypted message.
3117 *
3118 * @param cls the `struct CadetTunnel`
3119 * @param error error code
3120 */
3121static void
3122decrypted_error_cb (void *cls,
3123 enum GNUNET_MQ_Error error)
3124{
3125 GNUNET_break_op (0);
3126}
3127
3128
3129/**
3130 * Create a tunnel to @a destination. Must only be called
3131 * from within #GCP_get_tunnel().
3132 *
3133 * @param destination where to create the tunnel to
3134 * @return new tunnel to @a destination
3135 */
3136struct CadetTunnel *
3137GCT_create_tunnel (struct CadetPeer *destination)
3138{
3139 struct CadetTunnel *t = GNUNET_new (struct CadetTunnel);
3140 struct GNUNET_MQ_MessageHandler handlers[] = {
3141 GNUNET_MQ_hd_fixed_size (plaintext_keepalive,
3142 GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE,
3143 struct GNUNET_MessageHeader,
3144 t),
3145 GNUNET_MQ_hd_var_size (plaintext_data,
3146 GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA,
3147 struct GNUNET_CADET_ChannelAppDataMessage,
3148 t),
3149 GNUNET_MQ_hd_fixed_size (plaintext_data_ack,
3150 GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK,
3151 struct GNUNET_CADET_ChannelDataAckMessage,
3152 t),
3153 GNUNET_MQ_hd_fixed_size (plaintext_channel_open,
3154 GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN,
3155 struct GNUNET_CADET_ChannelOpenMessage,
3156 t),
3157 GNUNET_MQ_hd_fixed_size (plaintext_channel_open_ack,
3158 GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK,
3159 struct GNUNET_CADET_ChannelOpenAckMessage,
3160 t),
3161 GNUNET_MQ_hd_fixed_size (plaintext_channel_destroy,
3162 GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY,
3163 struct GNUNET_CADET_ChannelDestroyMessage,
3164 t),
3165 GNUNET_MQ_handler_end ()
3166 };
3167
3168 t->kx_retry_delay = INITIAL_KX_RETRY_DELAY;
3169 new_ephemeral (&t->ax);
3170 GNUNET_CRYPTO_ecdhe_key_create (&t->ax.kx_0);
3171 t->destination = destination;
3172 t->channels = GNUNET_CONTAINER_multihashmap32_create (8);
3173 t->maintain_connections_task
3174 = GNUNET_SCHEDULER_add_now (&maintain_connections_cb,
3175 t);
3176 t->mq = GNUNET_MQ_queue_for_callbacks (NULL,
3177 NULL,
3178 NULL,
3179 NULL,
3180 handlers,
3181 &decrypted_error_cb,
3182 t);
3183 t->mst = GNUNET_MST_create (&handle_decrypted,
3184 t);
3185 return t;
3186}
3187
3188
3189int
3190GCT_add_inbound_connection (struct CadetTunnel *t,
3191 const struct
3192 GNUNET_CADET_ConnectionTunnelIdentifier *cid,
3193 struct CadetPeerPath *path)
3194{
3195 struct CadetTConnection *ct;
3196
3197 ct = GNUNET_new (struct CadetTConnection);
3198 ct->created = GNUNET_TIME_absolute_get ();
3199 ct->t = t;
3200 ct->cc = GCC_create_inbound (t->destination,
3201 path,
3202 ct,
3203 cid,
3204 &connection_ready_cb,
3205 ct);
3206 if (NULL == ct->cc)
3207 {
3208 LOG (GNUNET_ERROR_TYPE_DEBUG,
3209 "%s refused inbound %s (duplicate)\n",
3210 GCT_2s (t),
3211 GCC_2s (ct->cc));
3212 GNUNET_free (ct);
3213 return GNUNET_SYSERR;
3214 }
3215 /* FIXME: schedule job to kill connection (and path?) if it takes
3216 too long to get ready! (And track performance data on how long
3217 other connections took with the tunnel!)
3218 => Note: to be done within 'connection'-logic! */
3219 GNUNET_CONTAINER_DLL_insert (t->connection_busy_head,
3220 t->connection_busy_tail,
3221 ct);
3222 t->num_busy_connections++;
3223 LOG (GNUNET_ERROR_TYPE_DEBUG,
3224 "%s has new %s\n",
3225 GCT_2s (t),
3226 GCC_2s (ct->cc));
3227 return GNUNET_OK;
3228}
3229
3230
3231/**
3232 * Handle encrypted message.
3233 *
3234 * @param ct connection/tunnel combo that received encrypted message
3235 * @param msg the encrypted message to decrypt
3236 */
3237void
3238GCT_handle_encrypted (struct CadetTConnection *ct,
3239 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
3240{
3241 struct CadetTunnel *t = ct->t;
3242 uint16_t size = ntohs (msg->header.size);
3243 char cbuf[size] GNUNET_ALIGN;
3244 ssize_t decrypted_size;
3245
3246 LOG (GNUNET_ERROR_TYPE_DEBUG,
3247 "%s received %u bytes of encrypted data in state %d\n",
3248 GCT_2s (t),
3249 (unsigned int) size,
3250 t->estate);
3251
3252 switch (t->estate)
3253 {
3254 case CADET_TUNNEL_KEY_UNINITIALIZED:
3255 case CADET_TUNNEL_KEY_AX_RECV:
3256 /* We did not even SEND our KX, how can the other peer
3257 send us encrypted data? Must have been that we went
3258 down and the other peer still things we are up.
3259 Let's send it KX back. */
3260 GNUNET_STATISTICS_update (stats,
3261 "# received encrypted without any KX",
3262 1,
3263 GNUNET_NO);
3264 if (NULL != t->kx_task)
3265 {
3266 GNUNET_SCHEDULER_cancel (t->kx_task);
3267 t->kx_task = NULL;
3268 }
3269 send_kx (t,
3270 ct,
3271 &t->ax);
3272 return;
3273
3274 case CADET_TUNNEL_KEY_AX_SENT_AND_RECV:
3275 /* We send KX, and other peer send KX to us at the same time.
3276 Neither KX is AUTH'ed, so let's try KX_AUTH this time. */
3277 GNUNET_STATISTICS_update (stats,
3278 "# received encrypted without KX_AUTH",
3279 1,
3280 GNUNET_NO);
3281 if (NULL != t->kx_task)
3282 {
3283 GNUNET_SCHEDULER_cancel (t->kx_task);
3284 t->kx_task = NULL;
3285 }
3286 send_kx_auth (t,
3287 ct,
3288 &t->ax,
3289 GNUNET_YES);
3290 return;
3291
3292 case CADET_TUNNEL_KEY_AX_SENT:
3293 /* We did not get the KX of the other peer, but that
3294 might have been lost. Send our KX again immediately. */
3295 GNUNET_STATISTICS_update (stats,
3296 "# received encrypted without KX",
3297 1,
3298 GNUNET_NO);
3299 if (NULL != t->kx_task)
3300 {
3301 GNUNET_SCHEDULER_cancel (t->kx_task);
3302 t->kx_task = NULL;
3303 }
3304 send_kx (t,
3305 ct,
3306 &t->ax);
3307 return;
3308
3309 case CADET_TUNNEL_KEY_AX_AUTH_SENT:
3310 /* Great, first payload, we might graduate to OK! */
3311 case CADET_TUNNEL_KEY_OK:
3312 /* We are up and running, all good. */
3313 break;
3314 }
3315
3316 decrypted_size = -1;
3317 if (CADET_TUNNEL_KEY_OK == t->estate)
3318 {
3319 /* We have well-established key material available,
3320 try that. (This is the common case.) */
3321 decrypted_size = t_ax_decrypt_and_validate (&t->ax,
3322 cbuf,
3323 msg,
3324 size);
3325 }
3326
3327 if ((-1 == decrypted_size) &&
3328 (NULL != t->unverified_ax))
3329 {
3330 /* We have un-authenticated KX material available. We should try
3331 this as a back-up option, in case the sender crashed and
3332 switched keys. */
3333 decrypted_size = t_ax_decrypt_and_validate (t->unverified_ax,
3334 cbuf,
3335 msg,
3336 size);
3337 if (-1 != decrypted_size)
3338 {
3339 /* It worked! Treat this as authentication of the AX data! */
3340 cleanup_ax (&t->ax);
3341 t->ax = *t->unverified_ax;
3342 GNUNET_free (t->unverified_ax);
3343 t->unverified_ax = NULL;
3344 }
3345 if (CADET_TUNNEL_KEY_AX_AUTH_SENT == t->estate)
3346 {
3347 /* First time it worked, move tunnel into production! */
3348 GCT_change_estate (t,
3349 CADET_TUNNEL_KEY_OK);
3350 if (NULL != t->send_task)
3351 GNUNET_SCHEDULER_cancel (t->send_task);
3352 t->send_task = GNUNET_SCHEDULER_add_now (&trigger_transmissions,
3353 t);
3354 }
3355 }
3356 if (NULL != t->unverified_ax)
3357 {
3358 /* We had unverified KX material that was useless; so increment
3359 counter and eventually move to ignore it. Note that we even do
3360 this increment if we successfully decrypted with the old KX
3361 material and thus didn't even both with the new one. This is
3362 the ideal case, as a malicious injection of bogus KX data
3363 basically only causes us to increment a counter a few times. */t->unverified_attempts++;
3364 LOG (GNUNET_ERROR_TYPE_DEBUG,
3365 "Failed to decrypt message with unverified KX data %u times\n",
3366 t->unverified_attempts);
3367 if (t->unverified_attempts > MAX_UNVERIFIED_ATTEMPTS)
3368 {
3369 cleanup_ax (t->unverified_ax);
3370 GNUNET_free (t->unverified_ax);
3371 t->unverified_ax = NULL;
3372 }
3373 }
3374
3375 if (-1 == decrypted_size)
3376 {
3377 /* Decryption failed for good, complain. */
3378 LOG (GNUNET_ERROR_TYPE_WARNING,
3379 "%s failed to decrypt and validate encrypted data, retrying KX\n",
3380 GCT_2s (t));
3381 GNUNET_STATISTICS_update (stats,
3382 "# unable to decrypt",
3383 1,
3384 GNUNET_NO);
3385 if (NULL != t->kx_task)
3386 {
3387 GNUNET_SCHEDULER_cancel (t->kx_task);
3388 t->kx_task = NULL;
3389 }
3390 send_kx (t,
3391 ct,
3392 &t->ax);
3393 return;
3394 }
3395 GNUNET_STATISTICS_update (stats,
3396 "# decrypted bytes",
3397 decrypted_size,
3398 GNUNET_NO);
3399
3400 /* The MST will ultimately call #handle_decrypted() on each message. */
3401 t->current_ct = ct;
3402 GNUNET_break_op (GNUNET_OK ==
3403 GNUNET_MST_from_buffer (t->mst,
3404 cbuf,
3405 decrypted_size,
3406 GNUNET_YES,
3407 GNUNET_NO));
3408 t->current_ct = NULL;
3409}
3410
3411
3412struct CadetTunnelQueueEntry *
3413GCT_send (struct CadetTunnel *t,
3414 const struct GNUNET_MessageHeader *message,
3415 GCT_SendContinuation cont,
3416 void *cont_cls,
3417 struct GNUNET_CADET_ChannelTunnelNumber *ctn)
3418{
3419 struct CadetTunnelQueueEntry *tq;
3420 uint16_t payload_size;
3421 struct GNUNET_MQ_Envelope *env;
3422 struct GNUNET_CADET_TunnelEncryptedMessage *ax_msg;
3423 struct CadetChannel *ch;
3424
3425 if (NULL != ctn)
3426 {
3427 ch = lookup_channel (t,
3428 *ctn);
3429 if ((NULL != ch) && GCCH_is_type_to_drop (ch, message))
3430 {
3431 GNUNET_break (0);
3432 return NULL;
3433 }
3434 }
3435
3436 if (CADET_TUNNEL_KEY_OK != t->estate)
3437 {
3438 GNUNET_break (0);
3439 return NULL;
3440 }
3441 payload_size = ntohs (message->size);
3442 LOG (GNUNET_ERROR_TYPE_DEBUG,
3443 "Encrypting %u bytes for %s\n",
3444 (unsigned int) payload_size,
3445 GCT_2s (t));
3446 env = GNUNET_MQ_msg_extra (ax_msg,
3447 payload_size,
3448 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED);
3449 t_ax_encrypt (&t->ax,
3450 &ax_msg[1],
3451 message,
3452 payload_size);
3453 GNUNET_STATISTICS_update (stats,
3454 "# encrypted bytes",
3455 payload_size,
3456 GNUNET_NO);
3457 ax_msg->ax_header.Ns = htonl (t->ax.Ns++);
3458 ax_msg->ax_header.PNs = htonl (t->ax.PNs);
3459 /* FIXME: we should do this once, not once per message;
3460 this is a point multiplication, and DHRs does not
3461 change all the time. */
3462 GNUNET_CRYPTO_ecdhe_key_get_public (&t->ax.DHRs,
3463 &ax_msg->ax_header.DHRs);
3464 t_h_encrypt (&t->ax,
3465 ax_msg);
3466 t_hmac (&ax_msg->ax_header,
3467 sizeof(struct GNUNET_CADET_AxHeader) + payload_size,
3468 0,
3469 &t->ax.HKs,
3470 &ax_msg->hmac);
3471
3472 tq = GNUNET_malloc (sizeof(*tq));
3473 tq->t = t;
3474 tq->env = env;
3475 tq->cid = &ax_msg->cid; /* will initialize 'ax_msg->cid' once we know the connection */
3476 tq->cont = cont;
3477 tq->cont_cls = cont_cls;
3478 GNUNET_CONTAINER_DLL_insert_tail (t->tq_head,
3479 t->tq_tail,
3480 tq);
3481 if (NULL != t->send_task)
3482 GNUNET_SCHEDULER_cancel (t->send_task);
3483 t->send_task
3484 = GNUNET_SCHEDULER_add_now (&trigger_transmissions,
3485 t);
3486 return tq;
3487}
3488
3489
3490/**
3491 * Cancel a previously sent message while it's in the queue.
3492 *
3493 * ONLY can be called before the continuation given to the send
3494 * function is called. Once the continuation is called, the message is
3495 * no longer in the queue!
3496 *
3497 * @param tq Handle to the queue entry to cancel.
3498 */
3499void
3500GCT_send_cancel (struct CadetTunnelQueueEntry *tq)
3501{
3502 struct CadetTunnel *t = tq->t;
3503
3504 GNUNET_CONTAINER_DLL_remove (t->tq_head,
3505 t->tq_tail,
3506 tq);
3507 GNUNET_MQ_discard (tq->env);
3508 GNUNET_free (tq);
3509}
3510
3511
3512/**
3513 * Iterate over all connections of a tunnel.
3514 *
3515 * @param t Tunnel whose connections to iterate.
3516 * @param iter Iterator.
3517 * @param iter_cls Closure for @c iter.
3518 */
3519void
3520GCT_iterate_connections (struct CadetTunnel *t,
3521 GCT_ConnectionIterator iter,
3522 void *iter_cls)
3523{
3524 struct CadetTConnection *n;
3525
3526 for (struct CadetTConnection *ct = t->connection_ready_head;
3527 NULL != ct;
3528 ct = n)
3529 {
3530 n = ct->next;
3531 iter (iter_cls,
3532 ct);
3533 }
3534 for (struct CadetTConnection *ct = t->connection_busy_head;
3535 NULL != ct;
3536 ct = n)
3537 {
3538 n = ct->next;
3539 iter (iter_cls,
3540 ct);
3541 }
3542}
3543
3544
3545/**
3546 * Closure for #iterate_channels_cb.
3547 */
3548struct ChanIterCls
3549{
3550 /**
3551 * Function to call.
3552 */
3553 GCT_ChannelIterator iter;
3554
3555 /**
3556 * Closure for @e iter.
3557 */
3558 void *iter_cls;
3559};
3560
3561
3562/**
3563 * Helper function for #GCT_iterate_channels.
3564 *
3565 * @param cls the `struct ChanIterCls`
3566 * @param key unused
3567 * @param value a `struct CadetChannel`
3568 * @return #GNUNET_OK
3569 */
3570static int
3571iterate_channels_cb (void *cls,
3572 uint32_t key,
3573 void *value)
3574{
3575 struct ChanIterCls *ctx = cls;
3576 struct CadetChannel *ch = value;
3577
3578 ctx->iter (ctx->iter_cls,
3579 ch);
3580 return GNUNET_OK;
3581}
3582
3583
3584/**
3585 * Iterate over all channels of a tunnel.
3586 *
3587 * @param t Tunnel whose channels to iterate.
3588 * @param iter Iterator.
3589 * @param iter_cls Closure for @c iter.
3590 */
3591void
3592GCT_iterate_channels (struct CadetTunnel *t,
3593 GCT_ChannelIterator iter,
3594 void *iter_cls)
3595{
3596 struct ChanIterCls ctx;
3597
3598 ctx.iter = iter;
3599 ctx.iter_cls = iter_cls;
3600 GNUNET_CONTAINER_multihashmap32_iterate (t->channels,
3601 &iterate_channels_cb,
3602 &ctx);
3603}
3604
3605
3606/**
3607 * Call #GCCH_debug() on a channel.
3608 *
3609 * @param cls points to the log level to use
3610 * @param key unused
3611 * @param value the `struct CadetChannel` to dump
3612 * @return #GNUNET_OK (continue iteration)
3613 */
3614static int
3615debug_channel (void *cls,
3616 uint32_t key,
3617 void *value)
3618{
3619 const enum GNUNET_ErrorType *level = cls;
3620 struct CadetChannel *ch = value;
3621
3622 GCCH_debug (ch, *level);
3623 return GNUNET_OK;
3624}
3625
3626
3627#define LOG2(level, ...) GNUNET_log_from_nocheck (level, "cadet-tun", \
3628 __VA_ARGS__)
3629
3630
3631/**
3632 * Log all possible info about the tunnel state.
3633 *
3634 * @param t Tunnel to debug.
3635 * @param level Debug level to use.
3636 */
3637void
3638GCT_debug (const struct CadetTunnel *t,
3639 enum GNUNET_ErrorType level)
3640{
3641#if ! defined(GNUNET_CULL_LOGGING)
3642 struct CadetTConnection *iter_c;
3643 int do_log;
3644
3645 do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
3646 "cadet-tun",
3647 __FILE__, __FUNCTION__, __LINE__);
3648 if (0 == do_log)
3649 return;
3650
3651 LOG2 (level,
3652 "TTT TUNNEL TOWARDS %s in estate %s tq_len: %u #cons: %u\n",
3653 GCT_2s (t),
3654 estate2s (t->estate),
3655 t->tq_len,
3656 GCT_count_any_connections (t));
3657 LOG2 (level,
3658 "TTT channels:\n");
3659 GNUNET_CONTAINER_multihashmap32_iterate (t->channels,
3660 &debug_channel,
3661 &level);
3662 LOG2 (level,
3663 "TTT connections:\n");
3664 for (iter_c = t->connection_ready_head; NULL != iter_c; iter_c = iter_c->next)
3665 GCC_debug (iter_c->cc,
3666 level);
3667 for (iter_c = t->connection_busy_head; NULL != iter_c; iter_c = iter_c->next)
3668 GCC_debug (iter_c->cc,
3669 level);
3670
3671 LOG2 (level,
3672 "TTT TUNNEL END\n");
3673#endif
3674}
3675
3676
3677/* 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 018a3ec73..000000000
--- a/src/cadet/gnunet-service-cadet_tunnels.h
+++ /dev/null
@@ -1,391 +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 * Returns the number of channels using a tunnel.
256 *
257 * @param t Tunnel in question.
258 * @return Number of channels using the tunnel.
259 */
260unsigned int
261GCT_count_channels (struct CadetTunnel *t);
262
263
264/**
265 * Counts the number of connections created for a tunnel,
266 * including busy connections.
267 *
268 * @param t Tunnel to be counted.
269 * @return Number of connections created for the tunnel.
270 */
271unsigned int
272GCT_count_any_connections (const struct CadetTunnel *t);
273
274
275/**
276 * Iterator over connections.
277 *
278 * @param cls closure
279 * @param ct one of the connections
280 */
281typedef void
282(*GCT_ConnectionIterator) (void *cls,
283 struct CadetTConnection *ct);
284
285
286/**
287 * Iterate over all connections of a tunnel.
288 *
289 * @param t Tunnel whose connections to iterate.
290 * @param iter Iterator.
291 * @param iter_cls Closure for @c iter.
292 */
293void
294GCT_iterate_connections (struct CadetTunnel *t,
295 GCT_ConnectionIterator iter,
296 void *iter_cls);
297
298
299/**
300 * Iterator over channels.
301 *
302 * @param cls closure
303 * @param ch one of the channels
304 */
305typedef void
306(*GCT_ChannelIterator) (void *cls,
307 struct CadetChannel *ch);
308
309
310/**
311 * Iterate over all channels of a tunnel.
312 *
313 * @param t Tunnel whose channels to iterate.
314 * @param iter Iterator.
315 * @param iter_cls Closure for @c iter.
316 */
317void
318GCT_iterate_channels (struct CadetTunnel *t,
319 GCT_ChannelIterator iter,
320 void *iter_cls);
321
322
323/**
324 * Get the encryption state of a tunnel.
325 *
326 * @param t Tunnel.
327 *
328 * @return Tunnel's encryption state.
329 */
330enum CadetTunnelEState
331GCT_get_estate (struct CadetTunnel *t);
332
333/**
334 * Change the tunnel encryption state.
335 * If the encryption state changes to OK, stop the rekey task.
336 *
337 * @param t Tunnel whose encryption state to change, or NULL.
338 * @param state New encryption state.
339 */
340void
341GCT_change_estate (struct CadetTunnel *t,
342 enum CadetTunnelEState state);
343
344/**
345 * Handle KX message that lacks authentication (and which will thus
346 * only be considered authenticated after we respond with our own
347 * KX_AUTH and finally successfully decrypt the payload).
348 *
349 * @param ct connection/tunnel combo that received encrypted message
350 * @param msg the key exchange message
351 */
352void
353GCT_handle_kx (struct CadetTConnection *ct,
354 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg);
355
356
357/**
358 * Handle KX_AUTH message.
359 *
360 * @param ct connection/tunnel combo that received encrypted message
361 * @param msg the key exchange message
362 */
363void
364GCT_handle_kx_auth (struct CadetTConnection *ct,
365 const struct
366 GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg);
367
368
369/**
370 * Handle encrypted message.
371 *
372 * @param ct connection/tunnel combo that received encrypted message
373 * @param msg the encrypted message to decrypt
374 */
375void
376GCT_handle_encrypted (struct CadetTConnection *ct,
377 const struct GNUNET_CADET_TunnelEncryptedMessage *msg);
378
379
380/**
381 * Log all possible info about the tunnel state.
382 *
383 * @param t Tunnel to debug.
384 * @param level Debug level to use.
385 */
386void
387GCT_debug (const struct CadetTunnel *t,
388 enum GNUNET_ErrorType level);
389
390
391#endif
diff --git a/src/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