diff options
Diffstat (limited to 'src/cadet')
46 files changed, 0 insertions, 24161 deletions
diff --git a/src/cadet/.gitignore b/src/cadet/.gitignore deleted file mode 100644 index b556fa4c8..000000000 --- a/src/cadet/.gitignore +++ /dev/null | |||
@@ -1,26 +0,0 @@ | |||
1 | gnunet-service-cadet | ||
2 | gnunet-cadet | ||
3 | gnunet-cadet-profiler | ||
4 | test_cadet_2_forward | ||
5 | test_cadet_2_keepalive | ||
6 | test_cadet_2_signal | ||
7 | test_cadet_2_speed | ||
8 | test_cadet_2_speed_ack | ||
9 | test_cadet_2_speed_backwards | ||
10 | test_cadet_2_speed_reliable | ||
11 | test_cadet_2_speed_reliable_backwards | ||
12 | test_cadet_5_forward | ||
13 | test_cadet_5_keepalive | ||
14 | test_cadet_5_signal | ||
15 | test_cadet_5_speed | ||
16 | test_cadet_5_speed_ack | ||
17 | test_cadet_5_speed_backwards | ||
18 | test_cadet_5_speed_reliable | ||
19 | test_cadet_5_speed_reliable_backwards | ||
20 | test_cadet_local | ||
21 | test_cadet_single | ||
22 | gnunet-service-cadet-new | ||
23 | test_cadet_local_mq | ||
24 | test_cadet_*_newtest_cadet_2_reopen | ||
25 | test_cadet_5_reopen | ||
26 | test_cadet_2_reopen | ||
diff --git a/src/cadet/Makefile.am b/src/cadet/Makefile.am deleted file mode 100644 index d942c6495..000000000 --- a/src/cadet/Makefile.am +++ /dev/null | |||
@@ -1,225 +0,0 @@ | |||
1 | # This Makefile.am is in the public domain | ||
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include | ||
3 | |||
4 | if USE_COVERAGE | ||
5 | AM_CFLAGS = --coverage -O0 | ||
6 | XLIB = -lgcov | ||
7 | endif | ||
8 | |||
9 | pkgcfgdir= $(pkgdatadir)/config.d/ | ||
10 | |||
11 | libexecdir= $(pkglibdir)/libexec/ | ||
12 | |||
13 | pkgcfg_DATA = \ | ||
14 | cadet.conf | ||
15 | |||
16 | plugindir = $(libdir)/gnunet | ||
17 | |||
18 | AM_CLFAGS = -g | ||
19 | |||
20 | libexec_PROGRAMS = \ | ||
21 | gnunet-service-cadet \ | ||
22 | $(EXP_LIBEXEC) | ||
23 | |||
24 | bin_PROGRAMS = \ | ||
25 | gnunet-cadet | ||
26 | |||
27 | lib_LTLIBRARIES = \ | ||
28 | libgnunetcadet.la \ | ||
29 | $(EXP_LIB) | ||
30 | |||
31 | libgnunetcadet_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 | ||
39 | libgnunetcadet_la_LIBADD = \ | ||
40 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
41 | $(XLIB) \ | ||
42 | $(LTLIBINTL) | ||
43 | libgnunetcadet_la_LDFLAGS = \ | ||
44 | $(GN_LIB_LDFLAGS) \ | ||
45 | -version-info 7:0:0 | ||
46 | |||
47 | gnunet_cadet_SOURCES = \ | ||
48 | gnunet-cadet.c | ||
49 | gnunet_cadet_LDADD = \ | ||
50 | libgnunetcadet.la \ | ||
51 | $(top_builddir)/src/util/libgnunetutil.la | ||
52 | gnunet_cadet_LDFLAGS = \ | ||
53 | $(GN_LIBINTL) | ||
54 | |||
55 | gnunet_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 | ||
65 | gnunet_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 | ||
75 | if LINUX | ||
76 | gnunet_service_cadet_LDFLAGS = -lrt \ | ||
77 | $(GN_LIBINTL) | ||
78 | endif | ||
79 | |||
80 | |||
81 | noinst_LTLIBRARIES = libgnunetcadettest.la $(noinst_LIB_EXP) | ||
82 | # noinst_PROGRAMS = gnunet-cadet-profiler | ||
83 | |||
84 | check_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 | |||
113 | test_cadet_local_mq_SOURCES = \ | ||
114 | test_cadet_local_mq.c | ||
115 | test_cadet_local_mq_LDADD = \ | ||
116 | libgnunetcadet.la \ | ||
117 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
118 | $(top_builddir)/src/util/libgnunetutil.la | ||
119 | |||
120 | |||
121 | libgnunetcadettest_la_SOURCES = \ | ||
122 | cadet_test_lib.c cadet_test_lib.h | ||
123 | libgnunetcadettest_la_LIBADD = \ | ||
124 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
125 | $(top_builddir)/src/testbed/libgnunettestbed.la \ | ||
126 | libgnunetcadet.la | ||
127 | |||
128 | ld_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 | ||
135 | dep_cadet_test_lib = \ | ||
136 | libgnunetcadet.la \ | ||
137 | libgnunetcadettest.la \ | ||
138 | $(top_builddir)/src/statistics/libgnunetstatistics.la | ||
139 | |||
140 | test_cadet_2_forward_SOURCES = \ | ||
141 | test_cadet.c | ||
142 | test_cadet_2_forward_LDADD = $(ld_cadet_test_lib) | ||
143 | |||
144 | test_cadet_2_signal_SOURCES = \ | ||
145 | test_cadet.c | ||
146 | test_cadet_2_signal_LDADD = $(ld_cadet_test_lib) | ||
147 | |||
148 | test_cadet_2_keepalive_SOURCES = \ | ||
149 | test_cadet.c | ||
150 | test_cadet_2_keepalive_LDADD = $(ld_cadet_test_lib) | ||
151 | |||
152 | test_cadet_2_speed_SOURCES = \ | ||
153 | test_cadet.c | ||
154 | test_cadet_2_speed_LDADD = $(ld_cadet_test_lib) | ||
155 | |||
156 | test_cadet_2_speed_ack_SOURCES = \ | ||
157 | test_cadet.c | ||
158 | test_cadet_2_speed_ack_LDADD = $(ld_cadet_test_lib) | ||
159 | |||
160 | test_cadet_2_speed_backwards_SOURCES = \ | ||
161 | test_cadet.c | ||
162 | test_cadet_2_speed_backwards_LDADD = $(ld_cadet_test_lib) | ||
163 | |||
164 | test_cadet_2_speed_reliable_SOURCES = \ | ||
165 | test_cadet.c | ||
166 | test_cadet_2_speed_reliable_LDADD = $(ld_cadet_test_lib) | ||
167 | |||
168 | test_cadet_2_speed_reliable_backwards_SOURCES = \ | ||
169 | test_cadet.c | ||
170 | test_cadet_2_speed_reliable_backwards_LDADD = $(ld_cadet_test_lib) | ||
171 | |||
172 | test_cadet_5_forward_SOURCES = \ | ||
173 | test_cadet.c | ||
174 | test_cadet_5_forward_LDADD = $(ld_cadet_test_lib) | ||
175 | |||
176 | test_cadet_5_signal_SOURCES = \ | ||
177 | test_cadet.c | ||
178 | test_cadet_5_signal_LDADD = $(ld_cadet_test_lib) | ||
179 | |||
180 | test_cadet_5_keepalive_SOURCES = \ | ||
181 | test_cadet.c | ||
182 | test_cadet_5_keepalive_LDADD = $(ld_cadet_test_lib) | ||
183 | |||
184 | test_cadet_5_speed_SOURCES = \ | ||
185 | test_cadet.c | ||
186 | test_cadet_5_speed_LDADD = $(ld_cadet_test_lib) | ||
187 | |||
188 | test_cadet_5_speed_ack_SOURCES = \ | ||
189 | test_cadet.c | ||
190 | test_cadet_5_speed_ack_LDADD = $(ld_cadet_test_lib) | ||
191 | |||
192 | test_cadet_5_speed_backwards_SOURCES = \ | ||
193 | test_cadet.c | ||
194 | test_cadet_5_speed_backwards_LDADD = $(ld_cadet_test_lib) | ||
195 | |||
196 | test_cadet_5_speed_reliable_SOURCES = \ | ||
197 | test_cadet.c | ||
198 | test_cadet_5_speed_reliable_LDADD = $(ld_cadet_test_lib) | ||
199 | |||
200 | test_cadet_5_speed_reliable_backwards_SOURCES = \ | ||
201 | test_cadet.c | ||
202 | test_cadet_5_speed_reliable_backwards_LDADD = $(ld_cadet_test_lib) | ||
203 | |||
204 | test_cadet_2_reopen_SOURCES = \ | ||
205 | test_cadet.c | ||
206 | test_cadet_2_reopen_LDADD = $(ld_cadet_test_lib) | ||
207 | |||
208 | test_cadet_5_reopen_SOURCES = \ | ||
209 | test_cadet.c | ||
210 | test_cadet_5_reopen_LDADD = $(ld_cadet_test_lib) | ||
211 | |||
212 | test_cadet_2_destroy_SOURCES = \ | ||
213 | test_cadet.c | ||
214 | test_cadet_2_destroy_LDADD = $(ld_cadet_test_lib) | ||
215 | |||
216 | if ENABLE_TEST_RUN | ||
217 | AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; | ||
218 | TESTS = \ | ||
219 | $(check_PROGRAMS) | ||
220 | endif | ||
221 | |||
222 | EXTRA_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] | ||
2 | IMMEDIATE_START = YES | ||
3 | START_ON_DEMAND = @START_ON_DEMAND@ | ||
4 | @JAVAPORT@PORT = 2096 | ||
5 | HOSTNAME = localhost | ||
6 | BINARY = gnunet-service-cadet | ||
7 | # PREFIX = valgrind --leak-check=yes | ||
8 | ACCEPT_FROM = 127.0.0.1; | ||
9 | ACCEPT_FROM6 = ::1; | ||
10 | UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-cadet.sock | ||
11 | UNIX_MATCH_UID = NO | ||
12 | UNIX_MATCH_GID = YES | ||
13 | |||
14 | |||
15 | # How often do we send KEEPALIVE messages on connections to keep them | ||
16 | # from timing out? | ||
17 | REFRESH_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? | ||
23 | ID_ANNOUNCE_TIME = 1 h | ||
24 | |||
25 | # FIXME: document | ||
26 | CONNECT_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. | ||
30 | DHT_REPLICATION_LEVEL = 3 | ||
31 | |||
32 | # FIXME: not implemented | ||
33 | # MAX_TUNNELS = 1000 | ||
34 | |||
35 | # FIXME: not implemented, replaced by MAX_ROUTES in NEW CADET! | ||
36 | MAX_CONNECTIONS = 1000 | ||
37 | |||
38 | # How many routes do we participate in at most? Should be smaller | ||
39 | # than MAX_MSGS_QUEUE | ||
40 | MAX_ROUTES = 5000 | ||
41 | |||
42 | # FIXME: not implemented | ||
43 | MAX_MSGS_QUEUE = 10000 | ||
44 | |||
45 | # FIXME: not implemented | ||
46 | MAX_PEERS = 1000 | ||
47 | |||
48 | # How often do we advance the ratchet even if there is not | ||
49 | # any traffic? | ||
50 | RATCHET_TIME = 1 h | ||
51 | |||
52 | # How often do we advance the ratched if there is traffic? | ||
53 | RATCHET_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 | ||
30 | extern "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 | |||
96 | GNUNET_NETWORK_STRUCT_BEGIN | ||
97 | |||
98 | /** | ||
99 | * Number uniquely identifying a channel of a client. | ||
100 | */ | ||
101 | struct 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 | */ | ||
116 | struct 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 | */ | ||
181 | struct 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 | */ | ||
201 | struct 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 | */ | ||
235 | struct 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 | */ | ||
252 | struct 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 | */ | ||
280 | struct 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 | */ | ||
299 | struct 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 | */ | ||
321 | struct 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 | */ | ||
344 | struct 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 | */ | ||
366 | struct 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 | */ | ||
390 | struct 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 | */ | ||
407 | struct 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 | */ | ||
424 | struct 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 | */ | ||
458 | struct 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 | |||
496 | GNUNET_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 | */ | ||
506 | char * | ||
507 | GC_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 | */ | ||
518 | int | ||
519 | GC_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 | */ | ||
530 | uint32_t | ||
531 | GC_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 | */ | ||
542 | uint32_t | ||
543 | GC_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 | */ | ||
555 | size_t | ||
556 | GC_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 | */ | ||
569 | const char * | ||
570 | GC_m2s (uint16_t m); | ||
571 | |||
572 | #if 0 /* keep Emacsens' auto-indent happy */ | ||
573 | { | ||
574 | #endif | ||
575 | #ifdef __cplusplus | ||
576 | } | ||
577 | #endif | ||
578 | |||
579 | #endif | ||
diff --git a/src/cadet/cadet_api.c b/src/cadet/cadet_api.c deleted file mode 100644 index c9f0722d5..000000000 --- a/src/cadet/cadet_api.c +++ /dev/null | |||
@@ -1,1088 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2011, 2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file cadet/cadet_api.c | ||
22 | * @brief cadet api: client implementation of cadet service | ||
23 | * @author Bartlomiej Polot | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include "gnunet_util_lib.h" | ||
28 | #include "gnunet_constants.h" | ||
29 | #include "gnunet_cadet_service.h" | ||
30 | #include "cadet.h" | ||
31 | #include "cadet_protocol.h" | ||
32 | |||
33 | #define LOG(kind, ...) GNUNET_log_from (kind, "cadet-api", __VA_ARGS__) | ||
34 | |||
35 | /** | ||
36 | * Opaque handle to the service. | ||
37 | */ | ||
38 | struct 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 | */ | ||
79 | struct 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 | */ | ||
130 | static struct GNUNET_CADET_Port * | ||
131 | find_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 | */ | ||
145 | static struct GNUNET_CADET_Channel * | ||
146 | find_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 | */ | ||
161 | static struct GNUNET_CADET_Channel * | ||
162 | create_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 | */ | ||
203 | static void | ||
204 | destroy_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 | */ | ||
238 | static void | ||
239 | reconnect (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 | */ | ||
251 | static int | ||
252 | open_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 | */ | ||
273 | static void | ||
274 | reconnect_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 | */ | ||
290 | static void | ||
291 | notify_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 | */ | ||
305 | static void | ||
306 | cadet_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 | */ | ||
347 | static void | ||
348 | cadet_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 | */ | ||
396 | static void | ||
397 | cadet_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 | */ | ||
414 | static void | ||
415 | cadet_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 | */ | ||
444 | static void | ||
445 | cadet_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 | */ | ||
467 | static void | ||
468 | handle_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 | */ | ||
535 | static void | ||
536 | handle_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 | */ | ||
566 | static int | ||
567 | check_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 | */ | ||
588 | static void | ||
589 | handle_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 | */ | ||
626 | static void | ||
627 | handle_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 | */ | ||
670 | static int | ||
671 | destroy_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 | */ | ||
693 | static void | ||
694 | handle_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 | */ | ||
714 | static void | ||
715 | reconnect (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 | */ | ||
751 | static int | ||
752 | destroy_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 | */ | ||
774 | void | ||
775 | GNUNET_CADET_disconnect (struct GNUNET_CADET_Handle *handle) | ||
776 | { | ||
777 | GNUNET_CONTAINER_multihashmap_iterate (handle->ports, | ||
778 | &destroy_port_cb, | ||
779 | handle); | ||
780 | GNUNET_CONTAINER_multihashmap_destroy (handle->ports); | ||
781 | handle->ports = NULL; | ||
782 | GNUNET_CONTAINER_multihashmap32_iterate (handle->channels, | ||
783 | &destroy_channel_cb, | ||
784 | handle); | ||
785 | GNUNET_CONTAINER_multihashmap32_destroy (handle->channels); | ||
786 | handle->channels = NULL; | ||
787 | if (NULL != handle->mq) | ||
788 | { | ||
789 | GNUNET_MQ_destroy (handle->mq); | ||
790 | handle->mq = NULL; | ||
791 | } | ||
792 | if (NULL != handle->reconnect_task) | ||
793 | { | ||
794 | GNUNET_SCHEDULER_cancel (handle->reconnect_task); | ||
795 | handle->reconnect_task = NULL; | ||
796 | } | ||
797 | GNUNET_free (handle); | ||
798 | } | ||
799 | |||
800 | |||
801 | /** | ||
802 | * Close a port opened with @a GNUNET_CADET_open_port(). | ||
803 | * The @a new_channel callback will no longer be called. | ||
804 | * | ||
805 | * @param p Port handle. | ||
806 | */ | ||
807 | void | ||
808 | GNUNET_CADET_close_port (struct GNUNET_CADET_Port *p) | ||
809 | { | ||
810 | GNUNET_assert ( | ||
811 | GNUNET_YES == | ||
812 | GNUNET_CONTAINER_multihashmap_remove (p->cadet->ports, &p->id, p)); | ||
813 | if (NULL != p->cadet->mq) | ||
814 | { | ||
815 | struct GNUNET_CADET_PortMessage *msg; | ||
816 | struct GNUNET_MQ_Envelope *env; | ||
817 | |||
818 | env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE); | ||
819 | msg->port = p->id; | ||
820 | GNUNET_MQ_send (p->cadet->mq, env); | ||
821 | } | ||
822 | GNUNET_free (p->handlers); | ||
823 | GNUNET_free (p); | ||
824 | } | ||
825 | |||
826 | |||
827 | /** | ||
828 | * Destroy an existing channel. | ||
829 | * | ||
830 | * The existing end callback for the channel will NOT be called. | ||
831 | * Any pending outgoing messages will be sent but no incoming messages will be | ||
832 | * accepted and no data callbacks will be called. | ||
833 | * | ||
834 | * @param channel Channel handle, becomes invalid after this call. | ||
835 | */ | ||
836 | void | ||
837 | GNUNET_CADET_channel_destroy (struct GNUNET_CADET_Channel *channel) | ||
838 | { | ||
839 | struct GNUNET_CADET_Handle *h = channel->cadet; | ||
840 | struct GNUNET_CADET_LocalChannelDestroyMessage *msg; | ||
841 | struct GNUNET_MQ_Envelope *env; | ||
842 | |||
843 | if (NULL != h->mq) | ||
844 | { | ||
845 | env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY); | ||
846 | msg->ccn = channel->ccn; | ||
847 | GNUNET_MQ_send (h->mq, env); | ||
848 | } | ||
849 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
850 | "Destroying channel due to GNUNET_CADET_channel_destroy()\n"); | ||
851 | channel->disconnects = NULL; | ||
852 | destroy_channel (channel); | ||
853 | } | ||
854 | |||
855 | |||
856 | /** | ||
857 | * Get information about a channel. | ||
858 | * | ||
859 | * @param channel Channel handle. | ||
860 | * @param option Query (GNUNET_CADET_OPTION_*). | ||
861 | * @param ... dependent on option, currently not used | ||
862 | * | ||
863 | * @return Union with an answer to the query. | ||
864 | */ | ||
865 | const union GNUNET_CADET_ChannelInfo * | ||
866 | GNUNET_CADET_channel_get_info (struct GNUNET_CADET_Channel *channel, | ||
867 | enum GNUNET_CADET_ChannelInfoOption option, | ||
868 | ...) | ||
869 | { | ||
870 | switch (option) | ||
871 | { | ||
872 | case GNUNET_CADET_OPTION_PEER: | ||
873 | return (const union GNUNET_CADET_ChannelInfo *) &channel->peer; | ||
874 | |||
875 | default: | ||
876 | GNUNET_break (0); | ||
877 | return NULL; | ||
878 | } | ||
879 | } | ||
880 | |||
881 | |||
882 | /** | ||
883 | * Send an ack on the channel to confirm the processing of a message. | ||
884 | * | ||
885 | * @param ch Channel on which to send the ACK. | ||
886 | */ | ||
887 | void | ||
888 | GNUNET_CADET_receive_done (struct GNUNET_CADET_Channel *channel) | ||
889 | { | ||
890 | struct GNUNET_CADET_LocalAck *msg; | ||
891 | struct GNUNET_MQ_Envelope *env; | ||
892 | |||
893 | env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK); | ||
894 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
895 | "Sending ACK on channel %X\n", | ||
896 | ntohl (channel->ccn.channel_of_client)); | ||
897 | msg->ccn = channel->ccn; | ||
898 | GNUNET_MQ_send (channel->cadet->mq, env); | ||
899 | } | ||
900 | |||
901 | |||
902 | /** | ||
903 | * Connect to the MQ-based cadet service. | ||
904 | * | ||
905 | * @param cfg Configuration to use. | ||
906 | * | ||
907 | * @return Handle to the cadet service NULL on error. | ||
908 | */ | ||
909 | struct GNUNET_CADET_Handle * | ||
910 | GNUNET_CADET_connect (const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
911 | { | ||
912 | struct GNUNET_CADET_Handle *h; | ||
913 | |||
914 | LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_CADET_connect()\n"); | ||
915 | h = GNUNET_new (struct GNUNET_CADET_Handle); | ||
916 | h->cfg = cfg; | ||
917 | h->ports = GNUNET_CONTAINER_multihashmap_create (4, GNUNET_YES); | ||
918 | h->channels = GNUNET_CONTAINER_multihashmap32_create (4); | ||
919 | reconnect (h); | ||
920 | if (NULL == h->mq) | ||
921 | { | ||
922 | GNUNET_break (0); | ||
923 | GNUNET_CADET_disconnect (h); | ||
924 | return NULL; | ||
925 | } | ||
926 | h->next_ccn.channel_of_client = htonl (GNUNET_CADET_LOCAL_CHANNEL_ID_CLI); | ||
927 | return h; | ||
928 | } | ||
929 | |||
930 | |||
931 | /** | ||
932 | * Function to return link to AGPL source upon request. | ||
933 | * | ||
934 | * @param cls closure with the identification of the client | ||
935 | * @param msg AGPL request | ||
936 | */ | ||
937 | static void | ||
938 | return_agpl (void *cls, const struct GNUNET_MessageHeader *msg) | ||
939 | { | ||
940 | struct GNUNET_SERVICE_Client *client = cls; | ||
941 | struct GNUNET_MQ_Handle *mq; | ||
942 | struct GNUNET_MQ_Envelope *env; | ||
943 | struct GNUNET_MessageHeader *res; | ||
944 | size_t slen; | ||
945 | const struct GNUNET_OS_ProjectData *pd = GNUNET_OS_project_data_get (); | ||
946 | |||
947 | (void) msg; | ||
948 | slen = strlen (pd->agpl_url) + 1; | ||
949 | env = GNUNET_MQ_msg_extra (res, GNUNET_MESSAGE_TYPE_RESPONSE_AGPL, slen); | ||
950 | memcpy (&res[1], GNUNET_AGPL_URL, slen); | ||
951 | mq = GNUNET_SERVICE_client_get_mq (client); | ||
952 | GNUNET_MQ_send (mq, env); | ||
953 | GNUNET_SERVICE_client_continue (client); | ||
954 | } | ||
955 | |||
956 | |||
957 | /** | ||
958 | * Open a port to receive incoming MQ-based channels. | ||
959 | * | ||
960 | * @param h CADET handle. | ||
961 | * @param port Hash identifying the port. | ||
962 | * @param connects Function called when an incoming channel is connected. | ||
963 | * @param connects_cls Closure for the @a connects handler. | ||
964 | * @param window_changes Function called when the transmit window size changes. | ||
965 | * @param disconnects Function called when a channel is disconnected. | ||
966 | * @param handlers Callbacks for messages we care about, NULL-terminated. | ||
967 | * @return Port handle, NULL if port is in use | ||
968 | */ | ||
969 | struct GNUNET_CADET_Port * | ||
970 | GNUNET_CADET_open_port (struct GNUNET_CADET_Handle *h, | ||
971 | const struct GNUNET_HashCode *port, | ||
972 | GNUNET_CADET_ConnectEventHandler connects, | ||
973 | void *connects_cls, | ||
974 | GNUNET_CADET_WindowSizeEventHandler window_changes, | ||
975 | GNUNET_CADET_DisconnectEventHandler disconnects, | ||
976 | const struct GNUNET_MQ_MessageHandler *handlers) | ||
977 | { | ||
978 | struct GNUNET_CADET_Port *p; | ||
979 | const struct GNUNET_OS_ProjectData *pd = GNUNET_OS_project_data_get (); | ||
980 | |||
981 | GNUNET_assert (NULL != connects); | ||
982 | GNUNET_assert (NULL != disconnects); | ||
983 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
984 | "Listening to CADET port %s\n", | ||
985 | GNUNET_h2s (port)); | ||
986 | |||
987 | p = GNUNET_new (struct GNUNET_CADET_Port); | ||
988 | p->cadet = h; | ||
989 | p->id = *port; | ||
990 | if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put ( | ||
991 | h->ports, | ||
992 | &p->id, | ||
993 | p, | ||
994 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) | ||
995 | { | ||
996 | GNUNET_free (p); | ||
997 | return NULL; | ||
998 | } | ||
999 | p->connects = connects; | ||
1000 | p->cls = connects_cls; | ||
1001 | p->window_changes = window_changes; | ||
1002 | p->disconnects = disconnects; | ||
1003 | p->handlers = (NULL == pd->agpl_url) | ||
1004 | ? GNUNET_MQ_copy_handlers (handlers) | ||
1005 | : GNUNET_MQ_copy_handlers2 (handlers, &return_agpl, NULL); | ||
1006 | |||
1007 | GNUNET_assert (GNUNET_OK == open_port_cb (h, &p->id, p)); | ||
1008 | return p; | ||
1009 | } | ||
1010 | |||
1011 | |||
1012 | /** | ||
1013 | * Create a new channel towards a remote peer. | ||
1014 | * | ||
1015 | * If the destination peer closes the channel after accepting it, | ||
1016 | * @a disconnects will be called for this channel (unless | ||
1017 | * #GNUNET_CADET_channel_destroy() was called on this end first). | ||
1018 | * | ||
1019 | * @param h CADET handle. | ||
1020 | * @param channel_cls Closure for the channel. It's given to: | ||
1021 | * - The disconnect handler @a disconnects | ||
1022 | * - Each message type callback in @a handlers | ||
1023 | * @param destination Peer identity the channel should go to. | ||
1024 | * @param port Identification of the destination port. | ||
1025 | * @param window_changes Function called when the transmit window size changes. | ||
1026 | * @param disconnects Function called when the channel is disconnected. | ||
1027 | * @param handlers Callbacks for messages we care about, NULL-terminated. | ||
1028 | * @return Handle to the channel. | ||
1029 | */ | ||
1030 | struct GNUNET_CADET_Channel * | ||
1031 | GNUNET_CADET_channel_create (struct GNUNET_CADET_Handle *h, | ||
1032 | void *channel_cls, | ||
1033 | const struct GNUNET_PeerIdentity *destination, | ||
1034 | const struct GNUNET_HashCode *port, | ||
1035 | GNUNET_CADET_WindowSizeEventHandler window_changes, | ||
1036 | GNUNET_CADET_DisconnectEventHandler disconnects, | ||
1037 | const struct GNUNET_MQ_MessageHandler *handlers) | ||
1038 | { | ||
1039 | struct GNUNET_CADET_Channel *ch; | ||
1040 | struct GNUNET_CADET_LocalChannelCreateMessage *msg; | ||
1041 | struct GNUNET_MQ_Envelope *env; | ||
1042 | |||
1043 | GNUNET_assert (NULL != disconnects); | ||
1044 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1045 | "Creating channel to peer %s at port %s\n", | ||
1046 | GNUNET_i2s (destination), | ||
1047 | GNUNET_h2s (port)); | ||
1048 | ch = create_channel (h, NULL); | ||
1049 | ch->ctx = channel_cls; | ||
1050 | ch->peer = *destination; | ||
1051 | ch->window_changes = window_changes; | ||
1052 | ch->disconnects = disconnects; | ||
1053 | |||
1054 | /* Create MQ for channel */ | ||
1055 | ch->mq = GNUNET_MQ_queue_for_callbacks (&cadet_mq_send_impl, | ||
1056 | &cadet_mq_destroy_impl, | ||
1057 | &cadet_mq_cancel_impl, | ||
1058 | ch, | ||
1059 | handlers, | ||
1060 | &cadet_mq_error_handler, | ||
1061 | ch); | ||
1062 | GNUNET_MQ_set_handlers_closure (ch->mq, channel_cls); | ||
1063 | |||
1064 | /* Request channel creation to service */ | ||
1065 | env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE); | ||
1066 | msg->ccn = ch->ccn; | ||
1067 | msg->port = *port; | ||
1068 | msg->peer = *destination; | ||
1069 | GNUNET_MQ_send (h->mq, env); | ||
1070 | return ch; | ||
1071 | } | ||
1072 | |||
1073 | |||
1074 | /** | ||
1075 | * Obtain the message queue for a connected peer. | ||
1076 | * | ||
1077 | * @param channel The channel handle from which to get the MQ. | ||
1078 | * | ||
1079 | * @return NULL if @a channel is not yet connected. | ||
1080 | */ | ||
1081 | struct GNUNET_MQ_Handle * | ||
1082 | GNUNET_CADET_get_mq (const struct GNUNET_CADET_Channel *channel) | ||
1083 | { | ||
1084 | return channel->mq; | ||
1085 | } | ||
1086 | |||
1087 | |||
1088 | /* end of cadet_api.c */ | ||
diff --git a/src/cadet/cadet_api_drop_message.c b/src/cadet/cadet_api_drop_message.c deleted file mode 100644 index 2b031b5c0..000000000 --- a/src/cadet/cadet_api_drop_message.c +++ /dev/null | |||
@@ -1,59 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2011, 2017, 2019 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file cadet/cadet_api_drop_message.c | ||
22 | * @brief cadet api: client implementation of cadet service | ||
23 | * @author t3sserakt | ||
24 | */ | ||
25 | #include "platform.h" | ||
26 | #include "cadet.h" | ||
27 | |||
28 | |||
29 | /** | ||
30 | * Drop the next cadet message of a given type.. | ||
31 | * | ||
32 | * @param mq message queue | ||
33 | * @param ccn client channel number. | ||
34 | * @param type of cadet message to be dropped. | ||
35 | */ | ||
36 | void | ||
37 | GNUNET_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 | */ | ||
37 | struct 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 | */ | ||
84 | static int | ||
85 | check_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 | */ | ||
100 | static void | ||
101 | handle_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 | */ | ||
121 | static void | ||
122 | handle_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 | */ | ||
138 | static void | ||
139 | reconnect (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 | */ | ||
148 | static void | ||
149 | error_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 | */ | ||
169 | static void | ||
170 | reconnect (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 | */ | ||
212 | struct GNUNET_CADET_ChannelMonitor * | ||
213 | GNUNET_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 | */ | ||
246 | void * | ||
247 | GNUNET_CADET_get_channel_cancel (struct GNUNET_CADET_ChannelMonitor *cm) | ||
248 | { | ||
249 | void *ret = cm->channel_cb_cls; | ||
250 | |||
251 | if (NULL != cm->mq) | ||
252 | GNUNET_MQ_destroy (cm->mq); | ||
253 | if (NULL != cm->reconnect_task) | ||
254 | GNUNET_SCHEDULER_cancel (cm->reconnect_task); | ||
255 | GNUNET_free (cm); | ||
256 | return ret; | ||
257 | } | ||
258 | |||
259 | |||
260 | /* end of cadet_api_get_channel.c */ | ||
diff --git a/src/cadet/cadet_api_get_path.c b/src/cadet/cadet_api_get_path.c deleted file mode 100644 index 68070eab2..000000000 --- a/src/cadet/cadet_api_get_path.c +++ /dev/null | |||
@@ -1,276 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2011, 2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file cadet/cadet_api_get_path.c | ||
22 | * @brief cadet api: client implementation of cadet service | ||
23 | * @author Bartlomiej Polot | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include "gnunet_util_lib.h" | ||
28 | #include "gnunet_constants.h" | ||
29 | #include "gnunet_cadet_service.h" | ||
30 | #include "cadet.h" | ||
31 | #include "cadet_protocol.h" | ||
32 | |||
33 | |||
34 | /** | ||
35 | * Operation handle. | ||
36 | */ | ||
37 | struct 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 | */ | ||
84 | static int | ||
85 | check_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 | */ | ||
113 | static void | ||
114 | handle_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 | */ | ||
136 | static void | ||
137 | handle_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 | */ | ||
154 | static void | ||
155 | reconnect (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 | */ | ||
164 | static void | ||
165 | error_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 | */ | ||
185 | static void | ||
186 | reconnect (void *cls) | ||
187 | { | ||
188 | struct GNUNET_CADET_GetPath *gp = cls; | ||
189 | struct GNUNET_MQ_MessageHandler handlers[] = { | ||
190 | GNUNET_MQ_hd_var_size (get_path, | ||
191 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PATH, | ||
192 | struct GNUNET_CADET_LocalInfoPath, | ||
193 | gp), | ||
194 | GNUNET_MQ_hd_fixed_size (get_path_end, | ||
195 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PATH_END, | ||
196 | struct GNUNET_MessageHeader, | ||
197 | gp), | ||
198 | GNUNET_MQ_handler_end () | ||
199 | }; | ||
200 | struct GNUNET_CADET_RequestPathInfoMessage *msg; | ||
201 | struct GNUNET_MQ_Envelope *env; | ||
202 | |||
203 | gp->reconnect_task = NULL; | ||
204 | gp->mq = GNUNET_CLIENT_connect (gp->cfg, | ||
205 | "cadet", | ||
206 | handlers, | ||
207 | &error_handler, | ||
208 | gp); | ||
209 | if (NULL == gp->mq) | ||
210 | return; | ||
211 | env = GNUNET_MQ_msg (msg, | ||
212 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_PATH); | ||
213 | msg->peer = gp->id; | ||
214 | GNUNET_MQ_send (gp->mq, | ||
215 | env); | ||
216 | } | ||
217 | |||
218 | |||
219 | /** | ||
220 | * Request information about paths known to the running cadet peer. | ||
221 | * | ||
222 | * @param cfg configuration to use | ||
223 | * @param id Peer whose paths to examine. | ||
224 | * @param callback Function to call with the requested data. | ||
225 | * @param callback_cls Closure for @c callback. | ||
226 | * @return NULL on error | ||
227 | */ | ||
228 | struct GNUNET_CADET_GetPath * | ||
229 | GNUNET_CADET_get_path (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
230 | const struct GNUNET_PeerIdentity *id, | ||
231 | GNUNET_CADET_PathCB callback, | ||
232 | void *callback_cls) | ||
233 | { | ||
234 | struct GNUNET_CADET_GetPath *gp; | ||
235 | |||
236 | if (NULL == callback) | ||
237 | { | ||
238 | GNUNET_break (0); | ||
239 | return NULL; | ||
240 | } | ||
241 | gp = GNUNET_new (struct GNUNET_CADET_GetPath); | ||
242 | gp->path_cb = callback; | ||
243 | gp->path_cb_cls = callback_cls; | ||
244 | gp->cfg = cfg; | ||
245 | gp->id = *id; | ||
246 | reconnect (gp); | ||
247 | if (NULL == gp->mq) | ||
248 | { | ||
249 | GNUNET_free (gp); | ||
250 | return NULL; | ||
251 | } | ||
252 | return gp; | ||
253 | } | ||
254 | |||
255 | |||
256 | /** | ||
257 | * Cancel @a gp operation. | ||
258 | * | ||
259 | * @param gp operation to cancel | ||
260 | * @return closure from #GNUNET_CADET_get_path(). | ||
261 | */ | ||
262 | void * | ||
263 | GNUNET_CADET_get_path_cancel (struct GNUNET_CADET_GetPath *gp) | ||
264 | { | ||
265 | void *ret = gp->path_cb_cls; | ||
266 | |||
267 | if (NULL != gp->mq) | ||
268 | GNUNET_MQ_destroy (gp->mq); | ||
269 | if (NULL != gp->reconnect_task) | ||
270 | GNUNET_SCHEDULER_cancel (gp->reconnect_task); | ||
271 | GNUNET_free (gp); | ||
272 | return ret; | ||
273 | } | ||
274 | |||
275 | |||
276 | /* end of cadet_api_get_path.c */ | ||
diff --git a/src/cadet/cadet_api_helper.c b/src/cadet/cadet_api_helper.c deleted file mode 100644 index 52aec6cc9..000000000 --- a/src/cadet/cadet_api_helper.c +++ /dev/null | |||
@@ -1,54 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2011, 2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file cadet/cadet_api_helper.c | ||
22 | * @brief cadet api: client implementation of cadet service | ||
23 | * @author Bartlomiej Polot | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include "gnunet_util_lib.h" | ||
28 | #include "gnunet_constants.h" | ||
29 | #include "gnunet_cadet_service.h" | ||
30 | #include "cadet.h" | ||
31 | #include "cadet_protocol.h" | ||
32 | |||
33 | |||
34 | /** | ||
35 | * Transitional function to convert an unsigned int port to a hash value. | ||
36 | * WARNING: local static value returned, NOT reentrant! | ||
37 | * WARNING: do not use this function for new code! | ||
38 | * | ||
39 | * @param port Numerical port (unsigned int format). | ||
40 | * | ||
41 | * @return A GNUNET_HashCode usable for the new CADET API. | ||
42 | */ | ||
43 | const struct GNUNET_HashCode * | ||
44 | GC_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 | */ | ||
37 | struct 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 | */ | ||
77 | static void | ||
78 | handle_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 | */ | ||
99 | static void | ||
100 | handle_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 | */ | ||
118 | static void | ||
119 | reconnect (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 | */ | ||
128 | static void | ||
129 | error_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 | */ | ||
149 | static void | ||
150 | reconnect (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 | */ | ||
192 | struct GNUNET_CADET_PeersLister * | ||
193 | GNUNET_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 | */ | ||
224 | void * | ||
225 | GNUNET_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 | */ | ||
37 | struct 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 | */ | ||
77 | static void | ||
78 | handle_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 | */ | ||
100 | static void | ||
101 | handle_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 | */ | ||
119 | static void | ||
120 | reconnect (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 | */ | ||
129 | static void | ||
130 | error_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 | */ | ||
150 | static void | ||
151 | reconnect (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 | */ | ||
193 | struct GNUNET_CADET_ListTunnels * | ||
194 | GNUNET_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 | */ | ||
225 | void * | ||
226 | GNUNET_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 | |||
45 | struct GNUNET_CADET_TunnelMessage; | ||
46 | extern "C" | ||
47 | { | ||
48 | #if 0 | ||
49 | /* keep Emacsens' auto-indent happy */ | ||
50 | } | ||
51 | #endif | ||
52 | #endif | ||
53 | |||
54 | /******************************************************************************/ | ||
55 | /******************** CADET NETWORK MESSAGES **************************/ | ||
56 | /******************************************************************************/ | ||
57 | |||
58 | GNUNET_NETWORK_STRUCT_BEGIN | ||
59 | |||
60 | |||
61 | /******************************************************************************/ | ||
62 | /***************************** CONNECTION **********************************/ | ||
63 | /******************************************************************************/ | ||
64 | |||
65 | |||
66 | /** | ||
67 | * Message for cadet connection creation. | ||
68 | */ | ||
69 | struct 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 | */ | ||
121 | struct 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 | */ | ||
143 | struct 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 | */ | ||
175 | struct 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 | */ | ||
205 | struct 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 | */ | ||
218 | enum 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 | */ | ||
235 | struct 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 | */ | ||
291 | struct 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 | */ | ||
319 | struct 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 | */ | ||
341 | struct 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 | */ | ||
385 | struct 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 | */ | ||
413 | struct 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 | */ | ||
442 | struct 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 | */ | ||
464 | struct 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 | */ | ||
476 | struct 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 | */ | ||
502 | struct 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 | |||
530 | GNUNET_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 | */ | ||
34 | struct 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 | */ | ||
101 | struct 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 | */ | ||
130 | static void * | ||
131 | cadet_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 | */ | ||
169 | static void | ||
170 | cadet_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 | */ | ||
200 | static void | ||
201 | cadet_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 | |||
237 | void | ||
238 | GNUNET_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 | */ | ||
267 | static void | ||
268 | cadet_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 | */ | ||
337 | void | ||
338 | GNUNET_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 | ||
29 | extern "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 | */ | ||
42 | struct 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 | */ | ||
54 | typedef 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 | */ | ||
76 | void | ||
77 | GNUNET_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 | */ | ||
93 | void | ||
94 | GNUNET_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 | |||
10 | int | ||
11 | main () | ||
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 | */ | ||
59 | static float rounds[] = { 0.8, 0.6, 0.8, 0.5, 0.3, 0.8, 0.0 }; | ||
60 | |||
61 | /** | ||
62 | * Message type for pings. | ||
63 | */ | ||
64 | struct 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 | */ | ||
90 | struct 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 | */ | ||
166 | static struct GNUNET_TIME_Relative round_time; | ||
167 | |||
168 | /** | ||
169 | * GNUNET_PeerIdentity -> CadetPeer | ||
170 | */ | ||
171 | static struct GNUNET_CONTAINER_MultiPeerMap *ids; | ||
172 | |||
173 | /** | ||
174 | * Testbed peer handles. | ||
175 | */ | ||
176 | static struct GNUNET_TESTBED_Peer **testbed_handles; | ||
177 | |||
178 | /** | ||
179 | * Testbed Operation (to get stats). | ||
180 | */ | ||
181 | static struct GNUNET_TESTBED_Operation *stats_op; | ||
182 | |||
183 | /** | ||
184 | * Operation to get peer ids. | ||
185 | */ | ||
186 | static struct CadetPeer *peers; | ||
187 | |||
188 | /** | ||
189 | * Peer ids counter. | ||
190 | */ | ||
191 | static unsigned int p_ids; | ||
192 | |||
193 | /** | ||
194 | * Total number of peers. | ||
195 | */ | ||
196 | static unsigned long long peers_total; | ||
197 | |||
198 | /** | ||
199 | * Number of currently running peers. | ||
200 | */ | ||
201 | static unsigned long long peers_running; | ||
202 | |||
203 | /** | ||
204 | * Number of peers doing pings. | ||
205 | */ | ||
206 | static unsigned long long peers_pinging; | ||
207 | |||
208 | /** | ||
209 | * Test context (to shut down). | ||
210 | */ | ||
211 | static struct GNUNET_CADET_TEST_Context *test_ctx; | ||
212 | |||
213 | /** | ||
214 | * Task called to disconnect peers, before shutdown. | ||
215 | */ | ||
216 | static struct GNUNET_SCHEDULER_Task *disconnect_task; | ||
217 | |||
218 | /** | ||
219 | * Task to perform tests | ||
220 | */ | ||
221 | static struct GNUNET_SCHEDULER_Task *test_task; | ||
222 | |||
223 | /** | ||
224 | * Round number. | ||
225 | */ | ||
226 | static unsigned int current_round; | ||
227 | |||
228 | /** | ||
229 | * Do preconnect? (Each peer creates a tunnel to one other peer). | ||
230 | */ | ||
231 | static int do_warmup; | ||
232 | |||
233 | /** | ||
234 | * Warmup progress. | ||
235 | */ | ||
236 | static unsigned int peers_warmup; | ||
237 | |||
238 | /** | ||
239 | * Flag to notify callbacks not to generate any new traffic anymore. | ||
240 | */ | ||
241 | static int test_finished; | ||
242 | |||
243 | /** | ||
244 | * Task running each round of the benchmark. | ||
245 | */ | ||
246 | static 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 | */ | ||
257 | static void | ||
258 | start_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 | */ | ||
268 | static struct GNUNET_TIME_Relative | ||
269 | delay_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 | */ | ||
285 | static unsigned int | ||
286 | get_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 | */ | ||
295 | static void | ||
296 | show_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 | */ | ||
321 | static void | ||
322 | disconnect_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 | */ | ||
370 | static void | ||
371 | shutdown_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 | */ | ||
399 | static void | ||
400 | abort_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 | */ | ||
420 | static void | ||
421 | stats_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 | */ | ||
444 | static int | ||
445 | stats_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 | */ | ||
469 | static void | ||
470 | collect_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 | */ | ||
487 | static void | ||
488 | finish_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 | */ | ||
501 | static void | ||
502 | adjust_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 | */ | ||
572 | static void | ||
573 | next_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 | */ | ||
602 | static size_t | ||
603 | tmt_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 | */ | ||
613 | static size_t | ||
614 | tmt_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 | */ | ||
638 | static void | ||
639 | ping (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 | */ | ||
665 | static void | ||
666 | pong (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 | */ | ||
687 | static size_t | ||
688 | tmt_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 | */ | ||
734 | int | ||
735 | ping_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 | */ | ||
762 | int | ||
763 | pong_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 | */ | ||
802 | static 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 | */ | ||
821 | static void * | ||
822 | incoming_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 | */ | ||
872 | static void | ||
873 | channel_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 | */ | ||
894 | static struct CadetPeer * | ||
895 | select_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 | */ | ||
918 | static void | ||
919 | start_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 | */ | ||
965 | static void | ||
966 | warmup (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 | */ | ||
998 | static void | ||
999 | peer_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 | */ | ||
1053 | static void | ||
1054 | tmain (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 | */ | ||
1092 | int | ||
1093 | main (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 | */ | ||
37 | static int request_peers; | ||
38 | |||
39 | /** | ||
40 | * Option --peer | ||
41 | */ | ||
42 | static char *peer_id; | ||
43 | |||
44 | /** | ||
45 | * Option -T. | ||
46 | */ | ||
47 | static int request_tunnels; | ||
48 | |||
49 | /** | ||
50 | * Option --connection | ||
51 | */ | ||
52 | static char *conn_id; | ||
53 | |||
54 | /** | ||
55 | * Option --channel | ||
56 | */ | ||
57 | static char *channel_id; | ||
58 | |||
59 | /** | ||
60 | * Port to listen on (-o). | ||
61 | */ | ||
62 | static char *listen_port; | ||
63 | |||
64 | /** | ||
65 | * Request echo service | ||
66 | */ | ||
67 | static int echo; | ||
68 | |||
69 | /** | ||
70 | * Time of last echo request. | ||
71 | */ | ||
72 | static struct GNUNET_TIME_Absolute echo_time; | ||
73 | |||
74 | /** | ||
75 | * Task for next echo request. | ||
76 | */ | ||
77 | static struct GNUNET_SCHEDULER_Task *echo_task; | ||
78 | |||
79 | /** | ||
80 | * Peer to connect to. | ||
81 | */ | ||
82 | static char *target_id; | ||
83 | |||
84 | /** | ||
85 | * Port to connect to | ||
86 | */ | ||
87 | static char *target_port = "default"; | ||
88 | |||
89 | /** | ||
90 | * Cadet handle. | ||
91 | */ | ||
92 | static struct GNUNET_CADET_Handle *mh; | ||
93 | |||
94 | /** | ||
95 | * Our configuration. | ||
96 | */ | ||
97 | static const struct GNUNET_CONFIGURATION_Handle *my_cfg; | ||
98 | |||
99 | /** | ||
100 | * Active get path operation. | ||
101 | */ | ||
102 | static struct GNUNET_CADET_GetPath *gpo; | ||
103 | |||
104 | /** | ||
105 | * Active peer listing operation. | ||
106 | */ | ||
107 | static struct GNUNET_CADET_PeersLister *plo; | ||
108 | |||
109 | /** | ||
110 | * Active tunnel listing operation. | ||
111 | */ | ||
112 | static struct GNUNET_CADET_ListTunnels *tio; | ||
113 | |||
114 | /** | ||
115 | * Channel handle. | ||
116 | */ | ||
117 | static struct GNUNET_CADET_Channel *ch; | ||
118 | |||
119 | /** | ||
120 | * HashCode of the given port string | ||
121 | */ | ||
122 | static struct GNUNET_HashCode porthash; | ||
123 | |||
124 | /** | ||
125 | * Data structure for ongoing reception of incoming virtual circuits. | ||
126 | */ | ||
127 | struct GNUNET_CADET_Port *lp; | ||
128 | |||
129 | /** | ||
130 | * Task for reading from stdin. | ||
131 | */ | ||
132 | static struct GNUNET_SCHEDULER_Task *rd_task; | ||
133 | |||
134 | /** | ||
135 | * Task for main job. | ||
136 | */ | ||
137 | static struct GNUNET_SCHEDULER_Task *job; | ||
138 | |||
139 | static unsigned int sent_pkt; | ||
140 | |||
141 | |||
142 | /** | ||
143 | * Wait for input on STDIO and send it out over the #ch. | ||
144 | */ | ||
145 | static void | ||
146 | listen_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 | */ | ||
156 | static const char * | ||
157 | enc_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 | */ | ||
186 | static const char * | ||
187 | conn_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 | */ | ||
217 | static void | ||
218 | shutdown_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 | |||
269 | void | ||
270 | mq_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 | */ | ||
281 | static void | ||
282 | read_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 | */ | ||
331 | static void | ||
332 | listen_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 | */ | ||
358 | static void | ||
359 | channel_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 | */ | ||
382 | static void * | ||
383 | channel_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 | */ | ||
406 | static void | ||
407 | send_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 | */ | ||
428 | static int | ||
429 | check_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 | */ | ||
445 | static void | ||
446 | handle_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 | */ | ||
511 | static void | ||
512 | peers_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 | */ | ||
535 | static void | ||
536 | path_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 | */ | ||
559 | static void | ||
560 | tunnels_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 | */ | ||
583 | static void | ||
584 | get_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 | */ | ||
596 | static void | ||
597 | show_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 | */ | ||
619 | static void | ||
620 | get_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 | */ | ||
632 | static void | ||
633 | show_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 | */ | ||
645 | static void | ||
646 | show_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 | */ | ||
661 | static void | ||
662 | run (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 | */ | ||
789 | int | ||
790 | main (int argc, char *const *argv) | ||
791 | { | ||
792 | int res; | ||
793 | const char helpstr[] = | ||
794 | "Create tunnels and retrieve info about CADET's status."; | ||
795 | struct GNUNET_GETOPT_CommandLineOption options[] = { /* I would use the terminology 'circuit' here... --lynX */ | ||
796 | GNUNET_GETOPT_option_string ( | ||
797 | 'C', | ||
798 | "connection", | ||
799 | "CONNECTION_ID", | ||
800 | gettext_noop ("Provide information about a particular connection"), | ||
801 | &conn_id), | ||
802 | GNUNET_GETOPT_option_flag ('e', | ||
803 | "echo", | ||
804 | gettext_noop ("Activate echo mode"), | ||
805 | &echo), | ||
806 | GNUNET_GETOPT_option_string ( | ||
807 | 'o', | ||
808 | "open-port", | ||
809 | "SHARED_SECRET", | ||
810 | gettext_noop ( | ||
811 | "Listen for connections using a shared secret among sender and recipient"), | ||
812 | &listen_port), | ||
813 | GNUNET_GETOPT_option_string ('p', | ||
814 | "peer", | ||
815 | "PEER_ID", | ||
816 | gettext_noop ( | ||
817 | "Provide information about a patricular peer"), | ||
818 | &peer_id), | ||
819 | GNUNET_GETOPT_option_flag ('P', | ||
820 | "peers", | ||
821 | gettext_noop ( | ||
822 | "Provide information about all peers"), | ||
823 | &request_peers), | ||
824 | GNUNET_GETOPT_option_flag ('T', | ||
825 | "tunnels", | ||
826 | gettext_noop ( | ||
827 | "Provide information about all tunnels"), | ||
828 | &request_tunnels), | ||
829 | GNUNET_GETOPT_OPTION_END | ||
830 | }; | ||
831 | |||
832 | if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) | ||
833 | return 2; | ||
834 | |||
835 | res = GNUNET_PROGRAM_run (argc, | ||
836 | argv, | ||
837 | "gnunet-cadet (OPTIONS | PEER_ID SHARED_SECRET)", | ||
838 | gettext_noop (helpstr), | ||
839 | options, | ||
840 | &run, | ||
841 | NULL); | ||
842 | |||
843 | GNUNET_free_nz ((void *) argv); | ||
844 | |||
845 | if (GNUNET_OK == res) | ||
846 | return 0; | ||
847 | return 1; | ||
848 | } | ||
849 | |||
850 | |||
851 | /* end of gnunet-cadet.c */ | ||
diff --git a/src/cadet/gnunet-service-cadet.c b/src/cadet/gnunet-service-cadet.c deleted file mode 100644 index 73e463e9b..000000000 --- a/src/cadet/gnunet-service-cadet.c +++ /dev/null | |||
@@ -1,1381 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2001-2013, 2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/gnunet-service-cadet.c | ||
23 | * @brief GNUnet CADET service with encryption | ||
24 | * @author Bartlomiej Polot | ||
25 | * @author Christian Grothoff | ||
26 | * | ||
27 | * Dictionary: | ||
28 | * - peer: other cadet instance. If there is direct connection it's a neighbor. | ||
29 | * - path: series of directly connected peer from one peer to another. | ||
30 | * - connection: path which is being used in a tunnel. | ||
31 | * - tunnel: encrypted connection to a peer, neighbor or not. | ||
32 | * - channel: logical link between two clients, on the same or different peers. | ||
33 | * have properties like reliability. | ||
34 | */ | ||
35 | #include "platform.h" | ||
36 | #include "gnunet_util_lib.h" | ||
37 | #include "cadet.h" | ||
38 | #include "gnunet_statistics_service.h" | ||
39 | #include "gnunet-service-cadet.h" | ||
40 | #include "gnunet-service-cadet_channel.h" | ||
41 | #include "gnunet-service-cadet_connection.h" | ||
42 | #include "gnunet-service-cadet_core.h" | ||
43 | #include "gnunet-service-cadet_dht.h" | ||
44 | #include "gnunet-service-cadet_hello.h" | ||
45 | #include "gnunet-service-cadet_tunnels.h" | ||
46 | #include "gnunet-service-cadet_peer.h" | ||
47 | #include "gnunet-service-cadet_paths.h" | ||
48 | |||
49 | #define LOG(level, ...) GNUNET_log (level, __VA_ARGS__) | ||
50 | |||
51 | |||
52 | /** | ||
53 | * Struct containing information about a client of the service | ||
54 | */ | ||
55 | struct 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 | */ | ||
111 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
112 | |||
113 | /** | ||
114 | * Handle to the statistics service. | ||
115 | */ | ||
116 | struct GNUNET_STATISTICS_Handle *stats; | ||
117 | |||
118 | /** | ||
119 | * Handle to communicate with ATS. | ||
120 | */ | ||
121 | struct GNUNET_ATS_ConnectivityHandle *ats_ch; | ||
122 | |||
123 | /** | ||
124 | * Local peer own ID. | ||
125 | */ | ||
126 | struct GNUNET_PeerIdentity my_full_id; | ||
127 | |||
128 | /** | ||
129 | * Own private key. | ||
130 | */ | ||
131 | struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key; | ||
132 | |||
133 | /** | ||
134 | * Signal that shutdown is happening: prevent recovery measures. | ||
135 | */ | ||
136 | int shutting_down; | ||
137 | |||
138 | /** | ||
139 | * DLL with all the clients, head. | ||
140 | */ | ||
141 | static struct CadetClient *clients_head; | ||
142 | |||
143 | /** | ||
144 | * DLL with all the clients, tail. | ||
145 | */ | ||
146 | static struct CadetClient *clients_tail; | ||
147 | |||
148 | /** | ||
149 | * Next ID to assign to a client. | ||
150 | */ | ||
151 | static 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 | */ | ||
157 | struct 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 | */ | ||
164 | struct GNUNET_CONTAINER_MultiHashMap *loose_channels; | ||
165 | |||
166 | /** | ||
167 | * Map from PIDs to `struct CadetPeer` entries. | ||
168 | */ | ||
169 | struct GNUNET_CONTAINER_MultiPeerMap *peers; | ||
170 | |||
171 | /** | ||
172 | * Map from `struct GNUNET_CADET_ConnectionTunnelIdentifier` | ||
173 | * hash codes to `struct CadetConnection` objects. | ||
174 | */ | ||
175 | struct GNUNET_CONTAINER_MultiShortmap *connections; | ||
176 | |||
177 | /** | ||
178 | * How many messages are needed to trigger an AXOLOTL ratchet advance. | ||
179 | */ | ||
180 | unsigned long long ratchet_messages; | ||
181 | |||
182 | /** | ||
183 | * How long until we trigger a ratched advance due to time. | ||
184 | */ | ||
185 | struct GNUNET_TIME_Relative ratchet_time; | ||
186 | |||
187 | /** | ||
188 | * How frequently do we send KEEPALIVE messages on idle connections? | ||
189 | */ | ||
190 | struct GNUNET_TIME_Relative keepalive_period; | ||
191 | |||
192 | /** | ||
193 | * Set to non-zero values to create random drops to test retransmissions. | ||
194 | */ | ||
195 | unsigned 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 | */ | ||
204 | void | ||
205 | GSC_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 | */ | ||
219 | const char * | ||
220 | GSC_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 | */ | ||
239 | static struct CadetChannel * | ||
240 | lookup_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 | */ | ||
254 | static struct GNUNET_CADET_ClientChannelNumber | ||
255 | client_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 | */ | ||
288 | struct GNUNET_CADET_ClientChannelNumber | ||
289 | GSC_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 | */ | ||
335 | static int | ||
336 | destroy_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 | */ | ||
359 | static int | ||
360 | destroy_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 | */ | ||
374 | static void | ||
375 | shutdown_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 | */ | ||
428 | static void | ||
429 | shutdown_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 | */ | ||
449 | static int | ||
450 | bind_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 | */ | ||
477 | static void | ||
478 | handle_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 | */ | ||
528 | static void | ||
529 | handle_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 | */ | ||
573 | static void | ||
574 | handle_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 | */ | ||
635 | static void | ||
636 | handle_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 | */ | ||
680 | static int | ||
681 | check_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 | */ | ||
734 | static void | ||
735 | handle_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 | */ | ||
785 | static void | ||
786 | handle_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 | */ | ||
821 | static int | ||
822 | get_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 | */ | ||
850 | static void | ||
851 | handle_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 | */ | ||
878 | static int | ||
879 | path_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 | */ | ||
931 | static void | ||
932 | handle_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 | */ | ||
962 | static int | ||
963 | get_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 | */ | ||
996 | static void | ||
997 | handle_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 | */ | ||
1020 | static void | ||
1021 | handle_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 | */ | ||
1045 | static void * | ||
1046 | client_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 | */ | ||
1079 | void | ||
1080 | GSC_handle_remote_channel_destroy (struct CadetClient *c, | ||
1081 | struct GNUNET_CADET_ClientChannelNumber ccn, | ||
1082 | struct CadetChannel *ch) | ||
1083 | { | ||
1084 | struct GNUNET_MQ_Envelope *env; | ||
1085 | struct GNUNET_CADET_LocalChannelDestroyMessage *tdm; | ||
1086 | |||
1087 | env = GNUNET_MQ_msg (tdm, | ||
1088 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY); | ||
1089 | tdm->ccn = ccn; | ||
1090 | GSC_send_to_client (c, | ||
1091 | env); | ||
1092 | GNUNET_assert (GNUNET_YES == | ||
1093 | GNUNET_CONTAINER_multihashmap32_remove (c->channels, | ||
1094 | ntohl ( | ||
1095 | ccn.channel_of_client), | ||
1096 | ch)); | ||
1097 | } | ||
1098 | |||
1099 | |||
1100 | /** | ||
1101 | * A client that created a loose channel that was not bound to a port | ||
1102 | * disconnected, drop it from the #loose_channels list. | ||
1103 | * | ||
1104 | * @param h_port the hashed port the channel was trying to bind to | ||
1105 | * @param ch the channel that was lost | ||
1106 | */ | ||
1107 | void | ||
1108 | GSC_drop_loose_channel (const struct GNUNET_HashCode *h_port, | ||
1109 | struct CadetChannel *ch) | ||
1110 | { | ||
1111 | GNUNET_assert (GNUNET_YES == | ||
1112 | GNUNET_CONTAINER_multihashmap_remove (loose_channels, | ||
1113 | h_port, | ||
1114 | ch)); | ||
1115 | } | ||
1116 | |||
1117 | |||
1118 | /** | ||
1119 | * Iterator for deleting each channel whose client endpoint disconnected. | ||
1120 | * | ||
1121 | * @param cls Closure (client that has disconnected). | ||
1122 | * @param key The local channel id in host byte order | ||
1123 | * @param value The value stored at the key (channel to destroy). | ||
1124 | * @return #GNUNET_OK, keep iterating. | ||
1125 | */ | ||
1126 | static int | ||
1127 | channel_destroy_iterator (void *cls, | ||
1128 | uint32_t key, | ||
1129 | void *value) | ||
1130 | { | ||
1131 | struct CadetClient *c = cls; | ||
1132 | struct GNUNET_CADET_ClientChannelNumber ccn; | ||
1133 | struct CadetChannel *ch = value; | ||
1134 | |||
1135 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1136 | "Destroying %s, due to %s disconnecting.\n", | ||
1137 | GCCH_2s (ch), | ||
1138 | GSC_2s (c)); | ||
1139 | ccn.channel_of_client = htonl (key); | ||
1140 | GNUNET_assert (GNUNET_YES == | ||
1141 | GNUNET_CONTAINER_multihashmap32_remove (c->channels, | ||
1142 | key, | ||
1143 | ch)); | ||
1144 | GCCH_channel_local_destroy (ch, | ||
1145 | c, | ||
1146 | ccn); | ||
1147 | return GNUNET_OK; | ||
1148 | } | ||
1149 | |||
1150 | |||
1151 | /** | ||
1152 | * Remove client's ports from the global hashmap on disconnect. | ||
1153 | * | ||
1154 | * @param cls the `struct CadetClient` | ||
1155 | * @param port the port. | ||
1156 | * @param value the `struct OpenPort` to remove | ||
1157 | * @return #GNUNET_OK, keep iterating. | ||
1158 | */ | ||
1159 | static int | ||
1160 | client_release_ports (void *cls, | ||
1161 | const struct GNUNET_HashCode *port, | ||
1162 | void *value) | ||
1163 | { | ||
1164 | struct CadetClient *c = cls; | ||
1165 | struct OpenPort *op = value; | ||
1166 | |||
1167 | GNUNET_assert (c == op->c); | ||
1168 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1169 | "Closing port %s due to %s disconnect.\n", | ||
1170 | GNUNET_h2s (port), | ||
1171 | GSC_2s (c)); | ||
1172 | GNUNET_assert (GNUNET_YES == | ||
1173 | GNUNET_CONTAINER_multihashmap_remove (open_ports, | ||
1174 | &op->h_port, | ||
1175 | op)); | ||
1176 | GNUNET_assert (GNUNET_YES == | ||
1177 | GNUNET_CONTAINER_multihashmap_remove (c->ports, | ||
1178 | port, | ||
1179 | op)); | ||
1180 | GNUNET_free (op); | ||
1181 | return GNUNET_OK; | ||
1182 | } | ||
1183 | |||
1184 | |||
1185 | /** | ||
1186 | * Callback called when a client disconnected from the service | ||
1187 | * | ||
1188 | * @param cls closure for the service | ||
1189 | * @param client the client that disconnected | ||
1190 | * @param internal_cls should be equal to @a c | ||
1191 | */ | ||
1192 | static void | ||
1193 | client_disconnect_cb (void *cls, | ||
1194 | struct GNUNET_SERVICE_Client *client, | ||
1195 | void *internal_cls) | ||
1196 | { | ||
1197 | struct CadetClient *c = internal_cls; | ||
1198 | |||
1199 | GNUNET_assert (c->client == client); | ||
1200 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1201 | "%s is disconnecting.\n", | ||
1202 | GSC_2s (c)); | ||
1203 | if (NULL != c->channels) | ||
1204 | { | ||
1205 | GNUNET_CONTAINER_multihashmap32_iterate (c->channels, | ||
1206 | &channel_destroy_iterator, | ||
1207 | c); | ||
1208 | GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap32_size (c->channels)); | ||
1209 | GNUNET_CONTAINER_multihashmap32_destroy (c->channels); | ||
1210 | } | ||
1211 | if (NULL != c->ports) | ||
1212 | { | ||
1213 | GNUNET_CONTAINER_multihashmap_iterate (c->ports, | ||
1214 | &client_release_ports, | ||
1215 | c); | ||
1216 | GNUNET_CONTAINER_multihashmap_destroy (c->ports); | ||
1217 | } | ||
1218 | GNUNET_CONTAINER_DLL_remove (clients_head, | ||
1219 | clients_tail, | ||
1220 | c); | ||
1221 | GNUNET_STATISTICS_update (stats, | ||
1222 | "# clients", | ||
1223 | -1, | ||
1224 | GNUNET_NO); | ||
1225 | GNUNET_free (c); | ||
1226 | if ((NULL == clients_head) && | ||
1227 | (GNUNET_YES == shutting_down)) | ||
1228 | shutdown_rest (); | ||
1229 | } | ||
1230 | |||
1231 | |||
1232 | /** | ||
1233 | * Setup CADET internals. | ||
1234 | * | ||
1235 | * @param cls closure | ||
1236 | * @param server the initialized server | ||
1237 | * @param c configuration to use | ||
1238 | */ | ||
1239 | static void | ||
1240 | run (void *cls, | ||
1241 | const struct GNUNET_CONFIGURATION_Handle *c, | ||
1242 | struct GNUNET_SERVICE_Handle *service) | ||
1243 | { | ||
1244 | cfg = c; | ||
1245 | if (GNUNET_OK != | ||
1246 | GNUNET_CONFIGURATION_get_value_number (c, | ||
1247 | "CADET", | ||
1248 | "RATCHET_MESSAGES", | ||
1249 | &ratchet_messages)) | ||
1250 | { | ||
1251 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, | ||
1252 | "CADET", | ||
1253 | "RATCHET_MESSAGES", | ||
1254 | "needs to be a number"); | ||
1255 | ratchet_messages = 64; | ||
1256 | } | ||
1257 | if (GNUNET_OK != | ||
1258 | GNUNET_CONFIGURATION_get_value_time (c, | ||
1259 | "CADET", | ||
1260 | "RATCHET_TIME", | ||
1261 | &ratchet_time)) | ||
1262 | { | ||
1263 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, | ||
1264 | "CADET", | ||
1265 | "RATCHET_TIME", | ||
1266 | "need delay value"); | ||
1267 | ratchet_time = GNUNET_TIME_UNIT_HOURS; | ||
1268 | } | ||
1269 | if (GNUNET_OK != | ||
1270 | GNUNET_CONFIGURATION_get_value_time (c, | ||
1271 | "CADET", | ||
1272 | "REFRESH_CONNECTION_TIME", | ||
1273 | &keepalive_period)) | ||
1274 | { | ||
1275 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, | ||
1276 | "CADET", | ||
1277 | "REFRESH_CONNECTION_TIME", | ||
1278 | "need delay value"); | ||
1279 | keepalive_period = GNUNET_TIME_UNIT_MINUTES; | ||
1280 | } | ||
1281 | if (GNUNET_OK != | ||
1282 | GNUNET_CONFIGURATION_get_value_number (c, | ||
1283 | "CADET", | ||
1284 | "DROP_PERCENT", | ||
1285 | &drop_percent)) | ||
1286 | { | ||
1287 | drop_percent = 0; | ||
1288 | } | ||
1289 | else | ||
1290 | { | ||
1291 | LOG (GNUNET_ERROR_TYPE_WARNING, "**************************************\n"); | ||
1292 | LOG (GNUNET_ERROR_TYPE_WARNING, "Cadet is running with DROP enabled.\n"); | ||
1293 | LOG (GNUNET_ERROR_TYPE_WARNING, "This is NOT a good idea!\n"); | ||
1294 | LOG (GNUNET_ERROR_TYPE_WARNING, "Remove DROP_PERCENT from config file.\n"); | ||
1295 | LOG (GNUNET_ERROR_TYPE_WARNING, "**************************************\n"); | ||
1296 | } | ||
1297 | my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (c); | ||
1298 | if (NULL == my_private_key) | ||
1299 | { | ||
1300 | GNUNET_break (0); | ||
1301 | GNUNET_SCHEDULER_shutdown (); | ||
1302 | return; | ||
1303 | } | ||
1304 | GNUNET_CRYPTO_eddsa_key_get_public (my_private_key, | ||
1305 | &my_full_id.public_key); | ||
1306 | stats = GNUNET_STATISTICS_create ("cadet", | ||
1307 | c); | ||
1308 | GNUNET_SCHEDULER_add_shutdown (&shutdown_task, | ||
1309 | NULL); | ||
1310 | ats_ch = GNUNET_ATS_connectivity_init (c); | ||
1311 | /* FIXME: optimize code to allow GNUNET_YES here! */ | ||
1312 | open_ports = GNUNET_CONTAINER_multihashmap_create (16, | ||
1313 | GNUNET_NO); | ||
1314 | loose_channels = GNUNET_CONTAINER_multihashmap_create (16, | ||
1315 | GNUNET_NO); | ||
1316 | peers = GNUNET_CONTAINER_multipeermap_create (16, | ||
1317 | GNUNET_YES); | ||
1318 | connections = GNUNET_CONTAINER_multishortmap_create (256, | ||
1319 | GNUNET_YES); | ||
1320 | GCH_init (c); | ||
1321 | GCD_init (c); | ||
1322 | GCO_init (c); | ||
1323 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1324 | "CADET started for peer %s\n", | ||
1325 | GNUNET_i2s (&my_full_id)); | ||
1326 | } | ||
1327 | |||
1328 | |||
1329 | /** | ||
1330 | * Define "main" method using service macro. | ||
1331 | */ | ||
1332 | GNUNET_SERVICE_MAIN | ||
1333 | ("cadet", | ||
1334 | GNUNET_SERVICE_OPTION_NONE, | ||
1335 | &run, | ||
1336 | &client_connect_cb, | ||
1337 | &client_disconnect_cb, | ||
1338 | NULL, | ||
1339 | GNUNET_MQ_hd_fixed_size (port_open, | ||
1340 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN, | ||
1341 | struct GNUNET_CADET_PortMessage, | ||
1342 | NULL), | ||
1343 | GNUNET_MQ_hd_fixed_size (port_close, | ||
1344 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE, | ||
1345 | struct GNUNET_CADET_PortMessage, | ||
1346 | NULL), | ||
1347 | GNUNET_MQ_hd_fixed_size (channel_create, | ||
1348 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE, | ||
1349 | struct GNUNET_CADET_LocalChannelCreateMessage, | ||
1350 | NULL), | ||
1351 | GNUNET_MQ_hd_fixed_size (channel_destroy, | ||
1352 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY, | ||
1353 | struct GNUNET_CADET_LocalChannelDestroyMessage, | ||
1354 | NULL), | ||
1355 | GNUNET_MQ_hd_var_size (local_data, | ||
1356 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA, | ||
1357 | struct GNUNET_CADET_LocalData, | ||
1358 | NULL), | ||
1359 | GNUNET_MQ_hd_fixed_size (local_ack, | ||
1360 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK, | ||
1361 | struct GNUNET_CADET_LocalAck, | ||
1362 | NULL), | ||
1363 | GNUNET_MQ_hd_fixed_size (get_peers, | ||
1364 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_PEERS, | ||
1365 | struct GNUNET_MessageHeader, | ||
1366 | NULL), | ||
1367 | GNUNET_MQ_hd_fixed_size (show_path, | ||
1368 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_PATH, | ||
1369 | struct GNUNET_CADET_RequestPathInfoMessage, | ||
1370 | NULL), | ||
1371 | GNUNET_MQ_hd_fixed_size (info_tunnels, | ||
1372 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_TUNNELS, | ||
1373 | struct GNUNET_MessageHeader, | ||
1374 | NULL), | ||
1375 | GNUNET_MQ_hd_fixed_size (drop_message, | ||
1376 | GNUNET_MESSAGE_TYPE_CADET_DROP_CADET_MESSAGE, | ||
1377 | struct GNUNET_CADET_RequestDropCadetMessage, | ||
1378 | NULL), | ||
1379 | GNUNET_MQ_handler_end ()); | ||
1380 | |||
1381 | /* end of gnunet-service-cadet-new.c */ | ||
diff --git a/src/cadet/gnunet-service-cadet.h b/src/cadet/gnunet-service-cadet.h deleted file mode 100644 index 3d61b9973..000000000 --- a/src/cadet/gnunet-service-cadet.h +++ /dev/null | |||
@@ -1,328 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2001-2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/gnunet-service-cadet.h | ||
23 | * @brief Information we track per peer. | ||
24 | * @author Bartlomiej Polot | ||
25 | * @author Christian Grothoff | ||
26 | */ | ||
27 | #ifndef GNUNET_SERVICE_CADET_H | ||
28 | #define GNUNET_SERVICE_CADET_H | ||
29 | |||
30 | #include "gnunet_util_lib.h" | ||
31 | #include "cadet_protocol.h" | ||
32 | |||
33 | /** | ||
34 | * A client to the CADET service. Each client gets a unique handle. | ||
35 | */ | ||
36 | struct 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 | */ | ||
42 | struct CadetPeer; | ||
43 | |||
44 | /** | ||
45 | * Tunnel from us to another peer. There can only be at most one | ||
46 | * tunnel per peer. | ||
47 | */ | ||
48 | struct CadetTunnel; | ||
49 | |||
50 | /** | ||
51 | * Entry in the message queue of a `struct CadetTunnel`. | ||
52 | */ | ||
53 | struct 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 | */ | ||
61 | struct CadetPeerPath; | ||
62 | |||
63 | /** | ||
64 | * Entry in a peer path. | ||
65 | */ | ||
66 | struct 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 | */ | ||
106 | struct 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 | */ | ||
148 | struct 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 | */ | ||
171 | struct 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 | */ | ||
181 | struct CadetRoute; | ||
182 | |||
183 | /** | ||
184 | * Logical end-to-end connection between clients. There can be | ||
185 | * any number of channels between clients. | ||
186 | */ | ||
187 | struct CadetChannel; | ||
188 | |||
189 | /** | ||
190 | * Handle to our configuration. | ||
191 | */ | ||
192 | extern const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
193 | |||
194 | /** | ||
195 | * Handle to the statistics service. | ||
196 | */ | ||
197 | extern struct GNUNET_STATISTICS_Handle *stats; | ||
198 | |||
199 | /** | ||
200 | * Handle to communicate with ATS. | ||
201 | */ | ||
202 | extern struct GNUNET_ATS_ConnectivityHandle *ats_ch; | ||
203 | |||
204 | /** | ||
205 | * Local peer own ID. | ||
206 | */ | ||
207 | extern struct GNUNET_PeerIdentity my_full_id; | ||
208 | |||
209 | /** | ||
210 | * Own private key. | ||
211 | */ | ||
212 | extern 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 | */ | ||
218 | extern struct GNUNET_CONTAINER_MultiHashMap *open_ports; | ||
219 | |||
220 | /** | ||
221 | * Map from `struct GNUNET_CADET_ConnectionTunnelIdentifier` | ||
222 | * hash codes to `struct CadetConnection` objects. | ||
223 | */ | ||
224 | extern 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 | */ | ||
231 | extern struct GNUNET_CONTAINER_MultiHashMap *loose_channels; | ||
232 | |||
233 | /** | ||
234 | * Map from PIDs to `struct CadetPeer` entries. | ||
235 | */ | ||
236 | extern struct GNUNET_CONTAINER_MultiPeerMap *peers; | ||
237 | |||
238 | /** | ||
239 | * How many messages are needed to trigger an AXOLOTL ratchet advance. | ||
240 | */ | ||
241 | extern unsigned long long ratchet_messages; | ||
242 | |||
243 | /** | ||
244 | * How long until we trigger a ratched advance due to time. | ||
245 | */ | ||
246 | extern struct GNUNET_TIME_Relative ratchet_time; | ||
247 | |||
248 | /** | ||
249 | * How frequently do we send KEEPALIVE messages on idle connections? | ||
250 | */ | ||
251 | extern struct GNUNET_TIME_Relative keepalive_period; | ||
252 | |||
253 | /** | ||
254 | * Signal that shutdown is happening: prevent recovery measures. | ||
255 | */ | ||
256 | extern int shutting_down; | ||
257 | |||
258 | /** | ||
259 | * Set to non-zero values to create random drops to test retransmissions. | ||
260 | */ | ||
261 | extern 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 | */ | ||
270 | void | ||
271 | GSC_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 | */ | ||
282 | void | ||
283 | GSC_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 | */ | ||
294 | void | ||
295 | GSC_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 | */ | ||
310 | struct GNUNET_CADET_ClientChannelNumber | ||
311 | GSC_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 | */ | ||
324 | const char * | ||
325 | GSC_2s (struct CadetClient *c); | ||
326 | |||
327 | |||
328 | #endif | ||
diff --git a/src/cadet/gnunet-service-cadet_channel.c b/src/cadet/gnunet-service-cadet_channel.c deleted file mode 100644 index 9a2180cc1..000000000 --- a/src/cadet/gnunet-service-cadet_channel.c +++ /dev/null | |||
@@ -1,2074 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2001-2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file cadet/gnunet-service-cadet_channel.c | ||
22 | * @brief logical links between CADET clients | ||
23 | * @author Bartlomiej Polot | ||
24 | * @author Christian Grothoff | ||
25 | * | ||
26 | * TODO: | ||
27 | * - Congestion/flow control: | ||
28 | * + estimate max bandwidth using bursts and use to for CONGESTION CONTROL! | ||
29 | * (and figure out how/where to use this!) | ||
30 | * + figure out flow control without ACKs (unreliable traffic!) | ||
31 | * - revisit handling of 'unbuffered' traffic! | ||
32 | * (need to push down through tunnel into connection selection) | ||
33 | * - revisit handling of 'buffered' traffic: 4 is a rather small buffer; maybe | ||
34 | * reserve more bits in 'options' to allow for buffer size control? | ||
35 | */ | ||
36 | #include "platform.h" | ||
37 | #include "cadet.h" | ||
38 | #include "gnunet_statistics_service.h" | ||
39 | #include "gnunet-service-cadet_channel.h" | ||
40 | #include "gnunet-service-cadet_connection.h" | ||
41 | #include "gnunet-service-cadet_tunnels.h" | ||
42 | #include "gnunet-service-cadet_paths.h" | ||
43 | |||
44 | #define LOG(level, ...) GNUNET_log_from (level, "cadet-chn", __VA_ARGS__) | ||
45 | |||
46 | /** | ||
47 | * How long do we initially wait before retransmitting? | ||
48 | */ | ||
49 | #define CADET_INITIAL_RETRANSMIT_TIME \ | ||
50 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 250) | ||
51 | |||
52 | /** | ||
53 | * How long do we wait before dropping state about incoming | ||
54 | * connection to closed port? | ||
55 | */ | ||
56 | #define TIMEOUT_CLOSED_PORT \ | ||
57 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) | ||
58 | |||
59 | /** | ||
60 | * How long do we wait at least before retransmitting ever? | ||
61 | */ | ||
62 | #define MIN_RTT_DELAY \ | ||
63 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 75) | ||
64 | |||
65 | /** | ||
66 | * Maximum message ID into the future we accept for out-of-order messages. | ||
67 | * If the message is more than this into the future, we drop it. This is | ||
68 | * important both to detect values that are actually in the past, as well | ||
69 | * as to limit adversarially triggerable memory consumption. | ||
70 | * | ||
71 | * Note that right now we have "max_pending_messages = 4" hard-coded in | ||
72 | * the logic below, so a value of 4 would suffice here. But we plan to | ||
73 | * allow larger windows in the future... | ||
74 | */ | ||
75 | #define MAX_OUT_OF_ORDER_DISTANCE 1024 | ||
76 | |||
77 | |||
78 | /** | ||
79 | * All the states a channel can be in. | ||
80 | */ | ||
81 | enum 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 | */ | ||
111 | struct 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 | */ | ||
176 | struct 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 | */ | ||
206 | struct 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 | */ | ||
248 | struct CadetChannel | ||
249 | { | ||
250 | /** | ||
251 | * Tunnel this channel is in. | ||
252 | */ | ||
253 | struct CadetTunnel *t; | ||
254 | |||
255 | /** | ||
256 | * Client owner of the tunnel, if any. | ||
257 | * (Used if this channel represends the initiating end of the tunnel.) | ||
258 | */ | ||
259 | struct CadetChannelClient *owner; | ||
260 | |||
261 | /** | ||
262 | * Client destination of the tunnel, if any. | ||
263 | * (Used if this channel represents the listening end of the tunnel.) | ||
264 | */ | ||
265 | struct CadetChannelClient *dest; | ||
266 | |||
267 | /** | ||
268 | * Last entry in the tunnel's queue relating to control messages | ||
269 | * (#GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN or | ||
270 | * #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK). Used to cancel | ||
271 | * transmission in case we receive updated information. | ||
272 | */ | ||
273 | struct CadetTunnelQueueEntry *last_control_qe; | ||
274 | |||
275 | /** | ||
276 | * Head of DLL of messages sent and not yet ACK'd. | ||
277 | */ | ||
278 | struct CadetReliableMessage *head_sent; | ||
279 | |||
280 | /** | ||
281 | * Tail of DLL of messages sent and not yet ACK'd. | ||
282 | */ | ||
283 | struct CadetReliableMessage *tail_sent; | ||
284 | |||
285 | /** | ||
286 | * Task to resend/poll in case no ACK is received. | ||
287 | */ | ||
288 | struct GNUNET_SCHEDULER_Task *retry_control_task; | ||
289 | |||
290 | /** | ||
291 | * Task to resend/poll in case no ACK is received. | ||
292 | */ | ||
293 | struct GNUNET_SCHEDULER_Task *retry_data_task; | ||
294 | |||
295 | /** | ||
296 | * Last time the channel was used | ||
297 | */ | ||
298 | struct GNUNET_TIME_Absolute timestamp; | ||
299 | |||
300 | /** | ||
301 | * Destination port of the channel. | ||
302 | */ | ||
303 | struct GNUNET_HashCode port; | ||
304 | |||
305 | /** | ||
306 | * Hash'ed port of the channel with initiator and destination PID. | ||
307 | */ | ||
308 | struct GNUNET_HashCode h_port; | ||
309 | |||
310 | /** | ||
311 | * Counter for exponential backoff. | ||
312 | */ | ||
313 | struct GNUNET_TIME_Relative retry_time; | ||
314 | |||
315 | /** | ||
316 | * Bitfield of already-received messages past @e mid_recv. | ||
317 | */ | ||
318 | uint64_t mid_futures; | ||
319 | |||
320 | /** | ||
321 | * Next MID expected for incoming traffic. | ||
322 | */ | ||
323 | struct ChannelMessageIdentifier mid_recv; | ||
324 | |||
325 | /** | ||
326 | * Next MID to use for outgoing traffic. | ||
327 | */ | ||
328 | struct ChannelMessageIdentifier mid_send; | ||
329 | |||
330 | /** | ||
331 | * Total (reliable) messages pending ACK for this channel. | ||
332 | */ | ||
333 | unsigned int pending_messages; | ||
334 | |||
335 | /** | ||
336 | * Maximum (reliable) messages pending ACK for this channel | ||
337 | * before we throttle the client. | ||
338 | */ | ||
339 | unsigned int max_pending_messages; | ||
340 | |||
341 | /** | ||
342 | * Number identifying this channel in its tunnel. | ||
343 | */ | ||
344 | struct GNUNET_CADET_ChannelTunnelNumber ctn; | ||
345 | |||
346 | /** | ||
347 | * Channel state. | ||
348 | */ | ||
349 | enum CadetChannelState state; | ||
350 | |||
351 | /** | ||
352 | * Count how many ACKs we skipped, used to prevent long | ||
353 | * sequences of ACK skipping. | ||
354 | */ | ||
355 | unsigned int skip_ack_series; | ||
356 | |||
357 | /** | ||
358 | * Is the tunnel bufferless (minimum latency)? | ||
359 | */ | ||
360 | int nobuffer; | ||
361 | |||
362 | /** | ||
363 | * Is the tunnel reliable? | ||
364 | */ | ||
365 | int reliable; | ||
366 | |||
367 | /** | ||
368 | * Is the tunnel out-of-order? | ||
369 | */ | ||
370 | int out_of_order; | ||
371 | |||
372 | /** | ||
373 | * Is this channel a loopback channel, where the destination is us again? | ||
374 | */ | ||
375 | int is_loopback; | ||
376 | |||
377 | /** | ||
378 | * Flag to signal the destruction of the channel. If this is set to | ||
379 | * #GNUNET_YES the channel will be destroyed once the queue is | ||
380 | * empty. | ||
381 | */ | ||
382 | int destroy; | ||
383 | |||
384 | /** | ||
385 | * Type of message to be dropped. See GCT_send. | ||
386 | */ | ||
387 | uint16_t type GNUNET_PACKED; | ||
388 | |||
389 | }; | ||
390 | |||
391 | /** | ||
392 | * Assign type of message to drop. | ||
393 | * @param ch CadetChannel to assign type to drop. | ||
394 | * @param message GNUNET_CADET_RequestDropCadetMessage to get the type from. | ||
395 | */ | ||
396 | void | ||
397 | GCCH_assign_type_to_drop (struct CadetChannel *ch, const struct | ||
398 | GNUNET_CADET_RequestDropCadetMessage *message) | ||
399 | { | ||
400 | |||
401 | ch->type = message->type; | ||
402 | |||
403 | } | ||
404 | |||
405 | |||
406 | /** | ||
407 | * Check if type of message is the one to drop. | ||
408 | * @param ch CadetChannel to check for message type to drop. | ||
409 | * @param message GNUNET_MessageHeader to compare the type with. | ||
410 | */ | ||
411 | int | ||
412 | GCCH_is_type_to_drop (struct CadetChannel *ch, const struct | ||
413 | GNUNET_MessageHeader *message) | ||
414 | { | ||
415 | |||
416 | if (ch->type == message->type) | ||
417 | { | ||
418 | ch->type = 0; | ||
419 | return GNUNET_YES; | ||
420 | } | ||
421 | else | ||
422 | return GNUNET_NO; | ||
423 | } | ||
424 | |||
425 | |||
426 | /** | ||
427 | * Get the static string for identification of the channel. | ||
428 | * | ||
429 | * @param ch Channel. | ||
430 | * | ||
431 | * @return Static string with the channel IDs. | ||
432 | */ | ||
433 | const char * | ||
434 | GCCH_2s (const struct CadetChannel *ch) | ||
435 | { | ||
436 | static char buf[128]; | ||
437 | |||
438 | GNUNET_snprintf (buf, | ||
439 | sizeof(buf), | ||
440 | "Channel %s:%s ctn:%X(%X/%X)", | ||
441 | (GNUNET_YES == ch->is_loopback) | ||
442 | ? "loopback" | ||
443 | : GNUNET_i2s (GCP_get_id (GCT_get_destination (ch->t))), | ||
444 | GNUNET_h2s (&ch->port), | ||
445 | ch->ctn.cn, | ||
446 | (NULL == ch->owner) | ||
447 | ? 0 | ||
448 | : ntohl (ch->owner->ccn.channel_of_client), | ||
449 | (NULL == ch->dest) | ||
450 | ? 0 | ||
451 | : ntohl (ch->dest->ccn.channel_of_client)); | ||
452 | return buf; | ||
453 | } | ||
454 | |||
455 | |||
456 | /** | ||
457 | * Hash the @a port and @a initiator and @a listener to | ||
458 | * calculate the "challenge" @a h_port we send to the other | ||
459 | * peer on #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN. | ||
460 | * | ||
461 | * @param[out] h_port set to the hash of @a port, @a initiator and @a listener | ||
462 | * @param port cadet port, as seen by CADET clients | ||
463 | * @param listener peer that is listining on @a port | ||
464 | */ | ||
465 | void | ||
466 | GCCH_hash_port (struct GNUNET_HashCode *h_port, | ||
467 | const struct GNUNET_HashCode *port, | ||
468 | const struct GNUNET_PeerIdentity *listener) | ||
469 | { | ||
470 | struct GNUNET_HashContext *hc; | ||
471 | |||
472 | hc = GNUNET_CRYPTO_hash_context_start (); | ||
473 | GNUNET_CRYPTO_hash_context_read (hc, port, sizeof(*port)); | ||
474 | GNUNET_CRYPTO_hash_context_read (hc, listener, sizeof(*listener)); | ||
475 | GNUNET_CRYPTO_hash_context_finish (hc, h_port); | ||
476 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
477 | "Calculated port hash %s\n", | ||
478 | GNUNET_h2s (h_port)); | ||
479 | } | ||
480 | |||
481 | |||
482 | /** | ||
483 | * Get the channel's public ID. | ||
484 | * | ||
485 | * @param ch Channel. | ||
486 | * | ||
487 | * @return ID used to identify the channel with the remote peer. | ||
488 | */ | ||
489 | struct GNUNET_CADET_ChannelTunnelNumber | ||
490 | GCCH_get_id (const struct CadetChannel *ch) | ||
491 | { | ||
492 | return ch->ctn; | ||
493 | } | ||
494 | |||
495 | |||
496 | /** | ||
497 | * Release memory associated with @a ccc | ||
498 | * | ||
499 | * @param ccc data structure to clean up | ||
500 | */ | ||
501 | static void | ||
502 | free_channel_client (struct CadetChannelClient *ccc) | ||
503 | { | ||
504 | struct CadetOutOfOrderMessage *com; | ||
505 | |||
506 | while (NULL != (com = ccc->head_recv)) | ||
507 | { | ||
508 | GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, com); | ||
509 | ccc->num_recv--; | ||
510 | GNUNET_MQ_discard (com->env); | ||
511 | GNUNET_free (com); | ||
512 | } | ||
513 | GNUNET_free (ccc); | ||
514 | } | ||
515 | |||
516 | |||
517 | /** | ||
518 | * Destroy the given channel. | ||
519 | * | ||
520 | * @param ch channel to destroy | ||
521 | */ | ||
522 | static void | ||
523 | channel_destroy (struct CadetChannel *ch) | ||
524 | { | ||
525 | struct CadetReliableMessage *crm; | ||
526 | |||
527 | while (NULL != (crm = ch->head_sent)) | ||
528 | { | ||
529 | GNUNET_assert (ch == crm->ch); | ||
530 | if (NULL != crm->qe) | ||
531 | { | ||
532 | GCT_send_cancel (crm->qe); | ||
533 | crm->qe = NULL; | ||
534 | } | ||
535 | GNUNET_CONTAINER_DLL_remove (ch->head_sent, ch->tail_sent, crm); | ||
536 | GNUNET_free (crm->data_message); | ||
537 | GNUNET_free (crm); | ||
538 | } | ||
539 | if (CADET_CHANNEL_LOOSE == ch->state) | ||
540 | { | ||
541 | GSC_drop_loose_channel (&ch->h_port, ch); | ||
542 | } | ||
543 | if (NULL != ch->owner) | ||
544 | { | ||
545 | free_channel_client (ch->owner); | ||
546 | ch->owner = NULL; | ||
547 | } | ||
548 | if (NULL != ch->dest) | ||
549 | { | ||
550 | free_channel_client (ch->dest); | ||
551 | ch->dest = NULL; | ||
552 | } | ||
553 | if (NULL != ch->last_control_qe) | ||
554 | { | ||
555 | GCT_send_cancel (ch->last_control_qe); | ||
556 | ch->last_control_qe = NULL; | ||
557 | } | ||
558 | if (NULL != ch->retry_data_task) | ||
559 | { | ||
560 | GNUNET_SCHEDULER_cancel (ch->retry_data_task); | ||
561 | ch->retry_data_task = NULL; | ||
562 | } | ||
563 | if (NULL != ch->retry_control_task) | ||
564 | { | ||
565 | GNUNET_SCHEDULER_cancel (ch->retry_control_task); | ||
566 | ch->retry_control_task = NULL; | ||
567 | } | ||
568 | if (GNUNET_NO == ch->is_loopback) | ||
569 | { | ||
570 | GCT_remove_channel (ch->t, ch, ch->ctn); | ||
571 | ch->t = NULL; | ||
572 | } | ||
573 | GNUNET_free (ch); | ||
574 | } | ||
575 | |||
576 | |||
577 | /** | ||
578 | * Send a channel create message. | ||
579 | * | ||
580 | * @param cls Channel for which to send. | ||
581 | */ | ||
582 | static void | ||
583 | send_channel_open (void *cls); | ||
584 | |||
585 | |||
586 | /** | ||
587 | * Function called once the tunnel confirms that we sent the | ||
588 | * create message. Delays for a bit until we retry. | ||
589 | * | ||
590 | * @param cls our `struct CadetChannel`. | ||
591 | * @param cid identifier of the connection within the tunnel, NULL | ||
592 | * if transmission failed | ||
593 | */ | ||
594 | static void | ||
595 | channel_open_sent_cb (void *cls, | ||
596 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid) | ||
597 | { | ||
598 | struct CadetChannel *ch = cls; | ||
599 | |||
600 | GNUNET_assert (NULL != ch->last_control_qe); | ||
601 | ch->last_control_qe = NULL; | ||
602 | ch->retry_time = GNUNET_TIME_STD_BACKOFF (ch->retry_time); | ||
603 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
604 | "Sent CADET_CHANNEL_OPEN on %s, retrying in %s\n", | ||
605 | GCCH_2s (ch), | ||
606 | GNUNET_STRINGS_relative_time_to_string (ch->retry_time, GNUNET_YES)); | ||
607 | ch->retry_control_task = | ||
608 | GNUNET_SCHEDULER_add_delayed (ch->retry_time, &send_channel_open, ch); | ||
609 | } | ||
610 | |||
611 | |||
612 | /** | ||
613 | * Send a channel open message. | ||
614 | * | ||
615 | * @param cls Channel for which to send. | ||
616 | */ | ||
617 | static void | ||
618 | send_channel_open (void *cls) | ||
619 | { | ||
620 | struct CadetChannel *ch = cls; | ||
621 | struct GNUNET_CADET_ChannelOpenMessage msgcc; | ||
622 | |||
623 | ch->retry_control_task = NULL; | ||
624 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
625 | "Sending CHANNEL_OPEN message for %s\n", | ||
626 | GCCH_2s (ch)); | ||
627 | msgcc.header.size = htons (sizeof(msgcc)); | ||
628 | msgcc.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN); | ||
629 | // TODO This will be removed in a major release, because this will be a protocol breaking change. We set the deprecated "reliable" bit here that was removed. | ||
630 | msgcc.opt = 2; | ||
631 | msgcc.h_port = ch->h_port; | ||
632 | msgcc.ctn = ch->ctn; | ||
633 | ch->state = CADET_CHANNEL_OPEN_SENT; | ||
634 | if (NULL != ch->last_control_qe) | ||
635 | GCT_send_cancel (ch->last_control_qe); | ||
636 | ch->last_control_qe = | ||
637 | GCT_send (ch->t, &msgcc.header, &channel_open_sent_cb, ch, &msgcc.ctn); | ||
638 | GNUNET_assert (NULL == ch->retry_control_task); | ||
639 | } | ||
640 | |||
641 | |||
642 | /** | ||
643 | * Function called once and only once after a channel was bound | ||
644 | * to its tunnel via #GCT_add_channel() is ready for transmission. | ||
645 | * Note that this is only the case for channels that this peer | ||
646 | * initiates, as for incoming channels we assume that they are | ||
647 | * ready for transmission immediately upon receiving the open | ||
648 | * message. Used to bootstrap the #GCT_send() process. | ||
649 | * | ||
650 | * @param ch the channel for which the tunnel is now ready | ||
651 | */ | ||
652 | void | ||
653 | GCCH_tunnel_up (struct CadetChannel *ch) | ||
654 | { | ||
655 | GNUNET_assert (NULL == ch->retry_control_task); | ||
656 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
657 | "Tunnel up, sending CHANNEL_OPEN on %s now\n", | ||
658 | GCCH_2s (ch)); | ||
659 | ch->retry_control_task = GNUNET_SCHEDULER_add_now (&send_channel_open, ch); | ||
660 | } | ||
661 | |||
662 | |||
663 | /** | ||
664 | * Create a new channel. | ||
665 | * | ||
666 | * @param owner local client owning the channel | ||
667 | * @param ccn local number of this channel at the @a owner | ||
668 | * @param destination peer to which we should build the channel | ||
669 | * @param port desired port at @a destination | ||
670 | * @param options options for the channel | ||
671 | * @return handle to the new channel | ||
672 | */ | ||
673 | struct CadetChannel * | ||
674 | GCCH_channel_local_new (struct CadetClient *owner, | ||
675 | struct GNUNET_CADET_ClientChannelNumber ccn, | ||
676 | struct CadetPeer *destination, | ||
677 | const struct GNUNET_HashCode *port, | ||
678 | uint32_t options) | ||
679 | { | ||
680 | struct CadetChannel *ch; | ||
681 | struct CadetChannelClient *ccco; | ||
682 | |||
683 | ccco = GNUNET_new (struct CadetChannelClient); | ||
684 | ccco->c = owner; | ||
685 | ccco->ccn = ccn; | ||
686 | ccco->client_ready = GNUNET_YES; | ||
687 | |||
688 | ch = GNUNET_new (struct CadetChannel); | ||
689 | ch->mid_recv.mid = htonl (1); /* The OPEN_ACK counts as message 0! */ | ||
690 | ch->nobuffer = GNUNET_NO; | ||
691 | ch->reliable = GNUNET_YES; | ||
692 | ch->out_of_order = GNUNET_NO; | ||
693 | ch->max_pending_messages = | ||
694 | (ch->nobuffer) ? 1 : 4; /* FIXME: 4!? Do not hardcode! */ | ||
695 | ch->owner = ccco; | ||
696 | ch->port = *port; | ||
697 | GCCH_hash_port (&ch->h_port, port, GCP_get_id (destination)); | ||
698 | if (0 == GNUNET_memcmp (&my_full_id, GCP_get_id (destination))) | ||
699 | { | ||
700 | struct OpenPort *op; | ||
701 | |||
702 | ch->is_loopback = GNUNET_YES; | ||
703 | op = GNUNET_CONTAINER_multihashmap_get (open_ports, &ch->h_port); | ||
704 | if (NULL == op) | ||
705 | { | ||
706 | /* port closed, wait for it to possibly open */ | ||
707 | ch->state = CADET_CHANNEL_LOOSE; | ||
708 | (void) GNUNET_CONTAINER_multihashmap_put ( | ||
709 | loose_channels, | ||
710 | &ch->h_port, | ||
711 | ch, | ||
712 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
713 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
714 | "Created loose incoming loopback channel to port %s\n", | ||
715 | GNUNET_h2s (&ch->port)); | ||
716 | } | ||
717 | else | ||
718 | { | ||
719 | GCCH_bind (ch, op->c, &op->port); | ||
720 | } | ||
721 | } | ||
722 | else | ||
723 | { | ||
724 | ch->t = GCP_get_tunnel (destination, GNUNET_YES); | ||
725 | ch->retry_time = CADET_INITIAL_RETRANSMIT_TIME; | ||
726 | ch->ctn = GCT_add_channel (ch->t, ch); | ||
727 | } | ||
728 | GNUNET_STATISTICS_update (stats, "# channels", 1, GNUNET_NO); | ||
729 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
730 | "Created channel to port %s at peer %s for %s using %s\n", | ||
731 | GNUNET_h2s (port), | ||
732 | GCP_2s (destination), | ||
733 | GSC_2s (owner), | ||
734 | (GNUNET_YES == ch->is_loopback) ? "loopback" : GCT_2s (ch->t)); | ||
735 | return ch; | ||
736 | } | ||
737 | |||
738 | |||
739 | /** | ||
740 | * We had an incoming channel to a port that is closed. | ||
741 | * It has not been opened for a while, drop it. | ||
742 | * | ||
743 | * @param cls the channel to drop | ||
744 | */ | ||
745 | static void | ||
746 | timeout_closed_cb (void *cls) | ||
747 | { | ||
748 | struct CadetChannel *ch = cls; | ||
749 | |||
750 | ch->retry_control_task = NULL; | ||
751 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
752 | "Closing incoming channel to port %s from peer %s due to timeout\n", | ||
753 | GNUNET_h2s (&ch->port), | ||
754 | GCP_2s (GCT_get_destination (ch->t))); | ||
755 | channel_destroy (ch); | ||
756 | } | ||
757 | |||
758 | |||
759 | /** | ||
760 | * Create a new channel based on a request coming in over the network. | ||
761 | * | ||
762 | * @param t tunnel to the remote peer | ||
763 | * @param ctn identifier of this channel in the tunnel | ||
764 | * @param h_port desired hash of local port | ||
765 | * @param options options for the channel | ||
766 | * @return handle to the new channel | ||
767 | */ | ||
768 | struct CadetChannel * | ||
769 | GCCH_channel_incoming_new (struct CadetTunnel *t, | ||
770 | struct GNUNET_CADET_ChannelTunnelNumber ctn, | ||
771 | const struct GNUNET_HashCode *h_port, | ||
772 | uint32_t options) | ||
773 | { | ||
774 | struct CadetChannel *ch; | ||
775 | struct OpenPort *op; | ||
776 | |||
777 | ch = GNUNET_new (struct CadetChannel); | ||
778 | ch->h_port = *h_port; | ||
779 | ch->t = t; | ||
780 | ch->ctn = ctn; | ||
781 | ch->retry_time = CADET_INITIAL_RETRANSMIT_TIME; | ||
782 | ch->nobuffer = GNUNET_NO; | ||
783 | ch->reliable = GNUNET_YES; | ||
784 | ch->out_of_order = GNUNET_NO; | ||
785 | ch->max_pending_messages = | ||
786 | (ch->nobuffer) ? 1 : 4; /* FIXME: 4!? Do not hardcode! */ | ||
787 | GNUNET_STATISTICS_update (stats, "# channels", 1, GNUNET_NO); | ||
788 | |||
789 | op = GNUNET_CONTAINER_multihashmap_get (open_ports, h_port); | ||
790 | if (NULL == op) | ||
791 | { | ||
792 | /* port closed, wait for it to possibly open */ | ||
793 | ch->state = CADET_CHANNEL_LOOSE; | ||
794 | (void) GNUNET_CONTAINER_multihashmap_put ( | ||
795 | loose_channels, | ||
796 | &ch->h_port, | ||
797 | ch, | ||
798 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
799 | GNUNET_assert (NULL == ch->retry_control_task); | ||
800 | ch->retry_control_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT_CLOSED_PORT, | ||
801 | &timeout_closed_cb, | ||
802 | ch); | ||
803 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
804 | "Created loose incoming channel to port %s from peer %s\n", | ||
805 | GNUNET_h2s (&ch->port), | ||
806 | GCP_2s (GCT_get_destination (ch->t))); | ||
807 | } | ||
808 | else | ||
809 | { | ||
810 | GCCH_bind (ch, op->c, &op->port); | ||
811 | } | ||
812 | GNUNET_STATISTICS_update (stats, "# channels", 1, GNUNET_NO); | ||
813 | return ch; | ||
814 | } | ||
815 | |||
816 | |||
817 | /** | ||
818 | * Function called once the tunnel confirms that we sent the | ||
819 | * ACK message. Just remembers it was sent, we do not expect | ||
820 | * ACKs for ACKs ;-). | ||
821 | * | ||
822 | * @param cls our `struct CadetChannel`. | ||
823 | * @param cid identifier of the connection within the tunnel, NULL | ||
824 | * if transmission failed | ||
825 | */ | ||
826 | static void | ||
827 | send_ack_cb (void *cls, | ||
828 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid) | ||
829 | { | ||
830 | struct CadetChannel *ch = cls; | ||
831 | |||
832 | GNUNET_assert (NULL != ch->last_control_qe); | ||
833 | ch->last_control_qe = NULL; | ||
834 | } | ||
835 | |||
836 | |||
837 | /** | ||
838 | * Compute and send the current #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK to the other peer. | ||
839 | * | ||
840 | * @param ch channel to send the #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK for | ||
841 | */ | ||
842 | static void | ||
843 | send_channel_data_ack (struct CadetChannel *ch) | ||
844 | { | ||
845 | struct GNUNET_CADET_ChannelDataAckMessage msg; | ||
846 | |||
847 | if (GNUNET_NO == ch->reliable) | ||
848 | return; /* no ACKs */ | ||
849 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK); | ||
850 | msg.header.size = htons (sizeof(msg)); | ||
851 | msg.ctn = ch->ctn; | ||
852 | msg.mid.mid = htonl (ntohl (ch->mid_recv.mid)); | ||
853 | msg.futures = GNUNET_htonll (ch->mid_futures); | ||
854 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
855 | "Sending DATA_ACK %u:%llX via %s\n", | ||
856 | (unsigned int) ntohl (msg.mid.mid), | ||
857 | (unsigned long long) ch->mid_futures, | ||
858 | GCCH_2s (ch)); | ||
859 | if (NULL != ch->last_control_qe) | ||
860 | GCT_send_cancel (ch->last_control_qe); | ||
861 | ch->last_control_qe = GCT_send (ch->t, &msg.header, &send_ack_cb, ch, | ||
862 | &msg.ctn); | ||
863 | } | ||
864 | |||
865 | |||
866 | /** | ||
867 | * Send our initial #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK to the client confirming that the | ||
868 | * connection is up. | ||
869 | * | ||
870 | * @param cls the `struct CadetChannel` | ||
871 | */ | ||
872 | static void | ||
873 | send_open_ack (void *cls) | ||
874 | { | ||
875 | struct CadetChannel *ch = cls; | ||
876 | struct GNUNET_CADET_ChannelOpenAckMessage msg; | ||
877 | |||
878 | ch->retry_control_task = NULL; | ||
879 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
880 | "Sending CHANNEL_OPEN_ACK on %s\n", | ||
881 | GCCH_2s (ch)); | ||
882 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK); | ||
883 | msg.header.size = htons (sizeof(msg)); | ||
884 | msg.reserved = htonl (0); | ||
885 | msg.ctn = ch->ctn; | ||
886 | msg.port = ch->port; | ||
887 | if (NULL != ch->last_control_qe) | ||
888 | GCT_send_cancel (ch->last_control_qe); | ||
889 | ch->last_control_qe = GCT_send (ch->t, &msg.header, &send_ack_cb, ch, | ||
890 | &msg.ctn); | ||
891 | } | ||
892 | |||
893 | |||
894 | /** | ||
895 | * We got a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN message again for | ||
896 | * this channel. If the binding was successful, (re)transmit the | ||
897 | * #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK. | ||
898 | * | ||
899 | * @param ch channel that got the duplicate open | ||
900 | * @param cti identifier of the connection that delivered the message | ||
901 | */ | ||
902 | void | ||
903 | GCCH_handle_duplicate_open ( | ||
904 | struct CadetChannel *ch, | ||
905 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti) | ||
906 | { | ||
907 | if (NULL == ch->dest) | ||
908 | { | ||
909 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
910 | "Ignoring duplicate CHANNEL_OPEN on %s: port is closed\n", | ||
911 | GCCH_2s (ch)); | ||
912 | return; | ||
913 | } | ||
914 | if (NULL != ch->retry_control_task) | ||
915 | { | ||
916 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
917 | "Ignoring duplicate CHANNEL_OPEN on %s: control message is pending\n", | ||
918 | GCCH_2s (ch)); | ||
919 | return; | ||
920 | } | ||
921 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
922 | "Retransmitting CHANNEL_OPEN_ACK on %s\n", | ||
923 | GCCH_2s (ch)); | ||
924 | ch->retry_control_task = GNUNET_SCHEDULER_add_now (&send_open_ack, ch); | ||
925 | } | ||
926 | |||
927 | |||
928 | /** | ||
929 | * Send a #GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK to the client to solicit more messages. | ||
930 | * | ||
931 | * @param ch channel the ack is for | ||
932 | * @param to_owner #GNUNET_YES to send to owner, | ||
933 | * #GNUNET_NO to send to dest | ||
934 | */ | ||
935 | static void | ||
936 | send_ack_to_client (struct CadetChannel *ch, int to_owner) | ||
937 | { | ||
938 | struct GNUNET_MQ_Envelope *env; | ||
939 | struct GNUNET_CADET_LocalAck *ack; | ||
940 | struct CadetChannelClient *ccc; | ||
941 | |||
942 | ccc = (GNUNET_YES == to_owner) ? ch->owner : ch->dest; | ||
943 | if (NULL == ccc) | ||
944 | { | ||
945 | /* This can happen if we are just getting ACKs after | ||
946 | our local client already disconnected. */ | ||
947 | GNUNET_assert (GNUNET_YES == ch->destroy); | ||
948 | return; | ||
949 | } | ||
950 | env = GNUNET_MQ_msg (ack, GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK); | ||
951 | ack->ccn = ccc->ccn; | ||
952 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
953 | "Sending CADET_LOCAL_ACK to %s (%s) at ccn %X (%u/%u pending)\n", | ||
954 | GSC_2s (ccc->c), | ||
955 | (GNUNET_YES == to_owner) ? "owner" : "dest", | ||
956 | ntohl (ack->ccn.channel_of_client), | ||
957 | ch->pending_messages, | ||
958 | ch->max_pending_messages); | ||
959 | GSC_send_to_client (ccc->c, env); | ||
960 | } | ||
961 | |||
962 | |||
963 | /** | ||
964 | * A client is bound to the port that we have a channel | ||
965 | * open to. Send the acknowledgement for the connection | ||
966 | * request and establish the link with the client. | ||
967 | * | ||
968 | * @param ch open incoming channel | ||
969 | * @param c client listening on the respective @a port | ||
970 | * @param port the port @a is listening on | ||
971 | */ | ||
972 | void | ||
973 | GCCH_bind (struct CadetChannel *ch, | ||
974 | struct CadetClient *c, | ||
975 | const struct GNUNET_HashCode *port) | ||
976 | { | ||
977 | uint32_t options; | ||
978 | struct CadetChannelClient *cccd; | ||
979 | |||
980 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
981 | "Binding %s from %s to port %s of %s\n", | ||
982 | GCCH_2s (ch), | ||
983 | GCT_2s (ch->t), | ||
984 | GNUNET_h2s (&ch->port), | ||
985 | GSC_2s (c)); | ||
986 | if (NULL != ch->retry_control_task) | ||
987 | { | ||
988 | /* there might be a timeout task here */ | ||
989 | GNUNET_SCHEDULER_cancel (ch->retry_control_task); | ||
990 | ch->retry_control_task = NULL; | ||
991 | } | ||
992 | options = 0; | ||
993 | cccd = GNUNET_new (struct CadetChannelClient); | ||
994 | GNUNET_assert (NULL == ch->dest); | ||
995 | ch->dest = cccd; | ||
996 | ch->port = *port; | ||
997 | cccd->c = c; | ||
998 | cccd->client_ready = GNUNET_YES; | ||
999 | cccd->ccn = GSC_bind (c, | ||
1000 | ch, | ||
1001 | (GNUNET_YES == ch->is_loopback) | ||
1002 | ? GCP_get (&my_full_id, GNUNET_YES) | ||
1003 | : GCT_get_destination (ch->t), | ||
1004 | port, | ||
1005 | options); | ||
1006 | GNUNET_assert (ntohl (cccd->ccn.channel_of_client) < | ||
1007 | GNUNET_CADET_LOCAL_CHANNEL_ID_CLI); | ||
1008 | ch->mid_recv.mid = htonl (1); /* The OPEN counts as message 0! */ | ||
1009 | if (GNUNET_YES == ch->is_loopback) | ||
1010 | { | ||
1011 | ch->state = CADET_CHANNEL_OPEN_SENT; | ||
1012 | GCCH_handle_channel_open_ack (ch, NULL, port); | ||
1013 | } | ||
1014 | else | ||
1015 | { | ||
1016 | /* notify other peer that we accepted the connection */ | ||
1017 | ch->state = CADET_CHANNEL_READY; | ||
1018 | ch->retry_control_task = GNUNET_SCHEDULER_add_now (&send_open_ack, ch); | ||
1019 | } | ||
1020 | /* give client it's initial supply of ACKs */ | ||
1021 | GNUNET_assert (ntohl (cccd->ccn.channel_of_client) < | ||
1022 | GNUNET_CADET_LOCAL_CHANNEL_ID_CLI); | ||
1023 | for (unsigned int i = 0; i < ch->max_pending_messages; i++) | ||
1024 | send_ack_to_client (ch, GNUNET_NO); | ||
1025 | } | ||
1026 | |||
1027 | |||
1028 | /** | ||
1029 | * One of our clients has disconnected, tell the other one that we | ||
1030 | * are finished. Done asynchronously to avoid concurrent modification | ||
1031 | * issues if this is the same client. | ||
1032 | * | ||
1033 | * @param cls the `struct CadetChannel` where one of the ends is now dead | ||
1034 | */ | ||
1035 | static void | ||
1036 | signal_remote_destroy_cb (void *cls) | ||
1037 | { | ||
1038 | struct CadetChannel *ch = cls; | ||
1039 | struct CadetChannelClient *ccc; | ||
1040 | |||
1041 | /* Find which end is left... */ | ||
1042 | ch->retry_control_task = NULL; | ||
1043 | ccc = (NULL != ch->owner) ? ch->owner : ch->dest; | ||
1044 | GSC_handle_remote_channel_destroy (ccc->c, ccc->ccn, ch); | ||
1045 | channel_destroy (ch); | ||
1046 | } | ||
1047 | |||
1048 | |||
1049 | /** | ||
1050 | * Destroy locally created channel. Called by the local client, so no | ||
1051 | * need to tell the client. | ||
1052 | * | ||
1053 | * @param ch channel to destroy | ||
1054 | * @param c client that caused the destruction | ||
1055 | * @param ccn client number of the client @a c | ||
1056 | */ | ||
1057 | void | ||
1058 | GCCH_channel_local_destroy (struct CadetChannel *ch, | ||
1059 | struct CadetClient *c, | ||
1060 | struct GNUNET_CADET_ClientChannelNumber ccn) | ||
1061 | { | ||
1062 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1063 | "%s asks for destruction of %s\n", | ||
1064 | GSC_2s (c), | ||
1065 | GCCH_2s (ch)); | ||
1066 | GNUNET_assert (NULL != c); | ||
1067 | if ((NULL != ch->owner) && (c == ch->owner->c) && | ||
1068 | (ccn.channel_of_client == ch->owner->ccn.channel_of_client)) | ||
1069 | { | ||
1070 | free_channel_client (ch->owner); | ||
1071 | ch->owner = NULL; | ||
1072 | } | ||
1073 | else if ((NULL != ch->dest) && (c == ch->dest->c) && | ||
1074 | (ccn.channel_of_client == ch->dest->ccn.channel_of_client)) | ||
1075 | { | ||
1076 | free_channel_client (ch->dest); | ||
1077 | ch->dest = NULL; | ||
1078 | } | ||
1079 | else | ||
1080 | { | ||
1081 | GNUNET_assert (0); | ||
1082 | } | ||
1083 | |||
1084 | if (GNUNET_YES == ch->destroy) | ||
1085 | { | ||
1086 | /* other end already destroyed, with the local client gone, no need | ||
1087 | to finish transmissions, just destroy immediately. */ | ||
1088 | channel_destroy (ch); | ||
1089 | return; | ||
1090 | } | ||
1091 | if ((NULL != ch->head_sent) && ((NULL != ch->owner) || (NULL != ch->dest))) | ||
1092 | { | ||
1093 | /* Wait for other end to destroy us as well, | ||
1094 | and otherwise allow send queue to be transmitted first */ | ||
1095 | ch->destroy = GNUNET_YES; | ||
1096 | return; | ||
1097 | } | ||
1098 | if ((GNUNET_YES == ch->is_loopback) && | ||
1099 | ((NULL != ch->owner) || (NULL != ch->dest))) | ||
1100 | { | ||
1101 | if (NULL != ch->retry_control_task) | ||
1102 | GNUNET_SCHEDULER_cancel (ch->retry_control_task); | ||
1103 | ch->retry_control_task = | ||
1104 | GNUNET_SCHEDULER_add_now (&signal_remote_destroy_cb, ch); | ||
1105 | return; | ||
1106 | } | ||
1107 | if (GNUNET_NO == ch->is_loopback) | ||
1108 | { | ||
1109 | /* If the we ever sent the CHANNEL_CREATE, we need to send a destroy message. */ | ||
1110 | switch (ch->state) | ||
1111 | { | ||
1112 | case CADET_CHANNEL_NEW: | ||
1113 | /* We gave up on a channel that we created as a client to a remote | ||
1114 | target, but that never went anywhere. Nothing to do here. */ | ||
1115 | break; | ||
1116 | |||
1117 | case CADET_CHANNEL_LOOSE: | ||
1118 | break; | ||
1119 | |||
1120 | default: | ||
1121 | GCT_send_channel_destroy (ch->t, ch->ctn); | ||
1122 | } | ||
1123 | } | ||
1124 | /* Nothing left to do, just finish destruction */ | ||
1125 | channel_destroy (ch); | ||
1126 | } | ||
1127 | |||
1128 | |||
1129 | /** | ||
1130 | * We got an acknowledgement for the creation of the channel | ||
1131 | * (the port is open on the other side). Verify that the | ||
1132 | * other end really has the right port, and begin transmissions. | ||
1133 | * | ||
1134 | * @param ch channel to destroy | ||
1135 | * @param cti identifier of the connection that delivered the message | ||
1136 | * @param port port number (needed to verify receiver knows the port) | ||
1137 | */ | ||
1138 | void | ||
1139 | GCCH_handle_channel_open_ack ( | ||
1140 | struct CadetChannel *ch, | ||
1141 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti, | ||
1142 | const struct GNUNET_HashCode *port) | ||
1143 | { | ||
1144 | switch (ch->state) | ||
1145 | { | ||
1146 | case CADET_CHANNEL_NEW: | ||
1147 | /* this should be impossible */ | ||
1148 | GNUNET_break (0); | ||
1149 | break; | ||
1150 | |||
1151 | case CADET_CHANNEL_LOOSE: | ||
1152 | /* This makes no sense. */ | ||
1153 | GNUNET_break_op (0); | ||
1154 | break; | ||
1155 | |||
1156 | case CADET_CHANNEL_OPEN_SENT: | ||
1157 | if (NULL == ch->owner) | ||
1158 | { | ||
1159 | /* We're not the owner, wrong direction! */ | ||
1160 | GNUNET_break_op (0); | ||
1161 | return; | ||
1162 | } | ||
1163 | if (0 != GNUNET_memcmp (&ch->port, port)) | ||
1164 | { | ||
1165 | /* Other peer failed to provide the right port, | ||
1166 | refuse connection. */ | ||
1167 | GNUNET_break_op (0); | ||
1168 | return; | ||
1169 | } | ||
1170 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1171 | "Received CHANNEL_OPEN_ACK for waiting %s, entering READY state\n", | ||
1172 | GCCH_2s (ch)); | ||
1173 | if (NULL != ch->retry_control_task) /* can be NULL if ch->is_loopback */ | ||
1174 | { | ||
1175 | GNUNET_SCHEDULER_cancel (ch->retry_control_task); | ||
1176 | ch->retry_control_task = NULL; | ||
1177 | } | ||
1178 | ch->state = CADET_CHANNEL_READY; | ||
1179 | /* On first connect, send client as many ACKs as we allow messages | ||
1180 | to be buffered! */ | ||
1181 | for (unsigned int i = 0; i < ch->max_pending_messages; i++) | ||
1182 | send_ack_to_client (ch, GNUNET_YES); | ||
1183 | break; | ||
1184 | |||
1185 | case CADET_CHANNEL_READY: | ||
1186 | /* duplicate ACK, maybe we retried the CREATE. Ignore. */ | ||
1187 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1188 | "Received duplicate channel OPEN_ACK for %s\n", | ||
1189 | GCCH_2s (ch)); | ||
1190 | GNUNET_STATISTICS_update (stats, "# duplicate CREATE_ACKs", 1, GNUNET_NO); | ||
1191 | break; | ||
1192 | } | ||
1193 | } | ||
1194 | |||
1195 | |||
1196 | /** | ||
1197 | * Test if element @a e1 comes before element @a e2. | ||
1198 | * | ||
1199 | * @param cls closure, to a flag where we indicate duplicate packets | ||
1200 | * @param m1 a message of to sort | ||
1201 | * @param m2 another message to sort | ||
1202 | * @return #GNUNET_YES if @e1 < @e2, otherwise #GNUNET_NO | ||
1203 | */ | ||
1204 | static int | ||
1205 | is_before (void *cls, | ||
1206 | struct CadetOutOfOrderMessage *m1, | ||
1207 | struct CadetOutOfOrderMessage *m2) | ||
1208 | { | ||
1209 | int *duplicate = cls; | ||
1210 | uint32_t v1 = ntohl (m1->mid.mid); | ||
1211 | uint32_t v2 = ntohl (m2->mid.mid); | ||
1212 | uint32_t delta; | ||
1213 | |||
1214 | delta = v2 - v1; | ||
1215 | if (0 == delta) | ||
1216 | *duplicate = GNUNET_YES; | ||
1217 | if (delta > (uint32_t) INT_MAX) | ||
1218 | { | ||
1219 | /* in overflow range, we can safely assume we wrapped around */ | ||
1220 | return GNUNET_NO; | ||
1221 | } | ||
1222 | else | ||
1223 | { | ||
1224 | /* result is small, thus v2 > v1, thus m1 < m2 */ | ||
1225 | return GNUNET_YES; | ||
1226 | } | ||
1227 | } | ||
1228 | |||
1229 | |||
1230 | /** | ||
1231 | * We got payload data for a channel. Pass it on to the client | ||
1232 | * and send an ACK to the other end (once flow control allows it!) | ||
1233 | * | ||
1234 | * @param ch channel that got data | ||
1235 | * @param cti identifier of the connection that delivered the message | ||
1236 | * @param msg message that was received | ||
1237 | */ | ||
1238 | void | ||
1239 | GCCH_handle_channel_plaintext_data ( | ||
1240 | struct CadetChannel *ch, | ||
1241 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti, | ||
1242 | const struct GNUNET_CADET_ChannelAppDataMessage *msg) | ||
1243 | { | ||
1244 | struct GNUNET_MQ_Envelope *env; | ||
1245 | struct GNUNET_CADET_LocalData *ld; | ||
1246 | struct CadetChannelClient *ccc; | ||
1247 | size_t payload_size; | ||
1248 | struct CadetOutOfOrderMessage *com; | ||
1249 | int duplicate; | ||
1250 | uint32_t mid_min; | ||
1251 | uint32_t mid_max; | ||
1252 | uint32_t mid_msg; | ||
1253 | uint32_t delta; | ||
1254 | |||
1255 | GNUNET_assert (GNUNET_NO == ch->is_loopback); | ||
1256 | if ((NULL == ch->owner) && (NULL == ch->dest)) | ||
1257 | { | ||
1258 | /* This client is gone, but we still have messages to send to | ||
1259 | the other end (which is why @a ch is not yet dead). However, | ||
1260 | we cannot pass messages to our client anymore. */ | ||
1261 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1262 | "Dropping incoming payload on %s as this end is already closed\n", | ||
1263 | GCCH_2s (ch)); | ||
1264 | /* send back DESTROY notification to stop further retransmissions! */ | ||
1265 | if (GNUNET_YES == ch->destroy) | ||
1266 | GCT_send_channel_destroy (ch->t, ch->ctn); | ||
1267 | return; | ||
1268 | } | ||
1269 | payload_size = ntohs (msg->header.size) - sizeof(*msg); | ||
1270 | env = GNUNET_MQ_msg_extra (ld, | ||
1271 | payload_size, | ||
1272 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA); | ||
1273 | ld->ccn = (NULL == ch->dest) ? ch->owner->ccn : ch->dest->ccn; | ||
1274 | GNUNET_memcpy (&ld[1], &msg[1], payload_size); | ||
1275 | ccc = (NULL != ch->owner) ? ch->owner : ch->dest; | ||
1276 | if (GNUNET_YES == ccc->client_ready) | ||
1277 | { | ||
1278 | /* | ||
1279 | * We ad-hoc send the message if | ||
1280 | * - The channel is out-of-order | ||
1281 | * - The channel is reliable and MID matches next expected MID | ||
1282 | * - The channel is unreliable and MID is before lowest seen MID | ||
1283 | */if ((GNUNET_YES == ch->out_of_order) || | ||
1284 | ((msg->mid.mid == ch->mid_recv.mid) && (GNUNET_YES == ch->reliable)) || | ||
1285 | ((GNUNET_NO == ch->reliable) && | ||
1286 | (ntohl (msg->mid.mid) >= ntohl (ch->mid_recv.mid)) && | ||
1287 | ((NULL == ccc->head_recv) || | ||
1288 | (ntohl (msg->mid.mid) < ntohl (ccc->head_recv->mid.mid))))) | ||
1289 | { | ||
1290 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1291 | "Giving %u bytes of payload with MID %u from %s to client %s\n", | ||
1292 | (unsigned int) payload_size, | ||
1293 | ntohl (msg->mid.mid), | ||
1294 | GCCH_2s (ch), | ||
1295 | GSC_2s (ccc->c)); | ||
1296 | ccc->client_ready = GNUNET_NO; | ||
1297 | GSC_send_to_client (ccc->c, env); | ||
1298 | if (GNUNET_NO == ch->out_of_order) | ||
1299 | ch->mid_recv.mid = htonl (1 + ntohl (msg->mid.mid)); | ||
1300 | else | ||
1301 | ch->mid_recv.mid = htonl (1 + ntohl (ch->mid_recv.mid)); | ||
1302 | ch->mid_futures >>= 1; | ||
1303 | if ((GNUNET_YES == ch->out_of_order) && (GNUNET_NO == ch->reliable)) | ||
1304 | { | ||
1305 | /* possibly shift by more if we skipped messages */ | ||
1306 | uint64_t delta = htonl (msg->mid.mid) - 1 - ntohl (ch->mid_recv.mid); | ||
1307 | |||
1308 | if (delta > 63) | ||
1309 | ch->mid_futures = 0; | ||
1310 | else | ||
1311 | ch->mid_futures >>= delta; | ||
1312 | ch->mid_recv.mid = htonl (1 + ntohl (msg->mid.mid)); | ||
1313 | } | ||
1314 | send_channel_data_ack (ch); | ||
1315 | return; | ||
1316 | } | ||
1317 | } | ||
1318 | |||
1319 | if (GNUNET_YES == ch->reliable) | ||
1320 | { | ||
1321 | /* check if message ought to be dropped because it is ancient/too distant/duplicate */ | ||
1322 | mid_min = ntohl (ch->mid_recv.mid); | ||
1323 | mid_max = mid_min + ch->max_pending_messages; | ||
1324 | mid_msg = ntohl (msg->mid.mid); | ||
1325 | if (((uint32_t) (mid_msg - mid_min) > ch->max_pending_messages) || | ||
1326 | ((uint32_t) (mid_max - mid_msg) > ch->max_pending_messages)) | ||
1327 | { | ||
1328 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1329 | "%s at %u drops ancient or far-future message %u\n", | ||
1330 | GCCH_2s (ch), | ||
1331 | (unsigned int) mid_min, | ||
1332 | ntohl (msg->mid.mid)); | ||
1333 | |||
1334 | GNUNET_STATISTICS_update (stats, | ||
1335 | "# duplicate DATA (ancient or future)", | ||
1336 | 1, | ||
1337 | GNUNET_NO); | ||
1338 | GNUNET_MQ_discard (env); | ||
1339 | send_channel_data_ack (ch); | ||
1340 | return; | ||
1341 | } | ||
1342 | /* mark bit for future ACKs */ | ||
1343 | delta = mid_msg - mid_min - 1; /* overflow/underflow are OK here */ | ||
1344 | if (delta < 64) | ||
1345 | { | ||
1346 | if (0 != (ch->mid_futures & (1LLU << delta))) | ||
1347 | { | ||
1348 | /* Duplicate within the queue, drop also */ | ||
1349 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1350 | "Duplicate payload of %u bytes on %s (mid %u) dropped\n", | ||
1351 | (unsigned int) payload_size, | ||
1352 | GCCH_2s (ch), | ||
1353 | ntohl (msg->mid.mid)); | ||
1354 | GNUNET_STATISTICS_update (stats, "# duplicate DATA", 1, GNUNET_NO); | ||
1355 | GNUNET_MQ_discard (env); | ||
1356 | send_channel_data_ack (ch); | ||
1357 | return; | ||
1358 | } | ||
1359 | ch->mid_futures |= (1LLU << delta); | ||
1360 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1361 | "Marked bit %llX for mid %u (base: %u); now: %llX\n", | ||
1362 | (1LLU << delta), | ||
1363 | mid_msg, | ||
1364 | mid_min, | ||
1365 | (unsigned long long) ch->mid_futures); | ||
1366 | } | ||
1367 | } | ||
1368 | else /* ! ch->reliable */ | ||
1369 | { | ||
1370 | struct CadetOutOfOrderMessage *next_msg; | ||
1371 | |||
1372 | /** | ||
1373 | * We always send if possible in this case. | ||
1374 | * It is guaranteed that the queued MID < received MID | ||
1375 | **/ | ||
1376 | if ((NULL != ccc->head_recv) && (GNUNET_YES == ccc->client_ready)) | ||
1377 | { | ||
1378 | next_msg = ccc->head_recv; | ||
1379 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1380 | "Giving queued MID %u from %s to client %s\n", | ||
1381 | ntohl (next_msg->mid.mid), | ||
1382 | GCCH_2s (ch), | ||
1383 | GSC_2s (ccc->c)); | ||
1384 | ccc->client_ready = GNUNET_NO; | ||
1385 | GSC_send_to_client (ccc->c, next_msg->env); | ||
1386 | ch->mid_recv.mid = htonl (1 + ntohl (next_msg->mid.mid)); | ||
1387 | ch->mid_futures >>= 1; | ||
1388 | send_channel_data_ack (ch); | ||
1389 | GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, next_msg); | ||
1390 | ccc->num_recv--; | ||
1391 | /* Do not process duplicate MID */ | ||
1392 | if (msg->mid.mid == next_msg->mid.mid) /* Duplicate */ | ||
1393 | { | ||
1394 | /* Duplicate within the queue, drop */ | ||
1395 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1396 | "Message on %s (mid %u) dropped, duplicate\n", | ||
1397 | GCCH_2s (ch), | ||
1398 | ntohl (msg->mid.mid)); | ||
1399 | GNUNET_free (next_msg); | ||
1400 | GNUNET_MQ_discard (env); | ||
1401 | return; | ||
1402 | } | ||
1403 | GNUNET_free (next_msg); | ||
1404 | } | ||
1405 | |||
1406 | if (ntohl (msg->mid.mid) < ntohl (ch->mid_recv.mid)) /* Old */ | ||
1407 | { | ||
1408 | /* Duplicate within the queue, drop */ | ||
1409 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1410 | "Message on %s (mid %u) dropped, old.\n", | ||
1411 | GCCH_2s (ch), | ||
1412 | ntohl (msg->mid.mid)); | ||
1413 | GNUNET_MQ_discard (env); | ||
1414 | return; | ||
1415 | } | ||
1416 | |||
1417 | /* Channel is unreliable, so we do not ACK. But we also cannot | ||
1418 | allow buffering everything, so check if we have space... */ | ||
1419 | if (ccc->num_recv >= ch->max_pending_messages) | ||
1420 | { | ||
1421 | struct CadetOutOfOrderMessage *drop; | ||
1422 | |||
1423 | /* Yep, need to drop. Drop the oldest message in | ||
1424 | the buffer. */ | ||
1425 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1426 | "Queue full due slow client on %s, dropping oldest message\n", | ||
1427 | GCCH_2s (ch)); | ||
1428 | GNUNET_STATISTICS_update (stats, | ||
1429 | "# messages dropped due to slow client", | ||
1430 | 1, | ||
1431 | GNUNET_NO); | ||
1432 | drop = ccc->head_recv; | ||
1433 | GNUNET_assert (NULL != drop); | ||
1434 | GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, drop); | ||
1435 | ccc->num_recv--; | ||
1436 | GNUNET_MQ_discard (drop->env); | ||
1437 | GNUNET_free (drop); | ||
1438 | } | ||
1439 | } | ||
1440 | |||
1441 | /* Insert message into sorted out-of-order queue */ | ||
1442 | com = GNUNET_new (struct CadetOutOfOrderMessage); | ||
1443 | com->mid = msg->mid; | ||
1444 | com->env = env; | ||
1445 | duplicate = GNUNET_NO; | ||
1446 | GNUNET_CONTAINER_DLL_insert_sorted (struct CadetOutOfOrderMessage, | ||
1447 | is_before, | ||
1448 | &duplicate, | ||
1449 | ccc->head_recv, | ||
1450 | ccc->tail_recv, | ||
1451 | com); | ||
1452 | ccc->num_recv++; | ||
1453 | if (GNUNET_YES == duplicate) | ||
1454 | { | ||
1455 | /* Duplicate within the queue, drop also (this is not covered by | ||
1456 | the case above if "delta" >= 64, which could be the case if | ||
1457 | max_pending_messages is also >= 64 or if our client is unready | ||
1458 | and we are seeing retransmissions of the message our client is | ||
1459 | blocked on. */LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1460 | "Duplicate payload of %u bytes on %s (mid %u) dropped\n", | ||
1461 | (unsigned int) payload_size, | ||
1462 | GCCH_2s (ch), | ||
1463 | ntohl (msg->mid.mid)); | ||
1464 | GNUNET_STATISTICS_update (stats, "# duplicate DATA", 1, GNUNET_NO); | ||
1465 | GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, com); | ||
1466 | ccc->num_recv--; | ||
1467 | GNUNET_MQ_discard (com->env); | ||
1468 | GNUNET_free (com); | ||
1469 | send_channel_data_ack (ch); | ||
1470 | return; | ||
1471 | } | ||
1472 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1473 | "Queued %s payload of %u bytes on %s-%X(%p) (mid %u, need %u first)\n", | ||
1474 | (GNUNET_YES == ccc->client_ready) ? "out-of-order" : "client-not-ready", | ||
1475 | (unsigned int) payload_size, | ||
1476 | GCCH_2s (ch), | ||
1477 | ntohl (ccc->ccn.channel_of_client), | ||
1478 | ccc, | ||
1479 | ntohl (msg->mid.mid), | ||
1480 | ntohl (ch->mid_recv.mid)); | ||
1481 | /* NOTE: this ACK we _could_ skip, as the packet is out-of-order and | ||
1482 | the sender may already be transmitting the previous one. Needs | ||
1483 | experimental evaluation to see if/when this ACK helps or | ||
1484 | hurts. (We might even want another option.) */ | ||
1485 | send_channel_data_ack (ch); | ||
1486 | } | ||
1487 | |||
1488 | |||
1489 | /** | ||
1490 | * Function called once the tunnel has sent one of our messages. | ||
1491 | * If the message is unreliable, simply frees the `crm`. If the | ||
1492 | * message was reliable, calculate retransmission time and | ||
1493 | * wait for ACK (or retransmit). | ||
1494 | * | ||
1495 | * @param cls the `struct CadetReliableMessage` that was sent | ||
1496 | * @param cid identifier of the connection within the tunnel, NULL | ||
1497 | * if transmission failed | ||
1498 | */ | ||
1499 | static void | ||
1500 | data_sent_cb (void *cls, | ||
1501 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid); | ||
1502 | |||
1503 | |||
1504 | /** | ||
1505 | * We need to retry a transmission, the last one took too long to | ||
1506 | * be acknowledged. | ||
1507 | * | ||
1508 | * @param cls the `struct CadetChannel` where we need to retransmit | ||
1509 | */ | ||
1510 | static void | ||
1511 | retry_transmission (void *cls) | ||
1512 | { | ||
1513 | struct CadetChannel *ch = cls; | ||
1514 | struct CadetReliableMessage *crm = ch->head_sent; | ||
1515 | |||
1516 | ch->retry_data_task = NULL; | ||
1517 | GNUNET_assert (NULL == crm->qe); | ||
1518 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1519 | "Retrying transmission on %s of message %u\n", | ||
1520 | GCCH_2s (ch), | ||
1521 | (unsigned int) ntohl (crm->data_message->mid.mid)); | ||
1522 | crm->qe = GCT_send (ch->t, &crm->data_message->header, &data_sent_cb, crm, | ||
1523 | &crm->data_message->ctn); | ||
1524 | GNUNET_assert (NULL == ch->retry_data_task); | ||
1525 | } | ||
1526 | |||
1527 | |||
1528 | /** | ||
1529 | * We got an PLAINTEXT_DATA_ACK for a message in our queue, remove it from | ||
1530 | * the queue and tell our client that it can send more. | ||
1531 | * | ||
1532 | * @param ch the channel that got the PLAINTEXT_DATA_ACK | ||
1533 | * @param cti identifier of the connection that delivered the message | ||
1534 | * @param crm the message that got acknowledged | ||
1535 | */ | ||
1536 | static void | ||
1537 | handle_matching_ack (struct CadetChannel *ch, | ||
1538 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti, | ||
1539 | struct CadetReliableMessage *crm) | ||
1540 | { | ||
1541 | GNUNET_CONTAINER_DLL_remove (ch->head_sent, ch->tail_sent, crm); | ||
1542 | ch->pending_messages--; | ||
1543 | GNUNET_assert (ch->pending_messages < ch->max_pending_messages); | ||
1544 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1545 | "Received DATA_ACK on %s for message %u (%u ACKs pending)\n", | ||
1546 | GCCH_2s (ch), | ||
1547 | (unsigned int) ntohl (crm->data_message->mid.mid), | ||
1548 | ch->pending_messages); | ||
1549 | if (NULL != crm->qe) | ||
1550 | { | ||
1551 | GCT_send_cancel (crm->qe); | ||
1552 | crm->qe = NULL; | ||
1553 | } | ||
1554 | if ((1 == crm->num_transmissions) && (NULL != cti)) | ||
1555 | { | ||
1556 | GCC_ack_observed (cti); | ||
1557 | if (0 == GNUNET_memcmp (cti, &crm->connection_taken)) | ||
1558 | { | ||
1559 | GCC_latency_observed (cti, | ||
1560 | GNUNET_TIME_absolute_get_duration ( | ||
1561 | crm->first_transmission_time)); | ||
1562 | } | ||
1563 | } | ||
1564 | GNUNET_free (crm->data_message); | ||
1565 | GNUNET_free (crm); | ||
1566 | send_ack_to_client (ch, (NULL == ch->owner) ? GNUNET_NO : GNUNET_YES); | ||
1567 | } | ||
1568 | |||
1569 | |||
1570 | /** | ||
1571 | * We got an acknowledgement for payload data for a channel. | ||
1572 | * Possibly resume transmissions. | ||
1573 | * | ||
1574 | * @param ch channel that got the ack | ||
1575 | * @param cti identifier of the connection that delivered the message | ||
1576 | * @param ack details about what was received | ||
1577 | */ | ||
1578 | void | ||
1579 | GCCH_handle_channel_plaintext_data_ack ( | ||
1580 | struct CadetChannel *ch, | ||
1581 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti, | ||
1582 | const struct GNUNET_CADET_ChannelDataAckMessage *ack) | ||
1583 | { | ||
1584 | struct CadetReliableMessage *crm; | ||
1585 | struct CadetReliableMessage *crmn; | ||
1586 | int found; | ||
1587 | uint32_t mid_base; | ||
1588 | uint64_t mid_mask; | ||
1589 | unsigned int delta; | ||
1590 | |||
1591 | GNUNET_break (GNUNET_NO == ch->is_loopback); | ||
1592 | if (GNUNET_NO == ch->reliable) | ||
1593 | { | ||
1594 | /* not expecting ACKs on unreliable channel, odd */ | ||
1595 | GNUNET_break_op (0); | ||
1596 | return; | ||
1597 | } | ||
1598 | /* mid_base is the MID of the next message that the | ||
1599 | other peer expects (i.e. that is missing!), everything | ||
1600 | LOWER (but excluding mid_base itself) was received. */ | ||
1601 | mid_base = ntohl (ack->mid.mid); | ||
1602 | mid_mask = GNUNET_htonll (ack->futures); | ||
1603 | found = GNUNET_NO; | ||
1604 | for (crm = ch->head_sent; NULL != crm; crm = crmn) | ||
1605 | { | ||
1606 | crmn = crm->next; | ||
1607 | delta = (unsigned int) (ntohl (crm->data_message->mid.mid) - mid_base); | ||
1608 | if (delta >= UINT_MAX - ch->max_pending_messages) | ||
1609 | { | ||
1610 | /* overflow, means crm was a bit in the past, so this ACK counts for it. */ | ||
1611 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1612 | "Got DATA_ACK with base %u satisfying past message %u on %s\n", | ||
1613 | (unsigned int) mid_base, | ||
1614 | ntohl (crm->data_message->mid.mid), | ||
1615 | GCCH_2s (ch)); | ||
1616 | handle_matching_ack (ch, cti, crm); | ||
1617 | found = GNUNET_YES; | ||
1618 | continue; | ||
1619 | } | ||
1620 | delta--; | ||
1621 | if (delta >= 64) | ||
1622 | continue; | ||
1623 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1624 | "Testing bit %llX for mid %u (base: %u)\n", | ||
1625 | (1LLU << delta), | ||
1626 | ntohl (crm->data_message->mid.mid), | ||
1627 | mid_base); | ||
1628 | if (0 != (mid_mask & (1LLU << delta))) | ||
1629 | { | ||
1630 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1631 | "Got DATA_ACK with mask for %u on %s\n", | ||
1632 | ntohl (crm->data_message->mid.mid), | ||
1633 | GCCH_2s (ch)); | ||
1634 | handle_matching_ack (ch, cti, crm); | ||
1635 | found = GNUNET_YES; | ||
1636 | } | ||
1637 | } | ||
1638 | if (GNUNET_NO == found) | ||
1639 | { | ||
1640 | /* ACK for message we already dropped, might have been a | ||
1641 | duplicate ACK? Ignore. */ | ||
1642 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1643 | "Duplicate DATA_ACK on %s, ignoring\n", | ||
1644 | GCCH_2s (ch)); | ||
1645 | GNUNET_STATISTICS_update (stats, "# duplicate DATA_ACKs", 1, GNUNET_NO); | ||
1646 | return; | ||
1647 | } | ||
1648 | if (NULL != ch->retry_data_task) | ||
1649 | { | ||
1650 | GNUNET_SCHEDULER_cancel (ch->retry_data_task); | ||
1651 | ch->retry_data_task = NULL; | ||
1652 | } | ||
1653 | if ((NULL != ch->head_sent) && (NULL == ch->head_sent->qe)) | ||
1654 | ch->retry_data_task = GNUNET_SCHEDULER_add_at (ch->head_sent->next_retry, | ||
1655 | &retry_transmission, | ||
1656 | ch); | ||
1657 | } | ||
1658 | |||
1659 | |||
1660 | /** | ||
1661 | * Destroy channel, based on the other peer closing the | ||
1662 | * connection. Also needs to remove this channel from | ||
1663 | * the tunnel. | ||
1664 | * | ||
1665 | * @param ch channel to destroy | ||
1666 | * @param cti identifier of the connection that delivered the message, | ||
1667 | * NULL if we are simulating receiving a destroy due to shutdown | ||
1668 | */ | ||
1669 | void | ||
1670 | GCCH_handle_remote_destroy ( | ||
1671 | struct CadetChannel *ch, | ||
1672 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti) | ||
1673 | { | ||
1674 | struct CadetChannelClient *ccc; | ||
1675 | |||
1676 | GNUNET_assert (GNUNET_NO == ch->is_loopback); | ||
1677 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1678 | "Received remote channel DESTROY for %s\n", | ||
1679 | GCCH_2s (ch)); | ||
1680 | if (GNUNET_YES == ch->destroy) | ||
1681 | { | ||
1682 | /* Local client already gone, this is instant-death. */ | ||
1683 | channel_destroy (ch); | ||
1684 | return; | ||
1685 | } | ||
1686 | ccc = (NULL != ch->owner) ? ch->owner : ch->dest; | ||
1687 | if ((NULL != ccc) && (NULL != ccc->head_recv)) | ||
1688 | { | ||
1689 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1690 | "Lost end of transmission due to remote shutdown on %s\n", | ||
1691 | GCCH_2s (ch)); | ||
1692 | /* FIXME: change API to notify client about truncated transmission! */ | ||
1693 | } | ||
1694 | ch->destroy = GNUNET_YES; | ||
1695 | if (NULL != ccc) | ||
1696 | GSC_handle_remote_channel_destroy (ccc->c, ccc->ccn, ch); | ||
1697 | channel_destroy (ch); | ||
1698 | } | ||
1699 | |||
1700 | |||
1701 | /** | ||
1702 | * Test if element @a e1 comes before element @a e2. | ||
1703 | * | ||
1704 | * @param cls closure, to a flag where we indicate duplicate packets | ||
1705 | * @param crm1 an element of to sort | ||
1706 | * @param crm2 another element to sort | ||
1707 | * @return #GNUNET_YES if @e1 < @e2, otherwise #GNUNET_NO | ||
1708 | */ | ||
1709 | static int | ||
1710 | cmp_crm_by_next_retry (void *cls, | ||
1711 | struct CadetReliableMessage *crm1, | ||
1712 | struct CadetReliableMessage *crm2) | ||
1713 | { | ||
1714 | if (crm1->next_retry.abs_value_us < crm2->next_retry.abs_value_us) | ||
1715 | return GNUNET_YES; | ||
1716 | return GNUNET_NO; | ||
1717 | } | ||
1718 | |||
1719 | |||
1720 | /** | ||
1721 | * Function called once the tunnel has sent one of our messages. | ||
1722 | * If the message is unreliable, simply frees the `crm`. If the | ||
1723 | * message was reliable, calculate retransmission time and | ||
1724 | * wait for ACK (or retransmit). | ||
1725 | * | ||
1726 | * @param cls the `struct CadetReliableMessage` that was sent | ||
1727 | * @param cid identifier of the connection within the tunnel, NULL | ||
1728 | * if transmission failed | ||
1729 | */ | ||
1730 | static void | ||
1731 | data_sent_cb (void *cls, | ||
1732 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid) | ||
1733 | { | ||
1734 | struct CadetReliableMessage *crm = cls; | ||
1735 | struct CadetChannel *ch = crm->ch; | ||
1736 | |||
1737 | GNUNET_assert (GNUNET_NO == ch->is_loopback); | ||
1738 | GNUNET_assert (NULL != crm->qe); | ||
1739 | crm->qe = NULL; | ||
1740 | GNUNET_CONTAINER_DLL_remove (ch->head_sent, ch->tail_sent, crm); | ||
1741 | if (GNUNET_NO == ch->reliable) | ||
1742 | { | ||
1743 | GNUNET_free (crm->data_message); | ||
1744 | GNUNET_free (crm); | ||
1745 | ch->pending_messages--; | ||
1746 | send_ack_to_client (ch, (NULL == ch->owner) ? GNUNET_NO : GNUNET_YES); | ||
1747 | return; | ||
1748 | } | ||
1749 | if (NULL == cid) | ||
1750 | { | ||
1751 | /* There was an error sending. */ | ||
1752 | crm->num_transmissions = GNUNET_SYSERR; | ||
1753 | } | ||
1754 | else if (GNUNET_SYSERR != crm->num_transmissions) | ||
1755 | { | ||
1756 | /* Increment transmission counter, and possibly store @a cid | ||
1757 | if this was the first transmission. */ | ||
1758 | crm->num_transmissions++; | ||
1759 | if (1 == crm->num_transmissions) | ||
1760 | { | ||
1761 | crm->first_transmission_time = GNUNET_TIME_absolute_get (); | ||
1762 | crm->connection_taken = *cid; | ||
1763 | GCC_ack_expected (cid); | ||
1764 | } | ||
1765 | } | ||
1766 | if ((0 == crm->retry_delay.rel_value_us) && (NULL != cid)) | ||
1767 | { | ||
1768 | struct CadetConnection *cc = GCC_lookup (cid); | ||
1769 | |||
1770 | if (NULL != cc) | ||
1771 | crm->retry_delay = GCC_get_metrics (cc)->aged_latency; | ||
1772 | else | ||
1773 | crm->retry_delay = ch->retry_time; | ||
1774 | } | ||
1775 | crm->retry_delay = GNUNET_TIME_STD_BACKOFF (crm->retry_delay); | ||
1776 | crm->retry_delay = GNUNET_TIME_relative_max (crm->retry_delay, MIN_RTT_DELAY); | ||
1777 | crm->next_retry = GNUNET_TIME_relative_to_absolute (crm->retry_delay); | ||
1778 | |||
1779 | GNUNET_CONTAINER_DLL_insert_sorted (struct CadetReliableMessage, | ||
1780 | cmp_crm_by_next_retry, | ||
1781 | NULL, | ||
1782 | ch->head_sent, | ||
1783 | ch->tail_sent, | ||
1784 | crm); | ||
1785 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1786 | "Message %u sent, next transmission on %s in %s\n", | ||
1787 | (unsigned int) ntohl (crm->data_message->mid.mid), | ||
1788 | GCCH_2s (ch), | ||
1789 | GNUNET_STRINGS_relative_time_to_string ( | ||
1790 | GNUNET_TIME_absolute_get_remaining ( | ||
1791 | ch->head_sent->next_retry), | ||
1792 | GNUNET_YES)); | ||
1793 | if (NULL == ch->head_sent->qe) | ||
1794 | { | ||
1795 | if (NULL != ch->retry_data_task) | ||
1796 | GNUNET_SCHEDULER_cancel (ch->retry_data_task); | ||
1797 | ch->retry_data_task = GNUNET_SCHEDULER_add_at (ch->head_sent->next_retry, | ||
1798 | &retry_transmission, | ||
1799 | ch); | ||
1800 | } | ||
1801 | } | ||
1802 | |||
1803 | |||
1804 | /** | ||
1805 | * Handle data given by a client. | ||
1806 | * | ||
1807 | * Check whether the client is allowed to send in this tunnel, save if | ||
1808 | * channel is reliable and send an ACK to the client if there is still | ||
1809 | * buffer space in the tunnel. | ||
1810 | * | ||
1811 | * @param ch Channel. | ||
1812 | * @param sender_ccn ccn of the sender | ||
1813 | * @param buf payload to transmit. | ||
1814 | * @param buf_len number of bytes in @a buf | ||
1815 | * @return #GNUNET_OK if everything goes well, | ||
1816 | * #GNUNET_SYSERR in case of an error. | ||
1817 | */ | ||
1818 | int | ||
1819 | GCCH_handle_local_data (struct CadetChannel *ch, | ||
1820 | struct GNUNET_CADET_ClientChannelNumber sender_ccn, | ||
1821 | const char *buf, | ||
1822 | size_t buf_len) | ||
1823 | { | ||
1824 | struct CadetReliableMessage *crm; | ||
1825 | |||
1826 | if (ch->pending_messages >= ch->max_pending_messages) | ||
1827 | { | ||
1828 | GNUNET_break (0); /* Fails: #5370 */ | ||
1829 | return GNUNET_SYSERR; | ||
1830 | } | ||
1831 | if (GNUNET_YES == ch->destroy) | ||
1832 | { | ||
1833 | /* we are going down, drop messages */ | ||
1834 | return GNUNET_OK; | ||
1835 | } | ||
1836 | ch->pending_messages++; | ||
1837 | |||
1838 | if (GNUNET_YES == ch->is_loopback) | ||
1839 | { | ||
1840 | struct CadetChannelClient *receiver; | ||
1841 | struct GNUNET_MQ_Envelope *env; | ||
1842 | struct GNUNET_CADET_LocalData *ld; | ||
1843 | int ack_to_owner; | ||
1844 | |||
1845 | env = | ||
1846 | GNUNET_MQ_msg_extra (ld, buf_len, GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA); | ||
1847 | if ((NULL != ch->owner) && | ||
1848 | (sender_ccn.channel_of_client == ch->owner->ccn.channel_of_client)) | ||
1849 | { | ||
1850 | receiver = ch->dest; | ||
1851 | ack_to_owner = GNUNET_YES; | ||
1852 | } | ||
1853 | else if ((NULL != ch->dest) && | ||
1854 | (sender_ccn.channel_of_client == ch->dest->ccn.channel_of_client)) | ||
1855 | { | ||
1856 | receiver = ch->owner; | ||
1857 | ack_to_owner = GNUNET_NO; | ||
1858 | } | ||
1859 | else | ||
1860 | { | ||
1861 | GNUNET_free (env); | ||
1862 | GNUNET_break (0); | ||
1863 | return GNUNET_SYSERR; | ||
1864 | } | ||
1865 | GNUNET_assert (NULL != receiver); | ||
1866 | ld->ccn = receiver->ccn; | ||
1867 | GNUNET_memcpy (&ld[1], buf, buf_len); | ||
1868 | if (GNUNET_YES == receiver->client_ready) | ||
1869 | { | ||
1870 | ch->pending_messages--; | ||
1871 | GSC_send_to_client (receiver->c, env); | ||
1872 | send_ack_to_client (ch, ack_to_owner); | ||
1873 | } | ||
1874 | else | ||
1875 | { | ||
1876 | struct CadetOutOfOrderMessage *oom; | ||
1877 | |||
1878 | oom = GNUNET_new (struct CadetOutOfOrderMessage); | ||
1879 | oom->env = env; | ||
1880 | GNUNET_CONTAINER_DLL_insert_tail (receiver->head_recv, | ||
1881 | receiver->tail_recv, | ||
1882 | oom); | ||
1883 | receiver->num_recv++; | ||
1884 | } | ||
1885 | return GNUNET_OK; | ||
1886 | } | ||
1887 | |||
1888 | /* Everything is correct, send the message. */ | ||
1889 | crm = GNUNET_malloc (sizeof(*crm)); | ||
1890 | crm->ch = ch; | ||
1891 | crm->data_message = GNUNET_malloc ( | ||
1892 | sizeof(struct GNUNET_CADET_ChannelAppDataMessage) + buf_len); | ||
1893 | crm->data_message->header.size = | ||
1894 | htons (sizeof(struct GNUNET_CADET_ChannelAppDataMessage) + buf_len); | ||
1895 | crm->data_message->header.type = | ||
1896 | htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA); | ||
1897 | ch->mid_send.mid = htonl (ntohl (ch->mid_send.mid) + 1); | ||
1898 | crm->data_message->mid = ch->mid_send; | ||
1899 | crm->data_message->ctn = ch->ctn; | ||
1900 | GNUNET_memcpy (&crm->data_message[1], buf, buf_len); | ||
1901 | GNUNET_CONTAINER_DLL_insert_tail (ch->head_sent, ch->tail_sent, crm); | ||
1902 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1903 | "Sending message %u from local client to %s with %lu bytes\n", | ||
1904 | ntohl (crm->data_message->mid.mid), | ||
1905 | GCCH_2s (ch), | ||
1906 | (unsigned long) buf_len); | ||
1907 | if (NULL != ch->retry_data_task) | ||
1908 | { | ||
1909 | GNUNET_SCHEDULER_cancel (ch->retry_data_task); | ||
1910 | ch->retry_data_task = NULL; | ||
1911 | } | ||
1912 | crm->qe = GCT_send (ch->t, &crm->data_message->header, &data_sent_cb, crm, | ||
1913 | &crm->data_message->ctn); | ||
1914 | GNUNET_assert (NULL == ch->retry_data_task); | ||
1915 | return GNUNET_OK; | ||
1916 | } | ||
1917 | |||
1918 | |||
1919 | /** | ||
1920 | * Handle ACK from client on local channel. Means the client is ready | ||
1921 | * for more data, see if we have any for it. | ||
1922 | * | ||
1923 | * @param ch channel to destroy | ||
1924 | * @param client_ccn ccn of the client sending the ack | ||
1925 | */ | ||
1926 | void | ||
1927 | GCCH_handle_local_ack (struct CadetChannel *ch, | ||
1928 | struct GNUNET_CADET_ClientChannelNumber client_ccn) | ||
1929 | { | ||
1930 | struct CadetChannelClient *ccc; | ||
1931 | struct CadetOutOfOrderMessage *com; | ||
1932 | |||
1933 | if ((NULL != ch->owner) && | ||
1934 | (ch->owner->ccn.channel_of_client == client_ccn.channel_of_client)) | ||
1935 | ccc = ch->owner; | ||
1936 | else if ((NULL != ch->dest) && | ||
1937 | (ch->dest->ccn.channel_of_client == client_ccn.channel_of_client)) | ||
1938 | ccc = ch->dest; | ||
1939 | else | ||
1940 | GNUNET_assert (0); | ||
1941 | ccc->client_ready = GNUNET_YES; | ||
1942 | com = ccc->head_recv; | ||
1943 | if (NULL == com) | ||
1944 | { | ||
1945 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1946 | "Got LOCAL_ACK, %s-%X ready to receive more data, but none pending on %s-%X(%p)!\n", | ||
1947 | GSC_2s (ccc->c), | ||
1948 | ntohl (client_ccn.channel_of_client), | ||
1949 | GCCH_2s (ch), | ||
1950 | ntohl (ccc->ccn.channel_of_client), | ||
1951 | ccc); | ||
1952 | return; /* none pending */ | ||
1953 | } | ||
1954 | if (GNUNET_YES == ch->is_loopback) | ||
1955 | { | ||
1956 | int to_owner; | ||
1957 | |||
1958 | /* Messages are always in-order, just send */ | ||
1959 | GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, com); | ||
1960 | ccc->num_recv--; | ||
1961 | GSC_send_to_client (ccc->c, com->env); | ||
1962 | /* Notify sender that we can receive more */ | ||
1963 | if ((NULL != ch->owner) && | ||
1964 | (ccc->ccn.channel_of_client == ch->owner->ccn.channel_of_client)) | ||
1965 | { | ||
1966 | to_owner = GNUNET_NO; | ||
1967 | } | ||
1968 | else | ||
1969 | { | ||
1970 | GNUNET_assert ((NULL != ch->dest) && (ccc->ccn.channel_of_client == | ||
1971 | ch->dest->ccn.channel_of_client)); | ||
1972 | to_owner = GNUNET_YES; | ||
1973 | } | ||
1974 | send_ack_to_client (ch, to_owner); | ||
1975 | GNUNET_free (com); | ||
1976 | return; | ||
1977 | } | ||
1978 | |||
1979 | if ((com->mid.mid != ch->mid_recv.mid) && (GNUNET_NO == ch->out_of_order) && | ||
1980 | (GNUNET_YES == ch->reliable)) | ||
1981 | { | ||
1982 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1983 | "Got LOCAL_ACK, %s-%X ready to receive more data (but next one is out-of-order %u vs. %u)!\n", | ||
1984 | GSC_2s (ccc->c), | ||
1985 | ntohl (ccc->ccn.channel_of_client), | ||
1986 | ntohl (com->mid.mid), | ||
1987 | ntohl (ch->mid_recv.mid)); | ||
1988 | return; /* missing next one in-order */ | ||
1989 | } | ||
1990 | |||
1991 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1992 | "Got LOCAL_ACK, giving payload message %u to %s-%X on %s\n", | ||
1993 | ntohl (com->mid.mid), | ||
1994 | GSC_2s (ccc->c), | ||
1995 | ntohl (ccc->ccn.channel_of_client), | ||
1996 | GCCH_2s (ch)); | ||
1997 | |||
1998 | /* all good, pass next message to client */ | ||
1999 | GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, com); | ||
2000 | ccc->num_recv--; | ||
2001 | /* FIXME: if unreliable, this is not aggressive | ||
2002 | enough, as it would be OK to have lost some! */ | ||
2003 | |||
2004 | ch->mid_recv.mid = htonl (1 + ntohl (com->mid.mid)); | ||
2005 | ch->mid_futures >>= 1; /* equivalent to division by 2 */ | ||
2006 | ccc->client_ready = GNUNET_NO; | ||
2007 | GSC_send_to_client (ccc->c, com->env); | ||
2008 | GNUNET_free (com); | ||
2009 | send_channel_data_ack (ch); | ||
2010 | if (NULL != ccc->head_recv) | ||
2011 | return; | ||
2012 | if (GNUNET_NO == ch->destroy) | ||
2013 | return; | ||
2014 | GCT_send_channel_destroy (ch->t, ch->ctn); | ||
2015 | channel_destroy (ch); | ||
2016 | } | ||
2017 | |||
2018 | |||
2019 | #define LOG2(level, ...) \ | ||
2020 | GNUNET_log_from_nocheck (level, "cadet-chn", __VA_ARGS__) | ||
2021 | |||
2022 | |||
2023 | /** | ||
2024 | * Log channel info. | ||
2025 | * | ||
2026 | * @param ch Channel. | ||
2027 | * @param level Debug level to use. | ||
2028 | */ | ||
2029 | void | ||
2030 | GCCH_debug (struct CadetChannel *ch, enum GNUNET_ErrorType level) | ||
2031 | { | ||
2032 | #if ! defined(GNUNET_CULL_LOGGING) | ||
2033 | int do_log; | ||
2034 | |||
2035 | do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK), | ||
2036 | "cadet-chn", | ||
2037 | __FILE__, | ||
2038 | __FUNCTION__, | ||
2039 | __LINE__); | ||
2040 | if (0 == do_log) | ||
2041 | return; | ||
2042 | |||
2043 | if (NULL == ch) | ||
2044 | { | ||
2045 | LOG2 (level, "CHN *** DEBUG NULL CHANNEL ***\n"); | ||
2046 | return; | ||
2047 | } | ||
2048 | LOG2 (level, "CHN %s:%X (%p)\n", GCT_2s (ch->t), ch->ctn.cn, ch); | ||
2049 | if (NULL != ch->owner) | ||
2050 | { | ||
2051 | LOG2 (level, | ||
2052 | "CHN origin %s ready %s local-id: %u\n", | ||
2053 | GSC_2s (ch->owner->c), | ||
2054 | ch->owner->client_ready ? "YES" : "NO", | ||
2055 | ntohl (ch->owner->ccn.channel_of_client)); | ||
2056 | } | ||
2057 | if (NULL != ch->dest) | ||
2058 | { | ||
2059 | LOG2 (level, | ||
2060 | "CHN destination %s ready %s local-id: %u\n", | ||
2061 | GSC_2s (ch->dest->c), | ||
2062 | ch->dest->client_ready ? "YES" : "NO", | ||
2063 | ntohl (ch->dest->ccn.channel_of_client)); | ||
2064 | } | ||
2065 | LOG2 (level, | ||
2066 | "CHN Message IDs recv: %d (%llX), send: %d\n", | ||
2067 | ntohl (ch->mid_recv.mid), | ||
2068 | (unsigned long long) ch->mid_futures, | ||
2069 | ntohl (ch->mid_send.mid)); | ||
2070 | #endif | ||
2071 | } | ||
2072 | |||
2073 | |||
2074 | /* end of gnunet-service-cadet_channel.c */ | ||
diff --git a/src/cadet/gnunet-service-cadet_channel.h b/src/cadet/gnunet-service-cadet_channel.h deleted file mode 100644 index 6d691cafc..000000000 --- a/src/cadet/gnunet-service-cadet_channel.h +++ /dev/null | |||
@@ -1,304 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2001-2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/gnunet-service-cadet_channel.h | ||
23 | * @brief GNUnet CADET service with encryption | ||
24 | * @author Bartlomiej Polot | ||
25 | * @author Christian Grothoff | ||
26 | */ | ||
27 | #ifndef GNUNET_SERVICE_CADET_CHANNEL_H | ||
28 | #define GNUNET_SERVICE_CADET_CHANNEL_H | ||
29 | |||
30 | #include "gnunet-service-cadet.h" | ||
31 | #include "gnunet-service-cadet_peer.h" | ||
32 | #include "cadet_protocol.h" | ||
33 | |||
34 | |||
35 | /** | ||
36 | * A channel is a bidirectional connection between two CADET | ||
37 | * clients. Communication can be reliable, unreliable, in-order | ||
38 | * or out-of-order. One client is the "local" client, this | ||
39 | * one initiated the connection. The other client is the | ||
40 | * "incoming" client, this one listened on a port to accept | ||
41 | * the connection from the "local" client. | ||
42 | */ | ||
43 | struct 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 | */ | ||
55 | void | ||
56 | GCCH_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 | */ | ||
65 | int | ||
66 | GCCH_is_type_to_drop (struct CadetChannel *ch, const struct | ||
67 | GNUNET_MessageHeader *message); | ||
68 | |||
69 | /** | ||
70 | * Check if type of message is the one to drop. | ||
71 | * @param ch CadetChannel to assign type to drop. | ||
72 | * @param message GNUNET_CADET_RequestDropCadetMessage to get the type from. | ||
73 | */ | ||
74 | void | ||
75 | GCCH_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 | */ | ||
85 | const char * | ||
86 | GCCH_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 | */ | ||
95 | void | ||
96 | GCCH_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 | */ | ||
107 | struct GNUNET_CADET_ChannelTunnelNumber | ||
108 | GCCH_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 | */ | ||
121 | struct CadetChannel * | ||
122 | GCCH_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 | */ | ||
138 | void | ||
139 | GCCH_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 | */ | ||
152 | void | ||
153 | GCCH_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 | */ | ||
168 | void | ||
169 | GCCH_tunnel_up (struct CadetChannel *ch); | ||
170 | |||
171 | |||
172 | /** | ||
173 | * Create a new channel based on a request coming in over the network. | ||
174 | * | ||
175 | * @param t tunnel to the remote peer | ||
176 | * @param chid identifier of this channel in the tunnel | ||
177 | * @param origin peer to who initiated the channel | ||
178 | * @param h_port hash of desired local port | ||
179 | * @param options options for the channel | ||
180 | * @return handle to the new channel | ||
181 | */ | ||
182 | struct CadetChannel * | ||
183 | GCCH_channel_incoming_new (struct CadetTunnel *t, | ||
184 | struct GNUNET_CADET_ChannelTunnelNumber chid, | ||
185 | const struct GNUNET_HashCode *h_port, | ||
186 | uint32_t options); | ||
187 | |||
188 | |||
189 | /** | ||
190 | * We got a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN message again for | ||
191 | * this channel. If the binding was successful, (re)transmit the | ||
192 | * #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK. | ||
193 | * | ||
194 | * @param ch channel that got the duplicate open | ||
195 | * @param cti identifier of the connection that delivered the message | ||
196 | */ | ||
197 | void | ||
198 | GCCH_handle_duplicate_open (struct CadetChannel *ch, | ||
199 | const struct | ||
200 | GNUNET_CADET_ConnectionTunnelIdentifier *cti); | ||
201 | |||
202 | |||
203 | /** | ||
204 | * We got payload data for a channel. Pass it on to the client. | ||
205 | * | ||
206 | * @param ch channel that got data | ||
207 | * @param cti identifier of the connection that delivered the message | ||
208 | * @param msg message that was received | ||
209 | */ | ||
210 | void | ||
211 | GCCH_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 | */ | ||
226 | void | ||
227 | GCCH_handle_channel_plaintext_data_ack (struct CadetChannel *ch, | ||
228 | const struct | ||
229 | GNUNET_CADET_ConnectionTunnelIdentifier | ||
230 | *cti, | ||
231 | const struct | ||
232 | GNUNET_CADET_ChannelDataAckMessage *ack); | ||
233 | |||
234 | |||
235 | /** | ||
236 | * We got an acknowledgement for the creation of the channel | ||
237 | * (the port is open on the other side). Begin transmissions. | ||
238 | * | ||
239 | * @param ch channel to destroy | ||
240 | * @param cti identifier of the connection that delivered the message, | ||
241 | * NULL if the ACK was inferred because we got payload or are on loopback | ||
242 | * @param port port number (needed to verify receiver knows the port) | ||
243 | */ | ||
244 | void | ||
245 | GCCH_handle_channel_open_ack (struct CadetChannel *ch, | ||
246 | const struct | ||
247 | GNUNET_CADET_ConnectionTunnelIdentifier *cti, | ||
248 | const struct GNUNET_HashCode *port); | ||
249 | |||
250 | |||
251 | /** | ||
252 | * Destroy channel, based on the other peer closing the | ||
253 | * connection. Also needs to remove this channel from | ||
254 | * the tunnel. | ||
255 | * | ||
256 | * FIXME: need to make it possible to defer destruction until we have | ||
257 | * received all messages up to the destroy, and right now the destroy | ||
258 | * message (and this API) fails to give is the information we need! | ||
259 | * | ||
260 | * FIXME: also need to know if the other peer got a destroy from | ||
261 | * us before! | ||
262 | * | ||
263 | * @param ch channel to destroy | ||
264 | * @param cti identifier of the connection that delivered the message, | ||
265 | * NULL during shutdown | ||
266 | */ | ||
267 | void | ||
268 | GCCH_handle_remote_destroy (struct CadetChannel *ch, | ||
269 | const struct | ||
270 | GNUNET_CADET_ConnectionTunnelIdentifier *cti); | ||
271 | |||
272 | |||
273 | /** | ||
274 | * Handle data given by a client. | ||
275 | * | ||
276 | * Check whether the client is allowed to send in this tunnel, save if | ||
277 | * channel is reliable and send an ACK to the client if there is still | ||
278 | * buffer space in the tunnel. | ||
279 | * | ||
280 | * @param ch Channel. | ||
281 | * @param sender_ccn ccn of the sender | ||
282 | * @param buf payload to transmit. | ||
283 | * @param buf_len number of bytes in @a buf | ||
284 | * @return #GNUNET_OK if everything goes well, | ||
285 | * #GNUNET_SYSERR in case of an error. | ||
286 | */ | ||
287 | int | ||
288 | GCCH_handle_local_data (struct CadetChannel *ch, | ||
289 | struct GNUNET_CADET_ClientChannelNumber sender_ccn, | ||
290 | const char *buf, | ||
291 | size_t buf_len); | ||
292 | |||
293 | |||
294 | /** | ||
295 | * Handle ACK from client on local channel. | ||
296 | * | ||
297 | * @param ch channel to destroy | ||
298 | * @param client_ccn ccn of the client sending the ack | ||
299 | */ | ||
300 | void | ||
301 | GCCH_handle_local_ack (struct CadetChannel *ch, | ||
302 | struct GNUNET_CADET_ClientChannelNumber client_ccn); | ||
303 | |||
304 | #endif | ||
diff --git a/src/cadet/gnunet-service-cadet_connection.c b/src/cadet/gnunet-service-cadet_connection.c deleted file mode 100644 index 637e8663b..000000000 --- a/src/cadet/gnunet-service-cadet_connection.c +++ /dev/null | |||
@@ -1,1106 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2001-2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/gnunet-service-cadet_connection.c | ||
23 | * @brief management of CORE-level end-to-end connections; establishes | ||
24 | * end-to-end routes and transmits messages along the route | ||
25 | * @author Bartlomiej Polot | ||
26 | * @author Christian Grothoff | ||
27 | */ | ||
28 | #include "platform.h" | ||
29 | #include "gnunet_signatures.h" | ||
30 | #include "gnunet-service-cadet_connection.h" | ||
31 | #include "gnunet-service-cadet_channel.h" | ||
32 | #include "gnunet-service-cadet_paths.h" | ||
33 | #include "gnunet-service-cadet_tunnels.h" | ||
34 | #include "gnunet_cadet_service.h" | ||
35 | #include "gnunet_statistics_service.h" | ||
36 | #include "cadet_protocol.h" | ||
37 | |||
38 | |||
39 | #define LOG(level, ...) GNUNET_log_from (level, "cadet-con", __VA_ARGS__) | ||
40 | |||
41 | |||
42 | /** | ||
43 | * How long do we wait initially before retransmitting the KX? | ||
44 | * TODO: replace by 2 RTT if/once we have connection-level RTT data! | ||
45 | */ | ||
46 | #define INITIAL_CONNECTION_CREATE_RETRY_DELAY \ | ||
47 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 200) | ||
48 | |||
49 | |||
50 | /** | ||
51 | * All the states a connection can be in. | ||
52 | */ | ||
53 | enum 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 | */ | ||
85 | struct 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 | */ | ||
185 | struct CadetConnection * | ||
186 | GCC_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 | */ | ||
201 | static void | ||
202 | update_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 | */ | ||
243 | static void | ||
244 | GCC_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 | */ | ||
283 | void | ||
284 | GCC_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 | */ | ||
302 | void | ||
303 | GCC_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 | */ | ||
328 | struct CadetTConnection * | ||
329 | GCC_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 | */ | ||
341 | const struct CadetConnectionMetrics * | ||
342 | GCC_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 | */ | ||
354 | static void | ||
355 | send_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 | */ | ||
366 | static void | ||
367 | keepalive_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 | */ | ||
385 | static void | ||
386 | send_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 | */ | ||
420 | void | ||
421 | GCC_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 | */ | ||
440 | void | ||
441 | GCC_ack_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid) | ||
442 | { | ||
443 | struct CadetConnection *cc; | ||
444 | |||
445 | cc = GCC_lookup (cid); | ||
446 | if (NULL == cc) | ||
447 | return; /* whopise, connection already down? */ | ||
448 | cc->metrics.num_successes++; | ||
449 | } | ||
450 | |||
451 | |||
452 | /** | ||
453 | * We observed some the given @a latency on the connection | ||
454 | * identified by @a cti. (The same connection was taken | ||
455 | * in both directions.) | ||
456 | * | ||
457 | * @param cid connection identifier where we measured latency | ||
458 | * @param latency the observed latency | ||
459 | */ | ||
460 | void | ||
461 | GCC_latency_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid, | ||
462 | struct GNUNET_TIME_Relative latency) | ||
463 | { | ||
464 | struct CadetConnection *cc; | ||
465 | double weight; | ||
466 | double result; | ||
467 | |||
468 | cc = GCC_lookup (cid); | ||
469 | if (NULL == cc) | ||
470 | return; /* whopise, connection already down? */ | ||
471 | GNUNET_STATISTICS_update (stats, "# latencies observed", 1, GNUNET_NO); | ||
472 | cc->latency_datapoints++; | ||
473 | if (cc->latency_datapoints >= 7) | ||
474 | weight = 7.0; | ||
475 | else | ||
476 | weight = cc->latency_datapoints; | ||
477 | /* Compute weighted average, giving at MOST weight 7 to the | ||
478 | existing values, or less if that value is based on fewer than 7 | ||
479 | measurements. */ | ||
480 | result = (weight * cc->metrics.aged_latency.rel_value_us) | ||
481 | + 1.0 * latency.rel_value_us; | ||
482 | result /= (weight + 1.0); | ||
483 | cc->metrics.aged_latency.rel_value_us = (uint64_t) result; | ||
484 | } | ||
485 | |||
486 | |||
487 | /** | ||
488 | * A #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK was received for | ||
489 | * this connection, implying that the end-to-end connection is up. | ||
490 | * Process it. | ||
491 | * | ||
492 | * @param cc the connection that got the ACK. | ||
493 | */ | ||
494 | void | ||
495 | GCC_handle_connection_create_ack (struct CadetConnection *cc) | ||
496 | { | ||
497 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
498 | "Received CADET_CONNECTION_CREATE_ACK for %s in state %d (%s)\n", | ||
499 | GCC_2s (cc), | ||
500 | cc->state, | ||
501 | (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy"); | ||
502 | if (CADET_CONNECTION_READY == cc->state) | ||
503 | return; /* Duplicate ACK, ignore */ | ||
504 | if (NULL != cc->task) | ||
505 | { | ||
506 | GNUNET_SCHEDULER_cancel (cc->task); | ||
507 | cc->task = NULL; | ||
508 | } | ||
509 | cc->metrics.age = GNUNET_TIME_absolute_get (); | ||
510 | update_state (cc, CADET_CONNECTION_READY, cc->mqm_ready); | ||
511 | if ((NULL == cc->keepalive_qe) && (GNUNET_YES == cc->mqm_ready) && | ||
512 | (NULL == cc->task)) | ||
513 | cc->task = | ||
514 | GNUNET_SCHEDULER_add_delayed (keepalive_period, &send_keepalive, cc); | ||
515 | } | ||
516 | |||
517 | |||
518 | /** | ||
519 | * Handle KX message. | ||
520 | * | ||
521 | * @param cc connection that received encrypted message | ||
522 | * @param msg the key exchange message | ||
523 | */ | ||
524 | void | ||
525 | GCC_handle_kx (struct CadetConnection *cc, | ||
526 | const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg) | ||
527 | { | ||
528 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
529 | "Received KX message with ephermal %s on CC %s in state %d\n", | ||
530 | GNUNET_e2s (&msg->ephemeral_key), | ||
531 | GNUNET_sh2s (&cc->cid.connection_of_tunnel), | ||
532 | cc->state); | ||
533 | if (CADET_CONNECTION_SENT == cc->state) | ||
534 | { | ||
535 | /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine, | ||
536 | clearly something is working, so pretend we got an ACK. */ | ||
537 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
538 | "Faking connection CADET_CONNECTION_CREATE_ACK for %s due to KX\n", | ||
539 | GCC_2s (cc)); | ||
540 | GCC_handle_connection_create_ack (cc); | ||
541 | } | ||
542 | GCT_handle_kx (cc->ct, msg); | ||
543 | } | ||
544 | |||
545 | |||
546 | /** | ||
547 | * Handle KX_AUTH message. | ||
548 | * | ||
549 | * @param cc connection that received encrypted message | ||
550 | * @param msg the key exchange message | ||
551 | */ | ||
552 | void | ||
553 | GCC_handle_kx_auth (struct CadetConnection *cc, | ||
554 | const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg) | ||
555 | { | ||
556 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
557 | "Received KX AUTH message with ephermal %s on CC %s in state %d\n", | ||
558 | GNUNET_e2s (&msg->kx.ephemeral_key), | ||
559 | GNUNET_sh2s (&cc->cid.connection_of_tunnel), | ||
560 | cc->state); | ||
561 | if (CADET_CONNECTION_SENT == cc->state) | ||
562 | { | ||
563 | /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine, | ||
564 | clearly something is working, so pretend we got an ACK. */ | ||
565 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
566 | "Faking connection CADET_CONNECTION_CREATE_ACK for %s due to KX\n", | ||
567 | GCC_2s (cc)); | ||
568 | GCC_handle_connection_create_ack (cc); | ||
569 | } | ||
570 | GCT_handle_kx_auth (cc->ct, msg); | ||
571 | } | ||
572 | |||
573 | |||
574 | /** | ||
575 | * Handle encrypted message. | ||
576 | * | ||
577 | * @param cc connection that received encrypted message | ||
578 | * @param msg the encrypted message to decrypt | ||
579 | */ | ||
580 | void | ||
581 | GCC_handle_encrypted (struct CadetConnection *cc, | ||
582 | const struct GNUNET_CADET_TunnelEncryptedMessage *msg) | ||
583 | { | ||
584 | if (CADET_CONNECTION_SENT == cc->state) | ||
585 | { | ||
586 | /* We didn't get the CREATE_ACK, but instead got payload. That's fine, | ||
587 | clearly something is working, so pretend we got an ACK. */ | ||
588 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
589 | "Faking connection ACK for %s due to ENCRYPTED payload\n", | ||
590 | GCC_2s (cc)); | ||
591 | GCC_handle_connection_create_ack (cc); | ||
592 | } | ||
593 | cc->metrics.last_use = GNUNET_TIME_absolute_get (); | ||
594 | GCT_handle_encrypted (cc->ct, msg); | ||
595 | } | ||
596 | |||
597 | |||
598 | /** | ||
599 | * Set the signature for a monotime value on a GNUNET_CADET_ConnectionCreateMessage. | ||
600 | * | ||
601 | * @param msg The GNUNET_CADET_ConnectionCreateMessage. | ||
602 | */ | ||
603 | void | ||
604 | set_monotime_sig (struct GNUNET_CADET_ConnectionCreateMessage *msg) | ||
605 | { | ||
606 | |||
607 | struct CadetConnectionCreatePS cp = { .purpose.purpose = htonl ( | ||
608 | GNUNET_SIGNATURE_PURPOSE_CADET_CONNECTION_INITIATOR), | ||
609 | .purpose.size = htonl (sizeof(cp)), | ||
610 | .monotonic_time = msg->monotime}; | ||
611 | |||
612 | GNUNET_CRYPTO_eddsa_sign (my_private_key, &cp, | ||
613 | &msg->monotime_sig); | ||
614 | |||
615 | } | ||
616 | |||
617 | |||
618 | /** | ||
619 | * Send a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE message to the | ||
620 | * first hop. | ||
621 | * | ||
622 | * @param cls the `struct CadetConnection` to initiate | ||
623 | */ | ||
624 | static void | ||
625 | send_create (void *cls) | ||
626 | { | ||
627 | struct CadetConnection *cc = cls; | ||
628 | struct GNUNET_CADET_ConnectionCreateMessage *create_msg; | ||
629 | struct GNUNET_PeerIdentity *pids; | ||
630 | struct GNUNET_MQ_Envelope *env; | ||
631 | struct CadetTunnel *t; | ||
632 | |||
633 | cc->task = NULL; | ||
634 | GNUNET_assert (GNUNET_YES == cc->mqm_ready); | ||
635 | env = | ||
636 | GNUNET_MQ_msg_extra (create_msg, | ||
637 | (2 + cc->off) * sizeof(struct GNUNET_PeerIdentity), | ||
638 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE); | ||
639 | // TODO This will be removed in a major release, because this will be a protocol breaking change. We set the deprecated 'reliable' bit here that was removed. | ||
640 | create_msg->options = 2; | ||
641 | create_msg->cid = cc->cid; | ||
642 | |||
643 | // check for tunnel state and set signed monotime (xrs,t3ss) | ||
644 | t = GCP_get_tunnel (cc->destination, GNUNET_YES); | ||
645 | if ((NULL != t) && (GCT_get_estate (t) == CADET_TUNNEL_KEY_UNINITIALIZED) && | ||
646 | (GCT_alice_or_betty (GCP_get_id (cc->destination)) == GNUNET_NO)) | ||
647 | { | ||
648 | create_msg->has_monotime = GNUNET_YES; | ||
649 | create_msg->monotime = GNUNET_TIME_absolute_hton ( | ||
650 | GNUNET_TIME_absolute_get_monotonic (cfg)); | ||
651 | set_monotime_sig (create_msg); | ||
652 | } | ||
653 | |||
654 | pids = (struct GNUNET_PeerIdentity *) &create_msg[1]; | ||
655 | pids[0] = my_full_id; | ||
656 | for (unsigned int i = 0; i <= cc->off; i++) | ||
657 | pids[i + 1] = *GCP_get_id (GCPP_get_peer_at_offset (cc->path, i)); | ||
658 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
659 | "Sending CADET_CONNECTION_CREATE message for %s with %u hops\n", | ||
660 | GCC_2s (cc), | ||
661 | cc->off + 2); | ||
662 | cc->env = env; | ||
663 | cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay); | ||
664 | cc->create_at = GNUNET_TIME_relative_to_absolute (cc->retry_delay); | ||
665 | update_state (cc, CADET_CONNECTION_SENT, GNUNET_NO); | ||
666 | GCP_send (cc->mq_man, env); | ||
667 | } | ||
668 | |||
669 | |||
670 | /** | ||
671 | * Send a CREATE_ACK message towards the origin. | ||
672 | * | ||
673 | * @param cls the `struct CadetConnection` to initiate | ||
674 | */ | ||
675 | static void | ||
676 | send_create_ack (void *cls) | ||
677 | { | ||
678 | struct CadetConnection *cc = cls; | ||
679 | struct GNUNET_CADET_ConnectionCreateAckMessage *ack_msg; | ||
680 | struct GNUNET_MQ_Envelope *env; | ||
681 | |||
682 | cc->task = NULL; | ||
683 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
684 | "Sending CONNECTION_CREATE_ACK message for %s\n", | ||
685 | GCC_2s (cc)); | ||
686 | GNUNET_assert (GNUNET_YES == cc->mqm_ready); | ||
687 | env = | ||
688 | GNUNET_MQ_msg (ack_msg, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK); | ||
689 | ack_msg->cid = cc->cid; | ||
690 | cc->env = env; | ||
691 | cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay); | ||
692 | cc->create_ack_at = GNUNET_TIME_relative_to_absolute (cc->retry_delay); | ||
693 | if (CADET_CONNECTION_CREATE_RECEIVED == cc->state) | ||
694 | update_state (cc, CADET_CONNECTION_READY, GNUNET_NO); | ||
695 | if (CADET_CONNECTION_READY == cc->state) | ||
696 | cc->task = | ||
697 | GNUNET_SCHEDULER_add_delayed (keepalive_period, &send_keepalive, cc); | ||
698 | GCP_send (cc->mq_man, env); | ||
699 | } | ||
700 | |||
701 | |||
702 | /** | ||
703 | * We got a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE for a | ||
704 | * connection that we already have. Either our ACK got lost | ||
705 | * or something is fishy. Consider retransmitting the ACK. | ||
706 | * | ||
707 | * @param cc connection that got the duplicate CREATE | ||
708 | */ | ||
709 | void | ||
710 | GCC_handle_duplicate_create (struct CadetConnection *cc) | ||
711 | { | ||
712 | if (GNUNET_YES == cc->mqm_ready) | ||
713 | { | ||
714 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
715 | "Got duplicate CREATE for %s, scheduling another ACK (%s)\n", | ||
716 | GCC_2s (cc), | ||
717 | (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy"); | ||
718 | /* Revert back to the state of having only received the 'CREATE', | ||
719 | and immediately proceed to send the CREATE_ACK. */ | ||
720 | update_state (cc, CADET_CONNECTION_CREATE_RECEIVED, cc->mqm_ready); | ||
721 | if (NULL != cc->task) | ||
722 | GNUNET_SCHEDULER_cancel (cc->task); | ||
723 | cc->task = | ||
724 | GNUNET_SCHEDULER_add_at (cc->create_ack_at, &send_create_ack, cc); | ||
725 | } | ||
726 | else | ||
727 | { | ||
728 | /* We are currently sending something else back, which | ||
729 | can only be an ACK or payload, either of which would | ||
730 | do. So actually no need to do anything. */ | ||
731 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
732 | "Got duplicate CREATE for %s. MQ is busy, not queueing another ACK\n", | ||
733 | GCC_2s (cc)); | ||
734 | } | ||
735 | } | ||
736 | |||
737 | |||
738 | /** | ||
739 | * There has been a change in the message queue existence for our | ||
740 | * peer at the first hop. Adjust accordingly. | ||
741 | * | ||
742 | * @param cls the `struct CadetConnection` | ||
743 | * @param available #GNUNET_YES if sending is now possible, | ||
744 | * #GNUNET_NO if sending is no longer possible | ||
745 | * #GNUNET_SYSERR if sending is no longer possible | ||
746 | * and the last envelope was discarded | ||
747 | */ | ||
748 | static void | ||
749 | manage_first_hop_mq (void *cls, int available) | ||
750 | { | ||
751 | struct CadetConnection *cc = cls; | ||
752 | |||
753 | if (GNUNET_YES != available) | ||
754 | { | ||
755 | /* Connection is down, for now... */ | ||
756 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Core MQ for %s went down\n", GCC_2s (cc)); | ||
757 | update_state (cc, CADET_CONNECTION_NEW, GNUNET_NO); | ||
758 | cc->retry_delay = INITIAL_CONNECTION_CREATE_RETRY_DELAY; | ||
759 | if (NULL != cc->task) | ||
760 | { | ||
761 | GNUNET_SCHEDULER_cancel (cc->task); | ||
762 | cc->task = NULL; | ||
763 | } | ||
764 | return; | ||
765 | } | ||
766 | |||
767 | update_state (cc, cc->state, GNUNET_YES); | ||
768 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
769 | "Core MQ for %s became available in state %d\n", | ||
770 | GCC_2s (cc), | ||
771 | cc->state); | ||
772 | switch (cc->state) | ||
773 | { | ||
774 | case CADET_CONNECTION_NEW: | ||
775 | /* Transmit immediately */ | ||
776 | cc->task = GNUNET_SCHEDULER_add_at (cc->create_at, &send_create, cc); | ||
777 | break; | ||
778 | |||
779 | case CADET_CONNECTION_SENDING_CREATE: | ||
780 | /* Should not be possible to be called in this state. */ | ||
781 | GNUNET_assert (0); | ||
782 | break; | ||
783 | |||
784 | case CADET_CONNECTION_SENT: | ||
785 | /* Retry a bit later... */ | ||
786 | cc->task = GNUNET_SCHEDULER_add_at (cc->create_at, &send_create, cc); | ||
787 | break; | ||
788 | |||
789 | case CADET_CONNECTION_CREATE_RECEIVED: | ||
790 | /* We got the 'CREATE' (incoming connection), should send the CREATE_ACK */ | ||
791 | cc->metrics.age = GNUNET_TIME_absolute_get (); | ||
792 | cc->task = | ||
793 | GNUNET_SCHEDULER_add_at (cc->create_ack_at, &send_create_ack, cc); | ||
794 | break; | ||
795 | |||
796 | case CADET_CONNECTION_READY: | ||
797 | if ((NULL == cc->keepalive_qe) && (GNUNET_YES == cc->mqm_ready) && | ||
798 | (NULL == cc->task)) | ||
799 | { | ||
800 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
801 | "Scheduling keepalive for %s in %s\n", | ||
802 | GCC_2s (cc), | ||
803 | GNUNET_STRINGS_relative_time_to_string (keepalive_period, | ||
804 | GNUNET_YES)); | ||
805 | cc->task = | ||
806 | GNUNET_SCHEDULER_add_delayed (keepalive_period, &send_keepalive, cc); | ||
807 | } | ||
808 | break; | ||
809 | } | ||
810 | } | ||
811 | |||
812 | |||
813 | /** | ||
814 | * Create a connection to @a destination via @a path and notify @a cb | ||
815 | * whenever we are ready for more data. Shared logic independent of | ||
816 | * who is initiating the connection. | ||
817 | * | ||
818 | * @param destination where to go | ||
819 | * @param path which path to take (may not be the full path) | ||
820 | * @param off offset of @a destination on @a path | ||
821 | * @param ct which tunnel uses this connection | ||
822 | * @param init_state initial state for the connection | ||
823 | * @param ready_cb function to call when ready to transmit | ||
824 | * @param ready_cb_cls closure for @a cb | ||
825 | * @return handle to the connection | ||
826 | */ | ||
827 | static struct CadetConnection * | ||
828 | connection_create (struct CadetPeer *destination, | ||
829 | struct CadetPeerPath *path, | ||
830 | unsigned int off, | ||
831 | struct CadetTConnection *ct, | ||
832 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid, | ||
833 | enum CadetConnectionState init_state, | ||
834 | GCC_ReadyCallback ready_cb, | ||
835 | void *ready_cb_cls) | ||
836 | { | ||
837 | struct CadetConnection *cc; | ||
838 | struct CadetPeer *first_hop; | ||
839 | |||
840 | cc = GNUNET_new (struct CadetConnection); | ||
841 | cc->state = init_state; | ||
842 | cc->ct = ct; | ||
843 | cc->destination = destination; /* xrs,t3ss,lurchi*/ | ||
844 | cc->cid = *cid; | ||
845 | cc->retry_delay = | ||
846 | GNUNET_TIME_relative_multiply (INITIAL_CONNECTION_CREATE_RETRY_DELAY, off); | ||
847 | GNUNET_assert (GNUNET_OK == | ||
848 | GNUNET_CONTAINER_multishortmap_put ( | ||
849 | connections, | ||
850 | &GCC_get_id (cc)->connection_of_tunnel, | ||
851 | cc, | ||
852 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
853 | cc->ready_cb = ready_cb; | ||
854 | cc->ready_cb_cls = ready_cb_cls; | ||
855 | cc->path = path; | ||
856 | cc->off = off; | ||
857 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
858 | "Creating %s using path %s (offset: %u)\n", | ||
859 | GCC_2s (cc), | ||
860 | GCPP_2s (path), | ||
861 | off); | ||
862 | GCPP_add_connection (path, off, cc); | ||
863 | for (unsigned int i = 0; i < off; i++) | ||
864 | GCP_add_connection (GCPP_get_peer_at_offset (path, i), cc); | ||
865 | first_hop = GCPP_get_peer_at_offset (path, 0); | ||
866 | cc->mq_man = GCP_request_mq (first_hop, &manage_first_hop_mq, cc); | ||
867 | return cc; | ||
868 | } | ||
869 | |||
870 | |||
871 | /** | ||
872 | * Create a connection to @a destination via @a path and | ||
873 | * notify @a cb whenever we are ready for more data. This | ||
874 | * is an inbound tunnel, so we must use the existing @a cid | ||
875 | * | ||
876 | * @param destination where to go | ||
877 | * @param path which path to take (may not be the full path) | ||
878 | * @param ct which tunnel uses this connection | ||
879 | * @param ready_cb function to call when ready to transmit | ||
880 | * @param ready_cb_cls closure for @a cb | ||
881 | * @return handle to the connection, NULL if we already have | ||
882 | * a connection that takes precedence on @a path | ||
883 | */ | ||
884 | struct CadetConnection * | ||
885 | GCC_create_inbound (struct CadetPeer *destination, | ||
886 | struct CadetPeerPath *path, | ||
887 | struct CadetTConnection *ct, | ||
888 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid, | ||
889 | GCC_ReadyCallback ready_cb, | ||
890 | void *ready_cb_cls) | ||
891 | { | ||
892 | struct CadetConnection *cc; | ||
893 | unsigned int off; | ||
894 | |||
895 | off = GCPP_find_peer (path, destination); | ||
896 | GNUNET_assert (UINT_MAX != off); | ||
897 | cc = GCPP_get_connection (path, destination, off); | ||
898 | if (NULL != cc) | ||
899 | { | ||
900 | int cmp; | ||
901 | |||
902 | cmp = GNUNET_memcmp (cid, &cc->cid); | ||
903 | if (0 == cmp) | ||
904 | { | ||
905 | /* Two peers picked the SAME random connection identifier at the | ||
906 | same time for the same path? Must be malicious. Drop | ||
907 | connection (existing and inbound), even if it is the only | ||
908 | one. */ | ||
909 | GNUNET_break_op (0); | ||
910 | GCT_connection_lost (cc->ct); | ||
911 | GCC_destroy_without_tunnel (cc); | ||
912 | return NULL; | ||
913 | } | ||
914 | if (0 < cmp) | ||
915 | { | ||
916 | /* drop existing */ | ||
917 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
918 | "Got two connections on %s, dropping my existing %s\n", | ||
919 | GCPP_2s (path), | ||
920 | GCC_2s (cc)); | ||
921 | GCT_connection_lost (cc->ct); | ||
922 | GCC_destroy_without_tunnel (cc); | ||
923 | } | ||
924 | else | ||
925 | { | ||
926 | /* keep existing */ | ||
927 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
928 | "Got two connections on %s, keeping my existing %s\n", | ||
929 | GCPP_2s (path), | ||
930 | GCC_2s (cc)); | ||
931 | return NULL; | ||
932 | } | ||
933 | } | ||
934 | |||
935 | return connection_create (destination, | ||
936 | path, | ||
937 | off, | ||
938 | ct, | ||
939 | cid, | ||
940 | CADET_CONNECTION_CREATE_RECEIVED, | ||
941 | ready_cb, | ||
942 | ready_cb_cls); | ||
943 | } | ||
944 | |||
945 | |||
946 | /** | ||
947 | * Create a connection to @a destination via @a path and | ||
948 | * notify @a cb whenever we are ready for more data. | ||
949 | * | ||
950 | * @param destination where to go | ||
951 | * @param path which path to take (may not be the full path) | ||
952 | * @param off offset of @a destination on @a path | ||
953 | * @param ct tunnel that uses the connection | ||
954 | * @param ready_cb function to call when ready to transmit | ||
955 | * @param ready_cb_cls closure for @a cb | ||
956 | * @return handle to the connection | ||
957 | */ | ||
958 | struct CadetConnection * | ||
959 | GCC_create (struct CadetPeer *destination, | ||
960 | struct CadetPeerPath *path, | ||
961 | unsigned int off, | ||
962 | struct CadetTConnection *ct, | ||
963 | GCC_ReadyCallback ready_cb, | ||
964 | void *ready_cb_cls) | ||
965 | { | ||
966 | struct GNUNET_CADET_ConnectionTunnelIdentifier cid; | ||
967 | |||
968 | GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, &cid, sizeof(cid)); | ||
969 | return connection_create (destination, | ||
970 | path, | ||
971 | off, | ||
972 | ct, | ||
973 | &cid, | ||
974 | CADET_CONNECTION_NEW, | ||
975 | ready_cb, | ||
976 | ready_cb_cls); | ||
977 | } | ||
978 | |||
979 | |||
980 | /** | ||
981 | * Transmit message @a msg via connection @a cc. Must only be called | ||
982 | * (once) after the connection has signalled that it is ready via the | ||
983 | * `ready_cb`. Clients can also use #GCC_is_ready() to check if the | ||
984 | * connection is right now ready for transmission. | ||
985 | * | ||
986 | * @param cc connection identification | ||
987 | * @param env envelope with message to transmit; must NOT | ||
988 | * yet have a #GNUNET_MQ_notify_sent() callback attached to it | ||
989 | */ | ||
990 | void | ||
991 | GCC_transmit (struct CadetConnection *cc, struct GNUNET_MQ_Envelope *env) | ||
992 | { | ||
993 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
994 | "Scheduling message for transmission on %s\n", | ||
995 | GCC_2s (cc)); | ||
996 | GNUNET_assert (GNUNET_YES == cc->mqm_ready); | ||
997 | GNUNET_assert (CADET_CONNECTION_READY == cc->state); | ||
998 | cc->metrics.last_use = GNUNET_TIME_absolute_get (); | ||
999 | cc->mqm_ready = GNUNET_NO; | ||
1000 | if (NULL != cc->task) | ||
1001 | { | ||
1002 | GNUNET_SCHEDULER_cancel (cc->task); | ||
1003 | cc->task = NULL; | ||
1004 | } | ||
1005 | GCP_send (cc->mq_man, env); | ||
1006 | } | ||
1007 | |||
1008 | |||
1009 | /** | ||
1010 | * Obtain the path used by this connection. | ||
1011 | * | ||
1012 | * @param cc connection | ||
1013 | * @param off[out] set to the length of the path we use | ||
1014 | * @return path to @a cc | ||
1015 | */ | ||
1016 | struct CadetPeerPath * | ||
1017 | GCC_get_path (struct CadetConnection *cc, unsigned int *off) | ||
1018 | { | ||
1019 | *off = cc->off; | ||
1020 | return cc->path; | ||
1021 | } | ||
1022 | |||
1023 | |||
1024 | /** | ||
1025 | * Obtain unique ID for the connection. | ||
1026 | * | ||
1027 | * @param cc connection. | ||
1028 | * @return unique number of the connection | ||
1029 | */ | ||
1030 | const struct GNUNET_CADET_ConnectionTunnelIdentifier * | ||
1031 | GCC_get_id (struct CadetConnection *cc) | ||
1032 | { | ||
1033 | return &cc->cid; | ||
1034 | } | ||
1035 | |||
1036 | |||
1037 | /** | ||
1038 | * Get a (static) string for a connection. | ||
1039 | * | ||
1040 | * @param cc Connection. | ||
1041 | */ | ||
1042 | const char * | ||
1043 | GCC_2s (const struct CadetConnection *cc) | ||
1044 | { | ||
1045 | static char buf[128]; | ||
1046 | |||
1047 | if (NULL == cc) | ||
1048 | return "Connection(NULL)"; | ||
1049 | |||
1050 | if (NULL != cc->ct) | ||
1051 | { | ||
1052 | GNUNET_snprintf (buf, | ||
1053 | sizeof(buf), | ||
1054 | "Connection %s (%s)", | ||
1055 | GNUNET_sh2s (&cc->cid.connection_of_tunnel), | ||
1056 | GCT_2s (cc->ct->t)); | ||
1057 | return buf; | ||
1058 | } | ||
1059 | GNUNET_snprintf (buf, | ||
1060 | sizeof(buf), | ||
1061 | "Connection %s", | ||
1062 | GNUNET_sh2s (&cc->cid.connection_of_tunnel)); | ||
1063 | return buf; | ||
1064 | } | ||
1065 | |||
1066 | |||
1067 | #define LOG2(level, ...) \ | ||
1068 | GNUNET_log_from_nocheck (level, "cadet-con", __VA_ARGS__) | ||
1069 | |||
1070 | |||
1071 | /** | ||
1072 | * Log connection info. | ||
1073 | * | ||
1074 | * @param cc connection | ||
1075 | * @param level Debug level to use. | ||
1076 | */ | ||
1077 | void | ||
1078 | GCC_debug (struct CadetConnection *cc, enum GNUNET_ErrorType level) | ||
1079 | { | ||
1080 | #if ! defined(GNUNET_CULL_LOGGING) | ||
1081 | int do_log; | ||
1082 | |||
1083 | do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK), | ||
1084 | "cadet-con", | ||
1085 | __FILE__, | ||
1086 | __FUNCTION__, | ||
1087 | __LINE__); | ||
1088 | if (0 == do_log) | ||
1089 | return; | ||
1090 | if (NULL == cc) | ||
1091 | { | ||
1092 | LOG2 (level, "Connection (NULL)\n"); | ||
1093 | return; | ||
1094 | } | ||
1095 | LOG2 (level, | ||
1096 | "%s to %s via path %s in state %d is %s\n", | ||
1097 | GCC_2s (cc), | ||
1098 | GCP_2s (cc->destination), | ||
1099 | GCPP_2s (cc->path), | ||
1100 | cc->state, | ||
1101 | (GNUNET_YES == cc->mqm_ready) ? "ready" : "busy"); | ||
1102 | #endif | ||
1103 | } | ||
1104 | |||
1105 | |||
1106 | /* end of gnunet-service-cadet_connection.c */ | ||
diff --git a/src/cadet/gnunet-service-cadet_connection.h b/src/cadet/gnunet-service-cadet_connection.h deleted file mode 100644 index d646b3dc2..000000000 --- a/src/cadet/gnunet-service-cadet_connection.h +++ /dev/null | |||
@@ -1,361 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2001-2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/gnunet-service-cadet_connection.h | ||
23 | * @brief A connection is a live end-to-end messaging mechanism | ||
24 | * where the peers are identified by a path and know how | ||
25 | * to forward along the route using a connection identifier | ||
26 | * for routing the data. | ||
27 | * @author Bartlomiej Polot | ||
28 | * @author Christian Grothoff | ||
29 | */ | ||
30 | #ifndef GNUNET_SERVICE_CADET_CONNECTION_H | ||
31 | #define GNUNET_SERVICE_CADET_CONNECTION_H | ||
32 | |||
33 | #include "gnunet_util_lib.h" | ||
34 | #include "gnunet-service-cadet.h" | ||
35 | #include "gnunet-service-cadet_peer.h" | ||
36 | #include "cadet_protocol.h" | ||
37 | |||
38 | |||
39 | /** | ||
40 | * Function called to notify tunnel about change in our readiness. | ||
41 | * | ||
42 | * @param cls closure | ||
43 | * @param is_ready #GNUNET_YES if the connection is now ready for transmission, | ||
44 | * #GNUNET_NO if the connection is no longer ready for transmission | ||
45 | */ | ||
46 | typedef 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 | */ | ||
59 | void | ||
60 | GCC_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 | */ | ||
70 | void | ||
71 | GCC_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 | */ | ||
80 | struct CadetConnection * | ||
81 | GCC_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 | */ | ||
96 | struct CadetConnection * | ||
97 | GCC_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 | */ | ||
118 | struct CadetConnection * | ||
119 | GCC_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 | */ | ||
139 | void | ||
140 | GCC_transmit (struct CadetConnection *cc, | ||
141 | struct GNUNET_MQ_Envelope *env); | ||
142 | |||
143 | |||
144 | /** | ||
145 | * A CREATE_ACK was received for this connection, process it. | ||
146 | * | ||
147 | * @param cc the connection that got the ACK. | ||
148 | */ | ||
149 | void | ||
150 | GCC_handle_connection_create_ack (struct CadetConnection *cc); | ||
151 | |||
152 | |||
153 | /** | ||
154 | * We got a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE for a | ||
155 | * connection that we already have. Either our ACK got lost | ||
156 | * or something is fishy. Consider retransmitting the ACK. | ||
157 | * | ||
158 | * @param cc connection that got the duplicate CREATE | ||
159 | */ | ||
160 | void | ||
161 | GCC_handle_duplicate_create (struct CadetConnection *cc); | ||
162 | |||
163 | |||
164 | /** | ||
165 | * Handle KX message. | ||
166 | * | ||
167 | * @param cc connection that received encrypted message | ||
168 | * @param msg the key exchange message | ||
169 | */ | ||
170 | void | ||
171 | GCC_handle_kx (struct CadetConnection *cc, | ||
172 | const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg); | ||
173 | |||
174 | |||
175 | /** | ||
176 | * Handle KX_AUTH message. | ||
177 | * | ||
178 | * @param cc connection that received encrypted message | ||
179 | * @param msg the key exchange message | ||
180 | */ | ||
181 | void | ||
182 | GCC_handle_kx_auth (struct CadetConnection *cc, | ||
183 | const struct | ||
184 | GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg); | ||
185 | |||
186 | /** | ||
187 | * Purpose for the signature of a monotime. | ||
188 | */ | ||
189 | struct CadetConnectionCreatePS | ||
190 | { | ||
191 | |||
192 | /** | ||
193 | * Purpose is #GNUNET_SIGNATURE_PURPOSE_CADET_CONNECTION_INITIATOR | ||
194 | */ | ||
195 | struct GNUNET_CRYPTO_EccSignaturePurpose purpose; | ||
196 | |||
197 | /** | ||
198 | * Time at the initiator when generating the signature. | ||
199 | * | ||
200 | * Note that the receiver MUST IGNORE the absolute time, and only interpret | ||
201 | * the value as a mononic time and reject "older" values than the last one | ||
202 | * observed. This is necessary as we do not want to require synchronized | ||
203 | * clocks and may not have a bidirectional communication channel. | ||
204 | * | ||
205 | * Even with this, there is no real guarantee against replay achieved here, | ||
206 | * unless the latest timestamp is persisted. Persistence should be | ||
207 | * provided via PEERSTORE if possible. | ||
208 | */ | ||
209 | struct GNUNET_TIME_AbsoluteNBO monotonic_time; | ||
210 | |||
211 | }; | ||
212 | |||
213 | /** | ||
214 | * Performance metrics for a connection. | ||
215 | */ | ||
216 | struct CadetConnectionMetrics | ||
217 | { | ||
218 | /** | ||
219 | * Our current best estimate of the latency, based on a weighted | ||
220 | * average of at least @a latency_datapoints values. | ||
221 | */ | ||
222 | struct GNUNET_TIME_Relative aged_latency; | ||
223 | |||
224 | /** | ||
225 | * When was this connection first established? (by us sending or | ||
226 | * receiving the CREATE_ACK for the first time) | ||
227 | */ | ||
228 | struct GNUNET_TIME_Absolute age; | ||
229 | |||
230 | /** | ||
231 | * When was this connection last used? (by us sending or | ||
232 | * receiving a PAYLOAD message on it) | ||
233 | */ | ||
234 | struct GNUNET_TIME_Absolute last_use; | ||
235 | |||
236 | /** | ||
237 | * How many packets that ought to generate an ACK did we send via | ||
238 | * this connection? | ||
239 | */ | ||
240 | unsigned long long num_acked_transmissions; | ||
241 | |||
242 | /** | ||
243 | * Number of packets that were sent via this connection did actually | ||
244 | * receive an ACK? (Note: ACKs may be transmitted and lost via | ||
245 | * other connections, so this value should only be interpreted | ||
246 | * relative to @e num_acked_transmissions and in relation to other | ||
247 | * connections.) | ||
248 | */ | ||
249 | unsigned long long num_successes; | ||
250 | }; | ||
251 | |||
252 | |||
253 | /** | ||
254 | * Obtain performance @a metrics from @a cc. | ||
255 | * | ||
256 | * @param cc connection to query | ||
257 | * @return the metrics | ||
258 | */ | ||
259 | const struct CadetConnectionMetrics * | ||
260 | GCC_get_metrics (struct CadetConnection *cc); | ||
261 | |||
262 | |||
263 | /** | ||
264 | * Handle encrypted message. | ||
265 | * | ||
266 | * @param cc connection that received encrypted message | ||
267 | * @param msg the encrypted message to decrypt | ||
268 | */ | ||
269 | void | ||
270 | GCC_handle_encrypted (struct CadetConnection *cc, | ||
271 | const struct GNUNET_CADET_TunnelEncryptedMessage *msg); | ||
272 | |||
273 | |||
274 | /** | ||
275 | * We sent a message for which we expect to receive an ACK via | ||
276 | * the connection identified by @a cti. | ||
277 | * | ||
278 | * @param cid connection identifier where we expect an ACK | ||
279 | */ | ||
280 | void | ||
281 | GCC_ack_expected (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid); | ||
282 | |||
283 | |||
284 | /** | ||
285 | * We observed an ACK for a message that was originally sent via | ||
286 | * the connection identified by @a cti. | ||
287 | * | ||
288 | * @param cid connection identifier where we got an ACK for a message | ||
289 | * that was originally sent via this connection (the ACK | ||
290 | * may have gotten back to us via a different connection). | ||
291 | */ | ||
292 | void | ||
293 | GCC_ack_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid); | ||
294 | |||
295 | |||
296 | /** | ||
297 | * We observed some the given @a latency on the connection | ||
298 | * identified by @a cti. (The same connection was taken | ||
299 | * in both directions.) | ||
300 | * | ||
301 | * @param cti connection identifier where we measured latency | ||
302 | * @param latency the observed latency | ||
303 | */ | ||
304 | void | ||
305 | GCC_latency_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti, | ||
306 | struct GNUNET_TIME_Relative latency); | ||
307 | |||
308 | |||
309 | /** | ||
310 | * Return the tunnel associated with this connection. | ||
311 | * | ||
312 | * @param cc connection to query | ||
313 | * @return corresponding entry in the tunnel's connection list | ||
314 | */ | ||
315 | struct CadetTConnection * | ||
316 | GCC_get_ct (struct CadetConnection *cc); | ||
317 | |||
318 | |||
319 | /** | ||
320 | * Obtain the path used by this connection. | ||
321 | * | ||
322 | * @param cc connection | ||
323 | * @param off[out] set to offset in this path where the connection @a cc ends | ||
324 | * @return path to @a cc | ||
325 | */ | ||
326 | struct CadetPeerPath * | ||
327 | GCC_get_path (struct CadetConnection *cc, | ||
328 | unsigned int *off); | ||
329 | |||
330 | |||
331 | /** | ||
332 | * Obtain unique ID for the connection. | ||
333 | * | ||
334 | * @param cc connection. | ||
335 | * @return unique number of the connection | ||
336 | */ | ||
337 | const struct GNUNET_CADET_ConnectionTunnelIdentifier * | ||
338 | GCC_get_id (struct CadetConnection *cc); | ||
339 | |||
340 | |||
341 | /** | ||
342 | * Get a (static) string for a connection. | ||
343 | * | ||
344 | * @param cc Connection. | ||
345 | */ | ||
346 | const char * | ||
347 | GCC_2s (const struct CadetConnection *cc); | ||
348 | |||
349 | |||
350 | /** | ||
351 | * Log connection info. | ||
352 | * | ||
353 | * @param cc connection | ||
354 | * @param level Debug level to use. | ||
355 | */ | ||
356 | void | ||
357 | GCC_debug (struct CadetConnection *cc, | ||
358 | enum GNUNET_ErrorType level); | ||
359 | |||
360 | |||
361 | #endif | ||
diff --git a/src/cadet/gnunet-service-cadet_core.c b/src/cadet/gnunet-service-cadet_core.c deleted file mode 100644 index 95a5d3f63..000000000 --- a/src/cadet/gnunet-service-cadet_core.c +++ /dev/null | |||
@@ -1,1348 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/gnunet-service-cadet_core.c | ||
23 | * @brief cadet service; interaction with CORE service | ||
24 | * @author Bartlomiej Polot | ||
25 | * @author Christian Grothoff | ||
26 | * | ||
27 | * All functions in this file should use the prefix GCO (Gnunet Cadet cOre (bottom)) | ||
28 | * | ||
29 | * TODO: | ||
30 | * - Optimization: given BROKEN messages, destroy paths (?) | ||
31 | */ | ||
32 | #include "platform.h" | ||
33 | #include "gnunet-service-cadet_core.h" | ||
34 | #include "gnunet-service-cadet_paths.h" | ||
35 | #include "gnunet-service-cadet_peer.h" | ||
36 | #include "gnunet-service-cadet_connection.h" | ||
37 | #include "gnunet-service-cadet_tunnels.h" | ||
38 | #include "gnunet_core_service.h" | ||
39 | #include "gnunet_statistics_service.h" | ||
40 | #include "cadet_protocol.h" | ||
41 | |||
42 | #define LOG(level, ...) GNUNET_log_from (level, "cadet-cor", __VA_ARGS__) | ||
43 | |||
44 | /** | ||
45 | * Information we keep per direction for a route. | ||
46 | */ | ||
47 | struct 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 | */ | ||
55 | struct 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 | */ | ||
93 | struct RouteDirection | ||
94 | { | ||
95 | /** | ||
96 | * DLL of other route directions within the same `struct Rung`. | ||
97 | */ | ||
98 | struct RouteDirection *prev; | ||
99 | |||
100 | /** | ||
101 | * DLL of other route directions within the same `struct Rung`. | ||
102 | */ | ||
103 | struct RouteDirection *next; | ||
104 | |||
105 | /** | ||
106 | * Rung of this route direction (matches length of the buffer DLL). | ||
107 | */ | ||
108 | struct Rung *rung; | ||
109 | |||
110 | /** | ||
111 | * Head of DLL of envelopes we have in the buffer for this direction. | ||
112 | */ | ||
113 | struct GNUNET_MQ_Envelope *env_head; | ||
114 | |||
115 | /** | ||
116 | * Tail of DLL of envelopes we have in the buffer for this direction. | ||
117 | */ | ||
118 | struct GNUNET_MQ_Envelope *env_tail; | ||
119 | |||
120 | /** | ||
121 | * Target peer. | ||
122 | */ | ||
123 | struct CadetPeer *hop; | ||
124 | |||
125 | /** | ||
126 | * Route this direction is part of. | ||
127 | */ | ||
128 | struct CadetRoute *my_route; | ||
129 | |||
130 | /** | ||
131 | * Message queue manager for @e hop. | ||
132 | */ | ||
133 | struct GCP_MessageQueueManager *mqm; | ||
134 | |||
135 | /** | ||
136 | * Is @e mqm currently ready for transmission? | ||
137 | */ | ||
138 | int is_ready; | ||
139 | }; | ||
140 | |||
141 | |||
142 | /** | ||
143 | * Description of a segment of a `struct CadetConnection` at the | ||
144 | * intermediate peers. Routes are basically entries in a peer's | ||
145 | * routing table for forwarding traffic. At both endpoints, the | ||
146 | * routes are terminated by a `struct CadetConnection`, which knows | ||
147 | * the complete `struct CadetPath` that is formed by the individual | ||
148 | * routes. | ||
149 | */ | ||
150 | struct CadetRoute | ||
151 | { | ||
152 | /** | ||
153 | * Information about the next hop on this route. | ||
154 | */ | ||
155 | struct RouteDirection next; | ||
156 | |||
157 | /** | ||
158 | * Information about the previous hop on this route. | ||
159 | */ | ||
160 | struct RouteDirection prev; | ||
161 | |||
162 | /** | ||
163 | * Unique identifier for the connection that uses this route. | ||
164 | */ | ||
165 | struct GNUNET_CADET_ConnectionTunnelIdentifier cid; | ||
166 | |||
167 | /** | ||
168 | * When was this route last in use? | ||
169 | */ | ||
170 | struct GNUNET_TIME_Absolute last_use; | ||
171 | |||
172 | /** | ||
173 | * Position of this route in the #route_heap. | ||
174 | */ | ||
175 | struct GNUNET_CONTAINER_HeapNode *hn; | ||
176 | }; | ||
177 | |||
178 | |||
179 | /** | ||
180 | * Handle to the CORE service. | ||
181 | */ | ||
182 | static struct GNUNET_CORE_Handle *core; | ||
183 | |||
184 | /** | ||
185 | * Routes on which this peer is an intermediate. | ||
186 | */ | ||
187 | static struct GNUNET_CONTAINER_MultiShortmap *routes; | ||
188 | |||
189 | /** | ||
190 | * Heap of routes, MIN-sorted by last activity. | ||
191 | */ | ||
192 | static struct GNUNET_CONTAINER_Heap *route_heap; | ||
193 | |||
194 | /** | ||
195 | * Rung zero (always pointed to by #rung_head). | ||
196 | */ | ||
197 | static struct Rung rung_zero; | ||
198 | |||
199 | /** | ||
200 | * DLL of rungs, with the head always point to a rung of | ||
201 | * route directions with no messages in the queue. | ||
202 | */ | ||
203 | static struct Rung *rung_head = &rung_zero; | ||
204 | |||
205 | /** | ||
206 | * Tail of the #rung_head DLL. | ||
207 | */ | ||
208 | static struct Rung *rung_tail = &rung_zero; | ||
209 | |||
210 | /** | ||
211 | * Maximum number of concurrent routes this peer will support. | ||
212 | */ | ||
213 | static unsigned long long max_routes; | ||
214 | |||
215 | /** | ||
216 | * Maximum number of envelopes we will buffer at this peer. | ||
217 | */ | ||
218 | static unsigned long long max_buffers; | ||
219 | |||
220 | /** | ||
221 | * Current number of envelopes we have buffered at this peer. | ||
222 | */ | ||
223 | static unsigned long long cur_buffers; | ||
224 | |||
225 | /** | ||
226 | * Task to timeout routes. | ||
227 | */ | ||
228 | static struct GNUNET_SCHEDULER_Task *timeout_task; | ||
229 | |||
230 | /** | ||
231 | * Get the route corresponding to a hash. | ||
232 | * | ||
233 | * @param cid hash generated from the connection identifier | ||
234 | */ | ||
235 | static struct CadetRoute * | ||
236 | get_route (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid) | ||
237 | { | ||
238 | return GNUNET_CONTAINER_multishortmap_get (routes, | ||
239 | &cid->connection_of_tunnel); | ||
240 | } | ||
241 | |||
242 | |||
243 | /** | ||
244 | * Lower the rung in which @a dir is by 1. | ||
245 | * | ||
246 | * @param dir direction to lower in rung. | ||
247 | */ | ||
248 | static void | ||
249 | lower_rung (struct RouteDirection *dir) | ||
250 | { | ||
251 | struct Rung *rung = dir->rung; | ||
252 | struct Rung *prev; | ||
253 | |||
254 | GNUNET_CONTAINER_DLL_remove (rung->rd_head, rung->rd_tail, dir); | ||
255 | prev = rung->prev; | ||
256 | GNUNET_assert (NULL != prev); | ||
257 | if (prev->rung_off != rung->rung_off - 1) | ||
258 | { | ||
259 | prev = GNUNET_new (struct Rung); | ||
260 | prev->rung_off = rung->rung_off - 1; | ||
261 | GNUNET_CONTAINER_DLL_insert_after (rung_head, rung_tail, rung->prev, prev); | ||
262 | } | ||
263 | GNUNET_assert (NULL != prev); | ||
264 | GNUNET_CONTAINER_DLL_insert (prev->rd_head, prev->rd_tail, dir); | ||
265 | dir->rung = prev; | ||
266 | } | ||
267 | |||
268 | |||
269 | /** | ||
270 | * Discard the buffer @a env from the route direction @a dir and | ||
271 | * move @a dir down a rung. | ||
272 | * | ||
273 | * @param dir direction that contains the @a env in the buffer | ||
274 | * @param env envelope to discard | ||
275 | */ | ||
276 | static void | ||
277 | discard_buffer (struct RouteDirection *dir, struct GNUNET_MQ_Envelope *env) | ||
278 | { | ||
279 | GNUNET_MQ_dll_remove (&dir->env_head, &dir->env_tail, env); | ||
280 | cur_buffers--; | ||
281 | GNUNET_MQ_discard (env); | ||
282 | lower_rung (dir); | ||
283 | GNUNET_STATISTICS_set (stats, "# buffer use", cur_buffers, GNUNET_NO); | ||
284 | } | ||
285 | |||
286 | |||
287 | /** | ||
288 | * Discard all messages from the highest rung, to make space. | ||
289 | */ | ||
290 | static void | ||
291 | discard_all_from_rung_tail () | ||
292 | { | ||
293 | struct Rung *tail = rung_tail; | ||
294 | struct RouteDirection *dir; | ||
295 | |||
296 | while (NULL != (dir = tail->rd_head)) | ||
297 | { | ||
298 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
299 | "Queue full due new message on connection %s, dropping old message\n", | ||
300 | GNUNET_sh2s (&dir->my_route->cid.connection_of_tunnel)); | ||
301 | GNUNET_STATISTICS_update (stats, | ||
302 | "# messages dropped due to full buffer", | ||
303 | 1, | ||
304 | GNUNET_NO); | ||
305 | discard_buffer (dir, dir->env_head); | ||
306 | } | ||
307 | GNUNET_CONTAINER_DLL_remove (rung_head, rung_tail, tail); | ||
308 | GNUNET_free (tail); | ||
309 | } | ||
310 | |||
311 | |||
312 | /** | ||
313 | * We message @a msg from @a prev. Find its route by @a cid and | ||
314 | * forward to the next hop. Drop and signal broken route if we do not | ||
315 | * have a route. | ||
316 | * | ||
317 | * @param prev previous hop (sender) | ||
318 | * @param cid connection identifier, tells us which route to use | ||
319 | * @param msg the message to forward | ||
320 | */ | ||
321 | static void | ||
322 | route_message (struct CadetPeer *prev, | ||
323 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid, | ||
324 | const struct GNUNET_MessageHeader *msg, | ||
325 | const enum GNUNET_MQ_PriorityPreferences priority) | ||
326 | { | ||
327 | struct CadetRoute *route; | ||
328 | struct RouteDirection *dir; | ||
329 | struct Rung *rung; | ||
330 | struct Rung *nxt; | ||
331 | struct GNUNET_MQ_Envelope *env; | ||
332 | |||
333 | route = get_route (cid); | ||
334 | if (NULL == route) | ||
335 | { | ||
336 | struct GNUNET_MQ_Envelope *env; | ||
337 | struct GNUNET_CADET_ConnectionBrokenMessage *bm; | ||
338 | |||
339 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
340 | "Failed to route message of type %u from %s on connection %s: no route\n", | ||
341 | ntohs (msg->type), | ||
342 | GCP_2s (prev), | ||
343 | GNUNET_sh2s (&cid->connection_of_tunnel)); | ||
344 | switch (ntohs (msg->type)) | ||
345 | { | ||
346 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY: | ||
347 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN: | ||
348 | /* No need to respond to these! */ | ||
349 | return; | ||
350 | } | ||
351 | env = GNUNET_MQ_msg (bm, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN); | ||
352 | bm->cid = *cid; | ||
353 | bm->peer1 = my_full_id; | ||
354 | GCP_send_ooo (prev, env); | ||
355 | return; | ||
356 | } | ||
357 | route->last_use = GNUNET_TIME_absolute_get (); | ||
358 | GNUNET_CONTAINER_heap_update_cost (route->hn, route->last_use.abs_value_us); | ||
359 | dir = (prev == route->prev.hop) ? &route->next : &route->prev; | ||
360 | if (GNUNET_YES == dir->is_ready) | ||
361 | { | ||
362 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
363 | "Routing message of type %u from %s to %s on connection %s\n", | ||
364 | ntohs (msg->type), | ||
365 | GCP_2s (prev), | ||
366 | GNUNET_i2s (GCP_get_id (dir->hop)), | ||
367 | GNUNET_sh2s (&cid->connection_of_tunnel)); | ||
368 | dir->is_ready = GNUNET_NO; | ||
369 | GCP_send (dir->mqm, GNUNET_MQ_msg_copy (msg)); | ||
370 | return; | ||
371 | } | ||
372 | /* Check if low latency is required and if the previous message was | ||
373 | unreliable; if so, make sure we only queue one message per | ||
374 | direction (no buffering). */ | ||
375 | if ((0 != (priority & GNUNET_MQ_PREF_LOW_LATENCY)) && | ||
376 | (NULL != dir->env_head) && | ||
377 | (0 == | ||
378 | (GNUNET_MQ_env_get_options (dir->env_head) & GNUNET_MQ_PREF_UNRELIABLE))) | ||
379 | discard_buffer (dir, dir->env_head); | ||
380 | /* Check for duplicates */ | ||
381 | for (const struct GNUNET_MQ_Envelope *env = dir->env_head; NULL != env; | ||
382 | env = GNUNET_MQ_env_next (env)) | ||
383 | { | ||
384 | const struct GNUNET_MessageHeader *hdr = GNUNET_MQ_env_get_msg (env); | ||
385 | |||
386 | if ((hdr->size == msg->size) && (0 == memcmp (hdr, msg, ntohs (msg->size)))) | ||
387 | { | ||
388 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
389 | "Received duplicate of message already in buffer, dropping\n"); | ||
390 | GNUNET_STATISTICS_update (stats, | ||
391 | "# messages dropped due to duplicate in buffer", | ||
392 | 1, | ||
393 | GNUNET_NO); | ||
394 | return; | ||
395 | } | ||
396 | } | ||
397 | |||
398 | rung = dir->rung; | ||
399 | if (cur_buffers == max_buffers) | ||
400 | { | ||
401 | /* Need to make room. */ | ||
402 | if (NULL != rung->next) | ||
403 | { | ||
404 | /* Easy case, drop messages from route directions in highest rung */ | ||
405 | discard_all_from_rung_tail (); | ||
406 | } | ||
407 | else | ||
408 | { | ||
409 | /* We are in the highest rung, drop our own! */ | ||
410 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
411 | "Queue full due new message on connection %s, dropping old message\n", | ||
412 | GNUNET_sh2s (&dir->my_route->cid.connection_of_tunnel)); | ||
413 | GNUNET_STATISTICS_update (stats, | ||
414 | "# messages dropped due to full buffer", | ||
415 | 1, | ||
416 | GNUNET_NO); | ||
417 | discard_buffer (dir, dir->env_head); | ||
418 | rung = dir->rung; | ||
419 | } | ||
420 | } | ||
421 | /* remove 'dir' from current rung */ | ||
422 | GNUNET_CONTAINER_DLL_remove (rung->rd_head, rung->rd_tail, dir); | ||
423 | /* make 'nxt' point to the next higher rung, create if necessary */ | ||
424 | nxt = rung->next; | ||
425 | if ((NULL == nxt) || (rung->rung_off + 1 != nxt->rung_off)) | ||
426 | { | ||
427 | nxt = GNUNET_new (struct Rung); | ||
428 | nxt->rung_off = rung->rung_off + 1; | ||
429 | GNUNET_CONTAINER_DLL_insert_after (rung_head, rung_tail, rung, nxt); | ||
430 | } | ||
431 | /* insert 'dir' into next higher rung */ | ||
432 | GNUNET_CONTAINER_DLL_insert (nxt->rd_head, nxt->rd_tail, dir); | ||
433 | dir->rung = nxt; | ||
434 | |||
435 | /* add message into 'dir' buffer */ | ||
436 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
437 | "Queueing new message of type %u from %s to %s on connection %s\n", | ||
438 | ntohs (msg->type), | ||
439 | GCP_2s (prev), | ||
440 | GNUNET_i2s (GCP_get_id (dir->hop)), | ||
441 | GNUNET_sh2s (&cid->connection_of_tunnel)); | ||
442 | env = GNUNET_MQ_msg_copy (msg); | ||
443 | GNUNET_MQ_env_set_options (env, priority); | ||
444 | if ((0 != (priority & GNUNET_MQ_PREF_LOW_LATENCY)) && | ||
445 | (0 != (priority & GNUNET_MQ_PREF_OUT_OF_ORDER)) && | ||
446 | (NULL != dir->env_head) && | ||
447 | (0 == (GNUNET_MQ_env_get_options (dir->env_head) | ||
448 | & GNUNET_MQ_PREF_LOW_LATENCY))) | ||
449 | GNUNET_MQ_dll_insert_head (&dir->env_head, &dir->env_tail, env); | ||
450 | else | ||
451 | GNUNET_MQ_dll_insert_tail (&dir->env_head, &dir->env_tail, env); | ||
452 | cur_buffers++; | ||
453 | GNUNET_STATISTICS_set (stats, "# buffer use", cur_buffers, GNUNET_NO); | ||
454 | /* Clean up 'rung' if now empty (and not head) */ | ||
455 | if ((NULL == rung->rd_head) && (rung != rung_head)) | ||
456 | { | ||
457 | GNUNET_CONTAINER_DLL_remove (rung_head, rung_tail, rung); | ||
458 | GNUNET_free (rung); | ||
459 | } | ||
460 | } | ||
461 | |||
462 | |||
463 | /** | ||
464 | * Check if the create_connection message has the appropriate size. | ||
465 | * | ||
466 | * @param cls Closure (unused). | ||
467 | * @param msg Message to check. | ||
468 | * | ||
469 | * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise. | ||
470 | */ | ||
471 | static int | ||
472 | check_connection_create (void *cls, | ||
473 | const struct GNUNET_CADET_ConnectionCreateMessage *msg) | ||
474 | { | ||
475 | uint16_t size = ntohs (msg->header.size) - sizeof(*msg); | ||
476 | |||
477 | if (0 != (size % sizeof(struct GNUNET_PeerIdentity))) | ||
478 | { | ||
479 | GNUNET_break_op (0); | ||
480 | return GNUNET_NO; | ||
481 | } | ||
482 | return GNUNET_YES; | ||
483 | } | ||
484 | |||
485 | |||
486 | /** | ||
487 | * Free internal data of a route direction. | ||
488 | * | ||
489 | * @param dir direction to destroy (do NOT free memory of 'dir' itself) | ||
490 | */ | ||
491 | static void | ||
492 | destroy_direction (struct RouteDirection *dir) | ||
493 | { | ||
494 | struct GNUNET_MQ_Envelope *env; | ||
495 | |||
496 | while (NULL != (env = dir->env_head)) | ||
497 | { | ||
498 | GNUNET_STATISTICS_update (stats, | ||
499 | "# messages dropped due to route destruction", | ||
500 | 1, | ||
501 | GNUNET_NO); | ||
502 | discard_buffer (dir, env); | ||
503 | } | ||
504 | if (NULL != dir->mqm) | ||
505 | { | ||
506 | GCP_request_mq_cancel (dir->mqm, NULL); | ||
507 | dir->mqm = NULL; | ||
508 | } | ||
509 | GNUNET_CONTAINER_DLL_remove (rung_head->rd_head, rung_head->rd_tail, dir); | ||
510 | } | ||
511 | |||
512 | |||
513 | /** | ||
514 | * Destroy our state for @a route. | ||
515 | * | ||
516 | * @param route route to destroy | ||
517 | */ | ||
518 | static void | ||
519 | destroy_route (struct CadetRoute *route) | ||
520 | { | ||
521 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
522 | "Destroying route from %s to %s of connection %s\n", | ||
523 | GNUNET_i2s (GCP_get_id (route->prev.hop)), | ||
524 | GNUNET_i2s2 (GCP_get_id (route->next.hop)), | ||
525 | GNUNET_sh2s (&route->cid.connection_of_tunnel)); | ||
526 | GNUNET_assert (route == GNUNET_CONTAINER_heap_remove_node (route->hn)); | ||
527 | GNUNET_assert ( | ||
528 | GNUNET_YES == | ||
529 | GNUNET_CONTAINER_multishortmap_remove (routes, | ||
530 | &route->cid.connection_of_tunnel, | ||
531 | route)); | ||
532 | GNUNET_STATISTICS_set (stats, | ||
533 | "# routes", | ||
534 | GNUNET_CONTAINER_multishortmap_size (routes), | ||
535 | GNUNET_NO); | ||
536 | destroy_direction (&route->prev); | ||
537 | destroy_direction (&route->next); | ||
538 | GNUNET_free (route); | ||
539 | } | ||
540 | |||
541 | |||
542 | /** | ||
543 | * Send message that a route is broken between @a peer1 and @a peer2. | ||
544 | * | ||
545 | * @param target where to send the message | ||
546 | * @param cid connection identifier to use | ||
547 | * @param peer1 one of the peers where a link is broken | ||
548 | * @param peer2 another one of the peers where a link is broken | ||
549 | */ | ||
550 | static void | ||
551 | send_broken (struct RouteDirection *target, | ||
552 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid, | ||
553 | const struct GNUNET_PeerIdentity *peer1, | ||
554 | const struct GNUNET_PeerIdentity *peer2) | ||
555 | { | ||
556 | struct GNUNET_MQ_Envelope *env; | ||
557 | struct GNUNET_CADET_ConnectionBrokenMessage *bm; | ||
558 | |||
559 | if (NULL == target->mqm) | ||
560 | return; /* Can't send notification, connection is down! */ | ||
561 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
562 | "Notifying %s about BROKEN route at %s-%s of connection %s\n", | ||
563 | GCP_2s (target->hop), | ||
564 | GNUNET_i2s (peer1), | ||
565 | GNUNET_i2s2 (peer2), | ||
566 | GNUNET_sh2s (&cid->connection_of_tunnel)); | ||
567 | |||
568 | env = GNUNET_MQ_msg (bm, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN); | ||
569 | bm->cid = *cid; | ||
570 | if (NULL != peer1) | ||
571 | bm->peer1 = *peer1; | ||
572 | if (NULL != peer2) | ||
573 | bm->peer2 = *peer2; | ||
574 | GCP_request_mq_cancel (target->mqm, env); | ||
575 | target->mqm = NULL; | ||
576 | } | ||
577 | |||
578 | |||
579 | /** | ||
580 | * Function called to check if any routes have timed out, and if | ||
581 | * so, to clean them up. Finally, schedules itself again at the | ||
582 | * earliest time where there might be more work. | ||
583 | * | ||
584 | * @param cls NULL | ||
585 | */ | ||
586 | static void | ||
587 | timeout_cb (void *cls) | ||
588 | { | ||
589 | struct CadetRoute *r; | ||
590 | struct GNUNET_TIME_Relative linger; | ||
591 | struct GNUNET_TIME_Absolute exp; | ||
592 | |||
593 | timeout_task = NULL; | ||
594 | linger = GNUNET_TIME_relative_multiply (keepalive_period, 3); | ||
595 | while (NULL != (r = GNUNET_CONTAINER_heap_peek (route_heap))) | ||
596 | { | ||
597 | exp = GNUNET_TIME_absolute_add (r->last_use, linger); | ||
598 | if (0 != GNUNET_TIME_absolute_get_remaining (exp).rel_value_us) | ||
599 | { | ||
600 | /* Route not yet timed out, wait until it does. */ | ||
601 | timeout_task = GNUNET_SCHEDULER_add_at (exp, &timeout_cb, NULL); | ||
602 | return; | ||
603 | } | ||
604 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
605 | "Sending BROKEN due to timeout (%s was last use, %s linger)\n", | ||
606 | GNUNET_STRINGS_absolute_time_to_string (r->last_use), | ||
607 | GNUNET_STRINGS_relative_time_to_string (linger, GNUNET_YES)); | ||
608 | send_broken (&r->prev, &r->cid, NULL, NULL); | ||
609 | send_broken (&r->next, &r->cid, NULL, NULL); | ||
610 | destroy_route (r); | ||
611 | } | ||
612 | /* No more routes left, so no need for a #timeout_task */ | ||
613 | } | ||
614 | |||
615 | |||
616 | /** | ||
617 | * Function called when the message queue to the previous hop | ||
618 | * becomes available/unavailable. We expect this function to | ||
619 | * be called immediately when we register, and then again | ||
620 | * later if the connection ever goes down. | ||
621 | * | ||
622 | * @param cls the `struct RouteDirection` | ||
623 | * @param available #GNUNET_YES if sending is now possible, | ||
624 | * #GNUNET_NO if sending is no longer possible | ||
625 | * #GNUNET_SYSERR if sending is no longer possible | ||
626 | * and the last envelope was discarded | ||
627 | */ | ||
628 | static void | ||
629 | dir_ready_cb (void *cls, int ready) | ||
630 | { | ||
631 | struct RouteDirection *dir = cls; | ||
632 | struct CadetRoute *route = dir->my_route; | ||
633 | struct RouteDirection *odir; | ||
634 | |||
635 | if (GNUNET_YES == ready) | ||
636 | { | ||
637 | struct GNUNET_MQ_Envelope *env; | ||
638 | |||
639 | dir->is_ready = GNUNET_YES; | ||
640 | if (NULL != (env = dir->env_head)) | ||
641 | { | ||
642 | GNUNET_MQ_dll_remove (&dir->env_head, &dir->env_tail, env); | ||
643 | cur_buffers--; | ||
644 | GNUNET_STATISTICS_set (stats, "# buffer use", cur_buffers, GNUNET_NO); | ||
645 | lower_rung (dir); | ||
646 | dir->is_ready = GNUNET_NO; | ||
647 | GCP_send (dir->mqm, env); | ||
648 | } | ||
649 | return; | ||
650 | } | ||
651 | odir = (dir == &route->next) ? &route->prev : &route->next; | ||
652 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending BROKEN due to MQ going down\n"); | ||
653 | send_broken (&route->next, &route->cid, GCP_get_id (odir->hop), &my_full_id); | ||
654 | destroy_route (route); | ||
655 | } | ||
656 | |||
657 | |||
658 | /** | ||
659 | * Initialize one of the directions of a route. | ||
660 | * | ||
661 | * @param route route the direction belongs to | ||
662 | * @param dir direction to initialize | ||
663 | * @param hop next hop on in the @a dir | ||
664 | */ | ||
665 | static void | ||
666 | dir_init (struct RouteDirection *dir, | ||
667 | struct CadetRoute *route, | ||
668 | struct CadetPeer *hop) | ||
669 | { | ||
670 | dir->hop = hop; | ||
671 | dir->my_route = route; | ||
672 | dir->mqm = GCP_request_mq (hop, &dir_ready_cb, dir); | ||
673 | GNUNET_CONTAINER_DLL_insert (rung_head->rd_head, rung_head->rd_tail, dir); | ||
674 | dir->rung = rung_head; | ||
675 | GNUNET_assert (GNUNET_YES == dir->is_ready); | ||
676 | } | ||
677 | |||
678 | |||
679 | /** | ||
680 | * We could not create the desired route. Send a | ||
681 | * #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN | ||
682 | * message to @a target. | ||
683 | * | ||
684 | * @param target who should receive the message | ||
685 | * @param cid identifier of the connection/route that failed | ||
686 | * @param failure_at neighbour with which we failed to route, | ||
687 | * or NULL. | ||
688 | */ | ||
689 | static void | ||
690 | send_broken_without_mqm ( | ||
691 | struct CadetPeer *target, | ||
692 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid, | ||
693 | const struct GNUNET_PeerIdentity *failure_at) | ||
694 | { | ||
695 | struct GNUNET_MQ_Envelope *env; | ||
696 | struct GNUNET_CADET_ConnectionBrokenMessage *bm; | ||
697 | |||
698 | env = GNUNET_MQ_msg (bm, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN); | ||
699 | bm->cid = *cid; | ||
700 | bm->peer1 = my_full_id; | ||
701 | if (NULL != failure_at) | ||
702 | bm->peer2 = *failure_at; | ||
703 | GCP_send_ooo (target, env); | ||
704 | } | ||
705 | |||
706 | |||
707 | /** | ||
708 | * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE | ||
709 | * | ||
710 | * @param cls Closure (CadetPeer for neighbor that sent the message). | ||
711 | * @param msg Message itself. | ||
712 | */ | ||
713 | static void | ||
714 | handle_connection_create ( | ||
715 | void *cls, | ||
716 | const struct GNUNET_CADET_ConnectionCreateMessage *msg) | ||
717 | { | ||
718 | struct CadetPeer *sender = cls; | ||
719 | struct CadetPeer *next; | ||
720 | const struct GNUNET_PeerIdentity *pids = | ||
721 | (const struct GNUNET_PeerIdentity *) &msg[1]; | ||
722 | struct CadetRoute *route; | ||
723 | uint16_t size = ntohs (msg->header.size) - sizeof(*msg); | ||
724 | unsigned int path_length; | ||
725 | unsigned int off; | ||
726 | struct CadetTunnel *t; | ||
727 | |||
728 | path_length = size / sizeof(struct GNUNET_PeerIdentity); | ||
729 | if (0 == path_length) | ||
730 | { | ||
731 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
732 | "Dropping CADET_CONNECTION_CREATE with empty path\n"); | ||
733 | GNUNET_break_op (0); | ||
734 | return; | ||
735 | } | ||
736 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
737 | "Handling CADET_CONNECTION_CREATE from %s for CID %s with %u hops\n", | ||
738 | GCP_2s (sender), | ||
739 | GNUNET_sh2s (&msg->cid.connection_of_tunnel), | ||
740 | path_length); | ||
741 | /* Check for loops */ | ||
742 | { | ||
743 | struct GNUNET_CONTAINER_MultiPeerMap *map; | ||
744 | |||
745 | map = GNUNET_CONTAINER_multipeermap_create (path_length * 2, GNUNET_YES); | ||
746 | GNUNET_assert (NULL != map); | ||
747 | for (unsigned int i = 0; i < path_length; i++) | ||
748 | { | ||
749 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
750 | "CADET_CONNECTION_CREATE has peer %s at offset %u\n", | ||
751 | GNUNET_i2s (&pids[i]), | ||
752 | i); | ||
753 | if (GNUNET_SYSERR == GNUNET_CONTAINER_multipeermap_put ( | ||
754 | map, | ||
755 | &pids[i], | ||
756 | NULL, | ||
757 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) | ||
758 | { | ||
759 | /* bogus request */ | ||
760 | GNUNET_CONTAINER_multipeermap_destroy (map); | ||
761 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
762 | "Dropping CADET_CONNECTION_CREATE with cyclic path\n"); | ||
763 | GNUNET_break_op (0); | ||
764 | return; | ||
765 | } | ||
766 | } | ||
767 | GNUNET_CONTAINER_multipeermap_destroy (map); | ||
768 | } | ||
769 | /* Initiator is at offset 0, find us */ | ||
770 | for (off = 1; off < path_length; off++) | ||
771 | if (0 == GNUNET_memcmp (&my_full_id, &pids[off])) | ||
772 | break; | ||
773 | if (off == path_length) | ||
774 | { | ||
775 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
776 | "Dropping CADET_CONNECTION_CREATE without us in the path\n"); | ||
777 | GNUNET_break_op (0); | ||
778 | return; | ||
779 | } | ||
780 | /* Check previous hop */ | ||
781 | if (sender != GCP_get (&pids[off - 1], GNUNET_NO)) | ||
782 | { | ||
783 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
784 | "Dropping CADET_CONNECTION_CREATE without sender at previous hop in the path\n"); | ||
785 | GNUNET_break_op (0); | ||
786 | return; | ||
787 | } | ||
788 | if (NULL != (route = get_route (&msg->cid))) | ||
789 | { | ||
790 | /* Duplicate CREATE, pass it on, previous one might have been lost! */ | ||
791 | |||
792 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
793 | "Passing on duplicate CADET_CONNECTION_CREATE message on connection %s\n", | ||
794 | GNUNET_sh2s (&msg->cid.connection_of_tunnel)); | ||
795 | route_message (sender, | ||
796 | &msg->cid, | ||
797 | &msg->header, | ||
798 | GNUNET_MQ_PRIO_CRITICAL_CONTROL | ||
799 | | GNUNET_MQ_PREF_LOW_LATENCY); | ||
800 | return; | ||
801 | } | ||
802 | if (off == path_length - 1) | ||
803 | { | ||
804 | /* We are the destination, create connection */ | ||
805 | struct CadetConnection *cc; | ||
806 | struct CadetPeerPath *path; | ||
807 | struct CadetPeer *origin; | ||
808 | |||
809 | cc = GCC_lookup (&msg->cid); | ||
810 | if (NULL != cc) | ||
811 | { | ||
812 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
813 | "Received duplicate CADET_CONNECTION_CREATE message on connection %s\n", | ||
814 | GNUNET_sh2s (&msg->cid.connection_of_tunnel)); | ||
815 | GCC_handle_duplicate_create (cc); | ||
816 | return; | ||
817 | } | ||
818 | |||
819 | origin = GCP_get (&pids[0], GNUNET_YES); | ||
820 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
821 | "I am destination for CADET_CONNECTION_CREATE message from %s for connection %s, building inverse path\n", | ||
822 | GCP_2s (origin), | ||
823 | GNUNET_sh2s (&msg->cid.connection_of_tunnel)); | ||
824 | path = GCPP_get_path_from_route (path_length - 1, pids); | ||
825 | t = GCP_get_tunnel (origin, GNUNET_YES); | ||
826 | |||
827 | // Check for CADET state in case the other side has lost the tunnel (xrs,t3ss) | ||
828 | if ((GNUNET_YES == msg->has_monotime) && | ||
829 | (GNUNET_YES == GCP_check_and_update_monotime (origin, msg->monotime)) && | ||
830 | (GNUNET_OK == GCP_check_monotime_sig (origin, msg)) && | ||
831 | (CADET_TUNNEL_KEY_OK == GCT_get_estate (t))) | ||
832 | { | ||
833 | GCT_change_estate (t, CADET_TUNNEL_KEY_UNINITIALIZED); | ||
834 | } | ||
835 | |||
836 | if (GNUNET_OK != | ||
837 | GCT_add_inbound_connection (t, | ||
838 | &msg->cid, | ||
839 | path)) | ||
840 | { | ||
841 | /* Send back BROKEN: duplicate connection on the same path, | ||
842 | we will use the other one. */ | ||
843 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
844 | "Received CADET_CONNECTION_CREATE from %s for %s, but %s already has a connection. Sending BROKEN\n", | ||
845 | GCP_2s (sender), | ||
846 | GNUNET_sh2s (&msg->cid.connection_of_tunnel), | ||
847 | GCPP_2s (path)); | ||
848 | send_broken_without_mqm (sender, &msg->cid, NULL); | ||
849 | return; | ||
850 | } | ||
851 | return; | ||
852 | } | ||
853 | /* We are merely a hop on the way, check if we can support the route */ | ||
854 | next = GCP_get (&pids[off + 1], GNUNET_NO); | ||
855 | if ((NULL == next) || (GNUNET_NO == GCP_has_core_connection (next))) | ||
856 | { | ||
857 | /* unworkable, send back BROKEN notification */ | ||
858 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
859 | "Received CADET_CONNECTION_CREATE from %s for %s. Next hop %s:%u is down. Sending BROKEN\n", | ||
860 | GCP_2s (sender), | ||
861 | GNUNET_sh2s (&msg->cid.connection_of_tunnel), | ||
862 | GNUNET_i2s (&pids[off + 1]), | ||
863 | off + 1); | ||
864 | send_broken_without_mqm (sender, &msg->cid, &pids[off + 1]); | ||
865 | return; | ||
866 | } | ||
867 | if (max_routes <= GNUNET_CONTAINER_multishortmap_size (routes)) | ||
868 | { | ||
869 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
870 | "Received CADET_CONNECTION_CREATE from %s for %s. We have reached our route limit. Sending BROKEN\n", | ||
871 | GCP_2s (sender), | ||
872 | GNUNET_sh2s (&msg->cid.connection_of_tunnel)); | ||
873 | send_broken_without_mqm (sender, &msg->cid, &pids[off - 1]); | ||
874 | return; | ||
875 | } | ||
876 | |||
877 | /* Workable route, create routing entry */ | ||
878 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
879 | "Received CADET_CONNECTION_CREATE from %s for %s. Next hop %s:%u is up. Creating route\n", | ||
880 | GCP_2s (sender), | ||
881 | GNUNET_sh2s (&msg->cid.connection_of_tunnel), | ||
882 | GNUNET_i2s (&pids[off + 1]), | ||
883 | off + 1); | ||
884 | route = GNUNET_new (struct CadetRoute); | ||
885 | route->cid = msg->cid; | ||
886 | route->last_use = GNUNET_TIME_absolute_get (); | ||
887 | dir_init (&route->prev, route, sender); | ||
888 | dir_init (&route->next, route, next); | ||
889 | GNUNET_assert (GNUNET_OK == | ||
890 | GNUNET_CONTAINER_multishortmap_put ( | ||
891 | routes, | ||
892 | &route->cid.connection_of_tunnel, | ||
893 | route, | ||
894 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
895 | GNUNET_STATISTICS_set (stats, | ||
896 | "# routes", | ||
897 | GNUNET_CONTAINER_multishortmap_size (routes), | ||
898 | GNUNET_NO); | ||
899 | route->hn = GNUNET_CONTAINER_heap_insert (route_heap, | ||
900 | route, | ||
901 | route->last_use.abs_value_us); | ||
902 | if (NULL == timeout_task) | ||
903 | timeout_task = | ||
904 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply ( | ||
905 | keepalive_period, | ||
906 | 3), | ||
907 | &timeout_cb, | ||
908 | NULL); | ||
909 | /* also pass CREATE message along to next hop */ | ||
910 | route_message (sender, | ||
911 | &msg->cid, | ||
912 | &msg->header, | ||
913 | GNUNET_MQ_PRIO_CRITICAL_CONTROL | GNUNET_MQ_PREF_LOW_LATENCY); | ||
914 | } | ||
915 | |||
916 | |||
917 | /** | ||
918 | * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK | ||
919 | * | ||
920 | * @param cls Closure (CadetPeer for neighbor that sent the message). | ||
921 | * @param msg Message itself. | ||
922 | */ | ||
923 | static void | ||
924 | handle_connection_create_ack ( | ||
925 | void *cls, | ||
926 | const struct GNUNET_CADET_ConnectionCreateAckMessage *msg) | ||
927 | { | ||
928 | struct CadetPeer *peer = cls; | ||
929 | struct CadetConnection *cc; | ||
930 | |||
931 | /* First, check if ACK belongs to a connection that ends here. */ | ||
932 | cc = GCC_lookup (&msg->cid); | ||
933 | if (NULL != cc) | ||
934 | { | ||
935 | /* verify ACK came from the right direction */ | ||
936 | unsigned int len; | ||
937 | struct CadetPeerPath *path = GCC_get_path (cc, &len); | ||
938 | |||
939 | if (peer != GCPP_get_peer_at_offset (path, 0)) | ||
940 | { | ||
941 | /* received ACK from unexpected direction, ignore! */ | ||
942 | GNUNET_break_op (0); | ||
943 | return; | ||
944 | } | ||
945 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
946 | "Received CONNECTION_CREATE_ACK for connection %s.\n", | ||
947 | GNUNET_sh2s (&msg->cid.connection_of_tunnel)); | ||
948 | GCC_handle_connection_create_ack (cc); | ||
949 | return; | ||
950 | } | ||
951 | |||
952 | /* We're just an intermediary peer, route the message along its path */ | ||
953 | route_message (peer, | ||
954 | &msg->cid, | ||
955 | &msg->header, | ||
956 | GNUNET_MQ_PRIO_CRITICAL_CONTROL | GNUNET_MQ_PREF_LOW_LATENCY); | ||
957 | } | ||
958 | |||
959 | |||
960 | /** | ||
961 | * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN | ||
962 | * | ||
963 | * @param cls Closure (CadetPeer for neighbor that sent the message). | ||
964 | * @param msg Message itself. | ||
965 | * @deprecated duplicate logic with #handle_destroy(); dedup! | ||
966 | */ | ||
967 | static void | ||
968 | handle_connection_broken ( | ||
969 | void *cls, | ||
970 | const struct GNUNET_CADET_ConnectionBrokenMessage *msg) | ||
971 | { | ||
972 | struct CadetPeer *peer = cls; | ||
973 | struct CadetConnection *cc; | ||
974 | struct CadetRoute *route; | ||
975 | |||
976 | /* First, check if message belongs to a connection that ends here. */ | ||
977 | cc = GCC_lookup (&msg->cid); | ||
978 | if (NULL != cc) | ||
979 | { | ||
980 | /* verify message came from the right direction */ | ||
981 | unsigned int len; | ||
982 | struct CadetPeerPath *path = GCC_get_path (cc, &len); | ||
983 | |||
984 | if (peer != GCPP_get_peer_at_offset (path, 0)) | ||
985 | { | ||
986 | /* received message from unexpected direction, ignore! */ | ||
987 | GNUNET_break_op (0); | ||
988 | return; | ||
989 | } | ||
990 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
991 | "Received CONNECTION_BROKEN for connection %s. Destroying it.\n", | ||
992 | GNUNET_sh2s (&msg->cid.connection_of_tunnel)); | ||
993 | GCC_destroy_without_core (cc); | ||
994 | |||
995 | /* FIXME: also destroy the path up to the specified link! */ | ||
996 | return; | ||
997 | } | ||
998 | |||
999 | /* We're just an intermediary peer, route the message along its path */ | ||
1000 | route_message (peer, | ||
1001 | &msg->cid, | ||
1002 | &msg->header, | ||
1003 | GNUNET_MQ_PREF_LOW_LATENCY | GNUNET_MQ_PRIO_CRITICAL_CONTROL); | ||
1004 | route = get_route (&msg->cid); | ||
1005 | if (NULL != route) | ||
1006 | destroy_route (route); | ||
1007 | /* FIXME: also destroy paths we MAY have up to the specified link! */ | ||
1008 | } | ||
1009 | |||
1010 | |||
1011 | /** | ||
1012 | * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY | ||
1013 | * | ||
1014 | * @param cls Closure (CadetPeer for neighbor that sent the message). | ||
1015 | * @param msg Message itself. | ||
1016 | */ | ||
1017 | static void | ||
1018 | handle_connection_destroy ( | ||
1019 | void *cls, | ||
1020 | const struct GNUNET_CADET_ConnectionDestroyMessage *msg) | ||
1021 | { | ||
1022 | struct CadetPeer *peer = cls; | ||
1023 | struct CadetConnection *cc; | ||
1024 | struct CadetRoute *route; | ||
1025 | |||
1026 | /* First, check if message belongs to a connection that ends here. */ | ||
1027 | cc = GCC_lookup (&msg->cid); | ||
1028 | if (NULL != cc) | ||
1029 | { | ||
1030 | /* verify message came from the right direction */ | ||
1031 | unsigned int len; | ||
1032 | struct CadetPeerPath *path = GCC_get_path (cc, &len); | ||
1033 | |||
1034 | if (peer != GCPP_get_peer_at_offset (path, 0)) | ||
1035 | { | ||
1036 | /* received message from unexpected direction, ignore! */ | ||
1037 | GNUNET_break_op (0); | ||
1038 | return; | ||
1039 | } | ||
1040 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1041 | "Received CONNECTION_DESTROY for connection %s. Destroying connection.\n", | ||
1042 | GNUNET_sh2s (&msg->cid.connection_of_tunnel)); | ||
1043 | |||
1044 | GCC_destroy_without_core (cc); | ||
1045 | return; | ||
1046 | } | ||
1047 | |||
1048 | /* We're just an intermediary peer, route the message along its path */ | ||
1049 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1050 | "Received CONNECTION_DESTROY for connection %s. Destroying route.\n", | ||
1051 | GNUNET_sh2s (&msg->cid.connection_of_tunnel)); | ||
1052 | route_message (peer, | ||
1053 | &msg->cid, | ||
1054 | &msg->header, | ||
1055 | GNUNET_MQ_PREF_LOW_LATENCY | GNUNET_MQ_PRIO_CRITICAL_CONTROL); | ||
1056 | route = get_route (&msg->cid); | ||
1057 | if (NULL != route) | ||
1058 | destroy_route (route); | ||
1059 | } | ||
1060 | |||
1061 | |||
1062 | /** | ||
1063 | * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX | ||
1064 | * | ||
1065 | * @param cls Closure (CadetPeer for neighbor that sent the message). | ||
1066 | * @param msg Message itself. | ||
1067 | */ | ||
1068 | static void | ||
1069 | handle_tunnel_kx (void *cls, | ||
1070 | const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg) | ||
1071 | { | ||
1072 | struct CadetPeer *peer = cls; | ||
1073 | struct CadetConnection *cc; | ||
1074 | |||
1075 | /* First, check if message belongs to a connection that ends here. */ | ||
1076 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1077 | "Routing KX with ephemeral %s on CID %s\n", | ||
1078 | GNUNET_e2s (&msg->ephemeral_key), | ||
1079 | GNUNET_sh2s (&msg->cid.connection_of_tunnel)); | ||
1080 | |||
1081 | |||
1082 | cc = GCC_lookup (&msg->cid); | ||
1083 | if (NULL != cc) | ||
1084 | { | ||
1085 | /* verify message came from the right direction */ | ||
1086 | unsigned int len; | ||
1087 | struct CadetPeerPath *path = GCC_get_path (cc, &len); | ||
1088 | |||
1089 | if (peer != GCPP_get_peer_at_offset (path, 0)) | ||
1090 | { | ||
1091 | /* received message from unexpected direction, ignore! */ | ||
1092 | GNUNET_break_op (0); | ||
1093 | return; | ||
1094 | } | ||
1095 | GCC_handle_kx (cc, msg); | ||
1096 | return; | ||
1097 | } | ||
1098 | |||
1099 | /* We're just an intermediary peer, route the message along its path */ | ||
1100 | route_message (peer, | ||
1101 | &msg->cid, | ||
1102 | &msg->header, | ||
1103 | GNUNET_MQ_PRIO_CRITICAL_CONTROL | GNUNET_MQ_PREF_LOW_LATENCY); | ||
1104 | } | ||
1105 | |||
1106 | |||
1107 | /** | ||
1108 | * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX_AUTH | ||
1109 | * | ||
1110 | * @param cls Closure (CadetPeer for neighbor that sent the message). | ||
1111 | * @param msg Message itself. | ||
1112 | */ | ||
1113 | static void | ||
1114 | handle_tunnel_kx_auth ( | ||
1115 | void *cls, | ||
1116 | const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg) | ||
1117 | { | ||
1118 | struct CadetPeer *peer = cls; | ||
1119 | struct CadetConnection *cc; | ||
1120 | |||
1121 | /* First, check if message belongs to a connection that ends here. */ | ||
1122 | cc = GCC_lookup (&msg->kx.cid); | ||
1123 | if (NULL != cc) | ||
1124 | { | ||
1125 | /* verify message came from the right direction */ | ||
1126 | unsigned int len; | ||
1127 | struct CadetPeerPath *path = GCC_get_path (cc, &len); | ||
1128 | |||
1129 | if (peer != GCPP_get_peer_at_offset (path, 0)) | ||
1130 | { | ||
1131 | /* received message from unexpected direction, ignore! */ | ||
1132 | GNUNET_break_op (0); | ||
1133 | return; | ||
1134 | } | ||
1135 | GCC_handle_kx_auth (cc, msg); | ||
1136 | return; | ||
1137 | } | ||
1138 | |||
1139 | /* We're just an intermediary peer, route the message along its path */ | ||
1140 | route_message (peer, | ||
1141 | &msg->kx.cid, | ||
1142 | &msg->kx.header, | ||
1143 | GNUNET_MQ_PRIO_CRITICAL_CONTROL | GNUNET_MQ_PREF_LOW_LATENCY); | ||
1144 | } | ||
1145 | |||
1146 | |||
1147 | /** | ||
1148 | * Check if the encrypted message has the appropriate size. | ||
1149 | * | ||
1150 | * @param cls Closure (unused). | ||
1151 | * @param msg Message to check. | ||
1152 | * | ||
1153 | * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise. | ||
1154 | */ | ||
1155 | static int | ||
1156 | check_tunnel_encrypted (void *cls, | ||
1157 | const struct GNUNET_CADET_TunnelEncryptedMessage *msg) | ||
1158 | { | ||
1159 | return GNUNET_YES; | ||
1160 | } | ||
1161 | |||
1162 | |||
1163 | /** | ||
1164 | * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED. | ||
1165 | * | ||
1166 | * @param cls Closure (CadetPeer for neighbor that sent the message). | ||
1167 | * @param msg Message itself. | ||
1168 | */ | ||
1169 | static void | ||
1170 | handle_tunnel_encrypted (void *cls, | ||
1171 | const struct GNUNET_CADET_TunnelEncryptedMessage *msg) | ||
1172 | { | ||
1173 | struct CadetPeer *peer = cls; | ||
1174 | struct CadetConnection *cc; | ||
1175 | |||
1176 | /* First, check if message belongs to a connection that ends here. */ | ||
1177 | cc = GCC_lookup (&msg->cid); | ||
1178 | if (NULL != cc) | ||
1179 | { | ||
1180 | /* verify message came from the right direction */ | ||
1181 | unsigned int len; | ||
1182 | struct CadetPeerPath *path = GCC_get_path (cc, &len); | ||
1183 | |||
1184 | if (peer != GCPP_get_peer_at_offset (path, 0)) | ||
1185 | { | ||
1186 | /* received message from unexpected direction, ignore! */ | ||
1187 | GNUNET_break_op (0); | ||
1188 | return; | ||
1189 | } | ||
1190 | GCC_handle_encrypted (cc, msg); | ||
1191 | return; | ||
1192 | } | ||
1193 | /* We're just an intermediary peer, route the message along its path */ | ||
1194 | route_message (peer, &msg->cid, &msg->header, GNUNET_MQ_PRIO_BEST_EFFORT); | ||
1195 | } | ||
1196 | |||
1197 | |||
1198 | /** | ||
1199 | * Function called after #GNUNET_CORE_connect has succeeded (or failed | ||
1200 | * for good). Note that the private key of the peer is intentionally | ||
1201 | * not exposed here; if you need it, your process should try to read | ||
1202 | * the private key file directly (which should work if you are | ||
1203 | * authorized...). Implementations of this function must not call | ||
1204 | * #GNUNET_CORE_disconnect (other than by scheduling a new task to | ||
1205 | * do this later). | ||
1206 | * | ||
1207 | * @param cls closure | ||
1208 | * @param my_identity ID of this peer, NULL if we failed | ||
1209 | */ | ||
1210 | static void | ||
1211 | core_init_cb (void *cls, const struct GNUNET_PeerIdentity *my_identity) | ||
1212 | { | ||
1213 | if (NULL == my_identity) | ||
1214 | { | ||
1215 | GNUNET_break (0); | ||
1216 | return; | ||
1217 | } | ||
1218 | GNUNET_break (0 == GNUNET_memcmp (my_identity, &my_full_id)); | ||
1219 | } | ||
1220 | |||
1221 | |||
1222 | /** | ||
1223 | * Method called whenever a given peer connects. | ||
1224 | * | ||
1225 | * @param cls closure | ||
1226 | * @param peer peer identity this notification is about | ||
1227 | */ | ||
1228 | static void * | ||
1229 | core_connect_cb (void *cls, | ||
1230 | const struct GNUNET_PeerIdentity *peer, | ||
1231 | struct GNUNET_MQ_Handle *mq) | ||
1232 | { | ||
1233 | struct CadetPeer *cp; | ||
1234 | |||
1235 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1236 | "CORE connection to peer %s was established.\n", | ||
1237 | GNUNET_i2s (peer)); | ||
1238 | cp = GCP_get (peer, GNUNET_YES); | ||
1239 | GCP_set_mq (cp, mq); | ||
1240 | return cp; | ||
1241 | } | ||
1242 | |||
1243 | |||
1244 | /** | ||
1245 | * Method called whenever a peer disconnects. | ||
1246 | * | ||
1247 | * @param cls closure | ||
1248 | * @param peer peer identity this notification is about | ||
1249 | */ | ||
1250 | static void | ||
1251 | core_disconnect_cb (void *cls, | ||
1252 | const struct GNUNET_PeerIdentity *peer, | ||
1253 | void *peer_cls) | ||
1254 | { | ||
1255 | struct CadetPeer *cp = peer_cls; | ||
1256 | |||
1257 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1258 | "CORE connection to peer %s went down.\n", | ||
1259 | GNUNET_i2s (peer)); | ||
1260 | GCP_set_mq (cp, NULL); | ||
1261 | } | ||
1262 | |||
1263 | |||
1264 | /** | ||
1265 | * Initialize the CORE subsystem. | ||
1266 | * | ||
1267 | * @param c Configuration. | ||
1268 | */ | ||
1269 | void | ||
1270 | GCO_init (const struct GNUNET_CONFIGURATION_Handle *c) | ||
1271 | { | ||
1272 | struct GNUNET_MQ_MessageHandler handlers[] = | ||
1273 | { GNUNET_MQ_hd_var_size (connection_create, | ||
1274 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE, | ||
1275 | struct GNUNET_CADET_ConnectionCreateMessage, | ||
1276 | NULL), | ||
1277 | GNUNET_MQ_hd_fixed_size (connection_create_ack, | ||
1278 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK, | ||
1279 | struct GNUNET_CADET_ConnectionCreateAckMessage, | ||
1280 | NULL), | ||
1281 | GNUNET_MQ_hd_fixed_size (connection_broken, | ||
1282 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN, | ||
1283 | struct GNUNET_CADET_ConnectionBrokenMessage, | ||
1284 | NULL), | ||
1285 | GNUNET_MQ_hd_fixed_size (connection_destroy, | ||
1286 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY, | ||
1287 | struct GNUNET_CADET_ConnectionDestroyMessage, | ||
1288 | NULL), | ||
1289 | GNUNET_MQ_hd_fixed_size (tunnel_kx, | ||
1290 | GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX, | ||
1291 | struct GNUNET_CADET_TunnelKeyExchangeMessage, | ||
1292 | NULL), | ||
1293 | GNUNET_MQ_hd_fixed_size (tunnel_kx_auth, | ||
1294 | GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX_AUTH, | ||
1295 | struct GNUNET_CADET_TunnelKeyExchangeAuthMessage, | ||
1296 | NULL), | ||
1297 | GNUNET_MQ_hd_var_size (tunnel_encrypted, | ||
1298 | GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED, | ||
1299 | struct GNUNET_CADET_TunnelEncryptedMessage, | ||
1300 | NULL), | ||
1301 | GNUNET_MQ_handler_end () }; | ||
1302 | |||
1303 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (c, | ||
1304 | "CADET", | ||
1305 | "MAX_ROUTES", | ||
1306 | &max_routes)) | ||
1307 | max_routes = 5000; | ||
1308 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (c, | ||
1309 | "CADET", | ||
1310 | "MAX_MSGS_QUEUE", | ||
1311 | &max_buffers)) | ||
1312 | max_buffers = 10000; | ||
1313 | routes = GNUNET_CONTAINER_multishortmap_create (1024, GNUNET_NO); | ||
1314 | route_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); | ||
1315 | core = GNUNET_CORE_connect (c, | ||
1316 | NULL, | ||
1317 | &core_init_cb, | ||
1318 | &core_connect_cb, | ||
1319 | &core_disconnect_cb, | ||
1320 | handlers); | ||
1321 | } | ||
1322 | |||
1323 | |||
1324 | /** | ||
1325 | * Shut down the CORE subsystem. | ||
1326 | */ | ||
1327 | void | ||
1328 | GCO_shutdown () | ||
1329 | { | ||
1330 | if (NULL != core) | ||
1331 | { | ||
1332 | GNUNET_CORE_disconnect (core); | ||
1333 | core = NULL; | ||
1334 | } | ||
1335 | GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (routes)); | ||
1336 | GNUNET_CONTAINER_multishortmap_destroy (routes); | ||
1337 | routes = NULL; | ||
1338 | GNUNET_CONTAINER_heap_destroy (route_heap); | ||
1339 | route_heap = NULL; | ||
1340 | if (NULL != timeout_task) | ||
1341 | { | ||
1342 | GNUNET_SCHEDULER_cancel (timeout_task); | ||
1343 | timeout_task = NULL; | ||
1344 | } | ||
1345 | } | ||
1346 | |||
1347 | |||
1348 | /* end of gnunet-cadet-service_core.c */ | ||
diff --git a/src/cadet/gnunet-service-cadet_core.h b/src/cadet/gnunet-service-cadet_core.h deleted file mode 100644 index 3438dcb31..000000000 --- a/src/cadet/gnunet-service-cadet_core.h +++ /dev/null | |||
@@ -1,69 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/gnunet-service-cadet_core.h | ||
23 | * @brief cadet service; interaction with CORE service | ||
24 | * @author Bartlomiej Polot | ||
25 | * @author Christian Grothoff | ||
26 | * | ||
27 | * All functions in this file should use the prefix GCO (Gnunet Cadet cOre (bottom)) | ||
28 | */ | ||
29 | |||
30 | #ifndef GNUNET_SERVICE_CADET_CORE_H | ||
31 | #define GNUNET_SERVICE_CADET_CORE_H | ||
32 | |||
33 | #ifdef __cplusplus | ||
34 | extern "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 | */ | ||
49 | void | ||
50 | GCO_init (const struct GNUNET_CONFIGURATION_Handle *c); | ||
51 | |||
52 | |||
53 | /** | ||
54 | * Shut down the CORE subsystem. | ||
55 | */ | ||
56 | void | ||
57 | GCO_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 3df2687de..000000000 --- a/src/cadet/gnunet-service-cadet_dht.c +++ /dev/null | |||
@@ -1,357 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2013, 2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file cadet/gnunet-service-cadet_dht.c | ||
22 | * @brief Information we track per peer. | ||
23 | * @author Bartlomiej Polot | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | |||
27 | #include "platform.h" | ||
28 | #include "gnunet_util_lib.h" | ||
29 | #include "gnunet_dht_service.h" | ||
30 | #include "gnunet_statistics_service.h" | ||
31 | #include "gnunet-service-cadet.h" | ||
32 | #include "gnunet-service-cadet_dht.h" | ||
33 | #include "gnunet-service-cadet_hello.h" | ||
34 | #include "gnunet-service-cadet_peer.h" | ||
35 | #include "gnunet-service-cadet_paths.h" | ||
36 | |||
37 | /** | ||
38 | * How long do we wait before first announcing our presence to the DHT. | ||
39 | * Used to wait for our HELLO to be available. Note that we also get | ||
40 | * notifications when our HELLO is ready, so this is just the maximum | ||
41 | * we wait for the first notification. | ||
42 | */ | ||
43 | #define STARTUP_DELAY GNUNET_TIME_relative_multiply ( \ | ||
44 | GNUNET_TIME_UNIT_MILLISECONDS, 500) | ||
45 | |||
46 | /** | ||
47 | * How long do we wait after we get an updated HELLO before publishing? | ||
48 | * Allows for the HELLO to be updated again quickly, for example in | ||
49 | * case multiple addresses changed and we got a partial update. | ||
50 | */ | ||
51 | #define CHANGE_DELAY GNUNET_TIME_relative_multiply ( \ | ||
52 | GNUNET_TIME_UNIT_MILLISECONDS, 100) | ||
53 | |||
54 | |||
55 | #define LOG(level, ...) GNUNET_log_from (level, "cadet-dht", __VA_ARGS__) | ||
56 | |||
57 | |||
58 | /** | ||
59 | * Handle for DHT searches. | ||
60 | */ | ||
61 | struct GCD_search_handle | ||
62 | { | ||
63 | /** | ||
64 | * DHT_GET handle. | ||
65 | */ | ||
66 | struct GNUNET_DHT_GetHandle *dhtget; | ||
67 | }; | ||
68 | |||
69 | |||
70 | /** | ||
71 | * Handle to use DHT. | ||
72 | */ | ||
73 | static struct GNUNET_DHT_Handle *dht_handle; | ||
74 | |||
75 | /** | ||
76 | * How often to PUT own ID in the DHT. | ||
77 | */ | ||
78 | static struct GNUNET_TIME_Relative id_announce_time; | ||
79 | |||
80 | /** | ||
81 | * DHT replication level, see DHT API: #GNUNET_DHT_get_start(), #GNUNET_DHT_put(). | ||
82 | */ | ||
83 | static unsigned long long dht_replication_level; | ||
84 | |||
85 | /** | ||
86 | * Task to periodically announce itself in the network. | ||
87 | */ | ||
88 | static struct GNUNET_SCHEDULER_Task *announce_id_task; | ||
89 | |||
90 | /** | ||
91 | * Delay for the next ID announce. | ||
92 | */ | ||
93 | static struct GNUNET_TIME_Relative announce_delay; | ||
94 | |||
95 | |||
96 | /** | ||
97 | * Function to process paths received for a new peer addition. The recorded | ||
98 | * paths form the initial tunnel, which can be optimized later. | ||
99 | * Called on each result obtained for the DHT search. | ||
100 | * | ||
101 | * @param cls closure | ||
102 | * @param exp when will this value expire | ||
103 | * @param key key of the result | ||
104 | * @param trunc_peer peer preceeding with invalid signature, or NULL | ||
105 | * @param get_path path of the get request | ||
106 | * @param get_path_length length of @a get_path | ||
107 | * @param put_path path of the put request | ||
108 | * @param put_path_length length of the @a put_path | ||
109 | * @param type type of the result | ||
110 | * @param size number of bytes in data | ||
111 | * @param data pointer to the result data | ||
112 | */ | ||
113 | static void | ||
114 | dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp, | ||
115 | const struct GNUNET_HashCode *key, | ||
116 | const struct GNUNET_PeerIdentity *trunc_peer, | ||
117 | const struct GNUNET_DHT_PathElement *get_path, | ||
118 | unsigned int get_path_length, | ||
119 | const struct GNUNET_DHT_PathElement *put_path, | ||
120 | unsigned int put_path_length, | ||
121 | enum GNUNET_BLOCK_Type type, | ||
122 | size_t size, | ||
123 | const void *data) | ||
124 | { | ||
125 | const struct GNUNET_HELLO_Message *hello = data; | ||
126 | |||
127 | (void) trunc_peer; | ||
128 | GCPP_try_path_from_dht (get_path, | ||
129 | get_path_length, | ||
130 | put_path, | ||
131 | put_path_length); | ||
132 | if ((size >= sizeof(struct GNUNET_HELLO_Message)) && | ||
133 | (ntohs (hello->header.size) == size) && | ||
134 | (size == GNUNET_HELLO_size (hello))) | ||
135 | { | ||
136 | struct CadetPeer *peer; | ||
137 | |||
138 | peer = GCP_get (&put_path[0].pred, | ||
139 | GNUNET_YES); | ||
140 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
141 | "Got HELLO for %s\n", | ||
142 | GCP_2s (peer)); | ||
143 | GCP_set_hello (peer, | ||
144 | hello); | ||
145 | } | ||
146 | } | ||
147 | |||
148 | |||
149 | /** | ||
150 | * Periodically announce self id in the DHT | ||
151 | * | ||
152 | * @param cls closure | ||
153 | */ | ||
154 | static void | ||
155 | announce_id (void *cls) | ||
156 | { | ||
157 | struct GNUNET_HashCode phash; | ||
158 | const struct GNUNET_HELLO_Message *hello; | ||
159 | size_t size; | ||
160 | struct GNUNET_TIME_Absolute expiration; | ||
161 | struct GNUNET_TIME_Relative next_put; | ||
162 | |||
163 | hello = GCH_get_mine (); | ||
164 | size = (NULL != hello) ? GNUNET_HELLO_size (hello) : 0; | ||
165 | if (0 == size) | ||
166 | { | ||
167 | expiration = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), | ||
168 | announce_delay); | ||
169 | announce_delay = GNUNET_TIME_STD_BACKOFF (announce_delay); | ||
170 | } | ||
171 | else | ||
172 | { | ||
173 | expiration = GNUNET_HELLO_get_last_expiration (hello); | ||
174 | announce_delay = GNUNET_TIME_UNIT_SECONDS; | ||
175 | } | ||
176 | |||
177 | /* Call again in id_announce_time, unless HELLO expires first, | ||
178 | * but wait at least 1s. */ | ||
179 | next_put | ||
180 | = GNUNET_TIME_absolute_get_remaining (expiration); | ||
181 | next_put | ||
182 | = GNUNET_TIME_relative_min (next_put, | ||
183 | id_announce_time); | ||
184 | next_put | ||
185 | = GNUNET_TIME_relative_max (next_put, | ||
186 | GNUNET_TIME_UNIT_SECONDS); | ||
187 | announce_id_task | ||
188 | = GNUNET_SCHEDULER_add_delayed (next_put, | ||
189 | &announce_id, | ||
190 | cls); | ||
191 | GNUNET_STATISTICS_update (stats, | ||
192 | "# DHT announce", | ||
193 | 1, | ||
194 | GNUNET_NO); | ||
195 | memset (&phash, | ||
196 | 0, | ||
197 | sizeof(phash)); | ||
198 | GNUNET_memcpy (&phash, | ||
199 | &my_full_id, | ||
200 | sizeof(my_full_id)); | ||
201 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
202 | "Announcing my HELLO (%lu bytes) in the DHT\n", | ||
203 | (unsigned long) size); | ||
204 | GNUNET_DHT_put (dht_handle, /* DHT handle */ | ||
205 | &phash, /* Key to use */ | ||
206 | dht_replication_level, /* Replication level */ | ||
207 | GNUNET_DHT_RO_RECORD_ROUTE | ||
208 | | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, /* DHT options */ | ||
209 | GNUNET_BLOCK_TYPE_DHT_HELLO, /* Block type */ | ||
210 | size, /* Size of the data */ | ||
211 | (const char *) hello, /* Data itself */ | ||
212 | expiration, /* Data expiration */ | ||
213 | NULL, /* Continuation */ | ||
214 | NULL); /* Continuation closure */ | ||
215 | } | ||
216 | |||
217 | |||
218 | /** | ||
219 | * Function called by the HELLO subsystem whenever OUR hello | ||
220 | * changes. Re-triggers the DHT PUT immediately. | ||
221 | */ | ||
222 | void | ||
223 | GCD_hello_update () | ||
224 | { | ||
225 | if (NULL == announce_id_task) | ||
226 | return; /* too early */ | ||
227 | GNUNET_SCHEDULER_cancel (announce_id_task); | ||
228 | announce_id_task | ||
229 | = GNUNET_SCHEDULER_add_delayed (CHANGE_DELAY, | ||
230 | &announce_id, | ||
231 | NULL); | ||
232 | } | ||
233 | |||
234 | |||
235 | /** | ||
236 | * Initialize the DHT subsystem. | ||
237 | * | ||
238 | * @param c Configuration. | ||
239 | */ | ||
240 | void | ||
241 | GCD_init (const struct GNUNET_CONFIGURATION_Handle *c) | ||
242 | { | ||
243 | if (GNUNET_OK != | ||
244 | GNUNET_CONFIGURATION_get_value_number (c, | ||
245 | "CADET", | ||
246 | "DHT_REPLICATION_LEVEL", | ||
247 | &dht_replication_level)) | ||
248 | { | ||
249 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, | ||
250 | "CADET", | ||
251 | "DHT_REPLICATION_LEVEL", | ||
252 | "USING DEFAULT"); | ||
253 | dht_replication_level = 3; | ||
254 | } | ||
255 | |||
256 | if (GNUNET_OK != | ||
257 | GNUNET_CONFIGURATION_get_value_time (c, | ||
258 | "CADET", | ||
259 | "ID_ANNOUNCE_TIME", | ||
260 | &id_announce_time)) | ||
261 | { | ||
262 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, | ||
263 | "CADET", | ||
264 | "ID_ANNOUNCE_TIME", | ||
265 | "MISSING"); | ||
266 | GNUNET_SCHEDULER_shutdown (); | ||
267 | return; | ||
268 | } | ||
269 | |||
270 | dht_handle = GNUNET_DHT_connect (c, | ||
271 | 64); | ||
272 | GNUNET_break (NULL != dht_handle); | ||
273 | announce_delay = GNUNET_TIME_UNIT_SECONDS; | ||
274 | announce_id_task = GNUNET_SCHEDULER_add_delayed (STARTUP_DELAY, | ||
275 | &announce_id, | ||
276 | NULL); | ||
277 | } | ||
278 | |||
279 | |||
280 | /** | ||
281 | * Shut down the DHT subsystem. | ||
282 | */ | ||
283 | void | ||
284 | GCD_shutdown (void) | ||
285 | { | ||
286 | if (NULL != dht_handle) | ||
287 | { | ||
288 | GNUNET_DHT_disconnect (dht_handle); | ||
289 | dht_handle = NULL; | ||
290 | } | ||
291 | if (NULL != announce_id_task) | ||
292 | { | ||
293 | GNUNET_SCHEDULER_cancel (announce_id_task); | ||
294 | announce_id_task = NULL; | ||
295 | } | ||
296 | } | ||
297 | |||
298 | |||
299 | /** | ||
300 | * Search DHT for paths to @a peeR_id | ||
301 | * | ||
302 | * @param peer_id peer to search for | ||
303 | * @return handle to abort search | ||
304 | */ | ||
305 | struct GCD_search_handle * | ||
306 | GCD_search (const struct GNUNET_PeerIdentity *peer_id) | ||
307 | { | ||
308 | struct GNUNET_HashCode phash; | ||
309 | struct GCD_search_handle *h; | ||
310 | |||
311 | GNUNET_STATISTICS_update (stats, | ||
312 | "# DHT search", | ||
313 | 1, | ||
314 | GNUNET_NO); | ||
315 | memset (&phash, | ||
316 | 0, | ||
317 | sizeof(phash)); | ||
318 | GNUNET_memcpy (&phash, | ||
319 | peer_id, | ||
320 | sizeof(*peer_id)); | ||
321 | |||
322 | h = GNUNET_new (struct GCD_search_handle); | ||
323 | h->dhtget = GNUNET_DHT_get_start (dht_handle, /* handle */ | ||
324 | GNUNET_BLOCK_TYPE_DHT_HELLO, /* type */ | ||
325 | &phash, /* key to search */ | ||
326 | dht_replication_level, /* replication level */ | ||
327 | GNUNET_DHT_RO_RECORD_ROUTE | ||
328 | | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, | ||
329 | NULL, /* xquery */ | ||
330 | 0, /* xquery bits */ | ||
331 | &dht_get_id_handler, | ||
332 | h); | ||
333 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
334 | "Starting DHT GET for peer %s (%p)\n", | ||
335 | GNUNET_i2s (peer_id), | ||
336 | h); | ||
337 | return h; | ||
338 | } | ||
339 | |||
340 | |||
341 | /** | ||
342 | * Stop DHT search started with #GCD_search(). | ||
343 | * | ||
344 | * @param h handle to search to stop | ||
345 | */ | ||
346 | void | ||
347 | GCD_search_stop (struct GCD_search_handle *h) | ||
348 | { | ||
349 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
350 | "Stopping DHT GET %p\n", | ||
351 | h); | ||
352 | GNUNET_DHT_get_stop (h->dhtget); | ||
353 | GNUNET_free (h); | ||
354 | } | ||
355 | |||
356 | |||
357 | /* 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 | ||
33 | extern "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 | */ | ||
46 | struct GCD_search_handle; | ||
47 | |||
48 | |||
49 | /** | ||
50 | * Initialize the DHT subsystem. | ||
51 | * | ||
52 | * @param c Configuration. | ||
53 | */ | ||
54 | void | ||
55 | GCD_init (const struct GNUNET_CONFIGURATION_Handle *c); | ||
56 | |||
57 | |||
58 | /** | ||
59 | * Shut down the DHT subsystem. | ||
60 | */ | ||
61 | void | ||
62 | GCD_shutdown (void); | ||
63 | |||
64 | |||
65 | /** | ||
66 | * Function called by the HELLO subsystem whenever OUR hello | ||
67 | * changes. Re-triggers the DHT PUT immediately. | ||
68 | */ | ||
69 | void | ||
70 | GCD_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 | */ | ||
78 | struct GCD_search_handle * | ||
79 | GCD_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 | */ | ||
87 | void | ||
88 | GCD_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 | */ | ||
43 | static struct GNUNET_HELLO_Message *mine; | ||
44 | |||
45 | /** | ||
46 | * Handle to peerinfo service. | ||
47 | */ | ||
48 | static struct GNUNET_PEERINFO_Handle *peerinfo; | ||
49 | |||
50 | /** | ||
51 | * Iterator context. | ||
52 | */ | ||
53 | static 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 | */ | ||
64 | static void | ||
65 | got_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 | */ | ||
102 | void | ||
103 | GCH_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 | */ | ||
117 | void | ||
118 | GCH_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 | */ | ||
143 | const struct GNUNET_HELLO_Message * | ||
144 | GCH_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 | ||
34 | extern "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 | */ | ||
51 | void | ||
52 | GCH_init (const struct GNUNET_CONFIGURATION_Handle *c); | ||
53 | |||
54 | |||
55 | /** | ||
56 | * Shut down the hello subsystem. | ||
57 | */ | ||
58 | void | ||
59 | GCH_shutdown (void); | ||
60 | |||
61 | |||
62 | /** | ||
63 | * Get own hello message. | ||
64 | * | ||
65 | * @return Own hello message. | ||
66 | */ | ||
67 | const struct GNUNET_HELLO_Message * | ||
68 | GCH_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 aa31aaa74..000000000 --- a/src/cadet/gnunet-service-cadet_paths.c +++ /dev/null | |||
@@ -1,785 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2001-2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file cadet/gnunet-service-cadet_paths.c | ||
22 | * @brief Information we track per path. | ||
23 | * @author Bartlomiej Polot | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include "gnunet-service-cadet_connection.h" | ||
28 | #include "gnunet-service-cadet_tunnels.h" | ||
29 | #include "gnunet-service-cadet_peer.h" | ||
30 | #include "gnunet-service-cadet_paths.h" | ||
31 | |||
32 | |||
33 | #define LOG(level, ...) GNUNET_log_from (level, "cadet-pat", __VA_ARGS__) | ||
34 | |||
35 | |||
36 | /** | ||
37 | * Information regarding a possible path to reach a peer. | ||
38 | */ | ||
39 | struct 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 | */ | ||
71 | static void | ||
72 | recalculate_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 | */ | ||
100 | GNUNET_CONTAINER_HeapCostType | ||
101 | GCPP_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 | */ | ||
117 | struct CadetConnection * | ||
118 | GCPP_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 | */ | ||
139 | void | ||
140 | GCPP_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 | */ | ||
167 | void | ||
168 | GCPP_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 | */ | ||
195 | static void | ||
196 | attach_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 | */ | ||
242 | void | ||
243 | GCPP_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 | */ | ||
281 | void | ||
282 | GCPP_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 | */ | ||
313 | struct 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 | */ | ||
342 | static int | ||
343 | check_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 | */ | ||
390 | static void | ||
391 | extend_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 | */ | ||
470 | void | ||
471 | GCPP_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 | |||
597 | /** | ||
598 | * We got an incoming connection, obtain the corresponding path. | ||
599 | * | ||
600 | * @param path_length number of segments on the @a path | ||
601 | * @param pids path through the network, in reverse order (we are at the end at index @a path_length) | ||
602 | * @return corresponding path object | ||
603 | */ | ||
604 | struct CadetPeerPath * | ||
605 | GCPP_get_path_from_route (unsigned int path_length, | ||
606 | const struct GNUNET_PeerIdentity *pids) | ||
607 | { | ||
608 | struct CheckMatchContext cm_ctx; | ||
609 | struct CadetPeer *cpath[path_length]; | ||
610 | struct CadetPeerPath *path; | ||
611 | |||
612 | /* precompute inverted 'cpath' so we can avoid doing the lookups and | ||
613 | have the correct order */ | ||
614 | for (unsigned int off = 0; off < path_length; off++) | ||
615 | cpath[off] = GCP_get (&pids[path_length - 1 - off], | ||
616 | GNUNET_YES); | ||
617 | |||
618 | /* First figure out if this path is a subset of an existing path, an | ||
619 | extension of an existing path, or a new path. */ | ||
620 | cm_ctx.cpath = cpath; | ||
621 | cm_ctx.cpath_length = path_length; | ||
622 | cm_ctx.match = NULL; | ||
623 | for (int i = path_length - 1; i >= 0; i--) | ||
624 | { | ||
625 | GCP_iterate_paths_at (cpath[i], | ||
626 | (unsigned int) i, | ||
627 | &check_match, | ||
628 | &cm_ctx); | ||
629 | if (NULL != cm_ctx.match) | ||
630 | { | ||
631 | if (i == path_length - 1) | ||
632 | { | ||
633 | /* Existing path includes this one, return the match! */ | ||
634 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
635 | "Returning existing path %s as inverse for incoming connection\n", | ||
636 | GCPP_2s (cm_ctx.match)); | ||
637 | return cm_ctx.match; | ||
638 | } | ||
639 | if (cm_ctx.match->entries_length == i + 1) | ||
640 | { | ||
641 | /* Existing path ends in the middle of new path, extend it! */ | ||
642 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
643 | "Extending existing path %s to create inverse for incoming connection\n", | ||
644 | GCPP_2s (cm_ctx.match)); | ||
645 | extend_path (cm_ctx.match, | ||
646 | &cpath[i + 1], | ||
647 | path_length - i - 1, | ||
648 | GNUNET_YES); | ||
649 | /* Check that extension was successful */ | ||
650 | GNUNET_assert (cm_ctx.match->entries_length == path_length); | ||
651 | return cm_ctx.match; | ||
652 | } | ||
653 | /* Eh, we found a match but couldn't use it? Something is wrong. */ | ||
654 | GNUNET_break (0); | ||
655 | } | ||
656 | } | ||
657 | |||
658 | /* No match at all, create completely new path */ | ||
659 | path = GNUNET_new (struct CadetPeerPath); | ||
660 | path->entries_length = path_length; | ||
661 | path->entries = GNUNET_new_array (path->entries_length, | ||
662 | struct CadetPeerPathEntry *); | ||
663 | for (int i = path_length - 1; i >= 0; i--) | ||
664 | { | ||
665 | struct CadetPeerPathEntry *entry = GNUNET_new (struct CadetPeerPathEntry); | ||
666 | |||
667 | path->entries[i] = entry; | ||
668 | entry->peer = cpath[i]; | ||
669 | entry->path = path; | ||
670 | } | ||
671 | for (int i = path_length - 1; i >= 0; i--) | ||
672 | { | ||
673 | struct CadetPeerPathEntry *entry = path->entries[i]; | ||
674 | |||
675 | GCP_path_entry_add (entry->peer, | ||
676 | entry, | ||
677 | i); | ||
678 | } | ||
679 | recalculate_path_desirability (path); | ||
680 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
681 | "Created new path %s to create inverse for incoming connection\n", | ||
682 | GCPP_2s (path)); | ||
683 | path->hn = GCP_attach_path (cpath[path_length - 1], | ||
684 | path, | ||
685 | path_length - 1, | ||
686 | GNUNET_YES); | ||
687 | return path; | ||
688 | } | ||
689 | |||
690 | |||
691 | /** | ||
692 | * Return the length of the path. Excludes one end of the | ||
693 | * path, so the loopback path has length 0. | ||
694 | * | ||
695 | * @param path path to return the length for | ||
696 | * @return number of peers on the path | ||
697 | */ | ||
698 | unsigned int | ||
699 | GCPP_get_length (struct CadetPeerPath *path) | ||
700 | { | ||
701 | return path->entries_length; | ||
702 | } | ||
703 | |||
704 | |||
705 | /** | ||
706 | * Find peer's offset on path. | ||
707 | * | ||
708 | * @param path path to search | ||
709 | * @param cp peer to look for | ||
710 | * @return offset of @a cp on @a path, or UINT_MAX if not found | ||
711 | */ | ||
712 | unsigned int | ||
713 | GCPP_find_peer (struct CadetPeerPath *path, | ||
714 | struct CadetPeer *cp) | ||
715 | { | ||
716 | for (unsigned int off = 0; | ||
717 | off < path->entries_length; | ||
718 | off++) | ||
719 | if (cp == GCPP_get_peer_at_offset (path, | ||
720 | off)) | ||
721 | return off; | ||
722 | return UINT_MAX; | ||
723 | } | ||
724 | |||
725 | |||
726 | /** | ||
727 | * Obtain the peer at offset @a off in @a path. | ||
728 | * | ||
729 | * @param path peer path to inspect | ||
730 | * @param off offset to return, must be smaller than path length | ||
731 | * @return the peer at offset @a off | ||
732 | */ | ||
733 | struct CadetPeer * | ||
734 | GCPP_get_peer_at_offset (struct CadetPeerPath *path, | ||
735 | unsigned int off) | ||
736 | { | ||
737 | GNUNET_assert (off < path->entries_length); | ||
738 | return path->entries[off]->peer; | ||
739 | } | ||
740 | |||
741 | |||
742 | /** | ||
743 | * Convert a path to a human-readable string. | ||
744 | * | ||
745 | * @param path path to convert | ||
746 | * @return string, to be freed by caller (unlike other *_2s APIs!) | ||
747 | */ | ||
748 | const char * | ||
749 | GCPP_2s (struct CadetPeerPath *path) | ||
750 | { | ||
751 | static char buf[2048]; | ||
752 | size_t off; | ||
753 | const unsigned int max_plen = (sizeof(buf) - 16) / 5 - 2; /* 5 characters per entry */ | ||
754 | |||
755 | off = 0; | ||
756 | for (unsigned int i = 0; | ||
757 | i < path->entries_length; | ||
758 | i++) | ||
759 | { | ||
760 | if ((path->entries_length > max_plen) && | ||
761 | (i == max_plen / 2)) | ||
762 | off += GNUNET_snprintf (&buf[off], | ||
763 | sizeof(buf) - off, | ||
764 | "...-"); | ||
765 | if ((path->entries_length > max_plen) && | ||
766 | (i > max_plen / 2) && | ||
767 | (i < path->entries_length - max_plen / 2)) | ||
768 | continue; | ||
769 | off += GNUNET_snprintf (&buf[off], | ||
770 | sizeof(buf) - off, | ||
771 | "%s%s", | ||
772 | GNUNET_i2s (GCP_get_id (GCPP_get_peer_at_offset ( | ||
773 | path, | ||
774 | i))), | ||
775 | (i == path->entries_length - 1) ? "" : "-"); | ||
776 | } | ||
777 | GNUNET_snprintf (&buf[off], | ||
778 | sizeof(buf) - off, | ||
779 | "(%p)", | ||
780 | path); | ||
781 | return buf; | ||
782 | } | ||
783 | |||
784 | |||
785 | /* end of gnunet-service-cadet-new_paths.c */ | ||
diff --git a/src/cadet/gnunet-service-cadet_paths.h b/src/cadet/gnunet-service-cadet_paths.h deleted file mode 100644 index afd193596..000000000 --- a/src/cadet/gnunet-service-cadet_paths.h +++ /dev/null | |||
@@ -1,182 +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 | */ | ||
45 | void | ||
46 | GCPP_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 (we are at the end!) | ||
57 | * @return corresponding path object | ||
58 | */ | ||
59 | struct CadetPeerPath * | ||
60 | GCPP_get_path_from_route (unsigned int path_length, | ||
61 | const struct GNUNET_PeerIdentity *pids); | ||
62 | |||
63 | |||
64 | /** | ||
65 | * Return the length of the path. Excludes one end of the | ||
66 | * path, so the loopback path has length 0. | ||
67 | * | ||
68 | * @param path path to return the length for | ||
69 | * @return number of peers on the path | ||
70 | */ | ||
71 | unsigned int | ||
72 | GCPP_get_length (struct CadetPeerPath *path); | ||
73 | |||
74 | |||
75 | /** | ||
76 | * Return connection to @a destination using @a path, or return | ||
77 | * NULL if no such connection exists. | ||
78 | * | ||
79 | * @param path path to traverse | ||
80 | * @param destination destination node to get to, must be on path | ||
81 | * @param off offset of @a destination on @a path | ||
82 | * @return NULL if we have no existing connection | ||
83 | * otherwise connection from us to @a destination via @a path | ||
84 | */ | ||
85 | struct CadetConnection * | ||
86 | GCPP_get_connection (struct CadetPeerPath *path, | ||
87 | struct CadetPeer *destination, | ||
88 | unsigned int off); | ||
89 | |||
90 | |||
91 | /** | ||
92 | * Notify @a path that it is used for connection @a cc | ||
93 | * which ends at the path's offset @a off. | ||
94 | * | ||
95 | * @param path the path to remember the @a cc | ||
96 | * @param off the offset where the @a cc ends | ||
97 | * @param cc the connection to remember | ||
98 | */ | ||
99 | void | ||
100 | GCPP_add_connection (struct CadetPeerPath *path, | ||
101 | unsigned int off, | ||
102 | struct CadetConnection *cc); | ||
103 | |||
104 | |||
105 | /** | ||
106 | * Notify @a path that it is no longer used for connection @a cc which | ||
107 | * ended at the path's offset @a off. | ||
108 | * | ||
109 | * @param path the path to forget the @a cc | ||
110 | * @param off the offset where the @a cc ended | ||
111 | * @param cc the connection to forget | ||
112 | */ | ||
113 | void | ||
114 | GCPP_del_connection (struct CadetPeerPath *path, | ||
115 | unsigned int off, | ||
116 | struct CadetConnection *cc); | ||
117 | |||
118 | |||
119 | /** | ||
120 | * Find peer's offset on path. | ||
121 | * | ||
122 | * @param path path to search | ||
123 | * @param cp peer to look for | ||
124 | * @return offset of @a cp on @a path, or UINT_MAX if not found | ||
125 | */ | ||
126 | unsigned int | ||
127 | GCPP_find_peer (struct CadetPeerPath *path, | ||
128 | struct CadetPeer *cp); | ||
129 | |||
130 | |||
131 | /** | ||
132 | * Return how much we like keeping the path. This is an aggregate | ||
133 | * score based on various factors, including the age of the path | ||
134 | * (older == better), and the value of this path to all of its adjacent | ||
135 | * peers. For example, long paths that end at a peer that we have no | ||
136 | * shorter way to reach are very desirable, while long paths that end | ||
137 | * at a peer for which we have a shorter way as well are much less | ||
138 | * desirable. Higher values indicate more valuable paths. The | ||
139 | * returned value should be used to decide which paths to remember. | ||
140 | * | ||
141 | * @param path path to return the length for | ||
142 | * @return desirability of the path, larger is more desirable | ||
143 | */ | ||
144 | GNUNET_CONTAINER_HeapCostType | ||
145 | GCPP_get_desirability (const struct CadetPeerPath *path); | ||
146 | |||
147 | |||
148 | /** | ||
149 | * The given peer @a cp used to own this @a path. However, it is no | ||
150 | * longer interested in maintaining it, so the path should be | ||
151 | * discarded or shortened (in case a previous peer on the path finds | ||
152 | * the path desirable). | ||
153 | * | ||
154 | * @param path the path that is being released | ||
155 | */ | ||
156 | void | ||
157 | GCPP_release (struct CadetPeerPath *path); | ||
158 | |||
159 | |||
160 | /** | ||
161 | * Obtain the peer at offset @a off in @a path. | ||
162 | * | ||
163 | * @param path peer path to inspect | ||
164 | * @param off offset to return, must be smaller than path length | ||
165 | * @return peer at offset @a off | ||
166 | */ | ||
167 | struct CadetPeer * | ||
168 | GCPP_get_peer_at_offset (struct CadetPeerPath *path, | ||
169 | unsigned int off); | ||
170 | |||
171 | |||
172 | /** | ||
173 | * Convert a path to a human-readable string. | ||
174 | * | ||
175 | * @param path path to convert | ||
176 | * @return string, statically allocated | ||
177 | */ | ||
178 | const char * | ||
179 | GCPP_2s (struct CadetPeerPath *p); | ||
180 | |||
181 | |||
182 | #endif | ||
diff --git a/src/cadet/gnunet-service-cadet_peer.c b/src/cadet/gnunet-service-cadet_peer.c deleted file mode 100644 index 2437a3e1b..000000000 --- a/src/cadet/gnunet-service-cadet_peer.c +++ /dev/null | |||
@@ -1,1609 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2001-2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/gnunet-service-cadet_peer.c | ||
23 | * @brief Information we track per peer. | ||
24 | * @author Bartlomiej Polot | ||
25 | * @author Christian Grothoff | ||
26 | * | ||
27 | * TODO: | ||
28 | * - optimize stopping/restarting DHT search to situations | ||
29 | * where we actually need it (i.e. not if we have a direct connection, | ||
30 | * or if we already have plenty of good short ones, or maybe even | ||
31 | * to take a break if we have some connections and have searched a lot (?)) | ||
32 | */ | ||
33 | #include "platform.h" | ||
34 | #include "gnunet_time_lib.h" | ||
35 | #include "gnunet_util_lib.h" | ||
36 | #include "gnunet_hello_lib.h" | ||
37 | #include "gnunet_signatures.h" | ||
38 | #include "gnunet_transport_service.h" | ||
39 | #include "gnunet_ats_service.h" | ||
40 | #include "gnunet_core_service.h" | ||
41 | #include "gnunet_statistics_service.h" | ||
42 | #include "gnunet-service-cadet_peer.h" | ||
43 | #include "gnunet-service-cadet.h" | ||
44 | #include "gnunet-service-cadet_connection.h" | ||
45 | #include "gnunet-service-cadet_dht.h" | ||
46 | #include "gnunet-service-cadet_paths.h" | ||
47 | #include "gnunet-service-cadet_tunnels.h" | ||
48 | |||
49 | |||
50 | #define LOG(level, ...) GNUNET_log_from (level, "cadet-per", __VA_ARGS__) | ||
51 | |||
52 | |||
53 | /** | ||
54 | * How long do we wait until tearing down an idle peer? | ||
55 | */ | ||
56 | #define IDLE_PEER_TIMEOUT GNUNET_TIME_relative_multiply ( \ | ||
57 | GNUNET_TIME_UNIT_MINUTES, 5) | ||
58 | |||
59 | /** | ||
60 | * How long do we keep paths around if we no longer care about the peer? | ||
61 | */ | ||
62 | #define IDLE_PATH_TIMEOUT GNUNET_TIME_relative_multiply ( \ | ||
63 | GNUNET_TIME_UNIT_MINUTES, 2) | ||
64 | |||
65 | /** | ||
66 | * Queue size when we start dropping OOO messages. | ||
67 | */ | ||
68 | #define MAX_OOO_QUEUE_SIZE 100 | ||
69 | |||
70 | /** | ||
71 | * Data structure used to track whom we have to notify about changes | ||
72 | * to our message queue. | ||
73 | */ | ||
74 | struct 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 | */ | ||
111 | struct 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 | */ | ||
241 | const char * | ||
242 | GCP_2s (const struct CadetPeer *cp) | ||
243 | { | ||
244 | static char buf[5]; | ||
245 | char *ret; | ||
246 | |||
247 | if ((NULL == cp) || | ||
248 | (GNUNET_YES == GNUNET_is_zero (&cp->pid.public_key))) | ||
249 | return "NULL"; | ||
250 | |||
251 | ret = GNUNET_CRYPTO_eddsa_public_key_to_string (&cp->pid.public_key); | ||
252 | if (NULL == ret) | ||
253 | return "NULL"; | ||
254 | |||
255 | GNUNET_strlcpy (buf, | ||
256 | ret, | ||
257 | sizeof(buf)); | ||
258 | GNUNET_free (ret); | ||
259 | return buf; | ||
260 | } | ||
261 | |||
262 | |||
263 | /** | ||
264 | * Calculate how desirable a path is for @a cp if @a cp | ||
265 | * is at offset @a off. | ||
266 | * | ||
267 | * The 'desirability_table.c' program can be used to compute a list of | ||
268 | * sample outputs for different scenarios. Basically, we score paths | ||
269 | * lower if there are many alternatives, and higher if they are | ||
270 | * shorter than average, and very high if they are much shorter than | ||
271 | * average and without many alternatives. | ||
272 | * | ||
273 | * @param cp a peer reachable via a path | ||
274 | * @param off offset of @a cp in the path | ||
275 | * @return score how useful a path is to reach @a cp, | ||
276 | * positive scores mean path is more desirable | ||
277 | */ | ||
278 | double | ||
279 | GCP_get_desirability_of_path (struct CadetPeer *cp, | ||
280 | unsigned int off) | ||
281 | { | ||
282 | unsigned int num_alts = cp->num_paths; | ||
283 | unsigned int off_sum; | ||
284 | double avg_sum; | ||
285 | double path_delta; | ||
286 | double weight_alts; | ||
287 | |||
288 | GNUNET_assert (num_alts >= 1); /* 'path' should be in there! */ | ||
289 | GNUNET_assert (0 != cp->path_dll_length); | ||
290 | |||
291 | /* We maintain 'off_sum' in 'peer' and thereby | ||
292 | avoid the SLOW recalculation each time. Kept here | ||
293 | just to document what is going on. */ | ||
294 | #if SLOW | ||
295 | off_sum = 0; | ||
296 | for (unsigned int j = 0; j < cp->path_dll_length; j++) | ||
297 | for (struct CadetPeerPathEntry *pe = cp->path_heads[j]; | ||
298 | NULL != pe; | ||
299 | pe = pe->next) | ||
300 | off_sum += j; | ||
301 | GNUNET_assert (off_sum == cp->off_sum); | ||
302 | #else | ||
303 | off_sum = cp->off_sum; | ||
304 | #endif | ||
305 | avg_sum = off_sum * 1.0 / cp->path_dll_length; | ||
306 | path_delta = off - avg_sum; | ||
307 | /* path_delta positive: path off of peer above average (bad path for peer), | ||
308 | path_delta negative: path off of peer below average (good path for peer) */ | ||
309 | if (path_delta <= -1.0) | ||
310 | weight_alts = -num_alts / path_delta; /* discount alternative paths */ | ||
311 | else if (path_delta >= 1.0) | ||
312 | weight_alts = num_alts * path_delta; /* overcount alternative paths */ | ||
313 | else | ||
314 | weight_alts = num_alts; /* count alternative paths normally */ | ||
315 | |||
316 | |||
317 | /* off+1: long paths are generally harder to find and thus count | ||
318 | a bit more as they get longer. However, above-average paths | ||
319 | still need to count less, hence the squaring of that factor. */ | ||
320 | return (off + 1.0) / (weight_alts * weight_alts); | ||
321 | } | ||
322 | |||
323 | |||
324 | /** | ||
325 | * This peer is no longer be needed, clean it up now. | ||
326 | * | ||
327 | * @param cls peer to clean up | ||
328 | */ | ||
329 | static void | ||
330 | destroy_peer (void *cls) | ||
331 | { | ||
332 | struct CadetPeer *cp = cls; | ||
333 | |||
334 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
335 | "Destroying state about peer %s\n", | ||
336 | GCP_2s (cp)); | ||
337 | cp->destroy_task = NULL; | ||
338 | GNUNET_assert (NULL == cp->t); | ||
339 | GNUNET_assert (NULL == cp->core_mq); | ||
340 | GNUNET_assert (0 == cp->num_paths); | ||
341 | for (unsigned int i = 0; i < cp->path_dll_length; i++) | ||
342 | GNUNET_assert (NULL == cp->path_heads[i]); | ||
343 | GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (cp->connections)); | ||
344 | GNUNET_assert (GNUNET_YES == | ||
345 | GNUNET_CONTAINER_multipeermap_remove (peers, | ||
346 | &cp->pid, | ||
347 | cp)); | ||
348 | GNUNET_free (cp->path_heads); | ||
349 | GNUNET_free (cp->path_tails); | ||
350 | cp->path_dll_length = 0; | ||
351 | if (NULL != cp->search_h) | ||
352 | { | ||
353 | GCD_search_stop (cp->search_h); | ||
354 | cp->search_h = NULL; | ||
355 | } | ||
356 | /* FIXME: clean up search_delayedXXX! */ | ||
357 | |||
358 | if (NULL != cp->hello_offer) | ||
359 | { | ||
360 | GNUNET_TRANSPORT_offer_hello_cancel (cp->hello_offer); | ||
361 | cp->hello_offer = NULL; | ||
362 | } | ||
363 | if (NULL != cp->connectivity_suggestion) | ||
364 | { | ||
365 | GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion); | ||
366 | cp->connectivity_suggestion = NULL; | ||
367 | } | ||
368 | GNUNET_CONTAINER_multishortmap_destroy (cp->connections); | ||
369 | if (NULL != cp->path_heap) | ||
370 | { | ||
371 | GNUNET_CONTAINER_heap_destroy (cp->path_heap); | ||
372 | cp->path_heap = NULL; | ||
373 | } | ||
374 | if (NULL != cp->heap_cleanup_task) | ||
375 | { | ||
376 | GNUNET_SCHEDULER_cancel (cp->heap_cleanup_task); | ||
377 | cp->heap_cleanup_task = NULL; | ||
378 | } | ||
379 | GNUNET_free (cp->hello); | ||
380 | /* Peer should not be freed if paths exist; if there are no paths, | ||
381 | there ought to be no connections, and without connections, no | ||
382 | notifications. Thus we can assert that mqm_head is empty at this | ||
383 | point. */ | ||
384 | GNUNET_assert (NULL == cp->mqm_head); | ||
385 | GNUNET_assert (NULL == cp->mqm_ready_ptr); | ||
386 | GNUNET_free (cp); | ||
387 | } | ||
388 | |||
389 | |||
390 | /** | ||
391 | * This peer is now on more "active" duty, activate processes related to it. | ||
392 | * | ||
393 | * @param cp the more-active peer | ||
394 | */ | ||
395 | static void | ||
396 | consider_peer_activate (struct CadetPeer *cp) | ||
397 | { | ||
398 | uint32_t strength; | ||
399 | |||
400 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
401 | "Updating peer %s activation state (%u connections)%s%s\n", | ||
402 | GCP_2s (cp), | ||
403 | GNUNET_CONTAINER_multishortmap_size (cp->connections), | ||
404 | (NULL == cp->t) ? "" : " with tunnel", | ||
405 | (NULL == cp->core_mq) ? "" : " with CORE link"); | ||
406 | if (NULL != cp->destroy_task) | ||
407 | { | ||
408 | /* It's active, do not destroy! */ | ||
409 | GNUNET_SCHEDULER_cancel (cp->destroy_task); | ||
410 | cp->destroy_task = NULL; | ||
411 | } | ||
412 | if ((0 == GNUNET_CONTAINER_multishortmap_size (cp->connections)) && | ||
413 | (NULL == cp->t)) | ||
414 | { | ||
415 | /* We're just on a path or directly connected; don't bother too much */ | ||
416 | if (NULL != cp->connectivity_suggestion) | ||
417 | { | ||
418 | GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion); | ||
419 | cp->connectivity_suggestion = NULL; | ||
420 | } | ||
421 | if (NULL != cp->search_h) | ||
422 | { | ||
423 | GCD_search_stop (cp->search_h); | ||
424 | cp->search_h = NULL; | ||
425 | } | ||
426 | return; | ||
427 | } | ||
428 | if (NULL == cp->core_mq) | ||
429 | { | ||
430 | /* Lacks direct connection, try to create one by querying the DHT */ | ||
431 | if ((NULL == cp->search_h) && | ||
432 | (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths)) | ||
433 | cp->search_h | ||
434 | = GCD_search (&cp->pid); | ||
435 | } | ||
436 | else | ||
437 | { | ||
438 | /* Have direct connection, stop DHT search if active */ | ||
439 | if (NULL != cp->search_h) | ||
440 | { | ||
441 | GCD_search_stop (cp->search_h); | ||
442 | cp->search_h = NULL; | ||
443 | } | ||
444 | } | ||
445 | |||
446 | /* If we have a tunnel, our urge for connections is much bigger */ | ||
447 | strength = (NULL != cp->t) ? 32 : 1; | ||
448 | if (NULL != cp->connectivity_suggestion) | ||
449 | GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion); | ||
450 | cp->connectivity_suggestion | ||
451 | = GNUNET_ATS_connectivity_suggest (ats_ch, | ||
452 | &cp->pid, | ||
453 | strength); | ||
454 | } | ||
455 | |||
456 | |||
457 | /** | ||
458 | * This peer may no longer be needed, consider cleaning it up. | ||
459 | * | ||
460 | * @param cp peer to clean up | ||
461 | */ | ||
462 | static void | ||
463 | consider_peer_destroy (struct CadetPeer *cp); | ||
464 | |||
465 | |||
466 | /** | ||
467 | * We really no longere care about a peer, stop hogging memory with paths to it. | ||
468 | * Afterwards, see if there is more to be cleaned up about this peer. | ||
469 | * | ||
470 | * @param cls a `struct CadetPeer`. | ||
471 | */ | ||
472 | static void | ||
473 | drop_paths (void *cls) | ||
474 | { | ||
475 | struct CadetPeer *cp = cls; | ||
476 | struct CadetPeerPath *path; | ||
477 | |||
478 | cp->destroy_task = NULL; | ||
479 | while (NULL != (path = GNUNET_CONTAINER_heap_remove_root (cp->path_heap))) | ||
480 | GCPP_release (path); | ||
481 | consider_peer_destroy (cp); | ||
482 | } | ||
483 | |||
484 | |||
485 | /** | ||
486 | * This peer may no longer be needed, consider cleaning it up. | ||
487 | * | ||
488 | * @param cp peer to clean up | ||
489 | */ | ||
490 | static void | ||
491 | consider_peer_destroy (struct CadetPeer *cp) | ||
492 | { | ||
493 | struct GNUNET_TIME_Relative exp; | ||
494 | |||
495 | if (NULL != cp->destroy_task) | ||
496 | { | ||
497 | GNUNET_SCHEDULER_cancel (cp->destroy_task); | ||
498 | cp->destroy_task = NULL; | ||
499 | } | ||
500 | if (NULL != cp->t) | ||
501 | return; /* still relevant! */ | ||
502 | if (NULL != cp->core_mq) | ||
503 | return; /* still relevant! */ | ||
504 | if (0 != GNUNET_CONTAINER_multishortmap_size (cp->connections)) | ||
505 | return; /* still relevant! */ | ||
506 | if ((NULL != cp->path_heap) && | ||
507 | (0 < GNUNET_CONTAINER_heap_get_size (cp->path_heap))) | ||
508 | { | ||
509 | cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PATH_TIMEOUT, | ||
510 | &drop_paths, | ||
511 | cp); | ||
512 | return; | ||
513 | } | ||
514 | if (0 != cp->num_paths) | ||
515 | return; /* still relevant! */ | ||
516 | if (NULL != cp->hello) | ||
517 | { | ||
518 | /* relevant only until HELLO expires */ | ||
519 | exp = GNUNET_TIME_absolute_get_remaining (GNUNET_HELLO_get_last_expiration ( | ||
520 | cp->hello)); | ||
521 | cp->destroy_task = GNUNET_SCHEDULER_add_delayed (exp, | ||
522 | &destroy_peer, | ||
523 | cp); | ||
524 | return; | ||
525 | } | ||
526 | cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PEER_TIMEOUT, | ||
527 | &destroy_peer, | ||
528 | cp); | ||
529 | } | ||
530 | |||
531 | |||
532 | /** | ||
533 | * Set the message queue to @a mq for peer @a cp and notify watchers. | ||
534 | * | ||
535 | * @param cp peer to modify | ||
536 | * @param mq message queue to set (can be NULL) | ||
537 | */ | ||
538 | void | ||
539 | GCP_set_mq (struct CadetPeer *cp, | ||
540 | struct GNUNET_MQ_Handle *mq) | ||
541 | { | ||
542 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
543 | "Message queue for peer %s is now %p\n", | ||
544 | GCP_2s (cp), | ||
545 | mq); | ||
546 | cp->core_mq = mq; | ||
547 | for (struct GCP_MessageQueueManager *mqm = cp->mqm_head, *next; | ||
548 | NULL != mqm; | ||
549 | mqm = next) | ||
550 | { | ||
551 | /* Save next pointer in case mqm gets freed by the callback */ | ||
552 | next = mqm->next; | ||
553 | if (NULL == mq) | ||
554 | { | ||
555 | if (NULL != mqm->env) | ||
556 | { | ||
557 | GNUNET_MQ_discard (mqm->env); | ||
558 | mqm->env = NULL; | ||
559 | mqm->cb (mqm->cb_cls, | ||
560 | GNUNET_SYSERR); | ||
561 | } | ||
562 | else | ||
563 | { | ||
564 | mqm->cb (mqm->cb_cls, | ||
565 | GNUNET_NO); | ||
566 | } | ||
567 | } | ||
568 | else | ||
569 | { | ||
570 | GNUNET_assert (NULL == mqm->env); | ||
571 | mqm->cb (mqm->cb_cls, | ||
572 | GNUNET_YES); | ||
573 | } | ||
574 | } | ||
575 | if ((NULL != mq) || | ||
576 | (NULL != cp->t)) | ||
577 | consider_peer_activate (cp); | ||
578 | else | ||
579 | consider_peer_destroy (cp); | ||
580 | |||
581 | if ((NULL != mq) && | ||
582 | (NULL != cp->t)) | ||
583 | { | ||
584 | /* have a new, direct path to the target, notify tunnel */ | ||
585 | struct CadetPeerPath *path; | ||
586 | |||
587 | path = GCPP_get_path_from_route (1, | ||
588 | &cp->pid); | ||
589 | GCT_consider_path (cp->t, | ||
590 | path, | ||
591 | 0); | ||
592 | } | ||
593 | } | ||
594 | |||
595 | |||
596 | /** | ||
597 | * Debug function should NEVER return true in production code, useful to | ||
598 | * simulate losses for testcases. | ||
599 | * | ||
600 | * @return #GNUNET_YES or #GNUNET_NO with the decision to drop. | ||
601 | */ | ||
602 | static int | ||
603 | should_I_drop (void) | ||
604 | { | ||
605 | if (0 == drop_percent) | ||
606 | return GNUNET_NO; | ||
607 | if (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, | ||
608 | 101) < drop_percent) | ||
609 | return GNUNET_YES; | ||
610 | return GNUNET_NO; | ||
611 | } | ||
612 | |||
613 | |||
614 | /** | ||
615 | * Function called when CORE took one of the messages from | ||
616 | * a message queue manager and transmitted it. | ||
617 | * | ||
618 | * @param cls the `struct CadetPeeer` where we made progress | ||
619 | */ | ||
620 | static void | ||
621 | mqm_send_done (void *cls); | ||
622 | |||
623 | |||
624 | /** | ||
625 | * Transmit current envelope from this @a mqm. | ||
626 | * | ||
627 | * @param mqm mqm to transmit message for now | ||
628 | */ | ||
629 | static void | ||
630 | mqm_execute (struct GCP_MessageQueueManager *mqm) | ||
631 | { | ||
632 | struct CadetPeer *cp = mqm->cp; | ||
633 | |||
634 | /* Move ready pointer to the next entry that might be ready. */ | ||
635 | if ((mqm == cp->mqm_ready_ptr) && | ||
636 | (NULL != mqm->next)) | ||
637 | cp->mqm_ready_ptr = mqm->next; | ||
638 | /* Move entry to the end of the DLL, to be fair. */ | ||
639 | if (mqm != cp->mqm_tail) | ||
640 | { | ||
641 | GNUNET_CONTAINER_DLL_remove (cp->mqm_head, | ||
642 | cp->mqm_tail, | ||
643 | mqm); | ||
644 | GNUNET_CONTAINER_DLL_insert_tail (cp->mqm_head, | ||
645 | cp->mqm_tail, | ||
646 | mqm); | ||
647 | } | ||
648 | cp->mqm_ready_counter--; | ||
649 | if (GNUNET_YES == should_I_drop ()) | ||
650 | { | ||
651 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
652 | "DROPPING message to peer %s from MQM %p\n", | ||
653 | GCP_2s (cp), | ||
654 | mqm); | ||
655 | GNUNET_MQ_discard (mqm->env); | ||
656 | mqm->env = NULL; | ||
657 | mqm_send_done (cp); | ||
658 | } | ||
659 | else | ||
660 | { | ||
661 | { | ||
662 | const struct GNUNET_MessageHeader *mh; | ||
663 | |||
664 | mh = GNUNET_MQ_env_get_msg (mqm->env); | ||
665 | switch (ntohs (mh->type)) | ||
666 | { | ||
667 | case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX: | ||
668 | { | ||
669 | const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg | ||
670 | = (const struct GNUNET_CADET_TunnelKeyExchangeMessage *) mh; | ||
671 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
672 | "P2P forwarding KX with ephemeral %s to %s on CID %s\n", | ||
673 | GNUNET_e2s (&msg->ephemeral_key), | ||
674 | GCP_2s (cp), | ||
675 | GNUNET_sh2s (&msg->cid.connection_of_tunnel)); | ||
676 | } | ||
677 | break; | ||
678 | |||
679 | default: | ||
680 | break; | ||
681 | } | ||
682 | } | ||
683 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
684 | "Sending to peer %s from MQM %p\n", | ||
685 | GCP_2s (cp), | ||
686 | mqm); | ||
687 | GNUNET_MQ_send (cp->core_mq, | ||
688 | mqm->env); | ||
689 | mqm->env = NULL; | ||
690 | } | ||
691 | mqm->cb (mqm->cb_cls, | ||
692 | GNUNET_YES); | ||
693 | } | ||
694 | |||
695 | |||
696 | /** | ||
697 | * Find the next ready message in the queue (starting | ||
698 | * the search from the `cp->mqm_ready_ptr`) and if possible | ||
699 | * execute the transmission. | ||
700 | * | ||
701 | * @param cp peer to try to send the next ready message to | ||
702 | */ | ||
703 | static void | ||
704 | send_next_ready (struct CadetPeer *cp) | ||
705 | { | ||
706 | struct GCP_MessageQueueManager *mqm; | ||
707 | |||
708 | if (0 == cp->mqm_ready_counter) | ||
709 | return; | ||
710 | while ((NULL != (mqm = cp->mqm_ready_ptr)) && | ||
711 | (NULL == mqm->env)) | ||
712 | cp->mqm_ready_ptr = mqm->next; | ||
713 | if (NULL == mqm) | ||
714 | return; /* nothing to do */ | ||
715 | mqm_execute (mqm); | ||
716 | } | ||
717 | |||
718 | |||
719 | /** | ||
720 | * Function called when CORE took one of the messages from | ||
721 | * a message queue manager and transmitted it. | ||
722 | * | ||
723 | * @param cls the `struct CadetPeeer` where we made progress | ||
724 | */ | ||
725 | static void | ||
726 | mqm_send_done (void *cls) | ||
727 | { | ||
728 | struct CadetPeer *cp = cls; | ||
729 | |||
730 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
731 | "Sending to peer %s completed\n", | ||
732 | GCP_2s (cp)); | ||
733 | send_next_ready (cp); | ||
734 | } | ||
735 | |||
736 | |||
737 | /** | ||
738 | * Send the message in @a env to @a cp. | ||
739 | * | ||
740 | * @param mqm the message queue manager to use for transmission | ||
741 | * @param env envelope with the message to send; must NOT | ||
742 | * yet have a #GNUNET_MQ_notify_sent() callback attached to it | ||
743 | */ | ||
744 | void | ||
745 | GCP_send (struct GCP_MessageQueueManager *mqm, | ||
746 | struct GNUNET_MQ_Envelope *env) | ||
747 | { | ||
748 | struct CadetPeer *cp = mqm->cp; | ||
749 | |||
750 | GNUNET_assert (NULL != env); | ||
751 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
752 | "Queueing message to peer %s in MQM %p\n", | ||
753 | GCP_2s (cp), | ||
754 | mqm); | ||
755 | GNUNET_assert (NULL != cp->core_mq); | ||
756 | GNUNET_assert (NULL == mqm->env); | ||
757 | GNUNET_MQ_notify_sent (env, | ||
758 | &mqm_send_done, | ||
759 | cp); | ||
760 | mqm->env = env; | ||
761 | cp->mqm_ready_counter++; | ||
762 | if (mqm != cp->mqm_ready_ptr) | ||
763 | cp->mqm_ready_ptr = cp->mqm_head; | ||
764 | if (1 == cp->mqm_ready_counter) | ||
765 | cp->mqm_ready_ptr = mqm; | ||
766 | if (0 != GNUNET_MQ_get_length (cp->core_mq)) | ||
767 | return; | ||
768 | send_next_ready (cp); | ||
769 | } | ||
770 | |||
771 | |||
772 | /** | ||
773 | * Function called to destroy a peer now. | ||
774 | * | ||
775 | * @param cls NULL | ||
776 | * @param pid identity of the peer (unused) | ||
777 | * @param value the `struct CadetPeer` to clean up | ||
778 | * @return #GNUNET_OK (continue to iterate) | ||
779 | */ | ||
780 | static int | ||
781 | destroy_iterator_cb (void *cls, | ||
782 | const struct GNUNET_PeerIdentity *pid, | ||
783 | void *value) | ||
784 | { | ||
785 | struct CadetPeer *cp = value; | ||
786 | |||
787 | if (NULL != cp->destroy_task) | ||
788 | { | ||
789 | GNUNET_SCHEDULER_cancel (cp->destroy_task); | ||
790 | cp->destroy_task = NULL; | ||
791 | } | ||
792 | destroy_peer (cp); | ||
793 | return GNUNET_OK; | ||
794 | } | ||
795 | |||
796 | |||
797 | /** | ||
798 | * Clean up all entries about all peers. | ||
799 | * Must only be called after all tunnels, CORE-connections and | ||
800 | * connections are down. | ||
801 | */ | ||
802 | void | ||
803 | GCP_destroy_all_peers () | ||
804 | { | ||
805 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
806 | "Destroying all peers now\n"); | ||
807 | GNUNET_CONTAINER_multipeermap_iterate (peers, | ||
808 | &destroy_iterator_cb, | ||
809 | NULL); | ||
810 | } | ||
811 | |||
812 | |||
813 | /** | ||
814 | * Drop all paths owned by this peer, and do not | ||
815 | * allow new ones to be added: We are shutting down. | ||
816 | * | ||
817 | * @param cp peer to drop paths to | ||
818 | */ | ||
819 | void | ||
820 | GCP_drop_owned_paths (struct CadetPeer *cp) | ||
821 | { | ||
822 | struct CadetPeerPath *path; | ||
823 | |||
824 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
825 | "Destroying all paths to %s\n", | ||
826 | GCP_2s (cp)); | ||
827 | while (NULL != (path = | ||
828 | GNUNET_CONTAINER_heap_remove_root (cp->path_heap))) | ||
829 | GCPP_release (path); | ||
830 | GNUNET_CONTAINER_heap_destroy (cp->path_heap); | ||
831 | cp->path_heap = NULL; | ||
832 | } | ||
833 | |||
834 | |||
835 | /** | ||
836 | * Add an entry to the DLL of all of the paths that this peer is on. | ||
837 | * | ||
838 | * @param cp peer to modify | ||
839 | * @param entry an entry on a path | ||
840 | * @param off offset of this peer on the path | ||
841 | */ | ||
842 | void | ||
843 | GCP_path_entry_add (struct CadetPeer *cp, | ||
844 | struct CadetPeerPathEntry *entry, | ||
845 | unsigned int off) | ||
846 | { | ||
847 | GNUNET_assert (cp == GCPP_get_peer_at_offset (entry->path, | ||
848 | off)); | ||
849 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
850 | "Discovered that peer %s is on path %s at offset %u\n", | ||
851 | GCP_2s (cp), | ||
852 | GCPP_2s (entry->path), | ||
853 | off); | ||
854 | if (off >= cp->path_dll_length) | ||
855 | { | ||
856 | unsigned int len = cp->path_dll_length; | ||
857 | |||
858 | GNUNET_array_grow (cp->path_heads, | ||
859 | len, | ||
860 | off + 4); | ||
861 | GNUNET_array_grow (cp->path_tails, | ||
862 | cp->path_dll_length, | ||
863 | off + 4); | ||
864 | } | ||
865 | GNUNET_CONTAINER_DLL_insert (cp->path_heads[off], | ||
866 | cp->path_tails[off], | ||
867 | entry); | ||
868 | cp->off_sum += off; | ||
869 | cp->num_paths++; | ||
870 | |||
871 | /* If we have a tunnel to this peer, tell the tunnel that there is a | ||
872 | new path available. */ | ||
873 | if (NULL != cp->t) | ||
874 | GCT_consider_path (cp->t, | ||
875 | entry->path, | ||
876 | off); | ||
877 | |||
878 | if ((NULL != cp->search_h) && | ||
879 | (DESIRED_CONNECTIONS_PER_TUNNEL <= cp->num_paths)) | ||
880 | { | ||
881 | /* Now I have enough paths, stop search */ | ||
882 | GCD_search_stop (cp->search_h); | ||
883 | cp->search_h = NULL; | ||
884 | } | ||
885 | if (NULL != cp->destroy_task) | ||
886 | { | ||
887 | /* paths changed, this resets the destroy timeout counter | ||
888 | and aborts a destroy task that may no longer be valid | ||
889 | to have (as we now have more paths via this peer). */ | ||
890 | consider_peer_destroy (cp); | ||
891 | } | ||
892 | } | ||
893 | |||
894 | |||
895 | /** | ||
896 | * Remove an entry from the DLL of all of the paths that this peer is on. | ||
897 | * | ||
898 | * @param cp peer to modify | ||
899 | * @param entry an entry on a path | ||
900 | * @param off offset of this peer on the path | ||
901 | */ | ||
902 | void | ||
903 | GCP_path_entry_remove (struct CadetPeer *cp, | ||
904 | struct CadetPeerPathEntry *entry, | ||
905 | unsigned int off) | ||
906 | { | ||
907 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
908 | "Removing knowledge about peer %s beging on path %s at offset %u\n", | ||
909 | GCP_2s (cp), | ||
910 | GCPP_2s (entry->path), | ||
911 | off); | ||
912 | GNUNET_CONTAINER_DLL_remove (cp->path_heads[off], | ||
913 | cp->path_tails[off], | ||
914 | entry); | ||
915 | GNUNET_assert (0 < cp->num_paths); | ||
916 | cp->off_sum -= off; | ||
917 | cp->num_paths--; | ||
918 | if ((NULL == cp->core_mq) && | ||
919 | (NULL != cp->t) && | ||
920 | (NULL == cp->search_h) && | ||
921 | (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths)) | ||
922 | cp->search_h | ||
923 | = GCD_search (&cp->pid); | ||
924 | if (NULL == cp->destroy_task) | ||
925 | { | ||
926 | /* paths changed, we might now be ready for destruction, check again */ | ||
927 | consider_peer_destroy (cp); | ||
928 | } | ||
929 | } | ||
930 | |||
931 | |||
932 | /** | ||
933 | * Prune down the number of paths to this peer, we seem to | ||
934 | * have way too many. | ||
935 | * | ||
936 | * @param cls the `struct CadetPeer` to maintain the path heap for | ||
937 | */ | ||
938 | static void | ||
939 | path_heap_cleanup (void *cls) | ||
940 | { | ||
941 | struct CadetPeer *cp = cls; | ||
942 | struct CadetPeerPath *root; | ||
943 | |||
944 | cp->heap_cleanup_task = NULL; | ||
945 | while (GNUNET_CONTAINER_heap_get_size (cp->path_heap) >= | ||
946 | 2 * DESIRED_CONNECTIONS_PER_TUNNEL) | ||
947 | { | ||
948 | /* Now we have way too many, drop least desirable UNLESS it is in use! | ||
949 | (Note that this intentionally keeps highly desirable, but currently | ||
950 | unused paths around in the hope that we might be able to switch, even | ||
951 | if the number of paths exceeds the threshold.) */ | ||
952 | root = GNUNET_CONTAINER_heap_peek (cp->path_heap); | ||
953 | GNUNET_assert (NULL != root); | ||
954 | if (NULL != | ||
955 | GCPP_get_connection (root, | ||
956 | cp, | ||
957 | GCPP_get_length (root) - 1)) | ||
958 | break; /* can't fix */ | ||
959 | /* Got plenty of paths to this destination, and this is a low-quality | ||
960 | one that we don't care about. Allow it to die. */ | ||
961 | GNUNET_assert (root == | ||
962 | GNUNET_CONTAINER_heap_remove_root (cp->path_heap)); | ||
963 | GCPP_release (root); | ||
964 | } | ||
965 | } | ||
966 | |||
967 | |||
968 | /** | ||
969 | * Try adding a @a path to this @a peer. If the peer already | ||
970 | * has plenty of paths, return NULL. | ||
971 | * | ||
972 | * @param cp peer to which the @a path leads to | ||
973 | * @param path a path looking for an owner; may not be fully initialized yet! | ||
974 | * @param off offset of @a cp in @a path | ||
975 | * @param force force attaching the path | ||
976 | * @return NULL if this peer does not care to become a new owner, | ||
977 | * otherwise the node in the peer's path heap for the @a path. | ||
978 | */ | ||
979 | struct GNUNET_CONTAINER_HeapNode * | ||
980 | GCP_attach_path (struct CadetPeer *cp, | ||
981 | struct CadetPeerPath *path, | ||
982 | unsigned int off, | ||
983 | int force) | ||
984 | { | ||
985 | GNUNET_CONTAINER_HeapCostType desirability; | ||
986 | struct CadetPeerPath *root; | ||
987 | GNUNET_CONTAINER_HeapCostType root_desirability; | ||
988 | struct GNUNET_CONTAINER_HeapNode *hn; | ||
989 | |||
990 | GNUNET_assert (off == GCPP_get_length (path) - 1); | ||
991 | GNUNET_assert (cp == GCPP_get_peer_at_offset (path, | ||
992 | off)); | ||
993 | if (NULL == cp->path_heap) | ||
994 | { | ||
995 | /* #GCP_drop_owned_paths() was already called, we cannot take new ones! */ | ||
996 | GNUNET_assert (GNUNET_NO == force); | ||
997 | return NULL; | ||
998 | } | ||
999 | desirability = GCPP_get_desirability (path); | ||
1000 | if (GNUNET_NO == force) | ||
1001 | { | ||
1002 | /* FIXME: desirability is not yet initialized; tricky! */ | ||
1003 | if (GNUNET_NO == | ||
1004 | GNUNET_CONTAINER_heap_peek2 (cp->path_heap, | ||
1005 | (void **) &root, | ||
1006 | &root_desirability)) | ||
1007 | { | ||
1008 | root = NULL; | ||
1009 | root_desirability = 0; | ||
1010 | } | ||
1011 | |||
1012 | if ((DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) && | ||
1013 | (desirability < root_desirability)) | ||
1014 | { | ||
1015 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1016 | "Decided to not attach path %s to peer %s due to undesirability\n", | ||
1017 | GCPP_2s (path), | ||
1018 | GCP_2s (cp)); | ||
1019 | return NULL; | ||
1020 | } | ||
1021 | } | ||
1022 | |||
1023 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1024 | "Attaching path %s to peer %s (%s)\n", | ||
1025 | GCPP_2s (path), | ||
1026 | GCP_2s (cp), | ||
1027 | (GNUNET_NO == force) ? "desirable" : "forced"); | ||
1028 | |||
1029 | /* Yes, we'd like to add this path, add to our heap */ | ||
1030 | hn = GNUNET_CONTAINER_heap_insert (cp->path_heap, | ||
1031 | path, | ||
1032 | desirability); | ||
1033 | |||
1034 | /* Consider maybe dropping other paths because of the new one */ | ||
1035 | if ((GNUNET_CONTAINER_heap_get_size (cp->path_heap) >= | ||
1036 | 2 * DESIRED_CONNECTIONS_PER_TUNNEL) && | ||
1037 | (NULL != cp->heap_cleanup_task)) | ||
1038 | cp->heap_cleanup_task = GNUNET_SCHEDULER_add_now (&path_heap_cleanup, | ||
1039 | cp); | ||
1040 | return hn; | ||
1041 | } | ||
1042 | |||
1043 | |||
1044 | /** | ||
1045 | * This peer can no longer own @a path as the path | ||
1046 | * has been extended and a peer further down the line | ||
1047 | * is now the new owner. | ||
1048 | * | ||
1049 | * @param cp old owner of the @a path | ||
1050 | * @param path path where the ownership is lost | ||
1051 | * @param hn note in @a cp's path heap that must be deleted | ||
1052 | */ | ||
1053 | void | ||
1054 | GCP_detach_path (struct CadetPeer *cp, | ||
1055 | struct CadetPeerPath *path, | ||
1056 | struct GNUNET_CONTAINER_HeapNode *hn) | ||
1057 | { | ||
1058 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1059 | "Detaching path %s from peer %s\n", | ||
1060 | GCPP_2s (path), | ||
1061 | GCP_2s (cp)); | ||
1062 | GNUNET_assert (path == | ||
1063 | GNUNET_CONTAINER_heap_remove_node (hn)); | ||
1064 | } | ||
1065 | |||
1066 | |||
1067 | /** | ||
1068 | * Add a @a connection to this @a cp. | ||
1069 | * | ||
1070 | * @param cp peer via which the @a connection goes | ||
1071 | * @param cc the connection to add | ||
1072 | */ | ||
1073 | void | ||
1074 | GCP_add_connection (struct CadetPeer *cp, | ||
1075 | struct CadetConnection *cc) | ||
1076 | { | ||
1077 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1078 | "Adding %s to peer %s\n", | ||
1079 | GCC_2s (cc), | ||
1080 | GCP_2s (cp)); | ||
1081 | GNUNET_assert (GNUNET_OK == | ||
1082 | GNUNET_CONTAINER_multishortmap_put (cp->connections, | ||
1083 | &GCC_get_id ( | ||
1084 | cc)->connection_of_tunnel, | ||
1085 | cc, | ||
1086 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
1087 | if (NULL != cp->destroy_task) | ||
1088 | { | ||
1089 | GNUNET_SCHEDULER_cancel (cp->destroy_task); | ||
1090 | cp->destroy_task = NULL; | ||
1091 | } | ||
1092 | } | ||
1093 | |||
1094 | |||
1095 | /** | ||
1096 | * Remove a @a connection that went via this @a cp. | ||
1097 | * | ||
1098 | * @param cp peer via which the @a connection went | ||
1099 | * @param cc the connection to remove | ||
1100 | */ | ||
1101 | void | ||
1102 | GCP_remove_connection (struct CadetPeer *cp, | ||
1103 | struct CadetConnection *cc) | ||
1104 | { | ||
1105 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1106 | "Removing connection %s from peer %s\n", | ||
1107 | GCC_2s (cc), | ||
1108 | GCP_2s (cp)); | ||
1109 | GNUNET_assert (GNUNET_YES == | ||
1110 | GNUNET_CONTAINER_multishortmap_remove (cp->connections, | ||
1111 | &GCC_get_id ( | ||
1112 | cc)-> | ||
1113 | connection_of_tunnel, | ||
1114 | cc)); | ||
1115 | consider_peer_destroy (cp); | ||
1116 | } | ||
1117 | |||
1118 | |||
1119 | /** | ||
1120 | * Retrieve the CadetPeer structure associated with the | ||
1121 | * peer. Optionally create one and insert it in the appropriate | ||
1122 | * structures if the peer is not known yet. | ||
1123 | * | ||
1124 | * @param peer_id Full identity of the peer. | ||
1125 | * @param create #GNUNET_YES if a new peer should be created if unknown. | ||
1126 | * #GNUNET_NO to return NULL if peer is unknown. | ||
1127 | * @return Existing or newly created peer structure. | ||
1128 | * NULL if unknown and not requested @a create | ||
1129 | */ | ||
1130 | struct CadetPeer * | ||
1131 | GCP_get (const struct GNUNET_PeerIdentity *peer_id, | ||
1132 | int create) | ||
1133 | { | ||
1134 | struct CadetPeer *cp; | ||
1135 | |||
1136 | cp = GNUNET_CONTAINER_multipeermap_get (peers, | ||
1137 | peer_id); | ||
1138 | if (NULL != cp) | ||
1139 | return cp; | ||
1140 | if (GNUNET_NO == create) | ||
1141 | return NULL; | ||
1142 | cp = GNUNET_new (struct CadetPeer); | ||
1143 | cp->pid = *peer_id; | ||
1144 | cp->connections = GNUNET_CONTAINER_multishortmap_create (32, | ||
1145 | GNUNET_YES); | ||
1146 | cp->path_heap = GNUNET_CONTAINER_heap_create ( | ||
1147 | GNUNET_CONTAINER_HEAP_ORDER_MIN); | ||
1148 | GNUNET_assert (GNUNET_YES == | ||
1149 | GNUNET_CONTAINER_multipeermap_put (peers, | ||
1150 | &cp->pid, | ||
1151 | cp, | ||
1152 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
1153 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1154 | "Creating peer %s\n", | ||
1155 | GCP_2s (cp)); | ||
1156 | return cp; | ||
1157 | } | ||
1158 | |||
1159 | |||
1160 | /** | ||
1161 | * Obtain the peer identity for a `struct CadetPeer`. | ||
1162 | * | ||
1163 | * @param cp our peer handle | ||
1164 | * @return the peer identity | ||
1165 | */ | ||
1166 | const struct GNUNET_PeerIdentity * | ||
1167 | GCP_get_id (struct CadetPeer *cp) | ||
1168 | { | ||
1169 | return &cp->pid; | ||
1170 | } | ||
1171 | |||
1172 | |||
1173 | /** | ||
1174 | * Iterate over all known peers. | ||
1175 | * | ||
1176 | * @param iter Iterator. | ||
1177 | * @param cls Closure for @c iter. | ||
1178 | */ | ||
1179 | void | ||
1180 | GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter, | ||
1181 | void *cls) | ||
1182 | { | ||
1183 | GNUNET_CONTAINER_multipeermap_iterate (peers, | ||
1184 | iter, | ||
1185 | cls); | ||
1186 | } | ||
1187 | |||
1188 | |||
1189 | /** | ||
1190 | * Count the number of known paths toward the peer. | ||
1191 | * | ||
1192 | * @param cp Peer to get path info. | ||
1193 | * @return Number of known paths. | ||
1194 | */ | ||
1195 | unsigned int | ||
1196 | GCP_count_paths (const struct CadetPeer *cp) | ||
1197 | { | ||
1198 | return cp->num_paths; | ||
1199 | } | ||
1200 | |||
1201 | |||
1202 | /** | ||
1203 | * Iterate over the paths to a peer. | ||
1204 | * | ||
1205 | * @param cp Peer to get path info. | ||
1206 | * @param callback Function to call for every path. | ||
1207 | * @param callback_cls Closure for @a callback. | ||
1208 | * @return Number of iterated paths. | ||
1209 | */ | ||
1210 | unsigned int | ||
1211 | GCP_iterate_paths (struct CadetPeer *cp, | ||
1212 | GCP_PathIterator callback, | ||
1213 | void *callback_cls) | ||
1214 | { | ||
1215 | unsigned int ret = 0; | ||
1216 | |||
1217 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1218 | "Iterating over paths to peer %s%s\n", | ||
1219 | GCP_2s (cp), | ||
1220 | (NULL == cp->core_mq) ? "" : " including direct link"); | ||
1221 | if (NULL != cp->core_mq) | ||
1222 | { | ||
1223 | /* FIXME: this branch seems to duplicate the | ||
1224 | i=0 case below (direct link). Leave out!??? -CG */ | ||
1225 | struct CadetPeerPath *path; | ||
1226 | |||
1227 | path = GCPP_get_path_from_route (1, | ||
1228 | &cp->pid); | ||
1229 | ret++; | ||
1230 | if (GNUNET_NO == | ||
1231 | callback (callback_cls, | ||
1232 | path, | ||
1233 | 0)) | ||
1234 | return ret; | ||
1235 | } | ||
1236 | for (unsigned int i = 0; i < cp->path_dll_length; i++) | ||
1237 | { | ||
1238 | for (struct CadetPeerPathEntry *pe = cp->path_heads[i]; | ||
1239 | NULL != pe; | ||
1240 | pe = pe->next) | ||
1241 | { | ||
1242 | ret++; | ||
1243 | if (GNUNET_NO == | ||
1244 | callback (callback_cls, | ||
1245 | pe->path, | ||
1246 | i)) | ||
1247 | return ret; | ||
1248 | } | ||
1249 | } | ||
1250 | return ret; | ||
1251 | } | ||
1252 | |||
1253 | |||
1254 | /** | ||
1255 | * Iterate over the paths to a peer without direct link. | ||
1256 | * | ||
1257 | * @param cp Peer to get path info. | ||
1258 | * @param callback Function to call for every path. | ||
1259 | * @param callback_cls Closure for @a callback. | ||
1260 | * @return Number of iterated paths. | ||
1261 | */ | ||
1262 | unsigned int | ||
1263 | GCP_iterate_indirect_paths (struct CadetPeer *cp, | ||
1264 | GCP_PathIterator callback, | ||
1265 | void *callback_cls) | ||
1266 | { | ||
1267 | unsigned int ret = 0; | ||
1268 | |||
1269 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1270 | "Iterating over paths to peer %s without direct link\n", | ||
1271 | GCP_2s (cp)); | ||
1272 | for (unsigned int i = 1; i < cp->path_dll_length; i++) | ||
1273 | { | ||
1274 | for (struct CadetPeerPathEntry *pe = cp->path_heads[i]; | ||
1275 | NULL != pe; | ||
1276 | pe = pe->next) | ||
1277 | { | ||
1278 | ret++; | ||
1279 | if (GNUNET_NO == | ||
1280 | callback (callback_cls, | ||
1281 | pe->path, | ||
1282 | i)) | ||
1283 | return ret; | ||
1284 | } | ||
1285 | } | ||
1286 | return ret; | ||
1287 | } | ||
1288 | |||
1289 | |||
1290 | /** | ||
1291 | * Iterate over the paths to @a cp where | ||
1292 | * @a cp is at distance @a dist from us. | ||
1293 | * | ||
1294 | * @param cp Peer to get path info. | ||
1295 | * @param dist desired distance of @a cp to us on the path | ||
1296 | * @param callback Function to call for every path. | ||
1297 | * @param callback_cls Closure for @a callback. | ||
1298 | * @return Number of iterated paths. | ||
1299 | */ | ||
1300 | unsigned int | ||
1301 | GCP_iterate_paths_at (struct CadetPeer *cp, | ||
1302 | unsigned int dist, | ||
1303 | GCP_PathIterator callback, | ||
1304 | void *callback_cls) | ||
1305 | { | ||
1306 | unsigned int ret = 0; | ||
1307 | |||
1308 | if (dist >= cp->path_dll_length) | ||
1309 | { | ||
1310 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1311 | "Asked to look for paths at distance %u, but maximum for me is < %u\n", | ||
1312 | dist, | ||
1313 | cp->path_dll_length); | ||
1314 | return 0; | ||
1315 | } | ||
1316 | for (struct CadetPeerPathEntry *pe = cp->path_heads[dist]; | ||
1317 | NULL != pe; | ||
1318 | pe = pe->next) | ||
1319 | { | ||
1320 | if (GNUNET_NO == | ||
1321 | callback (callback_cls, | ||
1322 | pe->path, | ||
1323 | dist)) | ||
1324 | return ret; | ||
1325 | ret++; | ||
1326 | } | ||
1327 | return ret; | ||
1328 | } | ||
1329 | |||
1330 | |||
1331 | /** | ||
1332 | * Get the tunnel towards a peer. | ||
1333 | * | ||
1334 | * @param cp Peer to get from. | ||
1335 | * @param create #GNUNET_YES to create a tunnel if we do not have one | ||
1336 | * @return Tunnel towards peer. | ||
1337 | */ | ||
1338 | struct CadetTunnel * | ||
1339 | GCP_get_tunnel (struct CadetPeer *cp, | ||
1340 | int create) | ||
1341 | { | ||
1342 | if (NULL == cp) | ||
1343 | return NULL; | ||
1344 | if ((NULL != cp->t) || | ||
1345 | (GNUNET_NO == create)) | ||
1346 | return cp->t; | ||
1347 | cp->t = GCT_create_tunnel (cp); | ||
1348 | consider_peer_activate (cp); | ||
1349 | return cp->t; | ||
1350 | } | ||
1351 | |||
1352 | |||
1353 | /** | ||
1354 | * Hello offer was passed to the transport service. Mark it | ||
1355 | * as done. | ||
1356 | * | ||
1357 | * @param cls the `struct CadetPeer` where the offer completed | ||
1358 | */ | ||
1359 | static void | ||
1360 | hello_offer_done (void *cls) | ||
1361 | { | ||
1362 | struct CadetPeer *cp = cls; | ||
1363 | |||
1364 | cp->hello_offer = NULL; | ||
1365 | } | ||
1366 | |||
1367 | |||
1368 | /** | ||
1369 | * We got a HELLO for a @a peer, remember it, and possibly | ||
1370 | * trigger adequate actions (like trying to connect). | ||
1371 | * | ||
1372 | * @param cp the peer we got a HELLO for | ||
1373 | * @param hello the HELLO to remember | ||
1374 | */ | ||
1375 | void | ||
1376 | GCP_set_hello (struct CadetPeer *cp, | ||
1377 | const struct GNUNET_HELLO_Message *hello) | ||
1378 | { | ||
1379 | struct GNUNET_HELLO_Message *mrg; | ||
1380 | |||
1381 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1382 | "Got %u byte HELLO for peer %s\n", | ||
1383 | (unsigned int) GNUNET_HELLO_size (hello), | ||
1384 | GCP_2s (cp)); | ||
1385 | if (NULL != cp->hello_offer) | ||
1386 | { | ||
1387 | GNUNET_TRANSPORT_offer_hello_cancel (cp->hello_offer); | ||
1388 | cp->hello_offer = NULL; | ||
1389 | } | ||
1390 | if (NULL != cp->hello) | ||
1391 | { | ||
1392 | mrg = GNUNET_HELLO_merge (hello, | ||
1393 | cp->hello); | ||
1394 | GNUNET_free (cp->hello); | ||
1395 | cp->hello = mrg; | ||
1396 | } | ||
1397 | else | ||
1398 | { | ||
1399 | cp->hello = GNUNET_memdup (hello, | ||
1400 | GNUNET_HELLO_size (hello)); | ||
1401 | } | ||
1402 | cp->hello_offer | ||
1403 | = GNUNET_TRANSPORT_offer_hello (cfg, | ||
1404 | GNUNET_HELLO_get_header (cp->hello), | ||
1405 | &hello_offer_done, | ||
1406 | cp); | ||
1407 | /* New HELLO means cp's destruction time may change... */ | ||
1408 | consider_peer_destroy (cp); | ||
1409 | } | ||
1410 | |||
1411 | |||
1412 | /** | ||
1413 | * The tunnel to the given peer no longer exists, remove it from our | ||
1414 | * data structures, and possibly clean up the peer itself. | ||
1415 | * | ||
1416 | * @param cp the peer affected | ||
1417 | * @param t the dead tunnel | ||
1418 | */ | ||
1419 | void | ||
1420 | GCP_drop_tunnel (struct CadetPeer *cp, | ||
1421 | struct CadetTunnel *t) | ||
1422 | { | ||
1423 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1424 | "Dropping tunnel %s to peer %s\n", | ||
1425 | GCT_2s (t), | ||
1426 | GCP_2s (cp)); | ||
1427 | GNUNET_assert (cp->t == t); | ||
1428 | cp->t = NULL; | ||
1429 | consider_peer_destroy (cp); | ||
1430 | } | ||
1431 | |||
1432 | |||
1433 | /** | ||
1434 | * Test if @a cp has a core-level connection | ||
1435 | * | ||
1436 | * @param cp peer to test | ||
1437 | * @return #GNUNET_YES if @a cp has a core-level connection | ||
1438 | */ | ||
1439 | int | ||
1440 | GCP_has_core_connection (struct CadetPeer *cp) | ||
1441 | { | ||
1442 | return (NULL != cp->core_mq) ? GNUNET_YES : GNUNET_NO; | ||
1443 | } | ||
1444 | |||
1445 | |||
1446 | /** | ||
1447 | * Start message queue change notifications. | ||
1448 | * | ||
1449 | * @param cp peer to notify for | ||
1450 | * @param cb function to call if mq becomes available or unavailable | ||
1451 | * @param cb_cls closure for @a cb | ||
1452 | * @return handle to cancel request | ||
1453 | */ | ||
1454 | struct GCP_MessageQueueManager * | ||
1455 | GCP_request_mq (struct CadetPeer *cp, | ||
1456 | GCP_MessageQueueNotificationCallback cb, | ||
1457 | void *cb_cls) | ||
1458 | { | ||
1459 | struct GCP_MessageQueueManager *mqm; | ||
1460 | |||
1461 | mqm = GNUNET_new (struct GCP_MessageQueueManager); | ||
1462 | mqm->cb = cb; | ||
1463 | mqm->cb_cls = cb_cls; | ||
1464 | mqm->cp = cp; | ||
1465 | GNUNET_CONTAINER_DLL_insert (cp->mqm_head, | ||
1466 | cp->mqm_tail, | ||
1467 | mqm); | ||
1468 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1469 | "Creating MQM %p for peer %s\n", | ||
1470 | mqm, | ||
1471 | GCP_2s (cp)); | ||
1472 | if (NULL != cp->core_mq) | ||
1473 | cb (cb_cls, | ||
1474 | GNUNET_YES); | ||
1475 | return mqm; | ||
1476 | } | ||
1477 | |||
1478 | |||
1479 | /** | ||
1480 | * Stops message queue change notifications. | ||
1481 | * | ||
1482 | * @param mqm handle matching request to cancel | ||
1483 | * @param last_env final message to transmit, or NULL | ||
1484 | */ | ||
1485 | void | ||
1486 | GCP_request_mq_cancel (struct GCP_MessageQueueManager *mqm, | ||
1487 | struct GNUNET_MQ_Envelope *last_env) | ||
1488 | { | ||
1489 | struct CadetPeer *cp = mqm->cp; | ||
1490 | |||
1491 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1492 | "Destroying MQM %p for peer %s%s\n", | ||
1493 | mqm, | ||
1494 | GCP_2s (cp), | ||
1495 | (NULL == last_env) ? "" : " with last ditch transmission"); | ||
1496 | if (NULL != mqm->env) | ||
1497 | GNUNET_MQ_discard (mqm->env); | ||
1498 | if (NULL != last_env) | ||
1499 | { | ||
1500 | if (NULL != cp->core_mq) | ||
1501 | { | ||
1502 | GNUNET_MQ_notify_sent (last_env, | ||
1503 | &mqm_send_done, | ||
1504 | cp); | ||
1505 | GNUNET_MQ_send (cp->core_mq, | ||
1506 | last_env); | ||
1507 | } | ||
1508 | else | ||
1509 | { | ||
1510 | GNUNET_MQ_discard (last_env); | ||
1511 | } | ||
1512 | } | ||
1513 | if (cp->mqm_ready_ptr == mqm) | ||
1514 | cp->mqm_ready_ptr = mqm->next; | ||
1515 | GNUNET_CONTAINER_DLL_remove (cp->mqm_head, | ||
1516 | cp->mqm_tail, | ||
1517 | mqm); | ||
1518 | GNUNET_free (mqm); | ||
1519 | } | ||
1520 | |||
1521 | |||
1522 | /** | ||
1523 | * Send the message in @a env to @a cp, overriding queueing logic. | ||
1524 | * This function should only be used to send error messages outside | ||
1525 | * of flow and congestion control, similar to ICMP. Note that | ||
1526 | * the envelope may be silently discarded as well. | ||
1527 | * | ||
1528 | * @param cp peer to send the message to | ||
1529 | * @param env envelope with the message to send | ||
1530 | */ | ||
1531 | void | ||
1532 | GCP_send_ooo (struct CadetPeer *cp, | ||
1533 | struct GNUNET_MQ_Envelope *env) | ||
1534 | { | ||
1535 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1536 | "Sending message to %s out of management\n", | ||
1537 | GCP_2s (cp)); | ||
1538 | if (NULL == cp->core_mq) | ||
1539 | { | ||
1540 | GNUNET_MQ_discard (env); | ||
1541 | return; | ||
1542 | } | ||
1543 | if (GNUNET_MQ_get_length (cp->core_mq) > MAX_OOO_QUEUE_SIZE) | ||
1544 | { | ||
1545 | GNUNET_MQ_discard (env); | ||
1546 | return; | ||
1547 | } | ||
1548 | GNUNET_MQ_notify_sent (env, | ||
1549 | &mqm_send_done, | ||
1550 | cp); | ||
1551 | GNUNET_MQ_send (cp->core_mq, | ||
1552 | env); | ||
1553 | } | ||
1554 | |||
1555 | |||
1556 | /** | ||
1557 | * Checking if a monotime value is newer than the last monotime value received from a peer. If the time value is newer it will be stored at the peer. | ||
1558 | * | ||
1559 | * @param peer The peer we received a new time value from. | ||
1560 | * @param monotime Time value we check against the last time value we received from a peer. | ||
1561 | * @return GNUNET_YES if monotime is newer than the last received time value, GNUNET_NO if monotime is not newer. | ||
1562 | */ | ||
1563 | int | ||
1564 | GCP_check_and_update_monotime (struct CadetPeer *peer, | ||
1565 | struct GNUNET_TIME_AbsoluteNBO monotime) | ||
1566 | { | ||
1567 | |||
1568 | struct GNUNET_TIME_Absolute mt = GNUNET_TIME_absolute_ntoh (monotime); | ||
1569 | |||
1570 | if (mt.abs_value_us > *(&peer->last_connection_create.abs_value_us)) | ||
1571 | { | ||
1572 | peer->last_connection_create = mt; | ||
1573 | return GNUNET_YES; | ||
1574 | } | ||
1575 | return GNUNET_NO; | ||
1576 | } | ||
1577 | |||
1578 | |||
1579 | /** | ||
1580 | * Checking the signature for a monotime of a GNUNET_CADET_ConnectionCreateMessage. | ||
1581 | * | ||
1582 | * @param peer The peer that signed the monotime value. | ||
1583 | * @param msg The GNUNET_CADET_ConnectionCreateMessage with the monotime value. | ||
1584 | * @return GNUNET_OK if the signature is good, GNUNET_SYSERR if not. | ||
1585 | */ | ||
1586 | int | ||
1587 | GCP_check_monotime_sig (struct CadetPeer *peer, | ||
1588 | const struct GNUNET_CADET_ConnectionCreateMessage *msg) | ||
1589 | { | ||
1590 | struct CadetConnectionCreatePS cp = { .purpose.purpose = htonl ( | ||
1591 | GNUNET_SIGNATURE_PURPOSE_CADET_CONNECTION_INITIATOR), | ||
1592 | .purpose.size = htonl (sizeof(cp)), | ||
1593 | .monotonic_time = msg->monotime}; | ||
1594 | |||
1595 | if (GNUNET_OK != | ||
1596 | GNUNET_CRYPTO_eddsa_verify ( | ||
1597 | GNUNET_SIGNATURE_PURPOSE_CADET_CONNECTION_INITIATOR, | ||
1598 | &cp, | ||
1599 | &msg->monotime_sig, | ||
1600 | &peer->pid.public_key)) | ||
1601 | { | ||
1602 | GNUNET_break_op (0); | ||
1603 | return GNUNET_SYSERR; | ||
1604 | } | ||
1605 | return GNUNET_OK; | ||
1606 | } | ||
1607 | |||
1608 | |||
1609 | /* end of gnunet-service-cadet-new_peer.c */ | ||
diff --git a/src/cadet/gnunet-service-cadet_peer.h b/src/cadet/gnunet-service-cadet_peer.h deleted file mode 100644 index 7a39615ff..000000000 --- a/src/cadet/gnunet-service-cadet_peer.h +++ /dev/null | |||
@@ -1,427 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2001-2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/gnunet-service-cadet_peer.h | ||
23 | * @brief Information we track per peer. | ||
24 | * @author Bartlomiej Polot | ||
25 | * @author Christian Grothoff | ||
26 | */ | ||
27 | #ifndef GNUNET_SERVICE_CADET_PEER_H | ||
28 | #define GNUNET_SERVICE_CADET_PEER_H | ||
29 | |||
30 | #include "gnunet-service-cadet.h" | ||
31 | #include "gnunet_hello_lib.h" | ||
32 | |||
33 | |||
34 | /** | ||
35 | * Get the static string for a peer ID. | ||
36 | * | ||
37 | * @param peer Peer. | ||
38 | * | ||
39 | * @return Static string for it's ID. | ||
40 | */ | ||
41 | const char * | ||
42 | GCP_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 | */ | ||
56 | struct CadetPeer * | ||
57 | GCP_get (const struct GNUNET_PeerIdentity *peer_id, | ||
58 | int create); | ||
59 | |||
60 | |||
61 | /** | ||
62 | * Calculate how desirable a path is for @a cp if | ||
63 | * @a cp is at offset @a off in the path. | ||
64 | * | ||
65 | * @param cp a peer reachable via a path | ||
66 | * @param off offset of @a cp in a path | ||
67 | * @return score how useful a path is to reach @a cp, | ||
68 | * positive scores mean path is more desirable | ||
69 | */ | ||
70 | double | ||
71 | GCP_get_desirability_of_path (struct CadetPeer *cp, | ||
72 | unsigned int off); | ||
73 | |||
74 | |||
75 | /** | ||
76 | * Obtain the peer identity for a `struct CadetPeer`. | ||
77 | * | ||
78 | * @param cp our peer handle | ||
79 | * @return the peer identity | ||
80 | */ | ||
81 | const struct GNUNET_PeerIdentity * | ||
82 | GCP_get_id (struct CadetPeer *cp); | ||
83 | |||
84 | |||
85 | /** | ||
86 | * Iterate over all known peers. | ||
87 | * | ||
88 | * @param iter Iterator. | ||
89 | * @param cls Closure for @c iter. | ||
90 | */ | ||
91 | void | ||
92 | GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter, | ||
93 | void *cls); | ||
94 | |||
95 | |||
96 | /** | ||
97 | * Count the number of known paths toward the peer. | ||
98 | * | ||
99 | * @param cp Peer to get path info. | ||
100 | * @return Number of known paths. | ||
101 | */ | ||
102 | unsigned int | ||
103 | GCP_count_paths (const struct CadetPeer *cp); | ||
104 | |||
105 | |||
106 | /** | ||
107 | * Drop all paths owned by this peer, and do not | ||
108 | * allow new ones to be added: We are shutting down. | ||
109 | * | ||
110 | * @param cp peer to drop paths to | ||
111 | */ | ||
112 | void | ||
113 | GCP_drop_owned_paths (struct CadetPeer *cp); | ||
114 | |||
115 | |||
116 | /** | ||
117 | * Peer path iterator. | ||
118 | * | ||
119 | * @param cls Closure. | ||
120 | * @param path Path itself | ||
121 | * @param off offset of the target peer in @a path | ||
122 | * @return #GNUNET_YES if should keep iterating. | ||
123 | * #GNUNET_NO otherwise. | ||
124 | */ | ||
125 | typedef int | ||
126 | (*GCP_PathIterator) (void *cls, | ||
127 | struct CadetPeerPath *path, | ||
128 | unsigned int off); | ||
129 | |||
130 | |||
131 | /** | ||
132 | * Iterate over the paths to a peer. | ||
133 | * | ||
134 | * @param cp Peer to get path info. | ||
135 | * @param callback Function to call for every path. | ||
136 | * @param callback_cls Closure for @a callback. | ||
137 | * @return Number of iterated paths. | ||
138 | */ | ||
139 | unsigned int | ||
140 | GCP_iterate_paths (struct CadetPeer *cp, | ||
141 | GCP_PathIterator callback, | ||
142 | void *callback_cls); | ||
143 | |||
144 | /** | ||
145 | * Iterate over the paths to a peer without direct link. | ||
146 | * | ||
147 | * @param cp Peer to get path info. | ||
148 | * @param callback Function to call for every path. | ||
149 | * @param callback_cls Closure for @a callback. | ||
150 | * @return Number of iterated paths. | ||
151 | */ | ||
152 | unsigned int | ||
153 | GCP_iterate_indirect_paths (struct CadetPeer *cp, | ||
154 | GCP_PathIterator callback, | ||
155 | void *callback_cls); | ||
156 | |||
157 | |||
158 | /** | ||
159 | * Iterate over the paths to @a peer where | ||
160 | * @a peer is at distance @a dist from us. | ||
161 | * | ||
162 | * @param cp Peer to get path info. | ||
163 | * @param dist desired distance of @a peer to us on the path | ||
164 | * @param callback Function to call for every path. | ||
165 | * @param callback_cls Closure for @a callback. | ||
166 | * @return Number of iterated paths. | ||
167 | */ | ||
168 | unsigned int | ||
169 | GCP_iterate_paths_at (struct CadetPeer *cp, | ||
170 | unsigned int dist, | ||
171 | GCP_PathIterator callback, | ||
172 | void *callback_cls); | ||
173 | |||
174 | |||
175 | /** | ||
176 | * Remove an entry from the DLL of all of the paths that this peer is on. | ||
177 | * | ||
178 | * @param cp peer to modify | ||
179 | * @param entry an entry on a path | ||
180 | * @param off offset of this peer on the path | ||
181 | */ | ||
182 | void | ||
183 | GCP_path_entry_remove (struct CadetPeer *cp, | ||
184 | struct CadetPeerPathEntry *entry, | ||
185 | unsigned int off); | ||
186 | |||
187 | |||
188 | /** | ||
189 | * Add an entry to the DLL of all of the paths that this peer is on. | ||
190 | * | ||
191 | * @param cp peer to modify | ||
192 | * @param entry an entry on a path | ||
193 | * @param off offset of this peer on the path | ||
194 | */ | ||
195 | void | ||
196 | GCP_path_entry_add (struct CadetPeer *cp, | ||
197 | struct CadetPeerPathEntry *entry, | ||
198 | unsigned int off); | ||
199 | |||
200 | |||
201 | /** | ||
202 | * Get the tunnel towards a peer. | ||
203 | * | ||
204 | * @param cp Peer to get from. | ||
205 | * @param create #GNUNET_YES to create a tunnel if we do not have one | ||
206 | * @return Tunnel towards peer. | ||
207 | */ | ||
208 | struct CadetTunnel * | ||
209 | GCP_get_tunnel (struct CadetPeer *cp, | ||
210 | int create); | ||
211 | |||
212 | |||
213 | /** | ||
214 | * The tunnel to the given peer no longer exists, remove it from our | ||
215 | * data structures, and possibly clean up the peer itself. | ||
216 | * | ||
217 | * @param cp the peer affected | ||
218 | * @param t the dead tunnel | ||
219 | */ | ||
220 | void | ||
221 | GCP_drop_tunnel (struct CadetPeer *cp, | ||
222 | struct CadetTunnel *t); | ||
223 | |||
224 | |||
225 | /** | ||
226 | * Try adding a @a path to this @a cp. If the peer already | ||
227 | * has plenty of paths, return NULL. | ||
228 | * | ||
229 | * @param cp peer to which the @a path leads to | ||
230 | * @param path a path looking for an owner; may not be fully initialized yet! | ||
231 | * @param off offset of @a cp in @a path | ||
232 | * @param force for attaching the path | ||
233 | * @return NULL if this peer does not care to become a new owner, | ||
234 | * otherwise the node in the peer's path heap for the @a path. | ||
235 | */ | ||
236 | struct GNUNET_CONTAINER_HeapNode * | ||
237 | GCP_attach_path (struct CadetPeer *cp, | ||
238 | struct CadetPeerPath *path, | ||
239 | unsigned int off, | ||
240 | int force); | ||
241 | |||
242 | |||
243 | /** | ||
244 | * This peer can no longer own @a path as the path | ||
245 | * has been extended and a peer further down the line | ||
246 | * is now the new owner. | ||
247 | * | ||
248 | * @param cp old owner of the @a path | ||
249 | * @param path path where the ownership is lost | ||
250 | * @param hn note in @a cp's path heap that must be deleted | ||
251 | */ | ||
252 | void | ||
253 | GCP_detach_path (struct CadetPeer *cp, | ||
254 | struct CadetPeerPath *path, | ||
255 | struct GNUNET_CONTAINER_HeapNode *hn); | ||
256 | |||
257 | |||
258 | /** | ||
259 | * Add a @a connection to this @a cp. | ||
260 | * | ||
261 | * @param cp peer via which the @a connection goes | ||
262 | * @param cc the connection to add | ||
263 | */ | ||
264 | void | ||
265 | GCP_add_connection (struct CadetPeer *cp, | ||
266 | struct CadetConnection *cc); | ||
267 | |||
268 | |||
269 | /** | ||
270 | * Remove a @a connection that went via this @a cp. | ||
271 | * | ||
272 | * @param cp peer via which the @a connection went | ||
273 | * @param cc the connection to remove | ||
274 | */ | ||
275 | void | ||
276 | GCP_remove_connection (struct CadetPeer *cp, | ||
277 | struct CadetConnection *cc); | ||
278 | |||
279 | |||
280 | /** | ||
281 | * We got a HELLO for a @a cp, remember it, and possibly | ||
282 | * trigger adequate actions (like trying to connect). | ||
283 | * | ||
284 | * @param cp the peer we got a HELLO for | ||
285 | * @param hello the HELLO to remember | ||
286 | */ | ||
287 | void | ||
288 | GCP_set_hello (struct CadetPeer *cp, | ||
289 | const struct GNUNET_HELLO_Message *hello); | ||
290 | |||
291 | |||
292 | /** | ||
293 | * Clean up all entries about all peers. | ||
294 | * Must only be called after all tunnels, CORE-connections and | ||
295 | * connections are down. | ||
296 | */ | ||
297 | void | ||
298 | GCP_destroy_all_peers (void); | ||
299 | |||
300 | |||
301 | /** | ||
302 | * Data structure used to track whom we have to notify about changes | ||
303 | * in our ability to transmit to a given peer. | ||
304 | * | ||
305 | * All queue managers will be given equal chance for sending messages | ||
306 | * to @a cp. This construct this guarantees fairness for access to @a | ||
307 | * cp among the different message queues. Each connection or route | ||
308 | * will have its respective message queue managers for each direction. | ||
309 | */ | ||
310 | struct GCP_MessageQueueManager; | ||
311 | |||
312 | |||
313 | /** | ||
314 | * Function to call with updated message queue object. | ||
315 | * | ||
316 | * @param cls closure | ||
317 | * @param available #GNUNET_YES if sending is now possible, | ||
318 | * #GNUNET_NO if sending is no longer possible | ||
319 | * #GNUNET_SYSERR if sending is no longer possible | ||
320 | * and the last envelope was discarded | ||
321 | */ | ||
322 | typedef void | ||
323 | (*GCP_MessageQueueNotificationCallback)(void *cls, | ||
324 | int available); | ||
325 | |||
326 | |||
327 | /** | ||
328 | * Start message queue change notifications. Will create a new slot | ||
329 | * to manage the message queue to the given @a cp. | ||
330 | * | ||
331 | * @param cp peer to notify for | ||
332 | * @param cb function to call if mq becomes available or unavailable | ||
333 | * @param cb_cls closure for @a cb | ||
334 | * @return handle to cancel request | ||
335 | */ | ||
336 | struct GCP_MessageQueueManager * | ||
337 | GCP_request_mq (struct CadetPeer *cp, | ||
338 | GCP_MessageQueueNotificationCallback cb, | ||
339 | void *cb_cls); | ||
340 | |||
341 | |||
342 | /** | ||
343 | * Test if @a cp has a core-level connection | ||
344 | * | ||
345 | * @param cp peer to test | ||
346 | * @return #GNUNET_YES if @a cp has a core-level connection | ||
347 | */ | ||
348 | int | ||
349 | GCP_has_core_connection (struct CadetPeer *cp); | ||
350 | |||
351 | |||
352 | /** | ||
353 | * Send the message in @a env via a @a mqm. Must only be called at | ||
354 | * most once after the respective | ||
355 | * #GCP_MessageQueueNotificationCallback was called with `available` | ||
356 | * set to #GNUNET_YES, and not after the callback was called with | ||
357 | * `available` set to #GNUNET_NO or #GNUNET_SYSERR. | ||
358 | * | ||
359 | * @param mqm message queue manager for the transmission | ||
360 | * @param env envelope with the message to send; must NOT | ||
361 | * yet have a #GNUNET_MQ_notify_sent() callback attached to it | ||
362 | */ | ||
363 | void | ||
364 | GCP_send (struct GCP_MessageQueueManager *mqm, | ||
365 | struct GNUNET_MQ_Envelope *env); | ||
366 | |||
367 | |||
368 | /** | ||
369 | * Send the message in @a env to @a cp, overriding queueing logic. | ||
370 | * This function should only be used to send error messages outside | ||
371 | * of flow and congestion control, similar to ICMP. Note that | ||
372 | * the envelope may be silently discarded as well. | ||
373 | * | ||
374 | * @param cp peer to send the message to | ||
375 | * @param env envelope with the message to send | ||
376 | */ | ||
377 | void | ||
378 | GCP_send_ooo (struct CadetPeer *cp, | ||
379 | struct GNUNET_MQ_Envelope *env); | ||
380 | |||
381 | |||
382 | /** | ||
383 | * Stops message queue change notifications and sends a last message. | ||
384 | * In practice, this is implemented by sending that @a last_env | ||
385 | * message immediately (if any), ignoring queue order. | ||
386 | * | ||
387 | * @param mqm handle matching request to cancel | ||
388 | * @param last_env final message to transmit, or NULL | ||
389 | */ | ||
390 | void | ||
391 | GCP_request_mq_cancel (struct GCP_MessageQueueManager *mqm, | ||
392 | struct GNUNET_MQ_Envelope *last_env); | ||
393 | |||
394 | |||
395 | /** | ||
396 | * Set the message queue to @a mq for peer @a cp and notify watchers. | ||
397 | * | ||
398 | * @param cp peer to modify | ||
399 | * @param mq message queue to set (can be NULL) | ||
400 | */ | ||
401 | void | ||
402 | GCP_set_mq (struct CadetPeer *cp, | ||
403 | struct GNUNET_MQ_Handle *mq); | ||
404 | |||
405 | /** | ||
406 | * Checking the signature for a monotime of a GNUNET_CADET_ConnectionCreateMessage. | ||
407 | * | ||
408 | * @param peer The peer that signed the monotime value. | ||
409 | * @param msg The GNUNET_CADET_ConnectionCreateMessage with the monotime value. | ||
410 | * @return GNUNET_OK if the signature is good, GNUNET_SYSERR if not. | ||
411 | */ | ||
412 | int | ||
413 | GCP_check_monotime_sig (struct CadetPeer *peer, const struct | ||
414 | GNUNET_CADET_ConnectionCreateMessage *msg); | ||
415 | |||
416 | /** | ||
417 | * Checking if a monotime value is newer than the last monotime value received from a peer. If the time value is newer it will be stored at the peer. | ||
418 | * | ||
419 | * @param peer The peer we received a new time value from. | ||
420 | * @param monotime Time value we check against the last time value we received from a peer. | ||
421 | * @return GNUNET_YES if monotime is newer than the last received time value, GNUNET_NO if monotime is not newer. | ||
422 | */ | ||
423 | int | ||
424 | GCP_check_and_update_monotime (struct CadetPeer *peer, | ||
425 | struct GNUNET_TIME_AbsoluteNBO monotime); | ||
426 | |||
427 | #endif | ||
diff --git a/src/cadet/gnunet-service-cadet_tunnels.c b/src/cadet/gnunet-service-cadet_tunnels.c deleted file mode 100644 index cabbeed0c..000000000 --- a/src/cadet/gnunet-service-cadet_tunnels.c +++ /dev/null | |||
@@ -1,3728 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2013, 2017, 2018 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file cadet/gnunet-service-cadet_tunnels.c | ||
22 | * @brief Information we track per tunnel. | ||
23 | * @author Bartlomiej Polot | ||
24 | * @author Christian Grothoff | ||
25 | * | ||
26 | * FIXME: | ||
27 | * - proper connection evaluation during connection management: | ||
28 | * + consider quality (or quality spread?) of current connection set | ||
29 | * when deciding how often to do maintenance | ||
30 | * + interact with PEER to drive DHT GET/PUT operations based | ||
31 | * on how much we like our connections | ||
32 | */ | ||
33 | #include "platform.h" | ||
34 | #include "gnunet_util_lib.h" | ||
35 | #include "gnunet_statistics_service.h" | ||
36 | #include "gnunet_signatures.h" | ||
37 | #include "cadet_protocol.h" | ||
38 | #include "gnunet-service-cadet_channel.h" | ||
39 | #include "gnunet-service-cadet_connection.h" | ||
40 | #include "gnunet-service-cadet_tunnels.h" | ||
41 | #include "gnunet-service-cadet_peer.h" | ||
42 | #include "gnunet-service-cadet_paths.h" | ||
43 | |||
44 | |||
45 | #define LOG(level, ...) GNUNET_log_from (level, "cadet-tun", __VA_ARGS__) | ||
46 | |||
47 | /** | ||
48 | * How often do we try to decrypt payload with unverified key | ||
49 | * material? Used to limit CPU increase upon receiving bogus | ||
50 | * KX. | ||
51 | */ | ||
52 | #define MAX_UNVERIFIED_ATTEMPTS 16 | ||
53 | |||
54 | /** | ||
55 | * How long do we wait until tearing down an idle tunnel? | ||
56 | */ | ||
57 | #define IDLE_DESTROY_DELAY GNUNET_TIME_relative_multiply ( \ | ||
58 | GNUNET_TIME_UNIT_SECONDS, 90) | ||
59 | |||
60 | /** | ||
61 | * How long do we wait initially before retransmitting the KX? | ||
62 | * TODO: replace by 2 RTT if/once we have connection-level RTT data! | ||
63 | */ | ||
64 | #define INITIAL_KX_RETRY_DELAY GNUNET_TIME_relative_multiply ( \ | ||
65 | GNUNET_TIME_UNIT_MILLISECONDS, 250) | ||
66 | |||
67 | /** | ||
68 | * Maximum number of skipped keys we keep in memory per tunnel. | ||
69 | */ | ||
70 | #define MAX_SKIPPED_KEYS 64 | ||
71 | |||
72 | /** | ||
73 | * Maximum number of keys (and thus ratchet steps) we are willing to | ||
74 | * skip before we decide this is either a bogus packet or a DoS-attempt. | ||
75 | */ | ||
76 | #define MAX_KEY_GAP 256 | ||
77 | |||
78 | |||
79 | /** | ||
80 | * Struct to old keys for skipped messages while advancing the Axolotl ratchet. | ||
81 | */ | ||
82 | struct 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 | */ | ||
119 | struct 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 | */ | ||
259 | struct 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 | */ | ||
302 | struct 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 | */ | ||
467 | int | ||
468 | GCT_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 | */ | ||
490 | static void | ||
491 | mark_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 | */ | ||
516 | const char * | ||
517 | GCT_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 | */ | ||
538 | static const char * | ||
539 | estate2s (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 | */ | ||
572 | struct CadetPeer * | ||
573 | GCT_get_destination (struct CadetTunnel *t) | ||
574 | { | ||
575 | return t->destination; | ||
576 | } | ||
577 | |||
578 | |||
579 | /** | ||
580 | * Count channels of a tunnel. | ||
581 | * | ||
582 | * @param t Tunnel on which to count. | ||
583 | * | ||
584 | * @return Number of channels. | ||
585 | */ | ||
586 | unsigned int | ||
587 | GCT_count_channels (struct CadetTunnel *t) | ||
588 | { | ||
589 | return GNUNET_CONTAINER_multihashmap32_size (t->channels); | ||
590 | } | ||
591 | |||
592 | |||
593 | /** | ||
594 | * Lookup a channel by its @a ctn. | ||
595 | * | ||
596 | * @param t tunnel to look in | ||
597 | * @param ctn number of channel to find | ||
598 | * @return NULL if channel does not exist | ||
599 | */ | ||
600 | struct CadetChannel * | ||
601 | lookup_channel (struct CadetTunnel *t, | ||
602 | struct GNUNET_CADET_ChannelTunnelNumber ctn) | ||
603 | { | ||
604 | return GNUNET_CONTAINER_multihashmap32_get (t->channels, | ||
605 | ntohl (ctn.cn)); | ||
606 | } | ||
607 | |||
608 | |||
609 | /** | ||
610 | * Count all created connections of a tunnel. Not necessarily ready connections! | ||
611 | * | ||
612 | * @param t Tunnel on which to count. | ||
613 | * | ||
614 | * @return Number of connections created, either being established or ready. | ||
615 | */ | ||
616 | unsigned int | ||
617 | GCT_count_any_connections (const struct CadetTunnel *t) | ||
618 | { | ||
619 | return t->num_ready_connections + t->num_busy_connections; | ||
620 | } | ||
621 | |||
622 | |||
623 | /** | ||
624 | * Find first connection that is ready in the list of | ||
625 | * our connections. Picks ready connections round-robin. | ||
626 | * | ||
627 | * @param t tunnel to search | ||
628 | * @return NULL if we have no connection that is ready | ||
629 | */ | ||
630 | static struct CadetTConnection * | ||
631 | get_ready_connection (struct CadetTunnel *t) | ||
632 | { | ||
633 | struct CadetTConnection *hd = t->connection_ready_head; | ||
634 | |||
635 | GNUNET_assert ((NULL == hd) || | ||
636 | (GNUNET_YES == hd->is_ready)); | ||
637 | return hd; | ||
638 | } | ||
639 | |||
640 | |||
641 | /** | ||
642 | * Get the encryption state of a tunnel. | ||
643 | * | ||
644 | * @param t Tunnel. | ||
645 | * | ||
646 | * @return Tunnel's encryption state. | ||
647 | */ | ||
648 | enum CadetTunnelEState | ||
649 | GCT_get_estate (struct CadetTunnel *t) | ||
650 | { | ||
651 | return t->estate; | ||
652 | } | ||
653 | |||
654 | |||
655 | /** | ||
656 | * Called when either we have a new connection, or a new message in the | ||
657 | * queue, or some existing connection has transmission capacity. Looks | ||
658 | * at our message queue and if there is a message, picks a connection | ||
659 | * to send it on. | ||
660 | * | ||
661 | * @param cls the `struct CadetTunnel` to process messages on | ||
662 | */ | ||
663 | static void | ||
664 | trigger_transmissions (void *cls); | ||
665 | |||
666 | |||
667 | /* ************************************** start core crypto ***************************** */ | ||
668 | |||
669 | |||
670 | /** | ||
671 | * Create a new Axolotl ephemeral (ratchet) key. | ||
672 | * | ||
673 | * @param ax key material to update | ||
674 | */ | ||
675 | static void | ||
676 | new_ephemeral (struct CadetTunnelAxolotl *ax) | ||
677 | { | ||
678 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
679 | "Creating new ephemeral ratchet key (DHRs)\n"); | ||
680 | GNUNET_CRYPTO_ecdhe_key_create (&ax->DHRs); | ||
681 | } | ||
682 | |||
683 | |||
684 | /** | ||
685 | * Calculate HMAC. | ||
686 | * | ||
687 | * @param plaintext Content to HMAC. | ||
688 | * @param size Size of @c plaintext. | ||
689 | * @param iv Initialization vector for the message. | ||
690 | * @param key Key to use. | ||
691 | * @param hmac[out] Destination to store the HMAC. | ||
692 | */ | ||
693 | static void | ||
694 | t_hmac (const void *plaintext, | ||
695 | size_t size, | ||
696 | uint32_t iv, | ||
697 | const struct GNUNET_CRYPTO_SymmetricSessionKey *key, | ||
698 | struct GNUNET_ShortHashCode *hmac) | ||
699 | { | ||
700 | static const char ctx[] = "cadet authentication key"; | ||
701 | struct GNUNET_CRYPTO_AuthKey auth_key; | ||
702 | struct GNUNET_HashCode hash; | ||
703 | |||
704 | GNUNET_CRYPTO_hmac_derive_key (&auth_key, | ||
705 | key, | ||
706 | &iv, sizeof(iv), | ||
707 | key, sizeof(*key), | ||
708 | ctx, sizeof(ctx), | ||
709 | NULL); | ||
710 | /* Two step: GNUNET_ShortHash is only 256 bits, | ||
711 | GNUNET_HashCode is 512, so we truncate. */ | ||
712 | GNUNET_CRYPTO_hmac (&auth_key, | ||
713 | plaintext, | ||
714 | size, | ||
715 | &hash); | ||
716 | GNUNET_memcpy (hmac, | ||
717 | &hash, | ||
718 | sizeof(*hmac)); | ||
719 | } | ||
720 | |||
721 | |||
722 | /** | ||
723 | * Perform a HMAC. | ||
724 | * | ||
725 | * @param key Key to use. | ||
726 | * @param[out] hash Resulting HMAC. | ||
727 | * @param source Source key material (data to HMAC). | ||
728 | * @param len Length of @a source. | ||
729 | */ | ||
730 | static void | ||
731 | t_ax_hmac_hash (const struct GNUNET_CRYPTO_SymmetricSessionKey *key, | ||
732 | struct GNUNET_HashCode *hash, | ||
733 | const void *source, | ||
734 | unsigned int len) | ||
735 | { | ||
736 | static const char ctx[] = "axolotl HMAC-HASH"; | ||
737 | struct GNUNET_CRYPTO_AuthKey auth_key; | ||
738 | |||
739 | GNUNET_CRYPTO_hmac_derive_key (&auth_key, | ||
740 | key, | ||
741 | ctx, sizeof(ctx), | ||
742 | NULL); | ||
743 | GNUNET_CRYPTO_hmac (&auth_key, | ||
744 | source, | ||
745 | len, | ||
746 | hash); | ||
747 | } | ||
748 | |||
749 | |||
750 | /** | ||
751 | * Derive a symmetric encryption key from an HMAC-HASH. | ||
752 | * | ||
753 | * @param key Key to use for the HMAC. | ||
754 | * @param[out] out Key to generate. | ||
755 | * @param source Source key material (data to HMAC). | ||
756 | * @param len Length of @a source. | ||
757 | */ | ||
758 | static void | ||
759 | t_hmac_derive_key (const struct GNUNET_CRYPTO_SymmetricSessionKey *key, | ||
760 | struct GNUNET_CRYPTO_SymmetricSessionKey *out, | ||
761 | const void *source, | ||
762 | unsigned int len) | ||
763 | { | ||
764 | static const char ctx[] = "axolotl derive key"; | ||
765 | struct GNUNET_HashCode h; | ||
766 | |||
767 | t_ax_hmac_hash (key, | ||
768 | &h, | ||
769 | source, | ||
770 | len); | ||
771 | GNUNET_CRYPTO_kdf (out, sizeof(*out), | ||
772 | ctx, sizeof(ctx), | ||
773 | &h, sizeof(h), | ||
774 | NULL); | ||
775 | } | ||
776 | |||
777 | |||
778 | /** | ||
779 | * Encrypt data with the axolotl tunnel key. | ||
780 | * | ||
781 | * @param ax key material to use. | ||
782 | * @param dst Destination with @a size bytes for the encrypted data. | ||
783 | * @param src Source of the plaintext. Can overlap with @c dst, must contain @a size bytes | ||
784 | * @param size Size of the buffers at @a src and @a dst | ||
785 | */ | ||
786 | static void | ||
787 | t_ax_encrypt (struct CadetTunnelAxolotl *ax, | ||
788 | void *dst, | ||
789 | const void *src, | ||
790 | size_t size) | ||
791 | { | ||
792 | struct GNUNET_CRYPTO_SymmetricSessionKey MK; | ||
793 | struct GNUNET_CRYPTO_SymmetricInitializationVector iv; | ||
794 | size_t out_size; | ||
795 | |||
796 | ax->ratchet_counter++; | ||
797 | if ((GNUNET_YES == ax->ratchet_allowed) && | ||
798 | ((ratchet_messages <= ax->ratchet_counter) || | ||
799 | (0 == GNUNET_TIME_absolute_get_remaining ( | ||
800 | ax->ratchet_expiration).rel_value_us))) | ||
801 | { | ||
802 | ax->ratchet_flag = GNUNET_YES; | ||
803 | } | ||
804 | if (GNUNET_YES == ax->ratchet_flag) | ||
805 | { | ||
806 | /* Advance ratchet */ | ||
807 | struct GNUNET_CRYPTO_SymmetricSessionKey keys[3]; | ||
808 | struct GNUNET_HashCode dh; | ||
809 | struct GNUNET_HashCode hmac; | ||
810 | static const char ctx[] = "axolotl ratchet"; | ||
811 | |||
812 | new_ephemeral (ax); | ||
813 | ax->HKs = ax->NHKs; | ||
814 | |||
815 | /* RK, NHKs, CKs = KDF( HMAC-HASH(RK, DH(DHRs, DHRr)) ) */ | ||
816 | GNUNET_CRYPTO_ecc_ecdh (&ax->DHRs, | ||
817 | &ax->DHRr, | ||
818 | &dh); | ||
819 | t_ax_hmac_hash (&ax->RK, | ||
820 | &hmac, | ||
821 | &dh, | ||
822 | sizeof(dh)); | ||
823 | GNUNET_CRYPTO_kdf (keys, sizeof(keys), | ||
824 | ctx, sizeof(ctx), | ||
825 | &hmac, sizeof(hmac), | ||
826 | NULL); | ||
827 | ax->RK = keys[0]; | ||
828 | ax->NHKs = keys[1]; | ||
829 | ax->CKs = keys[2]; | ||
830 | |||
831 | ax->PNs = ax->Ns; | ||
832 | ax->Ns = 0; | ||
833 | ax->ratchet_flag = GNUNET_NO; | ||
834 | ax->ratchet_allowed = GNUNET_NO; | ||
835 | ax->ratchet_counter = 0; | ||
836 | ax->ratchet_expiration | ||
837 | = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), | ||
838 | ratchet_time); | ||
839 | } | ||
840 | |||
841 | t_hmac_derive_key (&ax->CKs, | ||
842 | &MK, | ||
843 | "0", | ||
844 | 1); | ||
845 | GNUNET_CRYPTO_symmetric_derive_iv (&iv, | ||
846 | &MK, | ||
847 | NULL, 0, | ||
848 | NULL); | ||
849 | |||
850 | out_size = GNUNET_CRYPTO_symmetric_encrypt (src, | ||
851 | size, | ||
852 | &MK, | ||
853 | &iv, | ||
854 | dst); | ||
855 | GNUNET_assert (size == out_size); | ||
856 | t_hmac_derive_key (&ax->CKs, | ||
857 | &ax->CKs, | ||
858 | "1", | ||
859 | 1); | ||
860 | } | ||
861 | |||
862 | |||
863 | /** | ||
864 | * Decrypt data with the axolotl tunnel key. | ||
865 | * | ||
866 | * @param ax key material to use. | ||
867 | * @param dst Destination for the decrypted data, must contain @a size bytes. | ||
868 | * @param src Source of the ciphertext. Can overlap with @c dst, must contain @a size bytes. | ||
869 | * @param size Size of the @a src and @a dst buffers | ||
870 | */ | ||
871 | static void | ||
872 | t_ax_decrypt (struct CadetTunnelAxolotl *ax, | ||
873 | void *dst, | ||
874 | const void *src, | ||
875 | size_t size) | ||
876 | { | ||
877 | struct GNUNET_CRYPTO_SymmetricSessionKey MK; | ||
878 | struct GNUNET_CRYPTO_SymmetricInitializationVector iv; | ||
879 | size_t out_size; | ||
880 | |||
881 | t_hmac_derive_key (&ax->CKr, | ||
882 | &MK, | ||
883 | "0", | ||
884 | 1); | ||
885 | GNUNET_CRYPTO_symmetric_derive_iv (&iv, | ||
886 | &MK, | ||
887 | NULL, 0, | ||
888 | NULL); | ||
889 | GNUNET_assert (size >= sizeof(struct GNUNET_MessageHeader)); | ||
890 | out_size = GNUNET_CRYPTO_symmetric_decrypt (src, | ||
891 | size, | ||
892 | &MK, | ||
893 | &iv, | ||
894 | dst); | ||
895 | GNUNET_assert (out_size == size); | ||
896 | t_hmac_derive_key (&ax->CKr, | ||
897 | &ax->CKr, | ||
898 | "1", | ||
899 | 1); | ||
900 | } | ||
901 | |||
902 | |||
903 | /** | ||
904 | * Encrypt header with the axolotl header key. | ||
905 | * | ||
906 | * @param ax key material to use. | ||
907 | * @param[in|out] msg Message whose header to encrypt. | ||
908 | */ | ||
909 | static void | ||
910 | t_h_encrypt (struct CadetTunnelAxolotl *ax, | ||
911 | struct GNUNET_CADET_TunnelEncryptedMessage *msg) | ||
912 | { | ||
913 | struct GNUNET_CRYPTO_SymmetricInitializationVector iv; | ||
914 | size_t out_size; | ||
915 | |||
916 | GNUNET_CRYPTO_symmetric_derive_iv (&iv, | ||
917 | &ax->HKs, | ||
918 | NULL, 0, | ||
919 | NULL); | ||
920 | out_size = GNUNET_CRYPTO_symmetric_encrypt (&msg->ax_header, | ||
921 | sizeof(struct | ||
922 | GNUNET_CADET_AxHeader), | ||
923 | &ax->HKs, | ||
924 | &iv, | ||
925 | &msg->ax_header); | ||
926 | GNUNET_assert (sizeof(struct GNUNET_CADET_AxHeader) == out_size); | ||
927 | } | ||
928 | |||
929 | |||
930 | /** | ||
931 | * Decrypt header with the current axolotl header key. | ||
932 | * | ||
933 | * @param ax key material to use. | ||
934 | * @param src Message whose header to decrypt. | ||
935 | * @param dst Where to decrypt header to. | ||
936 | */ | ||
937 | static void | ||
938 | t_h_decrypt (struct CadetTunnelAxolotl *ax, | ||
939 | const struct GNUNET_CADET_TunnelEncryptedMessage *src, | ||
940 | struct GNUNET_CADET_TunnelEncryptedMessage *dst) | ||
941 | { | ||
942 | struct GNUNET_CRYPTO_SymmetricInitializationVector iv; | ||
943 | size_t out_size; | ||
944 | |||
945 | GNUNET_CRYPTO_symmetric_derive_iv (&iv, | ||
946 | &ax->HKr, | ||
947 | NULL, 0, | ||
948 | NULL); | ||
949 | out_size = GNUNET_CRYPTO_symmetric_decrypt (&src->ax_header.Ns, | ||
950 | sizeof(struct | ||
951 | GNUNET_CADET_AxHeader), | ||
952 | &ax->HKr, | ||
953 | &iv, | ||
954 | &dst->ax_header.Ns); | ||
955 | GNUNET_assert (sizeof(struct GNUNET_CADET_AxHeader) == out_size); | ||
956 | } | ||
957 | |||
958 | |||
959 | /** | ||
960 | * Delete a key from the list of skipped keys. | ||
961 | * | ||
962 | * @param ax key material to delete @a key from. | ||
963 | * @param key Key to delete. | ||
964 | */ | ||
965 | static void | ||
966 | delete_skipped_key (struct CadetTunnelAxolotl *ax, | ||
967 | struct CadetTunnelSkippedKey *key) | ||
968 | { | ||
969 | GNUNET_CONTAINER_DLL_remove (ax->skipped_head, | ||
970 | ax->skipped_tail, | ||
971 | key); | ||
972 | GNUNET_free (key); | ||
973 | ax->skipped--; | ||
974 | } | ||
975 | |||
976 | |||
977 | /** | ||
978 | * Decrypt and verify data with the appropriate tunnel key and verify that the | ||
979 | * data has not been altered since it was sent by the remote peer. | ||
980 | * | ||
981 | * @param ax key material to use. | ||
982 | * @param dst Destination for the plaintext. | ||
983 | * @param src Source of the message. Can overlap with @c dst. | ||
984 | * @param size Size of the message. | ||
985 | * @return Size of the decrypted data, -1 if an error was encountered. | ||
986 | */ | ||
987 | static ssize_t | ||
988 | try_old_ax_keys (struct CadetTunnelAxolotl *ax, | ||
989 | void *dst, | ||
990 | const struct GNUNET_CADET_TunnelEncryptedMessage *src, | ||
991 | size_t size) | ||
992 | { | ||
993 | struct CadetTunnelSkippedKey *key; | ||
994 | struct GNUNET_ShortHashCode *hmac; | ||
995 | struct GNUNET_CRYPTO_SymmetricInitializationVector iv; | ||
996 | struct GNUNET_CADET_TunnelEncryptedMessage plaintext_header; | ||
997 | struct GNUNET_CRYPTO_SymmetricSessionKey *valid_HK; | ||
998 | size_t esize; | ||
999 | size_t res; | ||
1000 | size_t len; | ||
1001 | unsigned int N; | ||
1002 | |||
1003 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1004 | "Trying skipped keys\n"); | ||
1005 | hmac = &plaintext_header.hmac; | ||
1006 | esize = size - sizeof(struct GNUNET_CADET_TunnelEncryptedMessage); | ||
1007 | |||
1008 | /* Find a correct Header Key */ | ||
1009 | valid_HK = NULL; | ||
1010 | for (key = ax->skipped_head; NULL != key; key = key->next) | ||
1011 | { | ||
1012 | t_hmac (&src->ax_header, | ||
1013 | sizeof(struct GNUNET_CADET_AxHeader) + esize, | ||
1014 | 0, | ||
1015 | &key->HK, | ||
1016 | hmac); | ||
1017 | if (0 == GNUNET_memcmp (hmac, | ||
1018 | &src->hmac)) | ||
1019 | { | ||
1020 | valid_HK = &key->HK; | ||
1021 | break; | ||
1022 | } | ||
1023 | } | ||
1024 | if (NULL == key) | ||
1025 | return -1; | ||
1026 | |||
1027 | /* Should've been checked in -cadet_connection.c handle_cadet_encrypted. */ | ||
1028 | GNUNET_assert (size > sizeof(struct GNUNET_CADET_TunnelEncryptedMessage)); | ||
1029 | len = size - sizeof(struct GNUNET_CADET_TunnelEncryptedMessage); | ||
1030 | GNUNET_assert (len >= sizeof(struct GNUNET_MessageHeader)); | ||
1031 | |||
1032 | /* Decrypt header */ | ||
1033 | GNUNET_CRYPTO_symmetric_derive_iv (&iv, | ||
1034 | &key->HK, | ||
1035 | NULL, 0, | ||
1036 | NULL); | ||
1037 | res = GNUNET_CRYPTO_symmetric_decrypt (&src->ax_header.Ns, | ||
1038 | sizeof(struct GNUNET_CADET_AxHeader), | ||
1039 | &key->HK, | ||
1040 | &iv, | ||
1041 | &plaintext_header.ax_header.Ns); | ||
1042 | GNUNET_assert (sizeof(struct GNUNET_CADET_AxHeader) == res); | ||
1043 | |||
1044 | /* Find the correct message key */ | ||
1045 | N = ntohl (plaintext_header.ax_header.Ns); | ||
1046 | while ((NULL != key) && | ||
1047 | (N != key->Kn)) | ||
1048 | key = key->next; | ||
1049 | if ((NULL == key) || | ||
1050 | (0 != GNUNET_memcmp (&key->HK, | ||
1051 | valid_HK))) | ||
1052 | return -1; | ||
1053 | |||
1054 | /* Decrypt payload */ | ||
1055 | GNUNET_CRYPTO_symmetric_derive_iv (&iv, | ||
1056 | &key->MK, | ||
1057 | NULL, | ||
1058 | 0, | ||
1059 | NULL); | ||
1060 | res = GNUNET_CRYPTO_symmetric_decrypt (&src[1], | ||
1061 | len, | ||
1062 | &key->MK, | ||
1063 | &iv, | ||
1064 | dst); | ||
1065 | delete_skipped_key (ax, | ||
1066 | key); | ||
1067 | return res; | ||
1068 | } | ||
1069 | |||
1070 | |||
1071 | /** | ||
1072 | * Delete a key from the list of skipped keys. | ||
1073 | * | ||
1074 | * @param ax key material to delete from. | ||
1075 | * @param HKr Header Key to use. | ||
1076 | */ | ||
1077 | static void | ||
1078 | store_skipped_key (struct CadetTunnelAxolotl *ax, | ||
1079 | const struct GNUNET_CRYPTO_SymmetricSessionKey *HKr) | ||
1080 | { | ||
1081 | struct CadetTunnelSkippedKey *key; | ||
1082 | |||
1083 | key = GNUNET_new (struct CadetTunnelSkippedKey); | ||
1084 | key->timestamp = GNUNET_TIME_absolute_get (); | ||
1085 | key->Kn = ax->Nr; | ||
1086 | key->HK = ax->HKr; | ||
1087 | t_hmac_derive_key (&ax->CKr, | ||
1088 | &key->MK, | ||
1089 | "0", | ||
1090 | 1); | ||
1091 | t_hmac_derive_key (&ax->CKr, | ||
1092 | &ax->CKr, | ||
1093 | "1", | ||
1094 | 1); | ||
1095 | GNUNET_CONTAINER_DLL_insert (ax->skipped_head, | ||
1096 | ax->skipped_tail, | ||
1097 | key); | ||
1098 | ax->skipped++; | ||
1099 | ax->Nr++; | ||
1100 | } | ||
1101 | |||
1102 | |||
1103 | /** | ||
1104 | * Stage skipped AX keys and calculate the message key. | ||
1105 | * Stores each HK and MK for skipped messages. | ||
1106 | * | ||
1107 | * @param ax key material to use | ||
1108 | * @param HKr Header key. | ||
1109 | * @param Np Received meesage number. | ||
1110 | * @return #GNUNET_OK if keys were stored. | ||
1111 | * #GNUNET_SYSERR if an error occurred (@a Np not expected). | ||
1112 | */ | ||
1113 | static int | ||
1114 | store_ax_keys (struct CadetTunnelAxolotl *ax, | ||
1115 | const struct GNUNET_CRYPTO_SymmetricSessionKey *HKr, | ||
1116 | uint32_t Np) | ||
1117 | { | ||
1118 | int gap; | ||
1119 | |||
1120 | gap = Np - ax->Nr; | ||
1121 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1122 | "Storing skipped keys [%u, %u)\n", | ||
1123 | ax->Nr, | ||
1124 | Np); | ||
1125 | if (MAX_KEY_GAP < gap) | ||
1126 | { | ||
1127 | /* Avoid DoS (forcing peer to do more than #MAX_KEY_GAP HMAC operations) */ | ||
1128 | /* TODO: start new key exchange on return */ | ||
1129 | GNUNET_break_op (0); | ||
1130 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1131 | "Got message %u, expected %u+\n", | ||
1132 | Np, | ||
1133 | ax->Nr); | ||
1134 | return GNUNET_SYSERR; | ||
1135 | } | ||
1136 | if (0 > gap) | ||
1137 | { | ||
1138 | /* Delayed message: don't store keys, flag to try old keys. */ | ||
1139 | return GNUNET_SYSERR; | ||
1140 | } | ||
1141 | |||
1142 | while (ax->Nr < Np) | ||
1143 | store_skipped_key (ax, | ||
1144 | HKr); | ||
1145 | |||
1146 | while (ax->skipped > MAX_SKIPPED_KEYS) | ||
1147 | delete_skipped_key (ax, | ||
1148 | ax->skipped_tail); | ||
1149 | return GNUNET_OK; | ||
1150 | } | ||
1151 | |||
1152 | |||
1153 | /** | ||
1154 | * Decrypt and verify data with the appropriate tunnel key and verify that the | ||
1155 | * data has not been altered since it was sent by the remote peer. | ||
1156 | * | ||
1157 | * @param ax key material to use | ||
1158 | * @param dst Destination for the plaintext. | ||
1159 | * @param src Source of the message. Can overlap with @c dst. | ||
1160 | * @param size Size of the message. | ||
1161 | * @return Size of the decrypted data, -1 if an error was encountered. | ||
1162 | */ | ||
1163 | static ssize_t | ||
1164 | t_ax_decrypt_and_validate (struct CadetTunnelAxolotl *ax, | ||
1165 | void *dst, | ||
1166 | const struct | ||
1167 | GNUNET_CADET_TunnelEncryptedMessage *src, | ||
1168 | size_t size) | ||
1169 | { | ||
1170 | struct GNUNET_ShortHashCode msg_hmac; | ||
1171 | struct GNUNET_HashCode hmac; | ||
1172 | struct GNUNET_CADET_TunnelEncryptedMessage plaintext_header; | ||
1173 | uint32_t Np; | ||
1174 | uint32_t PNp; | ||
1175 | size_t esize; /* Size of encryped payload */ | ||
1176 | |||
1177 | esize = size - sizeof(struct GNUNET_CADET_TunnelEncryptedMessage); | ||
1178 | |||
1179 | /* Try current HK */ | ||
1180 | t_hmac (&src->ax_header, | ||
1181 | sizeof(struct GNUNET_CADET_AxHeader) + esize, | ||
1182 | 0, &ax->HKr, | ||
1183 | &msg_hmac); | ||
1184 | if (0 != GNUNET_memcmp (&msg_hmac, | ||
1185 | &src->hmac)) | ||
1186 | { | ||
1187 | static const char ctx[] = "axolotl ratchet"; | ||
1188 | struct GNUNET_CRYPTO_SymmetricSessionKey keys[3]; /* RKp, NHKp, CKp */ | ||
1189 | struct GNUNET_CRYPTO_SymmetricSessionKey HK; | ||
1190 | struct GNUNET_HashCode dh; | ||
1191 | struct GNUNET_CRYPTO_EcdhePublicKey *DHRp; | ||
1192 | |||
1193 | /* Try Next HK */ | ||
1194 | t_hmac (&src->ax_header, | ||
1195 | sizeof(struct GNUNET_CADET_AxHeader) + esize, | ||
1196 | 0, | ||
1197 | &ax->NHKr, | ||
1198 | &msg_hmac); | ||
1199 | if (0 != GNUNET_memcmp (&msg_hmac, | ||
1200 | &src->hmac)) | ||
1201 | { | ||
1202 | /* Try the skipped keys, if that fails, we're out of luck. */ | ||
1203 | return try_old_ax_keys (ax, | ||
1204 | dst, | ||
1205 | src, | ||
1206 | size); | ||
1207 | } | ||
1208 | HK = ax->HKr; | ||
1209 | ax->HKr = ax->NHKr; | ||
1210 | t_h_decrypt (ax, | ||
1211 | src, | ||
1212 | &plaintext_header); | ||
1213 | Np = ntohl (plaintext_header.ax_header.Ns); | ||
1214 | PNp = ntohl (plaintext_header.ax_header.PNs); | ||
1215 | DHRp = &plaintext_header.ax_header.DHRs; | ||
1216 | store_ax_keys (ax, | ||
1217 | &HK, | ||
1218 | PNp); | ||
1219 | |||
1220 | /* RKp, NHKp, CKp = KDF (HMAC-HASH (RK, DH (DHRp, DHRs))) */ | ||
1221 | GNUNET_CRYPTO_ecc_ecdh (&ax->DHRs, | ||
1222 | DHRp, | ||
1223 | &dh); | ||
1224 | t_ax_hmac_hash (&ax->RK, | ||
1225 | &hmac, | ||
1226 | &dh, sizeof(dh)); | ||
1227 | GNUNET_CRYPTO_kdf (keys, sizeof(keys), | ||
1228 | ctx, sizeof(ctx), | ||
1229 | &hmac, sizeof(hmac), | ||
1230 | NULL); | ||
1231 | |||
1232 | /* Commit "purported" keys */ | ||
1233 | ax->RK = keys[0]; | ||
1234 | ax->NHKr = keys[1]; | ||
1235 | ax->CKr = keys[2]; | ||
1236 | ax->DHRr = *DHRp; | ||
1237 | ax->Nr = 0; | ||
1238 | ax->ratchet_allowed = GNUNET_YES; | ||
1239 | } | ||
1240 | else | ||
1241 | { | ||
1242 | t_h_decrypt (ax, | ||
1243 | src, | ||
1244 | &plaintext_header); | ||
1245 | Np = ntohl (plaintext_header.ax_header.Ns); | ||
1246 | PNp = ntohl (plaintext_header.ax_header.PNs); | ||
1247 | } | ||
1248 | if ((Np != ax->Nr) && | ||
1249 | (GNUNET_OK != store_ax_keys (ax, | ||
1250 | &ax->HKr, | ||
1251 | Np))) | ||
1252 | { | ||
1253 | /* Try the skipped keys, if that fails, we're out of luck. */ | ||
1254 | return try_old_ax_keys (ax, | ||
1255 | dst, | ||
1256 | src, | ||
1257 | size); | ||
1258 | } | ||
1259 | |||
1260 | t_ax_decrypt (ax, | ||
1261 | dst, | ||
1262 | &src[1], | ||
1263 | esize); | ||
1264 | ax->Nr = Np + 1; | ||
1265 | return esize; | ||
1266 | } | ||
1267 | |||
1268 | |||
1269 | /** | ||
1270 | * Our tunnel became ready for the first time, notify channels | ||
1271 | * that have been waiting. | ||
1272 | * | ||
1273 | * @param cls our tunnel, not used | ||
1274 | * @param key unique ID of the channel, not used | ||
1275 | * @param value the `struct CadetChannel` to notify | ||
1276 | * @return #GNUNET_OK (continue to iterate) | ||
1277 | */ | ||
1278 | static int | ||
1279 | notify_tunnel_up_cb (void *cls, | ||
1280 | uint32_t key, | ||
1281 | void *value) | ||
1282 | { | ||
1283 | struct CadetChannel *ch = value; | ||
1284 | |||
1285 | GCCH_tunnel_up (ch); | ||
1286 | return GNUNET_OK; | ||
1287 | } | ||
1288 | |||
1289 | |||
1290 | /** | ||
1291 | * Change the tunnel encryption state. | ||
1292 | * If the encryption state changes to OK, stop the rekey task. | ||
1293 | * | ||
1294 | * @param t Tunnel whose encryption state to change, or NULL. | ||
1295 | * @param state New encryption state. | ||
1296 | */ | ||
1297 | void | ||
1298 | GCT_change_estate (struct CadetTunnel *t, | ||
1299 | enum CadetTunnelEState state) | ||
1300 | { | ||
1301 | enum CadetTunnelEState old = t->estate; | ||
1302 | |||
1303 | t->estate = state; | ||
1304 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1305 | "%s estate changed from %s to %s\n", | ||
1306 | GCT_2s (t), | ||
1307 | estate2s (old), | ||
1308 | estate2s (state)); | ||
1309 | |||
1310 | if ((CADET_TUNNEL_KEY_OK != old) && | ||
1311 | (CADET_TUNNEL_KEY_OK == t->estate)) | ||
1312 | { | ||
1313 | if (NULL != t->kx_task) | ||
1314 | { | ||
1315 | GNUNET_SCHEDULER_cancel (t->kx_task); | ||
1316 | t->kx_task = NULL; | ||
1317 | } | ||
1318 | /* notify all channels that have been waiting */ | ||
1319 | GNUNET_CONTAINER_multihashmap32_iterate (t->channels, | ||
1320 | ¬ify_tunnel_up_cb, | ||
1321 | t); | ||
1322 | if (NULL != t->send_task) | ||
1323 | GNUNET_SCHEDULER_cancel (t->send_task); | ||
1324 | t->send_task = GNUNET_SCHEDULER_add_now (&trigger_transmissions, | ||
1325 | t); | ||
1326 | } | ||
1327 | } | ||
1328 | |||
1329 | |||
1330 | /** | ||
1331 | * Send a KX message. | ||
1332 | * | ||
1333 | * @param t tunnel on which to send the KX_AUTH | ||
1334 | * @param ct Tunnel and connection on which to send the KX_AUTH, NULL if | ||
1335 | * we are to find one that is ready. | ||
1336 | * @param ax axolotl key context to use | ||
1337 | */ | ||
1338 | static void | ||
1339 | send_kx (struct CadetTunnel *t, | ||
1340 | struct CadetTConnection *ct, | ||
1341 | struct CadetTunnelAxolotl *ax) | ||
1342 | { | ||
1343 | struct CadetConnection *cc; | ||
1344 | struct GNUNET_MQ_Envelope *env; | ||
1345 | struct GNUNET_CADET_TunnelKeyExchangeMessage *msg; | ||
1346 | enum GNUNET_CADET_KX_Flags flags; | ||
1347 | |||
1348 | if (GNUNET_YES != GCT_alice_or_betty (GCP_get_id (t->destination))) | ||
1349 | return; /* only Alice may send KX */ | ||
1350 | if ((NULL == ct) || | ||
1351 | (GNUNET_NO == ct->is_ready)) | ||
1352 | ct = get_ready_connection (t); | ||
1353 | if (NULL == ct) | ||
1354 | { | ||
1355 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1356 | "Wanted to send %s in state %s, but no connection is ready, deferring\n", | ||
1357 | GCT_2s (t), | ||
1358 | estate2s (t->estate)); | ||
1359 | t->next_kx_attempt = GNUNET_TIME_absolute_get (); | ||
1360 | return; | ||
1361 | } | ||
1362 | cc = ct->cc; | ||
1363 | env = GNUNET_MQ_msg (msg, | ||
1364 | GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX); | ||
1365 | flags = GNUNET_CADET_KX_FLAG_FORCE_REPLY; /* always for KX */ | ||
1366 | msg->flags = htonl (flags); | ||
1367 | msg->cid = *GCC_get_id (cc); | ||
1368 | GNUNET_CRYPTO_ecdhe_key_get_public (&ax->kx_0, | ||
1369 | &msg->ephemeral_key); | ||
1370 | #if DEBUG_KX | ||
1371 | msg->ephemeral_key_XXX = ax->kx_0; | ||
1372 | msg->private_key_XXX = *my_private_key; | ||
1373 | #endif | ||
1374 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1375 | "Sending KX message to %s with ephemeral %s on CID %s\n", | ||
1376 | GCT_2s (t), | ||
1377 | GNUNET_e2s (&msg->ephemeral_key), | ||
1378 | GNUNET_sh2s (&msg->cid.connection_of_tunnel)); | ||
1379 | GNUNET_CRYPTO_ecdhe_key_get_public (&ax->DHRs, | ||
1380 | &msg->ratchet_key); | ||
1381 | mark_connection_unready (ct); | ||
1382 | t->kx_retry_delay = GNUNET_TIME_STD_BACKOFF (t->kx_retry_delay); | ||
1383 | t->next_kx_attempt = GNUNET_TIME_relative_to_absolute (t->kx_retry_delay); | ||
1384 | if (CADET_TUNNEL_KEY_UNINITIALIZED == t->estate) | ||
1385 | GCT_change_estate (t, | ||
1386 | CADET_TUNNEL_KEY_AX_SENT); | ||
1387 | else if (CADET_TUNNEL_KEY_AX_RECV == t->estate) | ||
1388 | GCT_change_estate (t, | ||
1389 | CADET_TUNNEL_KEY_AX_SENT_AND_RECV); | ||
1390 | GCC_transmit (cc, | ||
1391 | env); | ||
1392 | GNUNET_STATISTICS_update (stats, | ||
1393 | "# KX transmitted", | ||
1394 | 1, | ||
1395 | GNUNET_NO); | ||
1396 | } | ||
1397 | |||
1398 | |||
1399 | /** | ||
1400 | * Send a KX_AUTH message. | ||
1401 | * | ||
1402 | * @param t tunnel on which to send the KX_AUTH | ||
1403 | * @param ct Tunnel and connection on which to send the KX_AUTH, NULL if | ||
1404 | * we are to find one that is ready. | ||
1405 | * @param ax axolotl key context to use | ||
1406 | * @param force_reply Force the other peer to reply with a KX_AUTH message | ||
1407 | * (set if we would like to transmit right now, but cannot) | ||
1408 | */ | ||
1409 | static void | ||
1410 | send_kx_auth (struct CadetTunnel *t, | ||
1411 | struct CadetTConnection *ct, | ||
1412 | struct CadetTunnelAxolotl *ax, | ||
1413 | int force_reply) | ||
1414 | { | ||
1415 | struct CadetConnection *cc; | ||
1416 | struct GNUNET_MQ_Envelope *env; | ||
1417 | struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg; | ||
1418 | enum GNUNET_CADET_KX_Flags flags; | ||
1419 | |||
1420 | if ((NULL == ct) || | ||
1421 | (GNUNET_NO == ct->is_ready)) | ||
1422 | ct = get_ready_connection (t); | ||
1423 | if (NULL == ct) | ||
1424 | { | ||
1425 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1426 | "Wanted to send KX_AUTH on %s, but no connection is ready, deferring\n", | ||
1427 | GCT_2s (t)); | ||
1428 | t->next_kx_attempt = GNUNET_TIME_absolute_get (); | ||
1429 | t->kx_auth_requested = GNUNET_YES; /* queue KX_AUTH independent of estate */ | ||
1430 | return; | ||
1431 | } | ||
1432 | t->kx_auth_requested = GNUNET_NO; /* clear flag */ | ||
1433 | cc = ct->cc; | ||
1434 | env = GNUNET_MQ_msg (msg, | ||
1435 | GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX_AUTH); | ||
1436 | flags = GNUNET_CADET_KX_FLAG_NONE; | ||
1437 | if (GNUNET_YES == force_reply) | ||
1438 | flags |= GNUNET_CADET_KX_FLAG_FORCE_REPLY; | ||
1439 | msg->kx.flags = htonl (flags); | ||
1440 | msg->kx.cid = *GCC_get_id (cc); | ||
1441 | GNUNET_CRYPTO_ecdhe_key_get_public (&ax->kx_0, | ||
1442 | &msg->kx.ephemeral_key); | ||
1443 | GNUNET_CRYPTO_ecdhe_key_get_public (&ax->DHRs, | ||
1444 | &msg->kx.ratchet_key); | ||
1445 | #if DEBUG_KX | ||
1446 | msg->kx.ephemeral_key_XXX = ax->kx_0; | ||
1447 | msg->kx.private_key_XXX = *my_private_key; | ||
1448 | msg->r_ephemeral_key_XXX = ax->last_ephemeral; | ||
1449 | #endif | ||
1450 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1451 | "Sending KX_AUTH message to %s with ephemeral %s on CID %s\n", | ||
1452 | GCT_2s (t), | ||
1453 | GNUNET_e2s (&msg->kx.ephemeral_key), | ||
1454 | GNUNET_sh2s (&msg->kx.cid.connection_of_tunnel)); | ||
1455 | |||
1456 | /* Compute authenticator (this is the main difference to #send_kx()) */ | ||
1457 | GNUNET_CRYPTO_hash (&ax->RK, | ||
1458 | sizeof(ax->RK), | ||
1459 | &msg->auth); | ||
1460 | /* Compute when to be triggered again; actual job will | ||
1461 | be scheduled via #connection_ready_cb() */ | ||
1462 | t->kx_retry_delay | ||
1463 | = GNUNET_TIME_STD_BACKOFF (t->kx_retry_delay); | ||
1464 | t->next_kx_attempt | ||
1465 | = GNUNET_TIME_relative_to_absolute (t->kx_retry_delay); | ||
1466 | |||
1467 | /* Send via cc, mark it as unready */ | ||
1468 | mark_connection_unready (ct); | ||
1469 | |||
1470 | /* Update state machine, unless we are already OK */ | ||
1471 | if (CADET_TUNNEL_KEY_OK != t->estate) | ||
1472 | GCT_change_estate (t, | ||
1473 | CADET_TUNNEL_KEY_AX_AUTH_SENT); | ||
1474 | GCC_transmit (cc, | ||
1475 | env); | ||
1476 | GNUNET_STATISTICS_update (stats, | ||
1477 | "# KX_AUTH transmitted", | ||
1478 | 1, | ||
1479 | GNUNET_NO); | ||
1480 | } | ||
1481 | |||
1482 | |||
1483 | /** | ||
1484 | * Cleanup state used by @a ax. | ||
1485 | * | ||
1486 | * @param ax state to free, but not memory of @a ax itself | ||
1487 | */ | ||
1488 | static void | ||
1489 | cleanup_ax (struct CadetTunnelAxolotl *ax) | ||
1490 | { | ||
1491 | while (NULL != ax->skipped_head) | ||
1492 | delete_skipped_key (ax, | ||
1493 | ax->skipped_head); | ||
1494 | GNUNET_assert (0 == ax->skipped); | ||
1495 | GNUNET_CRYPTO_ecdhe_key_clear (&ax->kx_0); | ||
1496 | GNUNET_CRYPTO_ecdhe_key_clear (&ax->DHRs); | ||
1497 | } | ||
1498 | |||
1499 | |||
1500 | /** | ||
1501 | * Update our Axolotl key state based on the KX data we received. | ||
1502 | * Computes the new chain keys, and root keys, etc, and also checks | ||
1503 | * whether this is a replay of the current chain. | ||
1504 | * | ||
1505 | * @param[in|out] axolotl chain key state to recompute | ||
1506 | * @param pid peer identity of the other peer | ||
1507 | * @param ephemeral_key ephemeral public key of the other peer | ||
1508 | * @param ratchet_key senders next ephemeral public key | ||
1509 | * @return #GNUNET_OK on success, #GNUNET_NO if the resulting | ||
1510 | * root key is already in @a ax and thus the KX is useless; | ||
1511 | * #GNUNET_SYSERR on hard errors (i.e. @a pid is #my_full_id) | ||
1512 | */ | ||
1513 | static int | ||
1514 | update_ax_by_kx (struct CadetTunnelAxolotl *ax, | ||
1515 | const struct GNUNET_PeerIdentity *pid, | ||
1516 | const struct GNUNET_CRYPTO_EcdhePublicKey *ephemeral_key, | ||
1517 | const struct GNUNET_CRYPTO_EcdhePublicKey *ratchet_key) | ||
1518 | { | ||
1519 | struct GNUNET_HashCode key_material[3]; | ||
1520 | struct GNUNET_CRYPTO_SymmetricSessionKey keys[5]; | ||
1521 | const char salt[] = "CADET Axolotl salt"; | ||
1522 | int am_I_alice; | ||
1523 | |||
1524 | if (GNUNET_SYSERR == (am_I_alice = GCT_alice_or_betty (pid))) | ||
1525 | { | ||
1526 | GNUNET_break_op (0); | ||
1527 | return GNUNET_SYSERR; | ||
1528 | } | ||
1529 | if (0 == GNUNET_memcmp (&ax->DHRr, | ||
1530 | ratchet_key)) | ||
1531 | { | ||
1532 | GNUNET_STATISTICS_update (stats, | ||
1533 | "# Ratchet key already known", | ||
1534 | 1, | ||
1535 | GNUNET_NO); | ||
1536 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1537 | "Ratchet key already known. Ignoring KX.\n"); | ||
1538 | return GNUNET_NO; | ||
1539 | } | ||
1540 | |||
1541 | ax->DHRr = *ratchet_key; | ||
1542 | ax->last_ephemeral = *ephemeral_key; | ||
1543 | /* ECDH A B0 */ | ||
1544 | if (GNUNET_YES == am_I_alice) | ||
1545 | { | ||
1546 | GNUNET_CRYPTO_eddsa_ecdh (my_private_key, /* a */ | ||
1547 | ephemeral_key, /* B0 */ | ||
1548 | &key_material[0]); | ||
1549 | } | ||
1550 | else | ||
1551 | { | ||
1552 | GNUNET_CRYPTO_ecdh_eddsa (&ax->kx_0, /* b0 */ | ||
1553 | &pid->public_key, /* A */ | ||
1554 | &key_material[0]); | ||
1555 | } | ||
1556 | /* ECDH A0 B */ | ||
1557 | if (GNUNET_YES == am_I_alice) | ||
1558 | { | ||
1559 | GNUNET_CRYPTO_ecdh_eddsa (&ax->kx_0, /* a0 */ | ||
1560 | &pid->public_key, /* B */ | ||
1561 | &key_material[1]); | ||
1562 | } | ||
1563 | else | ||
1564 | { | ||
1565 | GNUNET_CRYPTO_eddsa_ecdh (my_private_key, /* b */ | ||
1566 | ephemeral_key, /* A0 */ | ||
1567 | &key_material[1]); | ||
1568 | } | ||
1569 | |||
1570 | /* ECDH A0 B0 */ | ||
1571 | GNUNET_CRYPTO_ecc_ecdh (&ax->kx_0, /* a0 or b0 */ | ||
1572 | ephemeral_key, /* B0 or A0 */ | ||
1573 | &key_material[2]); | ||
1574 | /* KDF */ | ||
1575 | GNUNET_CRYPTO_kdf (keys, sizeof(keys), | ||
1576 | salt, sizeof(salt), | ||
1577 | &key_material, sizeof(key_material), | ||
1578 | NULL); | ||
1579 | |||
1580 | if (0 == memcmp (&ax->RK, | ||
1581 | &keys[0], | ||
1582 | sizeof(ax->RK))) | ||
1583 | { | ||
1584 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1585 | "Root key already known. Ignoring KX.\n"); | ||
1586 | GNUNET_STATISTICS_update (stats, | ||
1587 | "# Root key already known", | ||
1588 | 1, | ||
1589 | GNUNET_NO); | ||
1590 | return GNUNET_NO; | ||
1591 | } | ||
1592 | |||
1593 | ax->RK = keys[0]; | ||
1594 | if (GNUNET_YES == am_I_alice) | ||
1595 | { | ||
1596 | ax->HKr = keys[1]; | ||
1597 | ax->NHKs = keys[2]; | ||
1598 | ax->NHKr = keys[3]; | ||
1599 | ax->CKr = keys[4]; | ||
1600 | ax->ratchet_flag = GNUNET_YES; | ||
1601 | } | ||
1602 | else | ||
1603 | { | ||
1604 | ax->HKs = keys[1]; | ||
1605 | ax->NHKr = keys[2]; | ||
1606 | ax->NHKs = keys[3]; | ||
1607 | ax->CKs = keys[4]; | ||
1608 | ax->ratchet_flag = GNUNET_NO; | ||
1609 | ax->ratchet_expiration | ||
1610 | = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), | ||
1611 | ratchet_time); | ||
1612 | } | ||
1613 | return GNUNET_OK; | ||
1614 | } | ||
1615 | |||
1616 | |||
1617 | /** | ||
1618 | * Try to redo the KX or KX_AUTH handshake, if we can. | ||
1619 | * | ||
1620 | * @param cls the `struct CadetTunnel` to do KX for. | ||
1621 | */ | ||
1622 | static void | ||
1623 | retry_kx (void *cls) | ||
1624 | { | ||
1625 | struct CadetTunnel *t = cls; | ||
1626 | struct CadetTunnelAxolotl *ax; | ||
1627 | |||
1628 | t->kx_task = NULL; | ||
1629 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1630 | "Trying to make KX progress on %s in state %s\n", | ||
1631 | GCT_2s (t), | ||
1632 | estate2s (t->estate)); | ||
1633 | switch (t->estate) | ||
1634 | { | ||
1635 | case CADET_TUNNEL_KEY_UNINITIALIZED: /* first attempt */ | ||
1636 | case CADET_TUNNEL_KEY_AX_SENT: /* trying again */ | ||
1637 | send_kx (t, | ||
1638 | NULL, | ||
1639 | &t->ax); | ||
1640 | break; | ||
1641 | |||
1642 | case CADET_TUNNEL_KEY_AX_RECV: | ||
1643 | case CADET_TUNNEL_KEY_AX_SENT_AND_RECV: | ||
1644 | /* We are responding, so only require reply | ||
1645 | if WE have a channel waiting. */ | ||
1646 | if (NULL != t->unverified_ax) | ||
1647 | { | ||
1648 | /* Send AX_AUTH so we might get this one verified */ | ||
1649 | ax = t->unverified_ax; | ||
1650 | } | ||
1651 | else | ||
1652 | { | ||
1653 | /* How can this be? */ | ||
1654 | GNUNET_break (0); | ||
1655 | ax = &t->ax; | ||
1656 | } | ||
1657 | send_kx_auth (t, | ||
1658 | NULL, | ||
1659 | ax, | ||
1660 | (0 == GCT_count_channels (t)) | ||
1661 | ? GNUNET_NO | ||
1662 | : GNUNET_YES); | ||
1663 | break; | ||
1664 | |||
1665 | case CADET_TUNNEL_KEY_AX_AUTH_SENT: | ||
1666 | /* We are responding, so only require reply | ||
1667 | if WE have a channel waiting. */ | ||
1668 | if (NULL != t->unverified_ax) | ||
1669 | { | ||
1670 | /* Send AX_AUTH so we might get this one verified */ | ||
1671 | ax = t->unverified_ax; | ||
1672 | } | ||
1673 | else | ||
1674 | { | ||
1675 | /* How can this be? */ | ||
1676 | GNUNET_break (0); | ||
1677 | ax = &t->ax; | ||
1678 | } | ||
1679 | send_kx_auth (t, | ||
1680 | NULL, | ||
1681 | ax, | ||
1682 | (0 == GCT_count_channels (t)) | ||
1683 | ? GNUNET_NO | ||
1684 | : GNUNET_YES); | ||
1685 | break; | ||
1686 | |||
1687 | case CADET_TUNNEL_KEY_OK: | ||
1688 | /* Must have been the *other* peer asking us to | ||
1689 | respond with a KX_AUTH. */ | ||
1690 | if (NULL != t->unverified_ax) | ||
1691 | { | ||
1692 | /* Sending AX_AUTH in response to AX so we might get this one verified */ | ||
1693 | ax = t->unverified_ax; | ||
1694 | } | ||
1695 | else | ||
1696 | { | ||
1697 | /* Sending AX_AUTH in response to AX_AUTH */ | ||
1698 | ax = &t->ax; | ||
1699 | } | ||
1700 | send_kx_auth (t, | ||
1701 | NULL, | ||
1702 | ax, | ||
1703 | GNUNET_NO); | ||
1704 | break; | ||
1705 | } | ||
1706 | } | ||
1707 | |||
1708 | |||
1709 | /** | ||
1710 | * Handle KX message that lacks authentication (and which will thus | ||
1711 | * only be considered authenticated after we respond with our own | ||
1712 | * KX_AUTH and finally successfully decrypt payload). | ||
1713 | * | ||
1714 | * @param ct connection/tunnel combo that received encrypted message | ||
1715 | * @param msg the key exchange message | ||
1716 | */ | ||
1717 | void | ||
1718 | GCT_handle_kx (struct CadetTConnection *ct, | ||
1719 | const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg) | ||
1720 | { | ||
1721 | struct CadetTunnel *t = ct->t; | ||
1722 | int ret; | ||
1723 | |||
1724 | GNUNET_STATISTICS_update (stats, | ||
1725 | "# KX received", | ||
1726 | 1, | ||
1727 | GNUNET_NO); | ||
1728 | if (GNUNET_YES == | ||
1729 | GCT_alice_or_betty (GCP_get_id (t->destination))) | ||
1730 | { | ||
1731 | /* Betty/Bob is not allowed to send KX! */ | ||
1732 | GNUNET_break_op (0); | ||
1733 | return; | ||
1734 | } | ||
1735 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1736 | "Received KX message from %s with ephemeral %s from %s on connection %s\n", | ||
1737 | GCT_2s (t), | ||
1738 | GNUNET_e2s (&msg->ephemeral_key), | ||
1739 | GNUNET_i2s (GCP_get_id (t->destination)), | ||
1740 | GCC_2s (ct->cc)); | ||
1741 | #if 1 | ||
1742 | if ((0 == | ||
1743 | memcmp (&t->ax.DHRr, | ||
1744 | &msg->ratchet_key, | ||
1745 | sizeof(msg->ratchet_key))) && | ||
1746 | (0 == | ||
1747 | memcmp (&t->ax.last_ephemeral, | ||
1748 | &msg->ephemeral_key, | ||
1749 | sizeof(msg->ephemeral_key)))) | ||
1750 | |||
1751 | { | ||
1752 | GNUNET_STATISTICS_update (stats, | ||
1753 | "# Duplicate KX received", | ||
1754 | 1, | ||
1755 | GNUNET_NO); | ||
1756 | send_kx_auth (t, | ||
1757 | ct, | ||
1758 | &t->ax, | ||
1759 | GNUNET_NO); | ||
1760 | return; | ||
1761 | } | ||
1762 | #endif | ||
1763 | /* We only keep ONE unverified KX around, so if there is an existing one, | ||
1764 | clean it up. */ | ||
1765 | if (NULL != t->unverified_ax) | ||
1766 | { | ||
1767 | if ((0 == | ||
1768 | memcmp (&t->unverified_ax->DHRr, | ||
1769 | &msg->ratchet_key, | ||
1770 | sizeof(msg->ratchet_key))) && | ||
1771 | (0 == | ||
1772 | memcmp (&t->unverified_ax->last_ephemeral, | ||
1773 | &msg->ephemeral_key, | ||
1774 | sizeof(msg->ephemeral_key)))) | ||
1775 | { | ||
1776 | GNUNET_STATISTICS_update (stats, | ||
1777 | "# Duplicate unverified KX received", | ||
1778 | 1, | ||
1779 | GNUNET_NO); | ||
1780 | #if 1 | ||
1781 | send_kx_auth (t, | ||
1782 | ct, | ||
1783 | t->unverified_ax, | ||
1784 | GNUNET_NO); | ||
1785 | return; | ||
1786 | #endif | ||
1787 | } | ||
1788 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1789 | "Dropping old unverified KX state.\n"); | ||
1790 | GNUNET_STATISTICS_update (stats, | ||
1791 | "# Unverified KX dropped for fresh KX", | ||
1792 | 1, | ||
1793 | GNUNET_NO); | ||
1794 | GNUNET_break (NULL == t->unverified_ax->skipped_head); | ||
1795 | memset (t->unverified_ax, | ||
1796 | 0, | ||
1797 | sizeof(struct CadetTunnelAxolotl)); | ||
1798 | } | ||
1799 | else | ||
1800 | { | ||
1801 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1802 | "Creating fresh unverified KX for %s\n", | ||
1803 | GCT_2s (t)); | ||
1804 | GNUNET_STATISTICS_update (stats, | ||
1805 | "# Fresh KX setup", | ||
1806 | 1, | ||
1807 | GNUNET_NO); | ||
1808 | t->unverified_ax = GNUNET_new (struct CadetTunnelAxolotl); | ||
1809 | } | ||
1810 | /* Set as the 'current' RK/DHRr the one we are currently using, | ||
1811 | so that the duplicate-detection logic of | ||
1812 | #update_ax_by_kx can work. */ | ||
1813 | t->unverified_ax->RK = t->ax.RK; | ||
1814 | t->unverified_ax->DHRr = t->ax.DHRr; | ||
1815 | t->unverified_ax->DHRs = t->ax.DHRs; | ||
1816 | t->unverified_ax->kx_0 = t->ax.kx_0; | ||
1817 | t->unverified_attempts = 0; | ||
1818 | |||
1819 | /* Update 'ax' by the new key material */ | ||
1820 | ret = update_ax_by_kx (t->unverified_ax, | ||
1821 | GCP_get_id (t->destination), | ||
1822 | &msg->ephemeral_key, | ||
1823 | &msg->ratchet_key); | ||
1824 | GNUNET_break (GNUNET_SYSERR != ret); | ||
1825 | if (GNUNET_OK != ret) | ||
1826 | { | ||
1827 | GNUNET_STATISTICS_update (stats, | ||
1828 | "# Useless KX", | ||
1829 | 1, | ||
1830 | GNUNET_NO); | ||
1831 | return; /* duplicate KX, nothing to do */ | ||
1832 | } | ||
1833 | /* move ahead in our state machine */ | ||
1834 | if (CADET_TUNNEL_KEY_UNINITIALIZED == t->estate) | ||
1835 | GCT_change_estate (t, | ||
1836 | CADET_TUNNEL_KEY_AX_RECV); | ||
1837 | else if (CADET_TUNNEL_KEY_AX_SENT == t->estate) | ||
1838 | GCT_change_estate (t, | ||
1839 | CADET_TUNNEL_KEY_AX_SENT_AND_RECV); | ||
1840 | |||
1841 | /* KX is still not done, try again our end. */ | ||
1842 | if (CADET_TUNNEL_KEY_OK != t->estate) | ||
1843 | { | ||
1844 | if (NULL != t->kx_task) | ||
1845 | GNUNET_SCHEDULER_cancel (t->kx_task); | ||
1846 | t->kx_task | ||
1847 | = GNUNET_SCHEDULER_add_now (&retry_kx, | ||
1848 | t); | ||
1849 | } | ||
1850 | } | ||
1851 | |||
1852 | |||
1853 | #if DEBUG_KX | ||
1854 | static void | ||
1855 | check_ee (const struct GNUNET_CRYPTO_EcdhePrivateKey *e1, | ||
1856 | const struct GNUNET_CRYPTO_EcdhePrivateKey *e2) | ||
1857 | { | ||
1858 | struct GNUNET_CRYPTO_EcdhePublicKey p1; | ||
1859 | struct GNUNET_CRYPTO_EcdhePublicKey p2; | ||
1860 | struct GNUNET_HashCode hc1; | ||
1861 | struct GNUNET_HashCode hc2; | ||
1862 | |||
1863 | GNUNET_CRYPTO_ecdhe_key_get_public (e1, | ||
1864 | &p1); | ||
1865 | GNUNET_CRYPTO_ecdhe_key_get_public (e2, | ||
1866 | &p2); | ||
1867 | GNUNET_assert (GNUNET_OK == | ||
1868 | GNUNET_CRYPTO_ecc_ecdh (e1, | ||
1869 | &p2, | ||
1870 | &hc1)); | ||
1871 | GNUNET_assert (GNUNET_OK == | ||
1872 | GNUNET_CRYPTO_ecc_ecdh (e2, | ||
1873 | &p1, | ||
1874 | &hc2)); | ||
1875 | GNUNET_break (0 == GNUNET_memcmp (&hc1, | ||
1876 | &hc2)); | ||
1877 | } | ||
1878 | |||
1879 | |||
1880 | static void | ||
1881 | check_ed (const struct GNUNET_CRYPTO_EcdhePrivateKey *e1, | ||
1882 | const struct GNUNET_CRYPTO_EddsaPrivateKey *e2) | ||
1883 | { | ||
1884 | struct GNUNET_CRYPTO_EcdhePublicKey p1; | ||
1885 | struct GNUNET_CRYPTO_EddsaPublicKey p2; | ||
1886 | struct GNUNET_HashCode hc1; | ||
1887 | struct GNUNET_HashCode hc2; | ||
1888 | |||
1889 | GNUNET_CRYPTO_ecdhe_key_get_public (e1, | ||
1890 | &p1); | ||
1891 | GNUNET_CRYPTO_eddsa_key_get_public (e2, | ||
1892 | &p2); | ||
1893 | GNUNET_assert (GNUNET_OK == | ||
1894 | GNUNET_CRYPTO_ecdh_eddsa (e1, | ||
1895 | &p2, | ||
1896 | &hc1)); | ||
1897 | GNUNET_assert (GNUNET_OK == | ||
1898 | GNUNET_CRYPTO_eddsa_ecdh (e2, | ||
1899 | &p1, | ||
1900 | &hc2)); | ||
1901 | GNUNET_break (0 == GNUNET_memcmp (&hc1, | ||
1902 | &hc2)); | ||
1903 | } | ||
1904 | |||
1905 | |||
1906 | static void | ||
1907 | test_crypto_bug (const struct GNUNET_CRYPTO_EcdhePrivateKey *e1, | ||
1908 | const struct GNUNET_CRYPTO_EcdhePrivateKey *e2, | ||
1909 | const struct GNUNET_CRYPTO_EddsaPrivateKey *d1, | ||
1910 | const struct GNUNET_CRYPTO_EddsaPrivateKey *d2) | ||
1911 | { | ||
1912 | check_ee (e1, e2); | ||
1913 | check_ed (e1, d2); | ||
1914 | check_ed (e2, d1); | ||
1915 | } | ||
1916 | |||
1917 | |||
1918 | #endif | ||
1919 | |||
1920 | |||
1921 | /** | ||
1922 | * Handle KX_AUTH message. | ||
1923 | * | ||
1924 | * @param ct connection/tunnel combo that received encrypted message | ||
1925 | * @param msg the key exchange message | ||
1926 | */ | ||
1927 | void | ||
1928 | GCT_handle_kx_auth (struct CadetTConnection *ct, | ||
1929 | const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg) | ||
1930 | { | ||
1931 | struct CadetTunnel *t = ct->t; | ||
1932 | struct CadetTunnelAxolotl ax_tmp; | ||
1933 | struct GNUNET_HashCode kx_auth; | ||
1934 | int ret; | ||
1935 | |||
1936 | GNUNET_STATISTICS_update (stats, | ||
1937 | "# KX_AUTH received", | ||
1938 | 1, | ||
1939 | GNUNET_NO); | ||
1940 | if ((CADET_TUNNEL_KEY_UNINITIALIZED == t->estate) || | ||
1941 | (CADET_TUNNEL_KEY_AX_RECV == t->estate)) | ||
1942 | { | ||
1943 | /* Confusing, we got a KX_AUTH before we even send our own | ||
1944 | KX. This should not happen. We'll send our own KX ASAP anyway, | ||
1945 | so let's ignore this here. */ | ||
1946 | GNUNET_break_op (0); | ||
1947 | return; | ||
1948 | } | ||
1949 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1950 | "Handling KX_AUTH message from %s with ephemeral %s\n", | ||
1951 | GCT_2s (t), | ||
1952 | GNUNET_e2s (&msg->kx.ephemeral_key)); | ||
1953 | /* We do everything in ax_tmp until we've checked the authentication | ||
1954 | so we don't clobber anything we care about by accident. */ | ||
1955 | ax_tmp = t->ax; | ||
1956 | |||
1957 | /* Update 'ax' by the new key material */ | ||
1958 | ret = update_ax_by_kx (&ax_tmp, | ||
1959 | GCP_get_id (t->destination), | ||
1960 | &msg->kx.ephemeral_key, | ||
1961 | &msg->kx.ratchet_key); | ||
1962 | if (GNUNET_OK != ret) | ||
1963 | { | ||
1964 | if (GNUNET_NO == ret) | ||
1965 | GNUNET_STATISTICS_update (stats, | ||
1966 | "# redundant KX_AUTH received", | ||
1967 | 1, | ||
1968 | GNUNET_NO); | ||
1969 | else | ||
1970 | GNUNET_break (0); /* connect to self!? */ | ||
1971 | return; | ||
1972 | } | ||
1973 | GNUNET_CRYPTO_hash (&ax_tmp.RK, | ||
1974 | sizeof(ax_tmp.RK), | ||
1975 | &kx_auth); | ||
1976 | if (0 != GNUNET_memcmp (&kx_auth, | ||
1977 | &msg->auth)) | ||
1978 | { | ||
1979 | /* This KX_AUTH is not using the latest KX/KX_AUTH data | ||
1980 | we transmitted to the sender, refuse it, try KX again. */ | ||
1981 | GNUNET_STATISTICS_update (stats, | ||
1982 | "# KX_AUTH not using our last KX received (auth failure)", | ||
1983 | 1, | ||
1984 | GNUNET_NO); | ||
1985 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1986 | "KX AUTH mismatch!\n"); | ||
1987 | #if DEBUG_KX | ||
1988 | { | ||
1989 | struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key; | ||
1990 | |||
1991 | GNUNET_CRYPTO_ecdhe_key_get_public (&ax_tmp.kx_0, | ||
1992 | &ephemeral_key); | ||
1993 | if (0 != GNUNET_memcmp (&ephemeral_key, | ||
1994 | &msg->r_ephemeral_key_XXX)) | ||
1995 | { | ||
1996 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1997 | "My ephemeral is %s!\n", | ||
1998 | GNUNET_e2s (&ephemeral_key)); | ||
1999 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
2000 | "Response is for ephemeral %s!\n", | ||
2001 | GNUNET_e2s (&msg->r_ephemeral_key_XXX)); | ||
2002 | } | ||
2003 | else | ||
2004 | { | ||
2005 | test_crypto_bug (&ax_tmp.kx_0, | ||
2006 | &msg->kx.ephemeral_key_XXX, | ||
2007 | my_private_key, | ||
2008 | &msg->kx.private_key_XXX); | ||
2009 | } | ||
2010 | } | ||
2011 | #endif | ||
2012 | if (NULL == t->kx_task) | ||
2013 | t->kx_task | ||
2014 | = GNUNET_SCHEDULER_add_at (t->next_kx_attempt, | ||
2015 | &retry_kx, | ||
2016 | t); | ||
2017 | return; | ||
2018 | } | ||
2019 | /* Yep, we're good. */ | ||
2020 | t->ax = ax_tmp; | ||
2021 | if (NULL != t->unverified_ax) | ||
2022 | { | ||
2023 | /* We got some "stale" KX before, drop that. */ | ||
2024 | cleanup_ax (t->unverified_ax); | ||
2025 | GNUNET_free (t->unverified_ax); | ||
2026 | t->unverified_ax = NULL; | ||
2027 | } | ||
2028 | |||
2029 | /* move ahead in our state machine */ | ||
2030 | switch (t->estate) | ||
2031 | { | ||
2032 | case CADET_TUNNEL_KEY_UNINITIALIZED: | ||
2033 | case CADET_TUNNEL_KEY_AX_RECV: | ||
2034 | /* Checked above, this is impossible. */ | ||
2035 | GNUNET_assert (0); | ||
2036 | break; | ||
2037 | |||
2038 | case CADET_TUNNEL_KEY_AX_SENT: /* This is the normal case */ | ||
2039 | case CADET_TUNNEL_KEY_AX_SENT_AND_RECV: /* both peers started KX */ | ||
2040 | case CADET_TUNNEL_KEY_AX_AUTH_SENT: /* both peers now did KX_AUTH */ | ||
2041 | GCT_change_estate (t, | ||
2042 | CADET_TUNNEL_KEY_OK); | ||
2043 | break; | ||
2044 | |||
2045 | case CADET_TUNNEL_KEY_OK: | ||
2046 | /* Did not expect another KX_AUTH, but so what, still acceptable. | ||
2047 | Nothing to do here. */ | ||
2048 | break; | ||
2049 | } | ||
2050 | if (0 != (GNUNET_CADET_KX_FLAG_FORCE_REPLY & ntohl (msg->kx.flags))) | ||
2051 | { | ||
2052 | send_kx_auth (t, | ||
2053 | NULL, | ||
2054 | &t->ax, | ||
2055 | GNUNET_NO); | ||
2056 | } | ||
2057 | } | ||
2058 | |||
2059 | |||
2060 | /* ************************************** end core crypto ***************************** */ | ||
2061 | |||
2062 | |||
2063 | /** | ||
2064 | * Compute the next free channel tunnel number for this tunnel. | ||
2065 | * | ||
2066 | * @param t the tunnel | ||
2067 | * @return unused number that can uniquely identify a channel in the tunnel | ||
2068 | */ | ||
2069 | static struct GNUNET_CADET_ChannelTunnelNumber | ||
2070 | get_next_free_ctn (struct CadetTunnel *t) | ||
2071 | { | ||
2072 | #define HIGH_BIT 0x8000000 | ||
2073 | struct GNUNET_CADET_ChannelTunnelNumber ret; | ||
2074 | uint32_t ctn; | ||
2075 | int cmp; | ||
2076 | uint32_t highbit; | ||
2077 | |||
2078 | cmp = GNUNET_memcmp (&my_full_id, | ||
2079 | GCP_get_id (GCT_get_destination (t))); | ||
2080 | if (0 < cmp) | ||
2081 | highbit = HIGH_BIT; | ||
2082 | else if (0 > cmp) | ||
2083 | highbit = 0; | ||
2084 | else | ||
2085 | GNUNET_assert (0); // loopback must never go here! | ||
2086 | ctn = ntohl (t->next_ctn.cn); | ||
2087 | while (NULL != | ||
2088 | GNUNET_CONTAINER_multihashmap32_get (t->channels, | ||
2089 | ctn | highbit)) | ||
2090 | { | ||
2091 | ctn = ((ctn + 1) & (~HIGH_BIT)); | ||
2092 | } | ||
2093 | t->next_ctn.cn = htonl ((ctn + 1) & (~HIGH_BIT)); | ||
2094 | ret.cn = htonl (ctn | highbit); | ||
2095 | return ret; | ||
2096 | } | ||
2097 | |||
2098 | |||
2099 | /** | ||
2100 | * Add a channel to a tunnel, and notify channel that we are ready | ||
2101 | * for transmission if we are already up. Otherwise that notification | ||
2102 | * will be done later in #notify_tunnel_up_cb(). | ||
2103 | * | ||
2104 | * @param t Tunnel. | ||
2105 | * @param ch Channel | ||
2106 | * @return unique number identifying @a ch within @a t | ||
2107 | */ | ||
2108 | struct GNUNET_CADET_ChannelTunnelNumber | ||
2109 | GCT_add_channel (struct CadetTunnel *t, | ||
2110 | struct CadetChannel *ch) | ||
2111 | { | ||
2112 | struct GNUNET_CADET_ChannelTunnelNumber ctn; | ||
2113 | |||
2114 | ctn = get_next_free_ctn (t); | ||
2115 | if (NULL != t->destroy_task) | ||
2116 | { | ||
2117 | GNUNET_SCHEDULER_cancel (t->destroy_task); | ||
2118 | t->destroy_task = NULL; | ||
2119 | } | ||
2120 | GNUNET_assert (GNUNET_YES == | ||
2121 | GNUNET_CONTAINER_multihashmap32_put (t->channels, | ||
2122 | ntohl (ctn.cn), | ||
2123 | ch, | ||
2124 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
2125 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2126 | "Adding %s to %s with state %d\n", | ||
2127 | GCCH_2s (ch), | ||
2128 | GCT_2s (t), | ||
2129 | t->estate); | ||
2130 | switch (t->estate) | ||
2131 | { | ||
2132 | case CADET_TUNNEL_KEY_UNINITIALIZED: | ||
2133 | /* waiting for connection to start KX */ | ||
2134 | break; | ||
2135 | |||
2136 | case CADET_TUNNEL_KEY_AX_RECV: | ||
2137 | case CADET_TUNNEL_KEY_AX_SENT: | ||
2138 | case CADET_TUNNEL_KEY_AX_SENT_AND_RECV: | ||
2139 | /* we're currently waiting for KX to complete */ | ||
2140 | break; | ||
2141 | |||
2142 | case CADET_TUNNEL_KEY_AX_AUTH_SENT: | ||
2143 | /* waiting for OTHER peer to send us data, | ||
2144 | we might need to prompt more aggressively! */ | ||
2145 | if (NULL == t->kx_task) | ||
2146 | t->kx_task | ||
2147 | = GNUNET_SCHEDULER_add_at (t->next_kx_attempt, | ||
2148 | &retry_kx, | ||
2149 | t); | ||
2150 | break; | ||
2151 | |||
2152 | case CADET_TUNNEL_KEY_OK: | ||
2153 | /* We are ready. Tell the new channel that we are up. */ | ||
2154 | GCCH_tunnel_up (ch); | ||
2155 | break; | ||
2156 | } | ||
2157 | return ctn; | ||
2158 | } | ||
2159 | |||
2160 | |||
2161 | /** | ||
2162 | * We lost a connection, remove it from our list and clean up | ||
2163 | * the connection object itself. | ||
2164 | * | ||
2165 | * @param ct binding of connection to tunnel of the connection that was lost. | ||
2166 | */ | ||
2167 | void | ||
2168 | GCT_connection_lost (struct CadetTConnection *ct) | ||
2169 | { | ||
2170 | struct CadetTunnel *t = ct->t; | ||
2171 | |||
2172 | if (GNUNET_YES == ct->is_ready) | ||
2173 | { | ||
2174 | GNUNET_CONTAINER_DLL_remove (t->connection_ready_head, | ||
2175 | t->connection_ready_tail, | ||
2176 | ct); | ||
2177 | t->num_ready_connections--; | ||
2178 | } | ||
2179 | else | ||
2180 | { | ||
2181 | GNUNET_CONTAINER_DLL_remove (t->connection_busy_head, | ||
2182 | t->connection_busy_tail, | ||
2183 | ct); | ||
2184 | t->num_busy_connections--; | ||
2185 | } | ||
2186 | GNUNET_free (ct); | ||
2187 | } | ||
2188 | |||
2189 | |||
2190 | /** | ||
2191 | * Clean up connection @a ct of a tunnel. | ||
2192 | * | ||
2193 | * @param cls the `struct CadetTunnel` | ||
2194 | * @param ct connection to clean up | ||
2195 | */ | ||
2196 | static void | ||
2197 | destroy_t_connection (void *cls, | ||
2198 | struct CadetTConnection *ct) | ||
2199 | { | ||
2200 | struct CadetTunnel *t = cls; | ||
2201 | struct CadetConnection *cc = ct->cc; | ||
2202 | |||
2203 | GNUNET_assert (ct->t == t); | ||
2204 | GCT_connection_lost (ct); | ||
2205 | GCC_destroy_without_tunnel (cc); | ||
2206 | } | ||
2207 | |||
2208 | |||
2209 | /** | ||
2210 | * This tunnel is no longer used, destroy it. | ||
2211 | * | ||
2212 | * @param cls the idle tunnel | ||
2213 | */ | ||
2214 | static void | ||
2215 | destroy_tunnel (void *cls) | ||
2216 | { | ||
2217 | struct CadetTunnel *t = cls; | ||
2218 | struct CadetTunnelQueueEntry *tq; | ||
2219 | |||
2220 | t->destroy_task = NULL; | ||
2221 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2222 | "Destroying idle %s\n", | ||
2223 | GCT_2s (t)); | ||
2224 | GNUNET_assert (0 == GCT_count_channels (t)); | ||
2225 | GCT_iterate_connections (t, | ||
2226 | &destroy_t_connection, | ||
2227 | t); | ||
2228 | GNUNET_assert (NULL == t->connection_ready_head); | ||
2229 | GNUNET_assert (NULL == t->connection_busy_head); | ||
2230 | while (NULL != (tq = t->tq_head)) | ||
2231 | { | ||
2232 | if (NULL != tq->cont) | ||
2233 | tq->cont (tq->cont_cls, | ||
2234 | NULL); | ||
2235 | GCT_send_cancel (tq); | ||
2236 | } | ||
2237 | GCP_drop_tunnel (t->destination, | ||
2238 | t); | ||
2239 | GNUNET_CONTAINER_multihashmap32_destroy (t->channels); | ||
2240 | if (NULL != t->maintain_connections_task) | ||
2241 | { | ||
2242 | GNUNET_SCHEDULER_cancel (t->maintain_connections_task); | ||
2243 | t->maintain_connections_task = NULL; | ||
2244 | } | ||
2245 | if (NULL != t->send_task) | ||
2246 | { | ||
2247 | GNUNET_SCHEDULER_cancel (t->send_task); | ||
2248 | t->send_task = NULL; | ||
2249 | } | ||
2250 | if (NULL != t->kx_task) | ||
2251 | { | ||
2252 | GNUNET_SCHEDULER_cancel (t->kx_task); | ||
2253 | t->kx_task = NULL; | ||
2254 | } | ||
2255 | GNUNET_MST_destroy (t->mst); | ||
2256 | GNUNET_MQ_destroy (t->mq); | ||
2257 | if (NULL != t->unverified_ax) | ||
2258 | { | ||
2259 | cleanup_ax (t->unverified_ax); | ||
2260 | GNUNET_free (t->unverified_ax); | ||
2261 | } | ||
2262 | cleanup_ax (&t->ax); | ||
2263 | GNUNET_assert (NULL == t->destroy_task); | ||
2264 | GNUNET_free (t); | ||
2265 | } | ||
2266 | |||
2267 | |||
2268 | /** | ||
2269 | * Remove a channel from a tunnel. | ||
2270 | * | ||
2271 | * @param t Tunnel. | ||
2272 | * @param ch Channel | ||
2273 | * @param ctn unique number identifying @a ch within @a t | ||
2274 | */ | ||
2275 | void | ||
2276 | GCT_remove_channel (struct CadetTunnel *t, | ||
2277 | struct CadetChannel *ch, | ||
2278 | struct GNUNET_CADET_ChannelTunnelNumber ctn) | ||
2279 | { | ||
2280 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2281 | "Removing %s from %s\n", | ||
2282 | GCCH_2s (ch), | ||
2283 | GCT_2s (t)); | ||
2284 | GNUNET_assert (GNUNET_YES == | ||
2285 | GNUNET_CONTAINER_multihashmap32_remove (t->channels, | ||
2286 | ntohl (ctn.cn), | ||
2287 | ch)); | ||
2288 | if ((0 == | ||
2289 | GCT_count_channels (t)) && | ||
2290 | (NULL == t->destroy_task)) | ||
2291 | { | ||
2292 | t->destroy_task | ||
2293 | = GNUNET_SCHEDULER_add_delayed (IDLE_DESTROY_DELAY, | ||
2294 | &destroy_tunnel, | ||
2295 | t); | ||
2296 | } | ||
2297 | } | ||
2298 | |||
2299 | |||
2300 | /** | ||
2301 | * Destroy remaining channels during shutdown. | ||
2302 | * | ||
2303 | * @param cls the `struct CadetTunnel` of the channel | ||
2304 | * @param key key of the channel | ||
2305 | * @param value the `struct CadetChannel` | ||
2306 | * @return #GNUNET_OK (continue to iterate) | ||
2307 | */ | ||
2308 | static int | ||
2309 | destroy_remaining_channels (void *cls, | ||
2310 | uint32_t key, | ||
2311 | void *value) | ||
2312 | { | ||
2313 | struct CadetChannel *ch = value; | ||
2314 | |||
2315 | GCCH_handle_remote_destroy (ch, | ||
2316 | NULL); | ||
2317 | return GNUNET_OK; | ||
2318 | } | ||
2319 | |||
2320 | |||
2321 | /** | ||
2322 | * Destroys the tunnel @a t now, without delay. Used during shutdown. | ||
2323 | * | ||
2324 | * @param t tunnel to destroy | ||
2325 | */ | ||
2326 | void | ||
2327 | GCT_destroy_tunnel_now (struct CadetTunnel *t) | ||
2328 | { | ||
2329 | GNUNET_assert (GNUNET_YES == shutting_down); | ||
2330 | GNUNET_CONTAINER_multihashmap32_iterate (t->channels, | ||
2331 | &destroy_remaining_channels, | ||
2332 | t); | ||
2333 | GNUNET_assert (0 == | ||
2334 | GCT_count_channels (t)); | ||
2335 | if (NULL != t->destroy_task) | ||
2336 | { | ||
2337 | GNUNET_SCHEDULER_cancel (t->destroy_task); | ||
2338 | t->destroy_task = NULL; | ||
2339 | } | ||
2340 | destroy_tunnel (t); | ||
2341 | } | ||
2342 | |||
2343 | |||
2344 | /** | ||
2345 | * Send normal payload from queue in @a t via connection @a ct. | ||
2346 | * Does nothing if our payload queue is empty. | ||
2347 | * | ||
2348 | * @param t tunnel to send data from | ||
2349 | * @param ct connection to use for transmission (is ready) | ||
2350 | */ | ||
2351 | static void | ||
2352 | try_send_normal_payload (struct CadetTunnel *t, | ||
2353 | struct CadetTConnection *ct) | ||
2354 | { | ||
2355 | struct CadetTunnelQueueEntry *tq; | ||
2356 | |||
2357 | GNUNET_assert (GNUNET_YES == ct->is_ready); | ||
2358 | tq = t->tq_head; | ||
2359 | if (NULL == tq) | ||
2360 | { | ||
2361 | /* no messages pending right now */ | ||
2362 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2363 | "Not sending payload of %s on ready %s (nothing pending)\n", | ||
2364 | GCT_2s (t), | ||
2365 | GCC_2s (ct->cc)); | ||
2366 | return; | ||
2367 | } | ||
2368 | /* ready to send message 'tq' on tunnel 'ct' */ | ||
2369 | GNUNET_assert (t == tq->t); | ||
2370 | GNUNET_CONTAINER_DLL_remove (t->tq_head, | ||
2371 | t->tq_tail, | ||
2372 | tq); | ||
2373 | if (NULL != tq->cid) | ||
2374 | *tq->cid = *GCC_get_id (ct->cc); | ||
2375 | mark_connection_unready (ct); | ||
2376 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2377 | "Sending payload of %s on %s\n", | ||
2378 | GCT_2s (t), | ||
2379 | GCC_2s (ct->cc)); | ||
2380 | GCC_transmit (ct->cc, | ||
2381 | tq->env); | ||
2382 | if (NULL != tq->cont) | ||
2383 | tq->cont (tq->cont_cls, | ||
2384 | GCC_get_id (ct->cc)); | ||
2385 | GNUNET_free (tq); | ||
2386 | } | ||
2387 | |||
2388 | |||
2389 | /** | ||
2390 | * A connection is @a is_ready for transmission. Looks at our message | ||
2391 | * queue and if there is a message, sends it out via the connection. | ||
2392 | * | ||
2393 | * @param cls the `struct CadetTConnection` that is @a is_ready | ||
2394 | * @param is_ready #GNUNET_YES if connection are now ready, | ||
2395 | * #GNUNET_NO if connection are no longer ready | ||
2396 | */ | ||
2397 | static void | ||
2398 | connection_ready_cb (void *cls, | ||
2399 | int is_ready) | ||
2400 | { | ||
2401 | struct CadetTConnection *ct = cls; | ||
2402 | struct CadetTunnel *t = ct->t; | ||
2403 | |||
2404 | if (GNUNET_NO == is_ready) | ||
2405 | { | ||
2406 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2407 | "%s no longer ready for %s\n", | ||
2408 | GCC_2s (ct->cc), | ||
2409 | GCT_2s (t)); | ||
2410 | mark_connection_unready (ct); | ||
2411 | return; | ||
2412 | } | ||
2413 | GNUNET_assert (GNUNET_NO == ct->is_ready); | ||
2414 | GNUNET_CONTAINER_DLL_remove (t->connection_busy_head, | ||
2415 | t->connection_busy_tail, | ||
2416 | ct); | ||
2417 | GNUNET_assert (0 < t->num_busy_connections); | ||
2418 | t->num_busy_connections--; | ||
2419 | ct->is_ready = GNUNET_YES; | ||
2420 | GNUNET_CONTAINER_DLL_insert_tail (t->connection_ready_head, | ||
2421 | t->connection_ready_tail, | ||
2422 | ct); | ||
2423 | t->num_ready_connections++; | ||
2424 | |||
2425 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2426 | "%s now ready for %s in state %s\n", | ||
2427 | GCC_2s (ct->cc), | ||
2428 | GCT_2s (t), | ||
2429 | estate2s (t->estate)); | ||
2430 | switch (t->estate) | ||
2431 | { | ||
2432 | case CADET_TUNNEL_KEY_UNINITIALIZED: | ||
2433 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2434 | "Do not begin KX for %s if WE have no channels waiting. Retrying after %llu\n", | ||
2435 | GCT_2s (t), | ||
2436 | (unsigned long long) GNUNET_TIME_absolute_get_remaining ( | ||
2437 | t->next_kx_attempt).rel_value_us); | ||
2438 | /* Do not begin KX if WE have no channels waiting! */ | ||
2439 | if (0 != GNUNET_TIME_absolute_get_remaining ( | ||
2440 | t->next_kx_attempt).rel_value_us) | ||
2441 | return; /* wait for timeout before retrying */ | ||
2442 | /* We are uninitialized, just transmit immediately, | ||
2443 | without undue delay. */ | ||
2444 | |||
2445 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2446 | "Why for %s \n", | ||
2447 | GCT_2s (t)); | ||
2448 | |||
2449 | if (NULL != t->kx_task) | ||
2450 | { | ||
2451 | GNUNET_SCHEDULER_cancel (t->kx_task); | ||
2452 | t->kx_task = NULL; | ||
2453 | } | ||
2454 | send_kx (t, | ||
2455 | ct, | ||
2456 | &t->ax); | ||
2457 | if ((0 == | ||
2458 | GCT_count_channels (t)) && | ||
2459 | (NULL == t->destroy_task)) | ||
2460 | { | ||
2461 | t->destroy_task | ||
2462 | = GNUNET_SCHEDULER_add_delayed (IDLE_DESTROY_DELAY, | ||
2463 | &destroy_tunnel, | ||
2464 | t); | ||
2465 | } | ||
2466 | break; | ||
2467 | |||
2468 | case CADET_TUNNEL_KEY_AX_RECV: | ||
2469 | case CADET_TUNNEL_KEY_AX_SENT: | ||
2470 | case CADET_TUNNEL_KEY_AX_SENT_AND_RECV: | ||
2471 | case CADET_TUNNEL_KEY_AX_AUTH_SENT: | ||
2472 | /* we're currently waiting for KX to complete, schedule job */ | ||
2473 | if (NULL == t->kx_task) | ||
2474 | t->kx_task | ||
2475 | = GNUNET_SCHEDULER_add_at (t->next_kx_attempt, | ||
2476 | &retry_kx, | ||
2477 | t); | ||
2478 | break; | ||
2479 | |||
2480 | case CADET_TUNNEL_KEY_OK: | ||
2481 | if (GNUNET_YES == t->kx_auth_requested) | ||
2482 | { | ||
2483 | if (0 != GNUNET_TIME_absolute_get_remaining ( | ||
2484 | t->next_kx_attempt).rel_value_us) | ||
2485 | return; /* wait for timeout */ | ||
2486 | if (NULL != t->kx_task) | ||
2487 | { | ||
2488 | GNUNET_SCHEDULER_cancel (t->kx_task); | ||
2489 | t->kx_task = NULL; | ||
2490 | } | ||
2491 | send_kx_auth (t, | ||
2492 | ct, | ||
2493 | &t->ax, | ||
2494 | GNUNET_NO); | ||
2495 | return; | ||
2496 | } | ||
2497 | try_send_normal_payload (t, | ||
2498 | ct); | ||
2499 | break; | ||
2500 | } | ||
2501 | } | ||
2502 | |||
2503 | |||
2504 | /** | ||
2505 | * Called when either we have a new connection, or a new message in the | ||
2506 | * queue, or some existing connection has transmission capacity. Looks | ||
2507 | * at our message queue and if there is a message, picks a connection | ||
2508 | * to send it on. | ||
2509 | * | ||
2510 | * @param cls the `struct CadetTunnel` to process messages on | ||
2511 | */ | ||
2512 | static void | ||
2513 | trigger_transmissions (void *cls) | ||
2514 | { | ||
2515 | struct CadetTunnel *t = cls; | ||
2516 | struct CadetTConnection *ct; | ||
2517 | |||
2518 | t->send_task = NULL; | ||
2519 | if (NULL == t->tq_head) | ||
2520 | return; /* no messages pending right now */ | ||
2521 | ct = get_ready_connection (t); | ||
2522 | if (NULL == ct) | ||
2523 | return; /* no connections ready */ | ||
2524 | try_send_normal_payload (t, | ||
2525 | ct); | ||
2526 | } | ||
2527 | |||
2528 | |||
2529 | /** | ||
2530 | * Closure for #evaluate_connection. Used to assemble summary information | ||
2531 | * about the existing connections so we can evaluate a new path. | ||
2532 | */ | ||
2533 | struct EvaluationSummary | ||
2534 | { | ||
2535 | /** | ||
2536 | * Minimum length of any of our connections, `UINT_MAX` if we have none. | ||
2537 | */ | ||
2538 | unsigned int min_length; | ||
2539 | |||
2540 | /** | ||
2541 | * Maximum length of any of our connections, 0 if we have none. | ||
2542 | */ | ||
2543 | unsigned int max_length; | ||
2544 | |||
2545 | /** | ||
2546 | * Minimum desirability of any of our connections, UINT64_MAX if we have none. | ||
2547 | */ | ||
2548 | GNUNET_CONTAINER_HeapCostType min_desire; | ||
2549 | |||
2550 | /** | ||
2551 | * Maximum desirability of any of our connections, 0 if we have none. | ||
2552 | */ | ||
2553 | GNUNET_CONTAINER_HeapCostType max_desire; | ||
2554 | |||
2555 | /** | ||
2556 | * Path we are comparing against for #evaluate_connection, can be NULL. | ||
2557 | */ | ||
2558 | struct CadetPeerPath *path; | ||
2559 | |||
2560 | /** | ||
2561 | * Connection deemed the "worst" so far encountered by #evaluate_connection, | ||
2562 | * NULL if we did not yet encounter any connections. | ||
2563 | */ | ||
2564 | struct CadetTConnection *worst; | ||
2565 | |||
2566 | /** | ||
2567 | * Numeric score of @e worst, only set if @e worst is non-NULL. | ||
2568 | */ | ||
2569 | double worst_score; | ||
2570 | |||
2571 | /** | ||
2572 | * Set to #GNUNET_YES if we have a connection over @e path already. | ||
2573 | */ | ||
2574 | int duplicate; | ||
2575 | }; | ||
2576 | |||
2577 | |||
2578 | /** | ||
2579 | * Evaluate a connection, updating our summary information in @a cls about | ||
2580 | * what kinds of connections we have. | ||
2581 | * | ||
2582 | * @param cls the `struct EvaluationSummary *` to update | ||
2583 | * @param ct a connection to include in the summary | ||
2584 | */ | ||
2585 | static void | ||
2586 | evaluate_connection (void *cls, | ||
2587 | struct CadetTConnection *ct) | ||
2588 | { | ||
2589 | struct EvaluationSummary *es = cls; | ||
2590 | struct CadetConnection *cc = ct->cc; | ||
2591 | unsigned int ct_length; | ||
2592 | struct CadetPeerPath *ps; | ||
2593 | const struct CadetConnectionMetrics *metrics; | ||
2594 | GNUNET_CONTAINER_HeapCostType ct_desirability; | ||
2595 | struct GNUNET_TIME_Relative uptime; | ||
2596 | struct GNUNET_TIME_Relative last_use; | ||
2597 | double score; | ||
2598 | double success_rate; | ||
2599 | |||
2600 | ps = GCC_get_path (cc, | ||
2601 | &ct_length); | ||
2602 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2603 | "Evaluating path %s of existing %s\n", | ||
2604 | GCPP_2s (ps), | ||
2605 | GCC_2s (cc)); | ||
2606 | if (ps == es->path) | ||
2607 | { | ||
2608 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2609 | "Ignoring duplicate path %s.\n", | ||
2610 | GCPP_2s (es->path)); | ||
2611 | es->duplicate = GNUNET_YES; | ||
2612 | return; | ||
2613 | } | ||
2614 | if (NULL != es->path) | ||
2615 | { | ||
2616 | int duplicate = GNUNET_YES; | ||
2617 | |||
2618 | for (unsigned int i = 0; i < ct_length; i++) | ||
2619 | { | ||
2620 | GNUNET_assert (GCPP_get_length (es->path) > i); | ||
2621 | if (GCPP_get_peer_at_offset (es->path, | ||
2622 | i) != | ||
2623 | GCPP_get_peer_at_offset (ps, | ||
2624 | i)) | ||
2625 | { | ||
2626 | duplicate = GNUNET_NO; | ||
2627 | break; | ||
2628 | } | ||
2629 | } | ||
2630 | if (GNUNET_YES == duplicate) | ||
2631 | { | ||
2632 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2633 | "Ignoring overlapping path %s.\n", | ||
2634 | GCPP_2s (es->path)); | ||
2635 | es->duplicate = GNUNET_YES; | ||
2636 | return; | ||
2637 | } | ||
2638 | else | ||
2639 | { | ||
2640 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2641 | "Known path %s differs from proposed path\n", | ||
2642 | GCPP_2s (ps)); | ||
2643 | } | ||
2644 | } | ||
2645 | |||
2646 | ct_desirability = GCPP_get_desirability (ps); | ||
2647 | metrics = GCC_get_metrics (cc); | ||
2648 | uptime = GNUNET_TIME_absolute_get_duration (metrics->age); | ||
2649 | last_use = GNUNET_TIME_absolute_get_duration (metrics->last_use); | ||
2650 | /* We add 1.0 here to avoid division by zero. */ | ||
2651 | success_rate = (metrics->num_acked_transmissions + 1.0) | ||
2652 | / (metrics->num_successes + 1.0); | ||
2653 | score | ||
2654 | = ct_desirability | ||
2655 | + 100.0 / (1.0 + ct_length) /* longer paths = better */ | ||
2656 | + sqrt (uptime.rel_value_us / 60000000LL) /* larger uptime = better */ | ||
2657 | - last_use.rel_value_us / 1000L; /* longer idle = worse */ | ||
2658 | score *= success_rate; /* weigh overall by success rate */ | ||
2659 | |||
2660 | if ((NULL == es->worst) || | ||
2661 | (score < es->worst_score)) | ||
2662 | { | ||
2663 | es->worst = ct; | ||
2664 | es->worst_score = score; | ||
2665 | } | ||
2666 | es->min_length = GNUNET_MIN (es->min_length, | ||
2667 | ct_length); | ||
2668 | es->max_length = GNUNET_MAX (es->max_length, | ||
2669 | ct_length); | ||
2670 | es->min_desire = GNUNET_MIN (es->min_desire, | ||
2671 | ct_desirability); | ||
2672 | es->max_desire = GNUNET_MAX (es->max_desire, | ||
2673 | ct_desirability); | ||
2674 | } | ||
2675 | |||
2676 | |||
2677 | /** | ||
2678 | * Consider using the path @a p for the tunnel @a t. | ||
2679 | * The tunnel destination is at offset @a off in path @a p. | ||
2680 | * | ||
2681 | * @param cls our tunnel | ||
2682 | * @param path a path to our destination | ||
2683 | * @param off offset of the destination on path @a path | ||
2684 | * @return #GNUNET_YES (should keep iterating) | ||
2685 | */ | ||
2686 | static int | ||
2687 | consider_path_cb (void *cls, | ||
2688 | struct CadetPeerPath *path, | ||
2689 | unsigned int off) | ||
2690 | { | ||
2691 | struct CadetTunnel *t = cls; | ||
2692 | struct EvaluationSummary es; | ||
2693 | struct CadetTConnection *ct; | ||
2694 | |||
2695 | GNUNET_assert (off < GCPP_get_length (path)); | ||
2696 | GNUNET_assert (GCPP_get_peer_at_offset (path, | ||
2697 | off) == t->destination); | ||
2698 | es.min_length = UINT_MAX; | ||
2699 | es.max_length = 0; | ||
2700 | es.max_desire = 0; | ||
2701 | es.min_desire = UINT64_MAX; | ||
2702 | es.path = path; | ||
2703 | es.duplicate = GNUNET_NO; | ||
2704 | es.worst = NULL; | ||
2705 | |||
2706 | /* Compute evaluation summary over existing connections. */ | ||
2707 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2708 | "Evaluating proposed path %s for target %s\n", | ||
2709 | GCPP_2s (path), | ||
2710 | GCT_2s (t)); | ||
2711 | /* FIXME: suspect this does not ACTUALLY iterate | ||
2712 | over all existing paths, otherwise dup detection | ||
2713 | should work!!! */ | ||
2714 | GCT_iterate_connections (t, | ||
2715 | &evaluate_connection, | ||
2716 | &es); | ||
2717 | if (GNUNET_YES == es.duplicate) | ||
2718 | return GNUNET_YES; | ||
2719 | |||
2720 | /* FIXME: not sure we should really just count | ||
2721 | 'num_connections' here, as they may all have | ||
2722 | consistently failed to connect. */ | ||
2723 | |||
2724 | /* We iterate by increasing path length; if we have enough paths and | ||
2725 | this one is more than twice as long than what we are currently | ||
2726 | using, then ignore all of these super-long ones! */ | ||
2727 | if ((GCT_count_any_connections (t) > DESIRED_CONNECTIONS_PER_TUNNEL) && | ||
2728 | (es.min_length * 2 < off) && | ||
2729 | (es.max_length < off)) | ||
2730 | { | ||
2731 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2732 | "Ignoring paths of length %u, they are way too long.\n", | ||
2733 | es.min_length * 2); | ||
2734 | return GNUNET_NO; | ||
2735 | } | ||
2736 | /* If we have enough paths and this one looks no better, ignore it. */ | ||
2737 | if ((GCT_count_any_connections (t) >= DESIRED_CONNECTIONS_PER_TUNNEL) && | ||
2738 | (es.min_length < GCPP_get_length (path)) && | ||
2739 | (es.min_desire > GCPP_get_desirability (path)) && | ||
2740 | (es.max_length < off)) | ||
2741 | { | ||
2742 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2743 | "Ignoring path (%u/%llu) to %s, got something better already.\n", | ||
2744 | GCPP_get_length (path), | ||
2745 | (unsigned long long) GCPP_get_desirability (path), | ||
2746 | GCP_2s (t->destination)); | ||
2747 | return GNUNET_YES; | ||
2748 | } | ||
2749 | |||
2750 | /* Path is interesting (better by some metric, or we don't have | ||
2751 | enough paths yet). */ | ||
2752 | ct = GNUNET_new (struct CadetTConnection); | ||
2753 | ct->created = GNUNET_TIME_absolute_get (); | ||
2754 | ct->t = t; | ||
2755 | ct->cc = GCC_create (t->destination, | ||
2756 | path, | ||
2757 | off, | ||
2758 | ct, | ||
2759 | &connection_ready_cb, | ||
2760 | ct); | ||
2761 | |||
2762 | /* FIXME: schedule job to kill connection (and path?) if it takes | ||
2763 | too long to get ready! (And track performance data on how long | ||
2764 | other connections took with the tunnel!) | ||
2765 | => Note: to be done within 'connection'-logic! */ | ||
2766 | GNUNET_CONTAINER_DLL_insert (t->connection_busy_head, | ||
2767 | t->connection_busy_tail, | ||
2768 | ct); | ||
2769 | t->num_busy_connections++; | ||
2770 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2771 | "Found interesting path %s for %s, created %s\n", | ||
2772 | GCPP_2s (path), | ||
2773 | GCT_2s (t), | ||
2774 | GCC_2s (ct->cc)); | ||
2775 | return GNUNET_YES; | ||
2776 | } | ||
2777 | |||
2778 | |||
2779 | /** | ||
2780 | * Function called to maintain the connections underlying our tunnel. | ||
2781 | * Tries to maintain (incl. tear down) connections for the tunnel, and | ||
2782 | * if there is a significant change, may trigger transmissions. | ||
2783 | * | ||
2784 | * Basically, needs to check if there are connections that perform | ||
2785 | * badly, and if so eventually kill them and trigger a replacement. | ||
2786 | * The strategy is to open one more connection than | ||
2787 | * #DESIRED_CONNECTIONS_PER_TUNNEL, and then periodically kick out the | ||
2788 | * least-performing one, and then inquire for new ones. | ||
2789 | * | ||
2790 | * @param cls the `struct CadetTunnel` | ||
2791 | */ | ||
2792 | static void | ||
2793 | maintain_connections_cb (void *cls) | ||
2794 | { | ||
2795 | struct CadetTunnel *t = cls; | ||
2796 | struct GNUNET_TIME_Relative delay; | ||
2797 | struct EvaluationSummary es; | ||
2798 | |||
2799 | t->maintain_connections_task = NULL; | ||
2800 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2801 | "Performing connection maintenance for %s.\n", | ||
2802 | GCT_2s (t)); | ||
2803 | |||
2804 | es.min_length = UINT_MAX; | ||
2805 | es.max_length = 0; | ||
2806 | es.max_desire = 0; | ||
2807 | es.min_desire = UINT64_MAX; | ||
2808 | es.path = NULL; | ||
2809 | es.worst = NULL; | ||
2810 | es.duplicate = GNUNET_NO; | ||
2811 | GCT_iterate_connections (t, | ||
2812 | &evaluate_connection, | ||
2813 | &es); | ||
2814 | if ((NULL != es.worst) && | ||
2815 | (GCT_count_any_connections (t) > DESIRED_CONNECTIONS_PER_TUNNEL)) | ||
2816 | { | ||
2817 | /* Clear out worst-performing connection 'es.worst'. */ | ||
2818 | destroy_t_connection (t, | ||
2819 | es.worst); | ||
2820 | } | ||
2821 | |||
2822 | /* Consider additional paths */ | ||
2823 | (void) GCP_iterate_paths (t->destination, | ||
2824 | &consider_path_cb, | ||
2825 | t); | ||
2826 | |||
2827 | /* FIXME: calculate when to try again based on how well we are doing; | ||
2828 | in particular, if we have to few connections, we might be able | ||
2829 | to do without this (as PATHS should tell us whenever a new path | ||
2830 | is available instantly; however, need to make sure this job is | ||
2831 | restarted after that happens). | ||
2832 | Furthermore, if the paths we do know are in a reasonably narrow | ||
2833 | quality band and are plentyful, we might also consider us stabilized | ||
2834 | and then reduce the frequency accordingly. */delay = GNUNET_TIME_UNIT_MINUTES; | ||
2835 | t->maintain_connections_task | ||
2836 | = GNUNET_SCHEDULER_add_delayed (delay, | ||
2837 | &maintain_connections_cb, | ||
2838 | t); | ||
2839 | } | ||
2840 | |||
2841 | |||
2842 | /** | ||
2843 | * Consider using the path @a p for the tunnel @a t. | ||
2844 | * The tunnel destination is at offset @a off in path @a p. | ||
2845 | * | ||
2846 | * @param cls our tunnel | ||
2847 | * @param path a path to our destination | ||
2848 | * @param off offset of the destination on path @a path | ||
2849 | */ | ||
2850 | void | ||
2851 | GCT_consider_path (struct CadetTunnel *t, | ||
2852 | struct CadetPeerPath *p, | ||
2853 | unsigned int off) | ||
2854 | { | ||
2855 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2856 | "Considering %s for %s (offset %u)\n", | ||
2857 | GCPP_2s (p), | ||
2858 | GCT_2s (t), | ||
2859 | off); | ||
2860 | (void) consider_path_cb (t, | ||
2861 | p, | ||
2862 | off); | ||
2863 | } | ||
2864 | |||
2865 | |||
2866 | /** | ||
2867 | * We got a keepalive. Track in statistics. | ||
2868 | * | ||
2869 | * @param cls the `struct CadetTunnel` for which we decrypted the message | ||
2870 | * @param msg the message we received on the tunnel | ||
2871 | */ | ||
2872 | static void | ||
2873 | handle_plaintext_keepalive (void *cls, | ||
2874 | const struct GNUNET_MessageHeader *msg) | ||
2875 | { | ||
2876 | struct CadetTunnel *t = cls; | ||
2877 | |||
2878 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2879 | "Received KEEPALIVE on %s\n", | ||
2880 | GCT_2s (t)); | ||
2881 | GNUNET_STATISTICS_update (stats, | ||
2882 | "# keepalives received", | ||
2883 | 1, | ||
2884 | GNUNET_NO); | ||
2885 | } | ||
2886 | |||
2887 | |||
2888 | /** | ||
2889 | * Check that @a msg is well-formed. | ||
2890 | * | ||
2891 | * @param cls the `struct CadetTunnel` for which we decrypted the message | ||
2892 | * @param msg the message we received on the tunnel | ||
2893 | * @return #GNUNET_OK (any variable-size payload goes) | ||
2894 | */ | ||
2895 | static int | ||
2896 | check_plaintext_data (void *cls, | ||
2897 | const struct GNUNET_CADET_ChannelAppDataMessage *msg) | ||
2898 | { | ||
2899 | return GNUNET_OK; | ||
2900 | } | ||
2901 | |||
2902 | |||
2903 | /** | ||
2904 | * We received payload data for a channel. Locate the channel | ||
2905 | * and process the data, or return an error if the channel is unknown. | ||
2906 | * | ||
2907 | * @param cls the `struct CadetTunnel` for which we decrypted the message | ||
2908 | * @param msg the message we received on the tunnel | ||
2909 | */ | ||
2910 | static void | ||
2911 | handle_plaintext_data (void *cls, | ||
2912 | const struct GNUNET_CADET_ChannelAppDataMessage *msg) | ||
2913 | { | ||
2914 | struct CadetTunnel *t = cls; | ||
2915 | struct CadetChannel *ch; | ||
2916 | |||
2917 | ch = lookup_channel (t, | ||
2918 | msg->ctn); | ||
2919 | if (NULL == ch) | ||
2920 | { | ||
2921 | /* We don't know about such a channel, might have been destroyed on our | ||
2922 | end in the meantime, or never existed. Send back a DESTROY. */ | ||
2923 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2924 | "Received %u bytes of application data for unknown channel %u, sending DESTROY\n", | ||
2925 | (unsigned int) (ntohs (msg->header.size) - sizeof(*msg)), | ||
2926 | ntohl (msg->ctn.cn)); | ||
2927 | GCT_send_channel_destroy (t, | ||
2928 | msg->ctn); | ||
2929 | return; | ||
2930 | } | ||
2931 | GCCH_handle_channel_plaintext_data (ch, | ||
2932 | GCC_get_id (t->current_ct->cc), | ||
2933 | msg); | ||
2934 | } | ||
2935 | |||
2936 | |||
2937 | /** | ||
2938 | * We received an acknowledgement for data we sent on a channel. | ||
2939 | * Locate the channel and process it, or return an error if the | ||
2940 | * channel is unknown. | ||
2941 | * | ||
2942 | * @param cls the `struct CadetTunnel` for which we decrypted the message | ||
2943 | * @param ack the message we received on the tunnel | ||
2944 | */ | ||
2945 | static void | ||
2946 | handle_plaintext_data_ack (void *cls, | ||
2947 | const struct GNUNET_CADET_ChannelDataAckMessage *ack) | ||
2948 | { | ||
2949 | struct CadetTunnel *t = cls; | ||
2950 | struct CadetChannel *ch; | ||
2951 | |||
2952 | ch = lookup_channel (t, | ||
2953 | ack->ctn); | ||
2954 | if (NULL == ch) | ||
2955 | { | ||
2956 | /* We don't know about such a channel, might have been destroyed on our | ||
2957 | end in the meantime, or never existed. Send back a DESTROY. */ | ||
2958 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2959 | "Received DATA_ACK for unknown channel %u, sending DESTROY\n", | ||
2960 | ntohl (ack->ctn.cn)); | ||
2961 | GCT_send_channel_destroy (t, | ||
2962 | ack->ctn); | ||
2963 | return; | ||
2964 | } | ||
2965 | GCCH_handle_channel_plaintext_data_ack (ch, | ||
2966 | GCC_get_id (t->current_ct->cc), | ||
2967 | ack); | ||
2968 | } | ||
2969 | |||
2970 | |||
2971 | /** | ||
2972 | * We have received a request to open a channel to a port from | ||
2973 | * another peer. Creates the incoming channel. | ||
2974 | * | ||
2975 | * @param cls the `struct CadetTunnel` for which we decrypted the message | ||
2976 | * @param copen the message we received on the tunnel | ||
2977 | */ | ||
2978 | static void | ||
2979 | handle_plaintext_channel_open (void *cls, | ||
2980 | const struct | ||
2981 | GNUNET_CADET_ChannelOpenMessage *copen) | ||
2982 | { | ||
2983 | struct CadetTunnel *t = cls; | ||
2984 | struct CadetChannel *ch; | ||
2985 | |||
2986 | ch = GNUNET_CONTAINER_multihashmap32_get (t->channels, | ||
2987 | ntohl (copen->ctn.cn)); | ||
2988 | if (NULL != ch) | ||
2989 | { | ||
2990 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2991 | "Received duplicate channel CHANNEL_OPEN on h_port %s from %s (%s), resending ACK\n", | ||
2992 | GNUNET_h2s (&copen->h_port), | ||
2993 | GCT_2s (t), | ||
2994 | GCCH_2s (ch)); | ||
2995 | GCCH_handle_duplicate_open (ch, | ||
2996 | GCC_get_id (t->current_ct->cc)); | ||
2997 | return; | ||
2998 | } | ||
2999 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
3000 | "Received CHANNEL_OPEN on h_port %s from %s\n", | ||
3001 | GNUNET_h2s (&copen->h_port), | ||
3002 | GCT_2s (t)); | ||
3003 | ch = GCCH_channel_incoming_new (t, | ||
3004 | copen->ctn, | ||
3005 | &copen->h_port, | ||
3006 | ntohl (copen->opt)); | ||
3007 | if (NULL != t->destroy_task) | ||
3008 | { | ||
3009 | GNUNET_SCHEDULER_cancel (t->destroy_task); | ||
3010 | t->destroy_task = NULL; | ||
3011 | } | ||
3012 | GNUNET_assert (GNUNET_OK == | ||
3013 | GNUNET_CONTAINER_multihashmap32_put (t->channels, | ||
3014 | ntohl (copen->ctn.cn), | ||
3015 | ch, | ||
3016 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
3017 | } | ||
3018 | |||
3019 | |||
3020 | /** | ||
3021 | * Send a DESTROY message via the tunnel. | ||
3022 | * | ||
3023 | * @param t the tunnel to transmit over | ||
3024 | * @param ctn ID of the channel to destroy | ||
3025 | */ | ||
3026 | void | ||
3027 | GCT_send_channel_destroy (struct CadetTunnel *t, | ||
3028 | struct GNUNET_CADET_ChannelTunnelNumber ctn) | ||
3029 | { | ||
3030 | struct GNUNET_CADET_ChannelDestroyMessage msg; | ||
3031 | |||
3032 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
3033 | "Sending DESTROY message for channel ID %u\n", | ||
3034 | ntohl (ctn.cn)); | ||
3035 | msg.header.size = htons (sizeof(msg)); | ||
3036 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY); | ||
3037 | msg.reserved = htonl (0); | ||
3038 | msg.ctn = ctn; | ||
3039 | GCT_send (t, | ||
3040 | &msg.header, | ||
3041 | NULL, | ||
3042 | NULL, | ||
3043 | &ctn); | ||
3044 | } | ||
3045 | |||
3046 | |||
3047 | /** | ||
3048 | * We have received confirmation from the target peer that the | ||
3049 | * given channel could be established (the port is open). | ||
3050 | * Tell the client. | ||
3051 | * | ||
3052 | * @param cls the `struct CadetTunnel` for which we decrypted the message | ||
3053 | * @param cm the message we received on the tunnel | ||
3054 | */ | ||
3055 | static void | ||
3056 | handle_plaintext_channel_open_ack (void *cls, | ||
3057 | const struct | ||
3058 | GNUNET_CADET_ChannelOpenAckMessage *cm) | ||
3059 | { | ||
3060 | struct CadetTunnel *t = cls; | ||
3061 | struct CadetChannel *ch; | ||
3062 | |||
3063 | ch = lookup_channel (t, | ||
3064 | cm->ctn); | ||
3065 | if (NULL == ch) | ||
3066 | { | ||
3067 | /* We don't know about such a channel, might have been destroyed on our | ||
3068 | end in the meantime, or never existed. Send back a DESTROY. */ | ||
3069 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
3070 | "Received channel OPEN_ACK for unknown channel %u, sending DESTROY\n", | ||
3071 | ntohl (cm->ctn.cn)); | ||
3072 | GCT_send_channel_destroy (t, | ||
3073 | cm->ctn); | ||
3074 | return; | ||
3075 | } | ||
3076 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
3077 | "Received channel OPEN_ACK on channel %s from %s\n", | ||
3078 | GCCH_2s (ch), | ||
3079 | GCT_2s (t)); | ||
3080 | GCCH_handle_channel_open_ack (ch, | ||
3081 | GCC_get_id (t->current_ct->cc), | ||
3082 | &cm->port); | ||
3083 | } | ||
3084 | |||
3085 | |||
3086 | /** | ||
3087 | * We received a message saying that a channel should be destroyed. | ||
3088 | * Pass it on to the correct channel. | ||
3089 | * | ||
3090 | * @param cls the `struct CadetTunnel` for which we decrypted the message | ||
3091 | * @param cm the message we received on the tunnel | ||
3092 | */ | ||
3093 | static void | ||
3094 | handle_plaintext_channel_destroy (void *cls, | ||
3095 | const struct | ||
3096 | GNUNET_CADET_ChannelDestroyMessage *cm) | ||
3097 | { | ||
3098 | struct CadetTunnel *t = cls; | ||
3099 | struct CadetChannel *ch; | ||
3100 | |||
3101 | ch = lookup_channel (t, | ||
3102 | cm->ctn); | ||
3103 | if (NULL == ch) | ||
3104 | { | ||
3105 | /* We don't know about such a channel, might have been destroyed on our | ||
3106 | end in the meantime, or never existed. */ | ||
3107 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
3108 | "Received channel DESTROY for unknown channel %u. Ignoring.\n", | ||
3109 | ntohl (cm->ctn.cn)); | ||
3110 | return; | ||
3111 | } | ||
3112 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
3113 | "Received channel DESTROY on %s from %s\n", | ||
3114 | GCCH_2s (ch), | ||
3115 | GCT_2s (t)); | ||
3116 | GCCH_handle_remote_destroy (ch, | ||
3117 | GCC_get_id (t->current_ct->cc)); | ||
3118 | } | ||
3119 | |||
3120 | |||
3121 | /** | ||
3122 | * Handles a message we decrypted, by injecting it into | ||
3123 | * our message queue (which will do the dispatching). | ||
3124 | * | ||
3125 | * @param cls the `struct CadetTunnel` that got the message | ||
3126 | * @param msg the message | ||
3127 | * @return #GNUNET_OK on success (always) | ||
3128 | * #GNUNET_NO to stop further processing (no error) | ||
3129 | * #GNUNET_SYSERR to stop further processing with error | ||
3130 | */ | ||
3131 | static int | ||
3132 | handle_decrypted (void *cls, | ||
3133 | const struct GNUNET_MessageHeader *msg) | ||
3134 | { | ||
3135 | struct CadetTunnel *t = cls; | ||
3136 | |||
3137 | GNUNET_assert (NULL != t->current_ct); | ||
3138 | GNUNET_MQ_inject_message (t->mq, | ||
3139 | msg); | ||
3140 | return GNUNET_OK; | ||
3141 | } | ||
3142 | |||
3143 | |||
3144 | /** | ||
3145 | * Function called if we had an error processing | ||
3146 | * an incoming decrypted message. | ||
3147 | * | ||
3148 | * @param cls the `struct CadetTunnel` | ||
3149 | * @param error error code | ||
3150 | */ | ||
3151 | static void | ||
3152 | decrypted_error_cb (void *cls, | ||
3153 | enum GNUNET_MQ_Error error) | ||
3154 | { | ||
3155 | GNUNET_break_op (0); | ||
3156 | } | ||
3157 | |||
3158 | |||
3159 | /** | ||
3160 | * Create a tunnel to @a destination. Must only be called | ||
3161 | * from within #GCP_get_tunnel(). | ||
3162 | * | ||
3163 | * @param destination where to create the tunnel to | ||
3164 | * @return new tunnel to @a destination | ||
3165 | */ | ||
3166 | struct CadetTunnel * | ||
3167 | GCT_create_tunnel (struct CadetPeer *destination) | ||
3168 | { | ||
3169 | struct CadetTunnel *t = GNUNET_new (struct CadetTunnel); | ||
3170 | struct GNUNET_MQ_MessageHandler handlers[] = { | ||
3171 | GNUNET_MQ_hd_fixed_size (plaintext_keepalive, | ||
3172 | GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE, | ||
3173 | struct GNUNET_MessageHeader, | ||
3174 | t), | ||
3175 | GNUNET_MQ_hd_var_size (plaintext_data, | ||
3176 | GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA, | ||
3177 | struct GNUNET_CADET_ChannelAppDataMessage, | ||
3178 | t), | ||
3179 | GNUNET_MQ_hd_fixed_size (plaintext_data_ack, | ||
3180 | GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK, | ||
3181 | struct GNUNET_CADET_ChannelDataAckMessage, | ||
3182 | t), | ||
3183 | GNUNET_MQ_hd_fixed_size (plaintext_channel_open, | ||
3184 | GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN, | ||
3185 | struct GNUNET_CADET_ChannelOpenMessage, | ||
3186 | t), | ||
3187 | GNUNET_MQ_hd_fixed_size (plaintext_channel_open_ack, | ||
3188 | GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK, | ||
3189 | struct GNUNET_CADET_ChannelOpenAckMessage, | ||
3190 | t), | ||
3191 | GNUNET_MQ_hd_fixed_size (plaintext_channel_destroy, | ||
3192 | GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY, | ||
3193 | struct GNUNET_CADET_ChannelDestroyMessage, | ||
3194 | t), | ||
3195 | GNUNET_MQ_handler_end () | ||
3196 | }; | ||
3197 | |||
3198 | t->kx_retry_delay = INITIAL_KX_RETRY_DELAY; | ||
3199 | new_ephemeral (&t->ax); | ||
3200 | GNUNET_CRYPTO_ecdhe_key_create (&t->ax.kx_0); | ||
3201 | t->destination = destination; | ||
3202 | t->channels = GNUNET_CONTAINER_multihashmap32_create (8); | ||
3203 | t->maintain_connections_task | ||
3204 | = GNUNET_SCHEDULER_add_now (&maintain_connections_cb, | ||
3205 | t); | ||
3206 | t->mq = GNUNET_MQ_queue_for_callbacks (NULL, | ||
3207 | NULL, | ||
3208 | NULL, | ||
3209 | NULL, | ||
3210 | handlers, | ||
3211 | &decrypted_error_cb, | ||
3212 | t); | ||
3213 | t->mst = GNUNET_MST_create (&handle_decrypted, | ||
3214 | t); | ||
3215 | return t; | ||
3216 | } | ||
3217 | |||
3218 | |||
3219 | /** | ||
3220 | * Add a @a connection to the @a tunnel. | ||
3221 | * | ||
3222 | * @param t a tunnel | ||
3223 | * @param cid connection identifier to use for the connection | ||
3224 | * @param options options for the connection | ||
3225 | * @param path path to use for the connection | ||
3226 | * @return #GNUNET_OK on success, | ||
3227 | * #GNUNET_SYSERR on failure (duplicate connection) | ||
3228 | */ | ||
3229 | int | ||
3230 | GCT_add_inbound_connection (struct CadetTunnel *t, | ||
3231 | const struct | ||
3232 | GNUNET_CADET_ConnectionTunnelIdentifier *cid, | ||
3233 | struct CadetPeerPath *path) | ||
3234 | { | ||
3235 | struct CadetTConnection *ct; | ||
3236 | |||
3237 | ct = GNUNET_new (struct CadetTConnection); | ||
3238 | ct->created = GNUNET_TIME_absolute_get (); | ||
3239 | ct->t = t; | ||
3240 | ct->cc = GCC_create_inbound (t->destination, | ||
3241 | path, | ||
3242 | ct, | ||
3243 | cid, | ||
3244 | &connection_ready_cb, | ||
3245 | ct); | ||
3246 | if (NULL == ct->cc) | ||
3247 | { | ||
3248 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
3249 | "%s refused inbound %s (duplicate)\n", | ||
3250 | GCT_2s (t), | ||
3251 | GCC_2s (ct->cc)); | ||
3252 | GNUNET_free (ct); | ||
3253 | return GNUNET_SYSERR; | ||
3254 | } | ||
3255 | /* FIXME: schedule job to kill connection (and path?) if it takes | ||
3256 | too long to get ready! (And track performance data on how long | ||
3257 | other connections took with the tunnel!) | ||
3258 | => Note: to be done within 'connection'-logic! */ | ||
3259 | GNUNET_CONTAINER_DLL_insert (t->connection_busy_head, | ||
3260 | t->connection_busy_tail, | ||
3261 | ct); | ||
3262 | t->num_busy_connections++; | ||
3263 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
3264 | "%s has new %s\n", | ||
3265 | GCT_2s (t), | ||
3266 | GCC_2s (ct->cc)); | ||
3267 | return GNUNET_OK; | ||
3268 | } | ||
3269 | |||
3270 | |||
3271 | /** | ||
3272 | * Handle encrypted message. | ||
3273 | * | ||
3274 | * @param ct connection/tunnel combo that received encrypted message | ||
3275 | * @param msg the encrypted message to decrypt | ||
3276 | */ | ||
3277 | void | ||
3278 | GCT_handle_encrypted (struct CadetTConnection *ct, | ||
3279 | const struct GNUNET_CADET_TunnelEncryptedMessage *msg) | ||
3280 | { | ||
3281 | struct CadetTunnel *t = ct->t; | ||
3282 | uint16_t size = ntohs (msg->header.size); | ||
3283 | char cbuf[size] GNUNET_ALIGN; | ||
3284 | ssize_t decrypted_size; | ||
3285 | |||
3286 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
3287 | "%s received %u bytes of encrypted data in state %d\n", | ||
3288 | GCT_2s (t), | ||
3289 | (unsigned int) size, | ||
3290 | t->estate); | ||
3291 | |||
3292 | switch (t->estate) | ||
3293 | { | ||
3294 | case CADET_TUNNEL_KEY_UNINITIALIZED: | ||
3295 | case CADET_TUNNEL_KEY_AX_RECV: | ||
3296 | /* We did not even SEND our KX, how can the other peer | ||
3297 | send us encrypted data? Must have been that we went | ||
3298 | down and the other peer still things we are up. | ||
3299 | Let's send it KX back. */ | ||
3300 | GNUNET_STATISTICS_update (stats, | ||
3301 | "# received encrypted without any KX", | ||
3302 | 1, | ||
3303 | GNUNET_NO); | ||
3304 | if (NULL != t->kx_task) | ||
3305 | { | ||
3306 | GNUNET_SCHEDULER_cancel (t->kx_task); | ||
3307 | t->kx_task = NULL; | ||
3308 | } | ||
3309 | send_kx (t, | ||
3310 | ct, | ||
3311 | &t->ax); | ||
3312 | return; | ||
3313 | |||
3314 | case CADET_TUNNEL_KEY_AX_SENT_AND_RECV: | ||
3315 | /* We send KX, and other peer send KX to us at the same time. | ||
3316 | Neither KX is AUTH'ed, so let's try KX_AUTH this time. */ | ||
3317 | GNUNET_STATISTICS_update (stats, | ||
3318 | "# received encrypted without KX_AUTH", | ||
3319 | 1, | ||
3320 | GNUNET_NO); | ||
3321 | if (NULL != t->kx_task) | ||
3322 | { | ||
3323 | GNUNET_SCHEDULER_cancel (t->kx_task); | ||
3324 | t->kx_task = NULL; | ||
3325 | } | ||
3326 | send_kx_auth (t, | ||
3327 | ct, | ||
3328 | &t->ax, | ||
3329 | GNUNET_YES); | ||
3330 | return; | ||
3331 | |||
3332 | case CADET_TUNNEL_KEY_AX_SENT: | ||
3333 | /* We did not get the KX of the other peer, but that | ||
3334 | might have been lost. Send our KX again immediately. */ | ||
3335 | GNUNET_STATISTICS_update (stats, | ||
3336 | "# received encrypted without KX", | ||
3337 | 1, | ||
3338 | GNUNET_NO); | ||
3339 | if (NULL != t->kx_task) | ||
3340 | { | ||
3341 | GNUNET_SCHEDULER_cancel (t->kx_task); | ||
3342 | t->kx_task = NULL; | ||
3343 | } | ||
3344 | send_kx (t, | ||
3345 | ct, | ||
3346 | &t->ax); | ||
3347 | return; | ||
3348 | |||
3349 | case CADET_TUNNEL_KEY_AX_AUTH_SENT: | ||
3350 | /* Great, first payload, we might graduate to OK! */ | ||
3351 | case CADET_TUNNEL_KEY_OK: | ||
3352 | /* We are up and running, all good. */ | ||
3353 | break; | ||
3354 | } | ||
3355 | |||
3356 | decrypted_size = -1; | ||
3357 | if (CADET_TUNNEL_KEY_OK == t->estate) | ||
3358 | { | ||
3359 | /* We have well-established key material available, | ||
3360 | try that. (This is the common case.) */ | ||
3361 | decrypted_size = t_ax_decrypt_and_validate (&t->ax, | ||
3362 | cbuf, | ||
3363 | msg, | ||
3364 | size); | ||
3365 | } | ||
3366 | |||
3367 | if ((-1 == decrypted_size) && | ||
3368 | (NULL != t->unverified_ax)) | ||
3369 | { | ||
3370 | /* We have un-authenticated KX material available. We should try | ||
3371 | this as a back-up option, in case the sender crashed and | ||
3372 | switched keys. */ | ||
3373 | decrypted_size = t_ax_decrypt_and_validate (t->unverified_ax, | ||
3374 | cbuf, | ||
3375 | msg, | ||
3376 | size); | ||
3377 | if (-1 != decrypted_size) | ||
3378 | { | ||
3379 | /* It worked! Treat this as authentication of the AX data! */ | ||
3380 | cleanup_ax (&t->ax); | ||
3381 | t->ax = *t->unverified_ax; | ||
3382 | GNUNET_free (t->unverified_ax); | ||
3383 | t->unverified_ax = NULL; | ||
3384 | } | ||
3385 | if (CADET_TUNNEL_KEY_AX_AUTH_SENT == t->estate) | ||
3386 | { | ||
3387 | /* First time it worked, move tunnel into production! */ | ||
3388 | GCT_change_estate (t, | ||
3389 | CADET_TUNNEL_KEY_OK); | ||
3390 | if (NULL != t->send_task) | ||
3391 | GNUNET_SCHEDULER_cancel (t->send_task); | ||
3392 | t->send_task = GNUNET_SCHEDULER_add_now (&trigger_transmissions, | ||
3393 | t); | ||
3394 | } | ||
3395 | } | ||
3396 | if (NULL != t->unverified_ax) | ||
3397 | { | ||
3398 | /* We had unverified KX material that was useless; so increment | ||
3399 | counter and eventually move to ignore it. Note that we even do | ||
3400 | this increment if we successfully decrypted with the old KX | ||
3401 | material and thus didn't even both with the new one. This is | ||
3402 | the ideal case, as a malicious injection of bogus KX data | ||
3403 | basically only causes us to increment a counter a few times. */t->unverified_attempts++; | ||
3404 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
3405 | "Failed to decrypt message with unverified KX data %u times\n", | ||
3406 | t->unverified_attempts); | ||
3407 | if (t->unverified_attempts > MAX_UNVERIFIED_ATTEMPTS) | ||
3408 | { | ||
3409 | cleanup_ax (t->unverified_ax); | ||
3410 | GNUNET_free (t->unverified_ax); | ||
3411 | t->unverified_ax = NULL; | ||
3412 | } | ||
3413 | } | ||
3414 | |||
3415 | if (-1 == decrypted_size) | ||
3416 | { | ||
3417 | /* Decryption failed for good, complain. */ | ||
3418 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
3419 | "%s failed to decrypt and validate encrypted data, retrying KX\n", | ||
3420 | GCT_2s (t)); | ||
3421 | GNUNET_STATISTICS_update (stats, | ||
3422 | "# unable to decrypt", | ||
3423 | 1, | ||
3424 | GNUNET_NO); | ||
3425 | if (NULL != t->kx_task) | ||
3426 | { | ||
3427 | GNUNET_SCHEDULER_cancel (t->kx_task); | ||
3428 | t->kx_task = NULL; | ||
3429 | } | ||
3430 | send_kx (t, | ||
3431 | ct, | ||
3432 | &t->ax); | ||
3433 | return; | ||
3434 | } | ||
3435 | GNUNET_STATISTICS_update (stats, | ||
3436 | "# decrypted bytes", | ||
3437 | decrypted_size, | ||
3438 | GNUNET_NO); | ||
3439 | |||
3440 | /* The MST will ultimately call #handle_decrypted() on each message. */ | ||
3441 | t->current_ct = ct; | ||
3442 | GNUNET_break_op (GNUNET_OK == | ||
3443 | GNUNET_MST_from_buffer (t->mst, | ||
3444 | cbuf, | ||
3445 | decrypted_size, | ||
3446 | GNUNET_YES, | ||
3447 | GNUNET_NO)); | ||
3448 | t->current_ct = NULL; | ||
3449 | } | ||
3450 | |||
3451 | |||
3452 | /** | ||
3453 | * Sends an already built message on a tunnel, encrypting it and | ||
3454 | * choosing the best connection if not provided. | ||
3455 | * | ||
3456 | * @param message Message to send. Function modifies it. | ||
3457 | * @param t Tunnel on which this message is transmitted. | ||
3458 | * @param cont Continuation to call once message is really sent. | ||
3459 | * @param cont_cls Closure for @c cont. | ||
3460 | * @param The ID of the channel we are using for sending. | ||
3461 | * @return Handle to cancel message | ||
3462 | */ | ||
3463 | struct CadetTunnelQueueEntry * | ||
3464 | GCT_send (struct CadetTunnel *t, | ||
3465 | const struct GNUNET_MessageHeader *message, | ||
3466 | GCT_SendContinuation cont, | ||
3467 | void *cont_cls, | ||
3468 | struct GNUNET_CADET_ChannelTunnelNumber *ctn) | ||
3469 | { | ||
3470 | struct CadetTunnelQueueEntry *tq; | ||
3471 | uint16_t payload_size; | ||
3472 | struct GNUNET_MQ_Envelope *env; | ||
3473 | struct GNUNET_CADET_TunnelEncryptedMessage *ax_msg; | ||
3474 | struct CadetChannel *ch; | ||
3475 | |||
3476 | if (NULL != ctn) | ||
3477 | { | ||
3478 | ch = lookup_channel (t, | ||
3479 | *ctn); | ||
3480 | if ((NULL != ch) && GCCH_is_type_to_drop (ch, message)) | ||
3481 | { | ||
3482 | GNUNET_break (0); | ||
3483 | return NULL; | ||
3484 | } | ||
3485 | } | ||
3486 | |||
3487 | if (CADET_TUNNEL_KEY_OK != t->estate) | ||
3488 | { | ||
3489 | GNUNET_break (0); | ||
3490 | return NULL; | ||
3491 | } | ||
3492 | payload_size = ntohs (message->size); | ||
3493 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
3494 | "Encrypting %u bytes for %s\n", | ||
3495 | (unsigned int) payload_size, | ||
3496 | GCT_2s (t)); | ||
3497 | env = GNUNET_MQ_msg_extra (ax_msg, | ||
3498 | payload_size, | ||
3499 | GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED); | ||
3500 | t_ax_encrypt (&t->ax, | ||
3501 | &ax_msg[1], | ||
3502 | message, | ||
3503 | payload_size); | ||
3504 | GNUNET_STATISTICS_update (stats, | ||
3505 | "# encrypted bytes", | ||
3506 | payload_size, | ||
3507 | GNUNET_NO); | ||
3508 | ax_msg->ax_header.Ns = htonl (t->ax.Ns++); | ||
3509 | ax_msg->ax_header.PNs = htonl (t->ax.PNs); | ||
3510 | /* FIXME: we should do this once, not once per message; | ||
3511 | this is a point multiplication, and DHRs does not | ||
3512 | change all the time. */ | ||
3513 | GNUNET_CRYPTO_ecdhe_key_get_public (&t->ax.DHRs, | ||
3514 | &ax_msg->ax_header.DHRs); | ||
3515 | t_h_encrypt (&t->ax, | ||
3516 | ax_msg); | ||
3517 | t_hmac (&ax_msg->ax_header, | ||
3518 | sizeof(struct GNUNET_CADET_AxHeader) + payload_size, | ||
3519 | 0, | ||
3520 | &t->ax.HKs, | ||
3521 | &ax_msg->hmac); | ||
3522 | |||
3523 | tq = GNUNET_malloc (sizeof(*tq)); | ||
3524 | tq->t = t; | ||
3525 | tq->env = env; | ||
3526 | tq->cid = &ax_msg->cid; /* will initialize 'ax_msg->cid' once we know the connection */ | ||
3527 | tq->cont = cont; | ||
3528 | tq->cont_cls = cont_cls; | ||
3529 | GNUNET_CONTAINER_DLL_insert_tail (t->tq_head, | ||
3530 | t->tq_tail, | ||
3531 | tq); | ||
3532 | if (NULL != t->send_task) | ||
3533 | GNUNET_SCHEDULER_cancel (t->send_task); | ||
3534 | t->send_task | ||
3535 | = GNUNET_SCHEDULER_add_now (&trigger_transmissions, | ||
3536 | t); | ||
3537 | return tq; | ||
3538 | } | ||
3539 | |||
3540 | |||
3541 | /** | ||
3542 | * Cancel a previously sent message while it's in the queue. | ||
3543 | * | ||
3544 | * ONLY can be called before the continuation given to the send | ||
3545 | * function is called. Once the continuation is called, the message is | ||
3546 | * no longer in the queue! | ||
3547 | * | ||
3548 | * @param tq Handle to the queue entry to cancel. | ||
3549 | */ | ||
3550 | void | ||
3551 | GCT_send_cancel (struct CadetTunnelQueueEntry *tq) | ||
3552 | { | ||
3553 | struct CadetTunnel *t = tq->t; | ||
3554 | |||
3555 | GNUNET_CONTAINER_DLL_remove (t->tq_head, | ||
3556 | t->tq_tail, | ||
3557 | tq); | ||
3558 | GNUNET_MQ_discard (tq->env); | ||
3559 | GNUNET_free (tq); | ||
3560 | } | ||
3561 | |||
3562 | |||
3563 | /** | ||
3564 | * Iterate over all connections of a tunnel. | ||
3565 | * | ||
3566 | * @param t Tunnel whose connections to iterate. | ||
3567 | * @param iter Iterator. | ||
3568 | * @param iter_cls Closure for @c iter. | ||
3569 | */ | ||
3570 | void | ||
3571 | GCT_iterate_connections (struct CadetTunnel *t, | ||
3572 | GCT_ConnectionIterator iter, | ||
3573 | void *iter_cls) | ||
3574 | { | ||
3575 | struct CadetTConnection *n; | ||
3576 | |||
3577 | for (struct CadetTConnection *ct = t->connection_ready_head; | ||
3578 | NULL != ct; | ||
3579 | ct = n) | ||
3580 | { | ||
3581 | n = ct->next; | ||
3582 | iter (iter_cls, | ||
3583 | ct); | ||
3584 | } | ||
3585 | for (struct CadetTConnection *ct = t->connection_busy_head; | ||
3586 | NULL != ct; | ||
3587 | ct = n) | ||
3588 | { | ||
3589 | n = ct->next; | ||
3590 | iter (iter_cls, | ||
3591 | ct); | ||
3592 | } | ||
3593 | } | ||
3594 | |||
3595 | |||
3596 | /** | ||
3597 | * Closure for #iterate_channels_cb. | ||
3598 | */ | ||
3599 | struct ChanIterCls | ||
3600 | { | ||
3601 | /** | ||
3602 | * Function to call. | ||
3603 | */ | ||
3604 | GCT_ChannelIterator iter; | ||
3605 | |||
3606 | /** | ||
3607 | * Closure for @e iter. | ||
3608 | */ | ||
3609 | void *iter_cls; | ||
3610 | }; | ||
3611 | |||
3612 | |||
3613 | /** | ||
3614 | * Helper function for #GCT_iterate_channels. | ||
3615 | * | ||
3616 | * @param cls the `struct ChanIterCls` | ||
3617 | * @param key unused | ||
3618 | * @param value a `struct CadetChannel` | ||
3619 | * @return #GNUNET_OK | ||
3620 | */ | ||
3621 | static int | ||
3622 | iterate_channels_cb (void *cls, | ||
3623 | uint32_t key, | ||
3624 | void *value) | ||
3625 | { | ||
3626 | struct ChanIterCls *ctx = cls; | ||
3627 | struct CadetChannel *ch = value; | ||
3628 | |||
3629 | ctx->iter (ctx->iter_cls, | ||
3630 | ch); | ||
3631 | return GNUNET_OK; | ||
3632 | } | ||
3633 | |||
3634 | |||
3635 | /** | ||
3636 | * Iterate over all channels of a tunnel. | ||
3637 | * | ||
3638 | * @param t Tunnel whose channels to iterate. | ||
3639 | * @param iter Iterator. | ||
3640 | * @param iter_cls Closure for @c iter. | ||
3641 | */ | ||
3642 | void | ||
3643 | GCT_iterate_channels (struct CadetTunnel *t, | ||
3644 | GCT_ChannelIterator iter, | ||
3645 | void *iter_cls) | ||
3646 | { | ||
3647 | struct ChanIterCls ctx; | ||
3648 | |||
3649 | ctx.iter = iter; | ||
3650 | ctx.iter_cls = iter_cls; | ||
3651 | GNUNET_CONTAINER_multihashmap32_iterate (t->channels, | ||
3652 | &iterate_channels_cb, | ||
3653 | &ctx); | ||
3654 | } | ||
3655 | |||
3656 | |||
3657 | /** | ||
3658 | * Call #GCCH_debug() on a channel. | ||
3659 | * | ||
3660 | * @param cls points to the log level to use | ||
3661 | * @param key unused | ||
3662 | * @param value the `struct CadetChannel` to dump | ||
3663 | * @return #GNUNET_OK (continue iteration) | ||
3664 | */ | ||
3665 | static int | ||
3666 | debug_channel (void *cls, | ||
3667 | uint32_t key, | ||
3668 | void *value) | ||
3669 | { | ||
3670 | const enum GNUNET_ErrorType *level = cls; | ||
3671 | struct CadetChannel *ch = value; | ||
3672 | |||
3673 | GCCH_debug (ch, *level); | ||
3674 | return GNUNET_OK; | ||
3675 | } | ||
3676 | |||
3677 | |||
3678 | #define LOG2(level, ...) GNUNET_log_from_nocheck (level, "cadet-tun", \ | ||
3679 | __VA_ARGS__) | ||
3680 | |||
3681 | |||
3682 | /** | ||
3683 | * Log all possible info about the tunnel state. | ||
3684 | * | ||
3685 | * @param t Tunnel to debug. | ||
3686 | * @param level Debug level to use. | ||
3687 | */ | ||
3688 | void | ||
3689 | GCT_debug (const struct CadetTunnel *t, | ||
3690 | enum GNUNET_ErrorType level) | ||
3691 | { | ||
3692 | #if ! defined(GNUNET_CULL_LOGGING) | ||
3693 | struct CadetTConnection *iter_c; | ||
3694 | int do_log; | ||
3695 | |||
3696 | do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK), | ||
3697 | "cadet-tun", | ||
3698 | __FILE__, __FUNCTION__, __LINE__); | ||
3699 | if (0 == do_log) | ||
3700 | return; | ||
3701 | |||
3702 | LOG2 (level, | ||
3703 | "TTT TUNNEL TOWARDS %s in estate %s tq_len: %u #cons: %u\n", | ||
3704 | GCT_2s (t), | ||
3705 | estate2s (t->estate), | ||
3706 | t->tq_len, | ||
3707 | GCT_count_any_connections (t)); | ||
3708 | LOG2 (level, | ||
3709 | "TTT channels:\n"); | ||
3710 | GNUNET_CONTAINER_multihashmap32_iterate (t->channels, | ||
3711 | &debug_channel, | ||
3712 | &level); | ||
3713 | LOG2 (level, | ||
3714 | "TTT connections:\n"); | ||
3715 | for (iter_c = t->connection_ready_head; NULL != iter_c; iter_c = iter_c->next) | ||
3716 | GCC_debug (iter_c->cc, | ||
3717 | level); | ||
3718 | for (iter_c = t->connection_busy_head; NULL != iter_c; iter_c = iter_c->next) | ||
3719 | GCC_debug (iter_c->cc, | ||
3720 | level); | ||
3721 | |||
3722 | LOG2 (level, | ||
3723 | "TTT TUNNEL END\n"); | ||
3724 | #endif | ||
3725 | } | ||
3726 | |||
3727 | |||
3728 | /* end of gnunet-service-cadet_tunnels.c */ | ||
diff --git a/src/cadet/gnunet-service-cadet_tunnels.h b/src/cadet/gnunet-service-cadet_tunnels.h deleted file mode 100644 index aea131542..000000000 --- a/src/cadet/gnunet-service-cadet_tunnels.h +++ /dev/null | |||
@@ -1,388 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2001-2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/gnunet-service-cadet_tunnels.h | ||
23 | * @brief Information we track per tunnel. | ||
24 | * @author Bartlomiej Polot | ||
25 | * @author Christian Grothoff | ||
26 | */ | ||
27 | #ifndef GNUNET_SERVICE_CADET_TUNNELS_H | ||
28 | #define GNUNET_SERVICE_CADET_TUNNELS_H | ||
29 | |||
30 | #include "gnunet-service-cadet.h" | ||
31 | #include "cadet_protocol.h" | ||
32 | |||
33 | |||
34 | /** | ||
35 | * How many connections would we like to have per tunnel? | ||
36 | */ | ||
37 | #define DESIRED_CONNECTIONS_PER_TUNNEL 3 | ||
38 | |||
39 | |||
40 | /** | ||
41 | * All the encryption states a tunnel can be in. | ||
42 | */ | ||
43 | enum 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 | */ | ||
89 | int | ||
90 | GCT_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 | */ | ||
99 | const char * | ||
100 | GCT_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 | */ | ||
110 | struct CadetTunnel * | ||
111 | GCT_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 | */ | ||
119 | void | ||
120 | GCT_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 | */ | ||
132 | int | ||
133 | GCT_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 | */ | ||
145 | void | ||
146 | GCT_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 | */ | ||
155 | struct CadetPeer * | ||
156 | GCT_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 | */ | ||
167 | void | ||
168 | GCT_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 | */ | ||
180 | struct GNUNET_CADET_ChannelTunnelNumber | ||
181 | GCT_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 | */ | ||
192 | void | ||
193 | GCT_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 | */ | ||
204 | void | ||
205 | GCT_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 | */ | ||
217 | typedef 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 | */ | ||
233 | struct CadetTunnelQueueEntry * | ||
234 | GCT_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 | */ | ||
250 | void | ||
251 | GCT_send_cancel (struct CadetTunnelQueueEntry *q); | ||
252 | |||
253 | |||
254 | /** | ||
255 | * Return the number of channels using a tunnel. | ||
256 | * | ||
257 | * @param t tunnel to count obtain the number of channels for | ||
258 | * @return number of channels using the tunnel | ||
259 | */ | ||
260 | unsigned int | ||
261 | GCT_count_channels (struct CadetTunnel *t); | ||
262 | |||
263 | |||
264 | /** | ||
265 | * Return the number of connections available for a tunnel. | ||
266 | * | ||
267 | * @param t tunnel to count obtain the number of connections for | ||
268 | * @return number of connections available for the tunnel | ||
269 | */ | ||
270 | unsigned int | ||
271 | GCT_count_any_connections (const struct CadetTunnel *t); | ||
272 | |||
273 | |||
274 | /** | ||
275 | * Iterator over connections. | ||
276 | * | ||
277 | * @param cls closure | ||
278 | * @param ct one of the connections | ||
279 | */ | ||
280 | typedef void | ||
281 | (*GCT_ConnectionIterator) (void *cls, | ||
282 | struct CadetTConnection *ct); | ||
283 | |||
284 | |||
285 | /** | ||
286 | * Iterate over all connections of a tunnel. | ||
287 | * | ||
288 | * @param t Tunnel whose connections to iterate. | ||
289 | * @param iter Iterator. | ||
290 | * @param iter_cls Closure for @c iter. | ||
291 | */ | ||
292 | void | ||
293 | GCT_iterate_connections (struct CadetTunnel *t, | ||
294 | GCT_ConnectionIterator iter, | ||
295 | void *iter_cls); | ||
296 | |||
297 | |||
298 | /** | ||
299 | * Iterator over channels. | ||
300 | * | ||
301 | * @param cls closure | ||
302 | * @param ch one of the channels | ||
303 | */ | ||
304 | typedef void | ||
305 | (*GCT_ChannelIterator) (void *cls, | ||
306 | struct CadetChannel *ch); | ||
307 | |||
308 | |||
309 | /** | ||
310 | * Iterate over all channels of a tunnel. | ||
311 | * | ||
312 | * @param t Tunnel whose channels to iterate. | ||
313 | * @param iter Iterator. | ||
314 | * @param iter_cls Closure for @c iter. | ||
315 | */ | ||
316 | void | ||
317 | GCT_iterate_channels (struct CadetTunnel *t, | ||
318 | GCT_ChannelIterator iter, | ||
319 | void *iter_cls); | ||
320 | |||
321 | |||
322 | /** | ||
323 | * Get the encryption state of a tunnel. | ||
324 | * | ||
325 | * @param t Tunnel. | ||
326 | * | ||
327 | * @return Tunnel's encryption state. | ||
328 | */ | ||
329 | enum CadetTunnelEState | ||
330 | GCT_get_estate (struct CadetTunnel *t); | ||
331 | |||
332 | /** | ||
333 | * Change the tunnel encryption state. | ||
334 | * If the encryption state changes to OK, stop the rekey task. | ||
335 | * | ||
336 | * @param t Tunnel whose encryption state to change, or NULL. | ||
337 | * @param state New encryption state. | ||
338 | */ | ||
339 | void | ||
340 | GCT_change_estate (struct CadetTunnel *t, | ||
341 | enum CadetTunnelEState state); | ||
342 | |||
343 | /** | ||
344 | * Handle KX message. | ||
345 | * | ||
346 | * @param ct connection/tunnel combo that received encrypted message | ||
347 | * @param msg the key exchange message | ||
348 | */ | ||
349 | void | ||
350 | GCT_handle_kx (struct CadetTConnection *ct, | ||
351 | const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg); | ||
352 | |||
353 | |||
354 | /** | ||
355 | * Handle KX_AUTH message. | ||
356 | * | ||
357 | * @param ct connection/tunnel combo that received encrypted message | ||
358 | * @param msg the key exchange message | ||
359 | */ | ||
360 | void | ||
361 | GCT_handle_kx_auth (struct CadetTConnection *ct, | ||
362 | const struct | ||
363 | GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg); | ||
364 | |||
365 | |||
366 | /** | ||
367 | * Handle encrypted message. | ||
368 | * | ||
369 | * @param ct connection/tunnel combo that received encrypted message | ||
370 | * @param msg the encrypted message to decrypt | ||
371 | */ | ||
372 | void | ||
373 | GCT_handle_encrypted (struct CadetTConnection *ct, | ||
374 | const struct GNUNET_CADET_TunnelEncryptedMessage *msg); | ||
375 | |||
376 | |||
377 | /** | ||
378 | * Log all possible info about the tunnel state. | ||
379 | * | ||
380 | * @param t Tunnel to debug. | ||
381 | * @param level Debug level to use. | ||
382 | */ | ||
383 | void | ||
384 | GCT_debug (const struct CadetTunnel *t, | ||
385 | enum GNUNET_ErrorType level); | ||
386 | |||
387 | |||
388 | #endif | ||
diff --git a/src/cadet/loopcheck.sh b/src/cadet/loopcheck.sh deleted file mode 100755 index 9b867e95b..000000000 --- a/src/cadet/loopcheck.sh +++ /dev/null | |||
@@ -1,57 +0,0 @@ | |||
1 | #!/usr/bin/env bash | ||
2 | # This script is in the public domain | ||
3 | # POSIX shell solution for named pipes and pipestatus, | ||
4 | # http://shell.cfajohnson.com/cus-faq-2.html#Q11 | ||
5 | # run() { | ||
6 | # j=1 | ||
7 | # while eval "\${pipestatus_$j+:} false"; do | ||
8 | # unset pipestatus_$j | ||
9 | # j=$(($j+1)) | ||
10 | # done | ||
11 | # j=1 com= k=1 l= | ||
12 | # for a; do | ||
13 | # if [ "x$a" = 'x|' ]; then | ||
14 | # com="$com { $l "'3>&- | ||
15 | # echo "pipestatus_'$j'=$?" >&3 | ||
16 | # } 4>&- |' | ||
17 | # j=$(($j+1)) l= | ||
18 | # else | ||
19 | # l="$l \"\$$k\"" | ||
20 | # fi | ||
21 | # k=$(($k+1)) | ||
22 | # done | ||
23 | # com="$com $l"' 3>&- >&4 4>&- | ||
24 | # echo "pipestatus_'$j'=$?"' | ||
25 | # exec 4>&1 | ||
26 | # eval "$(exec 3>&1; eval "$com")" | ||
27 | # exec 4>&- | ||
28 | # j=1 | ||
29 | # while eval "\${pipestatus_$j+:} false"; do | ||
30 | # eval "[ \$pipestatus_$j -eq 0 ]" || return 1 | ||
31 | # j=$(($j+1)) | ||
32 | # done | ||
33 | # return 0 | ||
34 | # } | ||
35 | |||
36 | # # https://mywiki.wooledge.org/Bashism has another solution: | ||
37 | # # mkfifo fifo; command2 <fifo & command1 >fifo; echo "$?" | ||
38 | |||
39 | while 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 | ||
57 | done | ||
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] | ||
4 | OVERLAY_TOPOLOGY = RANDOM | ||
5 | OVERLAY_RANDOM_LINKS = %LINKS% | ||
6 | MAX_PARALLEL_SERVICE_CONNECTIONS=4000 | ||
7 | SETUP_TIMEOUT = 60 m | ||
8 | |||
9 | [transport] | ||
10 | #MANIPULATE_DELAY_IN = 50 ms | ||
11 | MANIPULATE_DELAY_OUT = 10 ms | ||
12 | |||
13 | [cadet] | ||
14 | REFRESH_CONNECTION_TIME = 1 h | ||
15 | DISABLE_TRY_CONNECT = YES | ||
16 | ID_ANNOUNCE_TIME = 5 s | ||
17 | |||
18 | [dht] | ||
19 | FORCE_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 | |||
3 | if [ "$#" -lt "3" ]; then | ||
4 | echo "usage: $0 ROUND_TIME PEERS PINGING_PEERS"; | ||
5 | echo "example: $0 30s 16 1"; | ||
6 | exit 1; | ||
7 | fi | ||
8 | |||
9 | ROUNDTIME=$1 | ||
10 | PEERS=$2 | ||
11 | PINGS=$3 | ||
12 | |||
13 | if [ $PEERS -eq 1 ]; then | ||
14 | echo "cannot run 1 peer"; | ||
15 | exit 1; | ||
16 | fi | ||
17 | |||
18 | LINKS=`echo "l($PEERS) * l($PEERS) * $PEERS / 2" | bc -l` | ||
19 | LINKS=`printf "%.0f" $LINKS` | ||
20 | NSE=`echo "l($PEERS)/l(2)" | bc -l` | ||
21 | echo "using $PEERS peers, $LINKS links"; | ||
22 | |||
23 | sed -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 @@ | |||
1 | 16 | ||
2 | 1:2 | ||
3 | 1:9 | ||
4 | 2:3 | ||
5 | 3:4 | ||
6 | 3:11 | ||
7 | 4:5 | ||
8 | 5:6 | ||
9 | 5:13 | ||
10 | 6:7 | ||
11 | 7:8 | ||
12 | 7:15 | ||
13 | 8:9 | ||
14 | 9:10 | ||
15 | 10:11 | ||
16 | 11:12 | ||
17 | 12:13 | ||
18 | 13:14 | ||
19 | 14:15 | ||
20 | 15:16 | ||
21 | 16: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 | */ | ||
38 | struct 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 | */ | ||
83 | static struct GNUNET_CADET_PeersLister *plo; | ||
84 | |||
85 | /* | ||
86 | * Task called to check for existing tunnel and depending on that reopen channel | ||
87 | */ | ||
88 | static struct GNUNET_SCHEDULER_Task *get_peers_task; | ||
89 | |||
90 | /** | ||
91 | * Which test are we running? | ||
92 | */ | ||
93 | static int test; | ||
94 | |||
95 | /** | ||
96 | * String with test name | ||
97 | */ | ||
98 | static char *test_name; | ||
99 | |||
100 | /** | ||
101 | * Flag to send traffic leaf->root in speed tests to test BCK_ACK logic. | ||
102 | */ | ||
103 | static int test_backwards = GNUNET_NO; | ||
104 | |||
105 | /** | ||
106 | * How many packets to send. | ||
107 | */ | ||
108 | static unsigned int total_packets; | ||
109 | |||
110 | /** | ||
111 | * Time to wait for fast operations. | ||
112 | */ | ||
113 | static struct GNUNET_TIME_Relative short_time; | ||
114 | |||
115 | /** | ||
116 | * How many events have happened | ||
117 | */ | ||
118 | static int ok; | ||
119 | |||
120 | /** | ||
121 | * Number of events expected to conclude the test successfully. | ||
122 | */ | ||
123 | static int ok_goal; | ||
124 | |||
125 | /** | ||
126 | * Size of each test packet's payload | ||
127 | */ | ||
128 | static size_t size_payload = sizeof(uint32_t); | ||
129 | |||
130 | /** | ||
131 | * Operation to get peer ids. | ||
132 | */ | ||
133 | static struct GNUNET_TESTBED_Operation *t_op[2]; | ||
134 | |||
135 | /** | ||
136 | * Peer ids. | ||
137 | */ | ||
138 | static struct GNUNET_PeerIdentity *testpeer_id[2]; | ||
139 | |||
140 | /** | ||
141 | * Peer ids. | ||
142 | */ | ||
143 | static struct GNUNET_CONFIGURATION_Handle *p_cfg[2]; | ||
144 | |||
145 | /** | ||
146 | * Port ID | ||
147 | */ | ||
148 | static struct GNUNET_HashCode port; | ||
149 | |||
150 | /** | ||
151 | * Peer ids counter. | ||
152 | */ | ||
153 | static unsigned int peerinfo_task_cnt; | ||
154 | |||
155 | /** | ||
156 | * Is the setup initialized? | ||
157 | */ | ||
158 | static int initialized; | ||
159 | |||
160 | /** | ||
161 | * Number of payload packes sent. | ||
162 | */ | ||
163 | static int data_sent; | ||
164 | |||
165 | /** | ||
166 | * Number of payload packets received. | ||
167 | */ | ||
168 | static int data_received; | ||
169 | |||
170 | /** | ||
171 | * Number of payload packed acknowledgements sent. | ||
172 | */ | ||
173 | static int ack_sent; | ||
174 | |||
175 | /** | ||
176 | * Number of payload packed explicitly (app level) acknowledged. | ||
177 | */ | ||
178 | static int ack_received; | ||
179 | |||
180 | /** | ||
181 | * Total number of peers asked to run. | ||
182 | */ | ||
183 | static unsigned long long peers_requested; | ||
184 | |||
185 | /** | ||
186 | * Number of currently running peers (should be same as @c peers_requested). | ||
187 | */ | ||
188 | static unsigned long long peers_running; | ||
189 | |||
190 | /** | ||
191 | * Test context (to shut down). | ||
192 | */ | ||
193 | struct GNUNET_CADET_TEST_Context *test_ctx; | ||
194 | |||
195 | /** | ||
196 | * Task called to disconnect peers. | ||
197 | */ | ||
198 | static struct GNUNET_SCHEDULER_Task *disconnect_task; | ||
199 | |||
200 | /** | ||
201 | * Task called to reconnect peers. | ||
202 | */ | ||
203 | static struct GNUNET_SCHEDULER_Task *reconnect_task; | ||
204 | |||
205 | /** | ||
206 | * Task To perform tests | ||
207 | */ | ||
208 | static struct GNUNET_SCHEDULER_Task *test_task; | ||
209 | |||
210 | /** | ||
211 | * Task runnining #send_next_msg(). | ||
212 | */ | ||
213 | static struct GNUNET_SCHEDULER_Task *send_next_msg_task; | ||
214 | |||
215 | /** | ||
216 | * Channel handle for the root peer | ||
217 | */ | ||
218 | static struct GNUNET_CADET_Channel *outgoing_ch; | ||
219 | |||
220 | /** | ||
221 | * Channel handle for the dest peer | ||
222 | */ | ||
223 | static struct GNUNET_CADET_Channel *incoming_ch; | ||
224 | |||
225 | /** | ||
226 | * Time we started the data transmission (after channel has been established | ||
227 | * and initialized). | ||
228 | */ | ||
229 | static struct GNUNET_TIME_Absolute start_time; | ||
230 | |||
231 | /** | ||
232 | * Peers handle. | ||
233 | */ | ||
234 | static struct GNUNET_TESTBED_Peer **testbed_peers; | ||
235 | |||
236 | |||
237 | struct GNUNET_CADET_Handle **cadets_running; | ||
238 | |||
239 | /** | ||
240 | * Statistics operation handle. | ||
241 | */ | ||
242 | static struct GNUNET_TESTBED_Operation *stats_op; | ||
243 | |||
244 | /** | ||
245 | * Keepalives sent. | ||
246 | */ | ||
247 | static unsigned int ka_sent; | ||
248 | |||
249 | /** | ||
250 | * Keepalives received. | ||
251 | */ | ||
252 | static unsigned int ka_received; | ||
253 | |||
254 | /** | ||
255 | * How many messages were dropped by CADET because of full buffers? | ||
256 | */ | ||
257 | static 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 | */ | ||
266 | void | ||
267 | GNUNET_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 | */ | ||
284 | static struct GNUNET_CADET_Channel * | ||
285 | get_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 | */ | ||
297 | static void | ||
298 | show_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 | */ | ||
330 | static void | ||
331 | disconnect_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 | */ | ||
364 | static void | ||
365 | shutdown_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 | */ | ||
398 | static void | ||
399 | stats_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 | */ | ||
433 | static int | ||
434 | stats_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 | */ | ||
469 | static void | ||
470 | gather_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 | */ | ||
500 | static void | ||
501 | send_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 | */ | ||
511 | static int | ||
512 | check_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 | */ | ||
521 | static void | ||
522 | handle_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 | */ | ||
536 | static void | ||
537 | disconnect_handler (void *cls, | ||
538 | const struct GNUNET_CADET_Channel *channel); | ||
539 | |||
540 | static struct GNUNET_PeerIdentity * | ||
541 | get_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 | |||
554 | static struct GNUNET_CADET_Handle * | ||
555 | get_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 | |||
573 | static unsigned int | ||
574 | get_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 | */ | ||
592 | static void | ||
593 | reconnect_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 | |||
633 | void | ||
634 | reopen_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 | |||
667 | static void | ||
668 | peers_callback (void *cls, const struct GNUNET_CADET_PeerListEntry *ple); | ||
669 | |||
670 | /** | ||
671 | * We ask the monitoring api for all the peers. | ||
672 | */ | ||
673 | static void | ||
674 | get_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 | */ | ||
697 | static void | ||
698 | peers_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 | */ | ||
754 | static void | ||
755 | disconnect_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 | */ | ||
817 | static void | ||
818 | abort_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 | */ | ||
840 | static void | ||
841 | send_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 | */ | ||
920 | static void | ||
921 | send_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 | */ | ||
954 | static void | ||
955 | reschedule_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 | */ | ||
980 | static int | ||
981 | check_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 | */ | ||
994 | static void | ||
995 | handle_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 | */ | ||
1158 | static void * | ||
1159 | connect_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 | */ | ||
1236 | static void | ||
1237 | start_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 | */ | ||
1316 | static void | ||
1317 | pi_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 | */ | ||
1380 | static void | ||
1381 | tmain (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 | */ | ||
1423 | int | ||
1424 | main (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] | ||
2 | HOSTNAME = localhost | ||
3 | OVERLAY_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 | ||
10 | REFRESH_CONNECTION_TIME = 1 s | ||
11 | ID_ANNOUNCE_TIME = 5 s | ||
12 | CONNECT_TIMEOUT = 30 s | ||
13 | DEFAULT_TTL = 16 | ||
14 | DHT_REPLICATION_LEVEL = 10 | ||
15 | MAX_TUNNELS = 10 | ||
16 | MAX_CONNECTIONS = 10 | ||
17 | MAX_MSGS_QUEUE = 20 | ||
18 | DISABLE_TRY_CONNECT = YES | ||
19 | REKEY_PERIOD = 2 s | ||
20 | |||
21 | [dht] | ||
22 | DISABLE_TRY_CONNECT = YES | ||
23 | FORCE_NSE = 3 | ||
24 | |||
25 | [dhtcache] | ||
26 | QUOTA = 1 MB | ||
27 | DATABASE = heap | ||
28 | |||
29 | [transport] | ||
30 | #PLUGINS = udp | ||
31 | PLUGINS = tcp | ||
32 | NEIGHBOUR_LIMIT = 50 | ||
33 | #MANIPULATE_DELAY_IN = 10 ms | ||
34 | #MANIPULATE_DELAY_OUT = 10 ms | ||
35 | |||
36 | [nat] | ||
37 | ENABLE_UPNP = NO | ||
38 | |||
39 | [ats] | ||
40 | # Network specific inbound/outbound quotas | ||
41 | UNSPECIFIED_QUOTA_IN = unlimited | ||
42 | UNSPECIFIED_QUOTA_OUT = unlimited | ||
43 | # LOOPBACK | ||
44 | LOOPBACK_QUOTA_IN = unlimited | ||
45 | LOOPBACK_QUOTA_OUT = unlimited | ||
46 | # LAN | ||
47 | LAN_QUOTA_IN = unlimited | ||
48 | LAN_QUOTA_OUT = unlimited | ||
49 | #WAN | ||
50 | WAN_QUOTA_OUT = unlimited | ||
51 | WAN_QUOTA_IN = unlimited | ||
52 | # WLAN | ||
53 | WLAN_QUOTA_IN = unlimited | ||
54 | WLAN_QUOTA_OUT = unlimited | ||
55 | # BLUETOOTH | ||
56 | BLUETOOTH_QUOTA_IN = unlimited | ||
57 | BLUETOOTH_QUOTA_OUT = unlimited | ||
58 | |||
59 | [core] | ||
60 | USE_EPHEMERAL_KEYS = NO | ||
61 | |||
62 | [PATHS] | ||
63 | GNUNET_TEST_HOME = $GNUNET_TMP/test-cadet/ | ||
64 | |||
65 | [peerinfo] | ||
66 | NO_IO = YES | ||
67 | |||
68 | [nse] | ||
69 | WORKBITS = 2 | ||
70 | |||
71 | [hostlist] | ||
72 | IMMEDIATE_START = NO | ||
73 | START_ON_DEMAND = NO | ||
74 | |||
75 | [fs] | ||
76 | IMMEDIATE_START = NO | ||
77 | START_ON_DEMAND = NO | ||
78 | |||
79 | [vpn] | ||
80 | IMMEDIATE_START = NO | ||
81 | START_ON_DEMAND = NO | ||
82 | |||
83 | [revocation] | ||
84 | IMMEDIATE_START = NO | ||
85 | START_ON_DEMAND = NO | ||
86 | |||
87 | [gns] | ||
88 | IMMEDIATE_START = NO | ||
89 | START_ON_DEMAND = NO | ||
90 | |||
91 | [namestore] | ||
92 | IMMEDIATE_START = NO | ||
93 | START_ON_DEMAND = NO | ||
94 | |||
95 | [namecache] | ||
96 | IMMEDIATE_START = NO | ||
97 | START_ON_DEMAND = NO | ||
98 | |||
99 | [topology] | ||
100 | IMMEDIATE_START = NO | ||
101 | START_ON_DEMAND = NO | ||
102 | |||
103 | [rps] | ||
104 | IMMEDIATE_START = NO | ||
105 | START_ON_DEMAND = NO | ||
106 | |||
107 | [rest] | ||
108 | IMMEDIATE_START = NO | ||
109 | START_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] | ||
4 | DROP_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 | */ | ||
37 | struct 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 | */ | ||
70 | static unsigned int total_packets = TOTAL_PACKETS_DEFAULT; | ||
71 | |||
72 | /** | ||
73 | * Time to wait for fast operations. | ||
74 | */ | ||
75 | static struct GNUNET_TIME_Relative short_time; | ||
76 | |||
77 | /** | ||
78 | * Size of each test packet's payload | ||
79 | */ | ||
80 | static size_t size_payload = sizeof(uint32_t); | ||
81 | |||
82 | /** | ||
83 | * Operation to get peer ids. | ||
84 | */ | ||
85 | static struct GNUNET_TESTBED_Operation *t_op[2]; | ||
86 | |||
87 | /** | ||
88 | * Peer ids. | ||
89 | */ | ||
90 | static struct GNUNET_PeerIdentity *p_id[2]; | ||
91 | |||
92 | /** | ||
93 | * Port ID | ||
94 | */ | ||
95 | static struct GNUNET_HashCode port; | ||
96 | |||
97 | /** | ||
98 | * Peer ids counter. | ||
99 | */ | ||
100 | static unsigned int p_ids; | ||
101 | |||
102 | /** | ||
103 | * Is the setup initialized? | ||
104 | */ | ||
105 | static int initialized; | ||
106 | |||
107 | /** | ||
108 | * Number of payload packes sent. | ||
109 | */ | ||
110 | static int data_sent; | ||
111 | |||
112 | /** | ||
113 | * Number of payload packets received. | ||
114 | */ | ||
115 | static int data_received; | ||
116 | |||
117 | /** | ||
118 | * Number of payload packed acknowledgements sent. | ||
119 | */ | ||
120 | static int ack_sent; | ||
121 | |||
122 | /** | ||
123 | * Number of payload packed explicitly (app level) acknowledged. | ||
124 | */ | ||
125 | static int ack_received; | ||
126 | |||
127 | /** | ||
128 | * Total number of peers asked to run. | ||
129 | */ | ||
130 | static unsigned int peers_requested = 2; | ||
131 | |||
132 | /** | ||
133 | * Number of currently running peers (should be same as @c peers_requested). | ||
134 | */ | ||
135 | static unsigned int peers_running; | ||
136 | |||
137 | /** | ||
138 | * Test context (to shut down). | ||
139 | */ | ||
140 | struct GNUNET_CADET_TEST_Context *test_ctx; | ||
141 | |||
142 | /** | ||
143 | * Task called to disconnect peers. | ||
144 | */ | ||
145 | static struct GNUNET_SCHEDULER_Task *disconnect_task; | ||
146 | |||
147 | /** | ||
148 | * Task To perform tests | ||
149 | */ | ||
150 | static struct GNUNET_SCHEDULER_Task *test_task; | ||
151 | |||
152 | /** | ||
153 | * Task runnining #send_next_msg(). | ||
154 | */ | ||
155 | static struct GNUNET_SCHEDULER_Task *send_next_msg_task; | ||
156 | |||
157 | /** | ||
158 | * Cadet handle for the root peer | ||
159 | */ | ||
160 | static struct GNUNET_CADET_Handle *h1; | ||
161 | |||
162 | /** | ||
163 | * Cadet handle for the first leaf peer | ||
164 | */ | ||
165 | static struct GNUNET_CADET_Handle *h2; | ||
166 | |||
167 | /** | ||
168 | * Channel handle for the root peer | ||
169 | */ | ||
170 | static struct GNUNET_CADET_Channel *outgoing_ch; | ||
171 | |||
172 | /** | ||
173 | * Channel handle for the dest peer | ||
174 | */ | ||
175 | static struct GNUNET_CADET_Channel *incoming_ch; | ||
176 | |||
177 | /** | ||
178 | * Time we started the data transmission (after channel has been established | ||
179 | * and initialized). | ||
180 | */ | ||
181 | static struct GNUNET_TIME_Absolute start_time; | ||
182 | |||
183 | /** | ||
184 | * Peers handle. | ||
185 | */ | ||
186 | static struct GNUNET_TESTBED_Peer **testbed_peers; | ||
187 | |||
188 | /** | ||
189 | * Statistics operation handle. | ||
190 | */ | ||
191 | static struct GNUNET_TESTBED_Operation *stats_op; | ||
192 | |||
193 | /** | ||
194 | * Keepalives sent. | ||
195 | */ | ||
196 | static unsigned int ka_sent; | ||
197 | |||
198 | /** | ||
199 | * Keepalives received. | ||
200 | */ | ||
201 | static unsigned int ka_received; | ||
202 | |||
203 | /** | ||
204 | * How many messages were dropped by CADET because of full buffers? | ||
205 | */ | ||
206 | static unsigned int msg_dropped; | ||
207 | |||
208 | |||
209 | /** | ||
210 | * Show the results of the test (banwidth achieved) and log them to GAUGER | ||
211 | */ | ||
212 | static void | ||
213 | show_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 | */ | ||
245 | static void | ||
246 | shutdown_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 | */ | ||
285 | static void | ||
286 | stats_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 | */ | ||
319 | static int | ||
320 | stats_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 | */ | ||
355 | static void | ||
356 | gather_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 | */ | ||
384 | static void | ||
385 | abort_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 | */ | ||
407 | static void | ||
408 | send_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 | */ | ||
475 | static void | ||
476 | send_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 | */ | ||
511 | static int | ||
512 | check_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 | */ | ||
525 | static void | ||
526 | handle_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 | */ | ||
617 | static void * | ||
618 | connect_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 | */ | ||
666 | static void | ||
667 | disconnect_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 | */ | ||
700 | static void | ||
701 | start_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 | */ | ||
748 | static void | ||
749 | pi_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 | */ | ||
791 | static void | ||
792 | tmain (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 | */ | ||
825 | int | ||
826 | main (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 | */ | ||
39 | struct 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 | |||
54 | struct GNUNET_TESTING_Peer *me; | ||
55 | |||
56 | static struct GNUNET_CADET_Handle *cadet_peer_1; | ||
57 | |||
58 | static struct GNUNET_CADET_Handle *cadet_peer_2; | ||
59 | |||
60 | static struct GNUNET_CADET_Channel *ch; | ||
61 | |||
62 | static int result = GNUNET_OK; | ||
63 | |||
64 | static int got_data = GNUNET_NO; | ||
65 | |||
66 | static struct GNUNET_SCHEDULER_Task *abort_task; | ||
67 | |||
68 | static struct GNUNET_SCHEDULER_Task *connect_task; | ||
69 | |||
70 | |||
71 | /** | ||
72 | * Connect to other client and send data | ||
73 | * | ||
74 | * @param cls Closue (unused). | ||
75 | */ | ||
76 | static void | ||
77 | do_connect (void *cls); | ||
78 | |||
79 | |||
80 | /** | ||
81 | * Shutdown nicely | ||
82 | */ | ||
83 | static void | ||
84 | do_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 | */ | ||
123 | static void | ||
124 | do_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 | */ | ||
147 | static void * | ||
148 | connected (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 | */ | ||
171 | static void | ||
172 | disconnected (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 | */ | ||
189 | static void | ||
190 | handle_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 | */ | ||
211 | static void | ||
212 | message_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 | */ | ||
224 | static void | ||
225 | do_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 | */ | ||
269 | static void | ||
270 | run (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 | */ | ||
323 | int | ||
324 | main (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 | ||